summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/EFI/Firmware
diff options
context:
space:
mode:
authorvboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2021-07-01 12:10:28 +0000
committervboxsync <vboxsync@cfe28804-0f27-0410-a406-dd0f0b0b656f>2021-07-01 12:10:28 +0000
commitd7bd94e87ad2101094e0a384e8fd284d015ff0f4 (patch)
treed5296be3598e28f8896ad8a9d1df67d43609e0e4 /src/VBox/Devices/EFI/Firmware
parent0f1af540eb1ef7ec95c12fdac92f97671485206c (diff)
downloadVirtualBox-svn-d7bd94e87ad2101094e0a384e8fd284d015ff0f4.tar.gz
Devices/EFI: Removed old EFI firmware. Using edk2-stable202105 from now on. bugref:4643
git-svn-id: https://www.virtualbox.org/svn/vbox/trunk@89989 cfe28804-0f27-0410-a406-dd0f0b0b656f
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware')
-rw-r--r--src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-GCC5.yml2
-rw-r--r--src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-PatchCheck.yml3
-rw-r--r--src/VBox/Devices/EFI/Firmware/.azurepipelines/Windows-VS2019.yml2
-rw-r--r--src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/platform-build-run-steps.yml6
-rw-r--r--src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-build-job.yml12
-rw-r--r--src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-steps.yml6
-rw-r--r--src/VBox/Devices/EFI/Firmware/.gitmodules5
-rw-r--r--src/VBox/Devices/EFI/Firmware/.mailmap8
-rw-r--r--src/VBox/Devices/EFI/Firmware/.mergify/config.yml16
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/CISettings.py69
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck.py309
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck_plug_in.yaml11
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/Readme.md15
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck.py115
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml11
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/Readme.md17
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Plugin/SpellCheck/cspell.base.yaml1
-rw-r--r--src/VBox/Devices/EFI/Firmware/.pytool/Readme.md18
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/AmlToC14
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BPDG12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BrotliCompress60
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/DevicePath29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Ecc13
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/EfiRom29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenCrc3229
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenDepex12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFds12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFfs29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFv29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFw29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenPatchPcdTable12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenSec29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenerateCapsule12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaCompress29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaF86Compress19
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/PatchPcdValue12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Pkcs7Sign12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256GenerateKeys12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256Sign12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Split29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TargetTool12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TianoCompress29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Trim13
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/UPT12
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VfrCompile29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VolInfo29
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/build12
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/posix_path_env.yaml11
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/AmlToC.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/BPDG.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Ecc.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenDepex.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenFds.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenPatchPcdTable.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenerateCapsule.bat1
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/PatchPcdValue.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Pkcs7Sign.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256GenerateKeys.bat1
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256Sign.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Split.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/TargetTool.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Trim.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/UPT.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/build.bat3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/win_build_tools_path_env.yaml11
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/BuildEnv12
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Conf/build_rule.template17
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Conf/diff.order26
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Conf/tools_def.template75
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.rst41
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.txt47
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertFceToStructurePcd.py69
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PatchCheck.py31
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c587
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h8
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c11
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c20
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h10
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h85
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h8
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h9
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c164
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c117
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h14
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c32
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c725
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt22
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile1
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk1
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile28
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/GNUmakefile17
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile16
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile.kmk35
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Split.c466
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile6
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g25
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AmlToC/AmlToC.py (renamed from src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AmlToHex/AmlToHex.py)82
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGenWorker.py28
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py2
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/DataPipe.py5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py65
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py19
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py45
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py66
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py175
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py24
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Capsule/GenerateCapsule.py5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/GlobalData.py1
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py2
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py19
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py28
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py19
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/EccToolError.py3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py6
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py7
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/exception.xml636
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py9
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py11
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py18
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py3
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py5
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py244
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py16
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/README.md29
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/Split.py210
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/__init__.py10
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py9
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py12
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py248
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py14
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py16
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py127
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py149
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/buildoptions.py4
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py115
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/set_vsprefix_envs.bat56
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/BaseTools/toolsetup.bat19
-rw-r--r--src/VBox/Devices/EFI/Firmware/CONTRIBUTING.md3
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.ci.yaml26
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dec1
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dsc18
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Driver/Crypto.c320
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Include/Library/BaseCryptLib.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSm3.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c152
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c46
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c175
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c60
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf8
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c93
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf92
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c46
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c60
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c74
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/CrtLibSupport.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/crypto/dso_conf.h (renamed from src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/internal/dso_conf.h)6
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/openssl/opensslconf.h10
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLib.inf75
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf65
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl25
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool.c275
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.c29
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.h29
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c43
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Private/Protocol/Crypto.h106
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc42
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/AuthenticodeTests.c1002
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c67
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BlockCipherTests.c293
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/DhTests.c106
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HashTests.c202
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HmacTests.c184
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/OaepEncryptTests.c308
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs5Pbkdf2Tests.c71
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTestSignatures.h789
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c524
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RandTests.c51
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPkcs7Tests.c415
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c191
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c312
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TSTests.c335
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h124
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf47
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf50
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/ChainCreationInstructions.txt92
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/CreateTestCerts.cmd11
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/SignFirmwareWithEKUs.cmd76
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingIssuingCA.ini45
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSigner.ini25
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid1.ini24
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid12345.ini27
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingNoEKUsInSigner.ini16
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingPolicyCA.ini28
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingRoot.ini28
-rw-r--r--src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/UnitTestMain.c81
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf8
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTables.dsc.inc28
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.ci.yaml104
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dec24
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dsc8
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/AcpiTableGenerator.h12
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/ArmNameSpaceObjects.h98
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h631
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h68
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/TableHelperLib.h51
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c254
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c245
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.c708
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.h51
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf34
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Template.asl81
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c371
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf33
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h767
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c546
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h178
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h188
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c805
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h330
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h18
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf76
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h183
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c382
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c219
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h93
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c320
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c701
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c256
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h59
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c1496
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h74
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c375
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h77
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c1458
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h188
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c1448
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h72
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.c328
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.h71
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.c103
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.h174
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c324
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c665
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h451
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c1022
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h401
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c205
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c673
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h212
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c566
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c1047
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h127
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c98
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c353
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h220
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c548
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h138
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c906
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h95
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.c536
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf32
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortTemplate.asl60
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c101
-rw-r--r--src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Readme.md216
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c9
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf10
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/EmbeddedPkg.dsc7
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/Library/TimeBaseLib.h126
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/libfdt_env.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiMemoryAllocationLib/MemoryAllocationLib.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c140
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c88
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/Diagnostics.c10
-rw-r--r--src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c40
-rw-r--r--src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.ci.yaml15
-rw-r--r--src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.dsc4
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm84
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm72
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c11
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h81
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec7
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc6
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py884
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py539
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py11
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py8
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h75
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h69
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h87
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf88
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml267
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc471
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py96
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md39
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c90
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf17
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c86
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf24
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h39
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec21
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc12
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf54
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c248
-rw-r--r--src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c26
-rw-r--r--src/VBox/Devices/EFI/Firmware/Maintainers.txt205
-rw-r--r--src/VBox/Devices/EFI/Firmware/Makefile.kmk2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c802
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h18
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.uni2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c35
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c184
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c91
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c59
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c106
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c17
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVol.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Gcd/Gcd.c69
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Image/Image.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Mem/Page.c19
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c7
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c52
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c57
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c445
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Image/Image.c130
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Memory/MemoryServices.c82
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.h170
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Ppi/Ppi.c286
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c10
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/MigratedFvInfo.h22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h54
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/HiiLib.h60
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h164
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyLib.h207
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/GenericMemoryTest.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/PeCoffImageEmulator.h9
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/VariablePolicy.h157
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootManagerUiLib/BootManager.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliDecompress.c23
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxePrintLibPrint2Protocol/PrintLib.c145
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c7
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zTypes.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h9
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c139
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c34
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-history.txt22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-sdk.txt2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c32
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h25
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxMmLib.c (renamed from src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c)82
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.c53
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf53
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxTraditionalMmLib.c53
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.h36
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibStandaloneMm.c38
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibTraditional.c38
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/StandaloneMmReportStatusCodeLib.inf53
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.c102
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.h23
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.c90
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.c31
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.inf44
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c39
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiLib.c14
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiString.c98
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckLib/VarCheckLib.c9
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c345
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.h42
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.c50
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.inf47
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibTraditional.c50
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c401
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf35
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md406
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c46
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c85
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c830
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf48
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf51
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.ci.yaml24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dec93
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dsc24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.uni43
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Test/MdeModulePkgHostTest.dsc11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c230
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.c (renamed from src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c)76
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.h50
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.c61
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.inf66
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceTraditional.c61
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/BdsDxe/BdsEntry.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c68
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c14
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c19
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c125
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.uni2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr36
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni16
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.uni2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PrintDxe/Print.c37
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterCommon.c (renamed from src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.c)59
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterCommon.h (renamed from src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.h)46
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.c33
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.inf49
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterTraditional.c33
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/SerialStatusCodeWorker.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/SerialStatusCodeWorker.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.c35
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.h11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/MemoryStatusCodeWorker.c36
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/SerialStatusCodeWorker.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c (renamed from src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.c)33
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h (renamed from src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.h)23
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf21
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c31
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf63
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c31
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.c565
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.inf36
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c52
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c60
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c49
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c30
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c60
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequestToLock.c94
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c573
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c7
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c56
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Base.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Guid/SystemResourceTable.h13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Ia32/Nasm.inc52
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Acpi10.h13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/ArmErrorSourceTable.h357
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl.h22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl11.h659
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h34
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Http11.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Pci.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/PciExpress21.h30
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/SmBios.h51
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Tpm2Acpi.h13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/BaseLib.h465
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/DebugLib.h28
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/MmUnblockMemoryLib.h44
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PcdLib.h520
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciExpressLib.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciSegmentInfoLib.h3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PrintLib.h110
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/RegisterFilterLib.h243
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h25
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UefiLib.h53
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UnitTestLib.h99
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/BlockIo.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/HiiPopup.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RedfishDiscover.h193
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/ResetNotification.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestEx.h390
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestJsonStructure.h161
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SerialIo.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SimpleTextOut.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/UgaDraw.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Fam17Msr.h46
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Ghcb.h157
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Intel/Cpuid.h86
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiBaseType.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiSpec.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Include/X64/Nasm.inc52
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c225
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf29
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni12
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c37
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf26
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c95
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c82
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c58
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c81
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c74
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm8
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/BaseLib.inf13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/CpuDeadLoop.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/FilePaths.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInline.c1181
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c1182
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c38
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm38
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c22
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm31
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XSetBv.nasm34
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S45
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/String.c626
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.c140
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.h66
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf251
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInline.c1240
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInlinePriv.c1246
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/ReadMsr64.c15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/VmgExit.nasm32
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/WriteMsr64.c13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XGetBv.nasm34
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XSetBv.nasm34
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X86UnitTestHost.c2977
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S50
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S50
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm24
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S28
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm28
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm9
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm20
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm9
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm11
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm9
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm19
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePcdLibNull/PcdLib.c361
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/PciExpressLib.c216
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLib.c118
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLibInternal.c15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S31
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm30
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S37
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm39
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h42
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/Rndr.c139
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRng.c87
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.inf23
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.uni7
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/Rand/RdRand.c131
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf36
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.uni15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/RngLibTimer.c189
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxePcdLib/DxePcdLib.c399
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.c199
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.inf38
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.uni15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c247
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.c44
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf34
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.uni21
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/PeiPcdLib/PeiPcdLib.c397
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.c271
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf23
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.uni13
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c218
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c56
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c33
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesDxeSmm.c51
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesStandaloneMm.c40
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibStandaloneMm.inf75
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiLib/UefiLib.c96
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/MdeLibs.dsc.inc15
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.ci.yaml16
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dec59
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dsc20
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Test/MdePkgHostTest.dsc5
-rw-r--r--src/VBox/Devices/EFI/Firmware/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h582
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDhcp.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDriver.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsProtocol.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootClient.c10
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.h3
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.c561
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.h242
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpDxe/HttpProto.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpIoLib.h328
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpLib.h53
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c854
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf46
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni12
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c153
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.dsc.inc5
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.fdf.inc5
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkBuildOptions.dsc.inc22
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkComponents.dsc.inc5
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkDefines.dsc.inc23
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkLibs.dsc.inc5
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.ci.yaml17
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dec16
-rw-r--r--src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dsc8
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/8254TimerDxe/Timer.c5
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.dsc856
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.fdf460
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/.gitignore1
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/Grub.inf39
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.cfg46
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.sh93
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c27
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf37
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.c25
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.inf35
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.c20
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.inf8
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c252
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h73
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf65
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c132
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c90
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c192
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf39
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl1140
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facp.aslc76
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facs.aslc80
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc72
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Madt.aslc145
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc57
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Platform.h72
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc63
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl15
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveDefines.fdf.inc85
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf66
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c201
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h149
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c543
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c393
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm342
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c259
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h912
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh80
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.dsc864
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.fdf490
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc65
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/License.txt68
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/AmdSev.c98
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/ClearCache.c111
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.c58
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.h50
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c21
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Fv.c94
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/MemDetect.c627
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.c608
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.h137
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf113
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia16/Real16ToFlat32.asm143
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia32/PageTables64.asm149
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.inf38
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.nasmb68
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c43
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c245
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h51
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf55
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/VarStore.fdf.inc115
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplug.c549
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.c123
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.h7
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/Smbase.c35
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3Data.c70
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h28
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/InstructionParsing.h83
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/LsiScsi.h105
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/PageTable.h161
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/QemuCpuHotplug.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Virtio10.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/VirtioFs.h454
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Xen/xen.h17
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/BhyveFwCtlLib.h47
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/MemEncryptSevLib.h102
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/PciHostBridgeUtilityLib.h185
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Pcd/CpuHotEjectData.h60
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Protocol/Legacy8259.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf (renamed from src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf)16
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c145
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c31
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c (renamed from src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c)73
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf57
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c159
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf51
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c155
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c32
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c893
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c100
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c960
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h178
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c428
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf40
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridge.h56
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c324
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/XenSupport.c5
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c460
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c29
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.c1662
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h190
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformBootManagerLibBhyve.inf75
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformData.c171
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c1484
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.h175
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf71
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformData.c214
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c111
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c15
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c103
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf45
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c109
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.c235
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf40
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c1877
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h53
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c24
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.c1210
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.h202
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf46
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.ci.yaml19
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.dec46
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc55
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.dsc52
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.fdf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc56
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf20
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.dsc35
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.fdf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/AmdSev.c127
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/MemDetect.c48
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf11
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c27
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h13
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c60
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/README24
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm148
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm118
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/PageTables64.asm415
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.inf12
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.nasmb25
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.c187
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/SioBusDxe/SioService.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmiFeatures.c41
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf40
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c87
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/DriverBinding.c232
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFlush.c111
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseForget.c85
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFsync.c121
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseGetAttr.c116
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseInit.c142
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseLookup.c148
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseMkDir.c134
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpen.c126
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenDir.c120
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenOrCreate.c155
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRead.c191
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRelease.c121
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRename.c131
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseSetAttr.c174
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseStatFs.c102
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseUnlink.c114
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseWrite.c155
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/Helpers.c2426
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsClose.c68
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c110
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsFlush.c42
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetInfo.c209
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetPosition.c27
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c516
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c98
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsRead.c434
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c582
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c67
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c81
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h544
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf136
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/AmdSev.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/MemDetect.c166
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.h10
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Xen.c252
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/XenPlatformPei.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPvBlkDxe/BlockFront.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm2
-rw-r--r--src/VBox/Devices/EFI/Firmware/OvmfPkg/XenTimerDxe/XenTimerDxe.c5
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c81
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c101
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h24
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c31
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf53
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.ci.yaml16
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dec16
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dsc7
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c120
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c54
-rw-r--r--src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf8
-rw-r--r--src/VBox/Devices/EFI/Firmware/ReadMe.rst41
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg965
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h169
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h61
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h800
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h91
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h52
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h42
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h38
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h78
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c421
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf31
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c166
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf44
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c983
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf87
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst35
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h41
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h19
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c1111
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf30
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c52
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf33
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c81
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf31
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h242
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h611
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c929
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf38
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c993
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf60
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c201
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h82
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h24
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h39
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h42
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c732
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c192
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c1396
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md117
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc21
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc20
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc22
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c265
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h101
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c587
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h159
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf60
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c209
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h75
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf51
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc27
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c218
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c1910
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf55
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h234
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c118
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c243
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf50
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc21
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml105
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec100
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc62
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c222
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c831
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h650
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf63
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni16
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni15
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c157
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h611
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c735
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c586
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf39
-rw-r--r--src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h33
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/FvReportPei/FvReportPei.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Guid/TpmNvsMm.h68
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/TcgEventLogRecordLib.h97
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/Tpm2CommandLib.h16
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Ppi/Tcg.h65
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthService.c30
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c24
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.c74
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf49
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.uni17
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.c398
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.h34
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c368
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.c42
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf62
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c197
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf40
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni17
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c40
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c42
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.h67
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmBase.c68
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.c66
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.inf54
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c40
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c15
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c126
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c (renamed from src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c)0
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h (renamed from src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h)0
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c (renamed from src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c)45
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h (renamed from src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h)17
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c145
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c168
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf24
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h117
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.ci.yaml16
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dec16
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dsc34
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c902
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf94
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tpm.asl (renamed from src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl)0
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c7
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c149
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.c48
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c857
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h115
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf27
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.c71
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.inf77
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c82
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.c90
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c170
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h21
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.c40
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.inf34
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.uni122
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c1905
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h92
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni117
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c61
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf57
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c137
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf62
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Guid/ShellLibHiiGuid.h5
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/AcpiViewCommandLib.h46
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellCommandLib.h81
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellLib.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c18
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h71
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c474
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h113
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.c246
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.h177
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c755
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hmat/HmatParser.c650
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.c615
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.h33
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c284
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h26
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf39
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c317
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h19
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c127
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c34
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c48
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h8
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c8
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c44
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c20
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni9
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf1
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c14
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h2
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni12
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLib/UefiShellLib.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.ci.yaml15
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dec4
-rw-r--r--src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dsc14
-rw-r--r--src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dependency.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dispatcher.c51
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/FwVol.c34
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Locate.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Mmi.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Pool.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.c45
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.h12
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c60
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c34
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h31
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf9
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Guid/MmCoreData.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h47
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/FvLib.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmDriverEntryPoint.h142
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmMemLib.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c64
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c183
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf12
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c71
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c330
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Common.c291
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf11
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/X64/StandaloneMmCoreHobLib.c298
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c27
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c62
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf13
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c155
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.ci.yaml84
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dec17
-rw-r--r--src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dsc31
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.c11
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.h12
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c52
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuPageTable.c6
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/X64/CpuAsm.nasm8
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.c402
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.h (renamed from src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.h)14
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c385
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.c32
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.inf45
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.c10
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.h17
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c34
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c32
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/AcpiCpuData.h20
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h85
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MicrocodeLib.h120
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MtrrLib.h47
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/UefiCpuLib.h14
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/VmgExitLib.h146
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h54
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c38
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf7
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c25
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c25
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c441
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni15
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c127
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h170
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c119
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c12
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c20
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c21
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf6
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm17
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm63
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c85
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf37
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni17
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c58
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf36
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni17
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.c322
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf32
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf10
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c121
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc43
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm108
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Microcode.c493
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpEqu.inc99
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.c419
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.h73
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf10
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c19
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc43
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm469
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/MtrrLib.c85
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c1163
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h195
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf43
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/RandomNumber.c5009
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c987
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c212
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c61
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf5
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeatures.h6
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c73
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h48
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c607
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c613
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibNoStm.c3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c26
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.c50
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf38
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/TraditionalMmCpuFeaturesLib.c28
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmmStmSupport.c2
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c165
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf27
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni15
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c16
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c145
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c26
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm19
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c80
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h15
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c37
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c9
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c9
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c86
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm20
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c19
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm9
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/Ia32/ResetVec.nasmb31
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecCore.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.c71
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c385
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h158
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf68
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni13
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc31
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.ci.yaml27
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dec28
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dsc22
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.uni11
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c15
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.h39
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf73
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt32
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/Hob.c (renamed from src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.c)494
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf39
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c59
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf36
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/FindPeiCore.c193
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/SecEntry.nasm78
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/Stack.nasm72
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecCore.inf58
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.c288
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.h131
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c365
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm71
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm46
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c307
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c201
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c (renamed from src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.c)454
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h134
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf93
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c107
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm47
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c939
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h330
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec5
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dsc (renamed from src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc)101
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf54
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32.dsc576
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c49
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf31
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni11
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c192
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c68
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c25
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c33
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c25
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf2
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c4
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.c1
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h1
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/ReadMe.md165
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTest.c510
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestSmm.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf3
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc5
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml18
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc7
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc11
-rw-r--r--src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc10
-rwxr-xr-xsrc/VBox/Devices/EFI/Firmware/edksetup.bat2
-rw-r--r--src/VBox/Devices/EFI/Firmware/pip-requirements.txt2
1402 files changed, 147237 insertions, 20685 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-GCC5.yml b/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-GCC5.yml
index ff920f82e9f..e50cdcf337f 100644
--- a/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-GCC5.yml
+++ b/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-GCC5.yml
@@ -7,8 +7,10 @@
##
trigger:
- master
+- stable/*
pr:
- master
+- stable/*
jobs:
- template: templates/pr-gate-build-job.yml
diff --git a/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-PatchCheck.yml b/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-PatchCheck.yml
index 369b8e9c07b..9ffd57c555e 100644
--- a/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-PatchCheck.yml
+++ b/src/VBox/Devices/EFI/Firmware/.azurepipelines/Ubuntu-PatchCheck.yml
@@ -5,7 +5,7 @@
# NOTE: This example monitors pull requests against the edk2-ci branch. Most
# environments would replace 'edk2-ci' with 'master'.
#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
# https://github.com/tianocore
@@ -16,6 +16,7 @@ trigger: none
pr:
- master
+- stable/*
pool:
vmImage: 'ubuntu-latest'
diff --git a/src/VBox/Devices/EFI/Firmware/.azurepipelines/Windows-VS2019.yml b/src/VBox/Devices/EFI/Firmware/.azurepipelines/Windows-VS2019.yml
index e00984b9619..65df692b800 100644
--- a/src/VBox/Devices/EFI/Firmware/.azurepipelines/Windows-VS2019.yml
+++ b/src/VBox/Devices/EFI/Firmware/.azurepipelines/Windows-VS2019.yml
@@ -6,9 +6,11 @@
##
trigger:
- master
+- stable/*
pr:
- master
+- stable/*
jobs:
- template: templates/pr-gate-build-job.yml
diff --git a/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/platform-build-run-steps.yml b/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/platform-build-run-steps.yml
index 447ac5e1b65..cdd41dcbee3 100644
--- a/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/platform-build-run-steps.yml
+++ b/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/platform-build-run-steps.yml
@@ -51,6 +51,12 @@ steps:
# Set default
- bash: echo "##vso[task.setvariable variable=pkg_count]${{ 1 }}"
+# Fetch the target branch so that pr_eval can diff them.
+# Seems like azure pipelines/github changed checkout process in nov 2020.
+- script: git fetch origin $(System.PullRequest.targetBranch)
+ displayName: fetch target branch
+ condition: eq(variables['Build.Reason'], 'PullRequest')
+
# trim the package list if this is a PR
- task: CmdLine@1
displayName: Check if ${{ parameters.build_pkg }} need testing
diff --git a/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-build-job.yml b/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-build-job.yml
index 57e47ec0fcb..2fb5758dbc7 100644
--- a/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-build-job.yml
+++ b/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-build-job.yml
@@ -4,6 +4,7 @@
# template file used to build supported packages.
#
# Copyright (c) Microsoft Corporation.
+# Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
@@ -20,6 +21,9 @@ jobs:
#Use matrix to speed up the build process
strategy:
matrix:
+ TARGET_ARM_ARMPLATFORM:
+ Build.Pkgs: 'ArmPkg,ArmPlatformPkg'
+ Build.Targets: 'DEBUG,RELEASE,NO-TARGET,NOOPT'
TARGET_MDE_CPU:
Build.Pkgs: 'MdePkg,UefiCpuPkg'
Build.Targets: 'DEBUG,RELEASE,NO-TARGET,NOOPT'
@@ -30,17 +34,17 @@ jobs:
Build.Pkgs: 'MdeModulePkg'
Build.Targets: 'RELEASE,NO-TARGET'
TARGET_NETWORK:
- Build.Pkgs: 'NetworkPkg'
+ Build.Pkgs: 'NetworkPkg,RedfishPkg'
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
TARGET_OTHER:
- Build.Pkgs: 'PcAtChipsetPkg,ShellPkg'
+ Build.Pkgs: 'PcAtChipsetPkg,ShellPkg,StandaloneMmPkg'
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
TARGET_FMP_FAT_TEST:
- Build.Pkgs: 'FmpDevicePkg,FatPkg,UnitTestFrameworkPkg'
+ Build.Pkgs: 'FmpDevicePkg,FatPkg,UnitTestFrameworkPkg,DynamicTablesPkg'
Build.Targets: 'DEBUG,RELEASE,NO-TARGET,NOOPT'
TARGET_CRYPTO:
Build.Pkgs: 'CryptoPkg'
- Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
+ Build.Targets: 'DEBUG,RELEASE,NO-TARGET,NOOPT'
TARGET_SECURITY:
Build.Pkgs: 'SecurityPkg'
Build.Targets: 'DEBUG,RELEASE,NO-TARGET'
diff --git a/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-steps.yml b/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-steps.yml
index 5bb7518b32f..61ffe8eb170 100644
--- a/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-steps.yml
+++ b/src/VBox/Devices/EFI/Firmware/.azurepipelines/templates/pr-gate-steps.yml
@@ -31,6 +31,12 @@ steps:
echo "##vso[task.setvariable variable=pkgs_to_build]${{ parameters.build_pkgs }}"
echo "##vso[task.setvariable variable=pkg_count]${{ 1 }}"
+# Fetch the target branch so that pr_eval can diff them.
+# Seems like azure pipelines/github changed checkout process in nov 2020.
+- script: git fetch origin $(System.PullRequest.targetBranch)
+ displayName: fetch target branch
+ condition: eq(variables['Build.Reason'], 'PullRequest')
+
# trim the package list if this is a PR
- task: CmdLine@1
displayName: Check if ${{ parameters.build_pkgs }} need testing
diff --git a/src/VBox/Devices/EFI/Firmware/.gitmodules b/src/VBox/Devices/EFI/Firmware/.gitmodules
index c3a4e4aeca6..b845c9ee3ff 100644
--- a/src/VBox/Devices/EFI/Firmware/.gitmodules
+++ b/src/VBox/Devices/EFI/Firmware/.gitmodules
@@ -6,7 +6,7 @@
url = https://github.com/ucb-bar/berkeley-softfloat-3.git
[submodule "UnitTestFrameworkPkg/Library/CmockaLib/cmocka"]
path = UnitTestFrameworkPkg/Library/CmockaLib/cmocka
- url = https://git.cryptomilk.org/projects/cmocka.git
+ url = https://github.com/tianocore/edk2-cmocka.git
[submodule "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma"]
path = MdeModulePkg/Universal/RegularExpressionDxe/oniguruma
url = https://github.com/kkos/oniguruma
@@ -17,3 +17,6 @@
path = BaseTools/Source/C/BrotliCompress/brotli
url = https://github.com/google/brotli
ignore = untracked
+[submodule "RedfishPkg/Library/JsonLib/jansson"]
+ path = RedfishPkg/Library/JsonLib/jansson
+ url = https://github.com/akheron/jansson
diff --git a/src/VBox/Devices/EFI/Firmware/.mailmap b/src/VBox/Devices/EFI/Firmware/.mailmap
index ba246ff6cd8..1721b8f10db 100644
--- a/src/VBox/Devices/EFI/Firmware/.mailmap
+++ b/src/VBox/Devices/EFI/Firmware/.mailmap
@@ -38,6 +38,7 @@ Jim Dailey <Jim.Dailey@Dell.com>
Jim Dailey <Jim.Dailey@Dell.com> <Jim_Dailey@Dell.com>
Laszlo Ersek <lersek@redhat.com> <lersek@6f19259b-4bc3-4df7-8a09-765794883524>
Laszlo Ersek <lersek@redhat.com> <lersek@Edk2>
+Liming Gao <gaoliming@byosoft.com.cn>
Liming Gao <liming.gao@intel.com> <Gao, Liming liming.gao@intel.com>
Liming Gao <liming.gao@intel.com> <lgao4@6f19259b-4bc3-4df7-8a09-765794883524>
Liming Gao <liming.gao@intel.com> <lgao4@Edk2>
@@ -47,6 +48,7 @@ Marc-André Lureau <marcandre.lureau@redhat.com> <marcandre.lureau@redhat.com>
Marvin Häuser <Marvin.Haeuser@outlook.com>
Marvin Häuser <Marvin.Haeuser@outlook.com> edk2-devel <edk2-devel-bounces@lists.01.org>
Marvin Häuser <mhaeuser@outlook.de>
+Matt DeVillier <matt.devillier@gmail.com>
Maurice Ma <maurice.ma@intel.com>
Michael Kubacki <michael.a.kubacki@intel.com>
Michael Kubacki <michael.a.kubacki@intel.com> </o=Intel/ou=External (FYDIBOHF25SPDLT)/cn=Recipients/cn=3c8b0226e75f4ab08d20c151cb7a8a72>
@@ -60,14 +62,20 @@ Ray Ni <ray.ni@intel.com> <niruiyu@Edk2>
Ray Ni <ray.ni@intel.com> <ruiyu.ni@intel.com>
Ray Ni <ray.ni@intel.com> <Ruiyu.ni@Intel.com>
Ray Ni <ray.ni@intel.com> <ruyu.ni@intel.com>
+Rebecca Cran <rebecca@bluestop.org>
+Rebecca Cran <rebecca@bsdio.com>
Samer El-Haj-Mahmoud <samer@elhajmahmoud.com> <elhaj@hpe.com>
Samer El-Haj-Mahmoud <samer@elhajmahmoud.com> <Samer El-Haj-Mahmoud elhaj@hp.com>
Shenglei Zhang <shenglei.zhang@intel.com>
Star Zeng <star.zeng@intel.com>
Star Zeng <star.zeng@intel.com> <lzeng14@6f19259b-4bc3-4df7-8a09-765794883524>
Star Zeng <star.zeng@intel.com> <lzeng14@Edk2>
+Tom Lendacky <thomas.lendacky@amd.com>
Vitaly Cheptsov <vit9696@protonmail.com> Vitaly Cheptsov via Groups.Io <vit9696=protonmail.com@groups.io>
Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com> Vladimir Olovyannikov via edk2-devel <edk2-devel@lists.01.org>
+Wei6 Xu <wei6.xu@intel.com>
Yonghong Zhu <yonghong.zhu@intel.com>
Yonghong Zhu <yonghong.zhu@intel.com> <yzhu52@Edk2>
Yu-Chen Lin <yuchenlin@synology.com>
+Zhichao Gao <zhichao.gao@intel.com>
+Zhiguang Liu <zhiguang.liu@intel.com>
diff --git a/src/VBox/Devices/EFI/Firmware/.mergify/config.yml b/src/VBox/Devices/EFI/Firmware/.mergify/config.yml
index 9ee0411885c..77b2c53782e 100644
--- a/src/VBox/Devices/EFI/Firmware/.mergify/config.yml
+++ b/src/VBox/Devices/EFI/Firmware/.mergify/config.yml
@@ -16,7 +16,7 @@
# * This file must be checked into the 'default' branch of a repo. Copies
# of this file on other branches of a repo are ignored by Mergify.
#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
# https://github.com/apps/mergify
@@ -28,7 +28,7 @@ pull_request_rules:
- name: Automatically merge a PR when all required checks pass and 'push' label is present
conditions:
- - base=master
+ - base~=(^master|^stable/)
- label=push
- author=@tianocore/edk-ii-maintainers
- status-success=tianocore.PatchCheck
@@ -41,7 +41,7 @@ pull_request_rules:
- name: Automatically close a PR when all required checks pass and 'push' label is not present
conditions:
- - base=master
+ - base~=(^master|^stable/)
- -label=push
- -closed
- status-success=tianocore.PatchCheck
@@ -55,7 +55,7 @@ pull_request_rules:
- name: Post a comment on a PR that can not be merged due to a merge conflict
conditions:
- - base=master
+ - base~=(^master|^stable/)
- conflict
actions:
comment:
@@ -63,7 +63,7 @@ pull_request_rules:
- name: Automatically close a PR that fails the EDK II Maintainers membership check and 'push' label is present
conditions:
- - base=master
+ - base~=(^master|^stable/)
- label=push
- -author=@tianocore/edk-ii-maintainers
actions:
@@ -72,7 +72,7 @@ pull_request_rules:
- name: Post a comment on a PR if PatchCheck fails
conditions:
- - base=master
+ - base~=(^master|^stable/)
- status-failure=tianocore.PatchCheck
actions:
comment:
@@ -80,7 +80,7 @@ pull_request_rules:
- name: Post a comment on a PR if Ubuntu GCC5 fails
conditions:
- - base=master
+ - base~=(^master|^stable/)
- status-failure=Ubuntu GCC5 PR
- status-success=Ubuntu GCC5 PR (FAILED)
actions:
@@ -89,7 +89,7 @@ pull_request_rules:
- name: Post a comment on a PR if Windows VS2019 fails
conditions:
- - base=master
+ - base~=(^master|^stable/)
- status-failure=Windows VS2019 PR
- status-success=Windows VS2019 PR (FAILED)
actions:
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/CISettings.py b/src/VBox/Devices/EFI/Firmware/.pytool/CISettings.py
index 2d1df3460be..ed0b473251b 100644
--- a/src/VBox/Devices/EFI/Firmware/.pytool/CISettings.py
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/CISettings.py
@@ -2,6 +2,7 @@
#
# Copyright (c) Microsoft Corporation.
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+# Copyright (c) 2020 - 2021, ARM Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
import os
@@ -21,16 +22,24 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
self.ActualTargets = []
self.ActualArchitectures = []
self.ActualToolChainTag = ""
+ self.UseBuiltInBaseTools = None
+ self.ActualScopes = None
# ####################################################################################### #
# Extra CmdLine configuration #
# ####################################################################################### #
def AddCommandLineOptions(self, parserObj):
- pass
+ group = parserObj.add_mutually_exclusive_group()
+ group.add_argument("-force_piptools", "--fpt", dest="force_piptools", action="store_true", default=False, help="Force the system to use pip tools")
+ group.add_argument("-no_piptools", "--npt", dest="no_piptools", action="store_true", default=False, help="Force the system to not use pip tools")
def RetrieveCommandLineOptions(self, args):
- pass
+ super().RetrieveCommandLineOptions(args)
+ if args.force_piptools:
+ self.UseBuiltInBaseTools = True
+ if args.no_piptools:
+ self.UseBuiltInBaseTools = False
# ####################################################################################### #
# Default Support for this Ci Build #
@@ -40,7 +49,10 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
''' return iterable of edk2 packages supported by this build.
These should be edk2 workspace relative paths '''
- return ("ArmVirtPkg",
+ return ("ArmPkg",
+ "ArmPlatformPkg",
+ "ArmVirtPkg",
+ "DynamicTablesPkg",
"EmulatorPkg",
"MdePkg",
"MdeModulePkg",
@@ -50,10 +62,12 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
"UefiCpuPkg",
"FmpDevicePkg",
"ShellPkg",
+ "StandaloneMmPkg",
"FatPkg",
"CryptoPkg",
"UnitTestFrameworkPkg",
- "OvmfPkg"
+ "OvmfPkg",
+ "RedfishPkg"
)
def GetArchitecturesSupported(self):
@@ -124,19 +138,38 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
def GetActiveScopes(self):
''' return tuple containing scopes that should be active for this process '''
- scopes = ("cibuild", "edk2-build", "host-based-test")
-
- self.ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "")
-
- if GetHostInfo().os.upper() == "LINUX" and self.ActualToolChainTag.upper().startswith("GCC"):
- if "AARCH64" in self.ActualArchitectures:
- scopes += ("gcc_aarch64_linux",)
- if "ARM" in self.ActualArchitectures:
- scopes += ("gcc_arm_linux",)
- if "RISCV64" in self.ActualArchitectures:
- scopes += ("gcc_riscv64_unknown",)
-
- return scopes
+ if self.ActualScopes is None:
+ scopes = ("cibuild", "edk2-build", "host-based-test")
+
+ self.ActualToolChainTag = shell_environment.GetBuildVars().GetValue("TOOL_CHAIN_TAG", "")
+
+ is_linux = GetHostInfo().os.upper() == "LINUX"
+
+ if self.UseBuiltInBaseTools is None:
+ is_linux = GetHostInfo().os.upper() == "LINUX"
+ # try and import the pip module for basetools
+ try:
+ import edk2basetools
+ self.UseBuiltInBaseTools = True
+ except ImportError:
+ self.UseBuiltInBaseTools = False
+ pass
+
+ if self.UseBuiltInBaseTools == True:
+ scopes += ('pipbuild-unix',) if is_linux else ('pipbuild-win',)
+ logging.warning("Using Pip Tools based BaseTools")
+ else:
+ logging.warning("Falling back to using in-tree BaseTools")
+
+ if is_linux and self.ActualToolChainTag.upper().startswith("GCC"):
+ if "AARCH64" in self.ActualArchitectures:
+ scopes += ("gcc_aarch64_linux",)
+ if "ARM" in self.ActualArchitectures:
+ scopes += ("gcc_arm_linux",)
+ if "RISCV64" in self.ActualArchitectures:
+ scopes += ("gcc_riscv64_unknown",)
+ self.ActualScopes = scopes
+ return self.ActualScopes
def GetRequiredSubmodules(self):
''' return iterable containing RequiredSubmodule objects.
@@ -155,6 +188,8 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
"MdeModulePkg/Library/BrotliCustomDecompressLib/brotli", False))
rs.append(RequiredSubmodule(
"BaseTools/Source/C/BrotliCompress/brotli", False))
+ rs.append(RequiredSubmodule(
+ "RedfishPkg/Library/JsonLib/jansson", False))
return rs
def GetName(self):
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck.py b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck.py
new file mode 100644
index 00000000000..601cf3d2419
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck.py
@@ -0,0 +1,309 @@
+# @file EccCheck.py
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+import os
+import shutil
+import re
+import csv
+import xml.dom.minidom
+from typing import List, Dict, Tuple
+import logging
+from io import StringIO
+from edk2toolext.environment import shell_environment
+from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
+from edk2toolext.environment.var_dict import VarDict
+from edk2toollib.utility_functions import RunCmd
+
+
+class EccCheck(ICiBuildPlugin):
+ """
+ A CiBuildPlugin that finds the Ecc issues of newly added code in pull request.
+
+ Configuration options:
+ "EccCheck": {
+ "ExceptionList": [],
+ "IgnoreFiles": []
+ },
+ """
+
+ ReModifyFile = re.compile(r'[B-Q,S-Z]+[\d]*\t(.*)')
+ FindModifyFile = re.compile(r'\+\+\+ b\/(.*)')
+ LineScopePattern = (r'@@ -\d*\,*\d* \+\d*\,*\d* @@.*')
+ LineNumRange = re.compile(r'@@ -\d*\,*\d* \+(\d*)\,*(\d*) @@.*')
+
+ def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
+ """ Provide the testcase name and classname for use in reporting
+ testclassname: a descriptive string for the testcase can include whitespace
+ classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
+
+ Args:
+ packagename: string containing name of package to build
+ environment: The VarDict for the test to run in
+ Returns:
+ a tuple containing the testcase name and the classname
+ (testcasename, classname)
+ """
+ return ("Check for efi coding style for " + packagename, packagename + ".EccCheck")
+
+ ##
+ # External function of plugin. This function is used to perform the task of the ci_build_plugin Plugin
+ #
+ # - package is the edk2 path to package. This means workspace/packagepath relative.
+ # - edk2path object configured with workspace and packages path
+ # - PkgConfig Object (dict) for the pkg
+ # - EnvConfig Object
+ # - Plugin Manager Instance
+ # - Plugin Helper Obj Instance
+ # - Junit Logger
+ # - output_stream the StringIO output stream from this plugin via logging
+ def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
+ edk2_path = Edk2pathObj.WorkspacePath
+ python_path = os.path.join(edk2_path, "BaseTools", "Source", "Python")
+ env = shell_environment.GetEnvironment()
+ env.set_shell_var('PYTHONPATH', python_path)
+ env.set_shell_var('WORKSPACE', edk2_path)
+ self.ECC_PASS = True
+ self.ApplyConfig(pkgconfig, edk2_path, packagename)
+ modify_dir_list = self.GetModifyDir(packagename)
+ patch = self.GetDiff(packagename)
+ ecc_diff_range = self.GetDiffRange(patch, packagename, edk2_path)
+ self.GenerateEccReport(modify_dir_list, ecc_diff_range, edk2_path)
+ ecc_log = os.path.join(edk2_path, "Ecc.log")
+ self.RevertCode()
+ if self.ECC_PASS:
+ tc.SetSuccess()
+ self.RemoveFile(ecc_log)
+ return 0
+ else:
+ with open(ecc_log, encoding='utf8') as output:
+ ecc_output = output.readlines()
+ for line in ecc_output:
+ logging.error(line.strip())
+ self.RemoveFile(ecc_log)
+ tc.SetFailed("EccCheck failed for {0}".format(packagename), "Ecc detected issues")
+ return 1
+
+ def RevertCode(self) -> None:
+ submoudle_params = "submodule update --init"
+ RunCmd("git", submoudle_params)
+ reset_params = "reset HEAD --hard"
+ RunCmd("git", reset_params)
+
+ def GetDiff(self, pkg: str) -> List[str]:
+ return_buffer = StringIO()
+ params = "diff --unified=0 origin/master HEAD"
+ RunCmd("git", params, outstream=return_buffer)
+ p = return_buffer.getvalue().strip()
+ patch = p.split("\n")
+ return_buffer.close()
+
+ return patch
+
+ def RemoveFile(self, file: str) -> None:
+ if os.path.exists(file):
+ os.remove(file)
+ return
+
+ def GetModifyDir(self, pkg: str) -> List[str]:
+ return_buffer = StringIO()
+ params = "diff --name-status" + ' HEAD' + ' origin/master'
+ RunCmd("git", params, outstream=return_buffer)
+ p1 = return_buffer.getvalue().strip()
+ dir_list = p1.split("\n")
+ return_buffer.close()
+ modify_dir_list = []
+ for modify_dir in dir_list:
+ file_path = self.ReModifyFile.findall(modify_dir)
+ if file_path:
+ file_dir = os.path.dirname(file_path[0])
+ else:
+ continue
+ if pkg in file_dir and file_dir != pkg:
+ modify_dir_list.append('%s' % file_dir)
+ else:
+ continue
+
+ modify_dir_list = list(set(modify_dir_list))
+ return modify_dir_list
+
+ def GetDiffRange(self, patch_diff: List[str], pkg: str, workingdir: str) -> Dict[str, List[Tuple[int, int]]]:
+ IsDelete = True
+ StartCheck = False
+ range_directory: Dict[str, List[Tuple[int, int]]] = {}
+ for line in patch_diff:
+ modify_file = self.FindModifyFile.findall(line)
+ if modify_file and pkg in modify_file[0] and not StartCheck and os.path.isfile(modify_file[0]):
+ modify_file_comment_dic = self.GetCommentRange(modify_file[0], workingdir)
+ IsDelete = False
+ StartCheck = True
+ modify_file_dic = modify_file[0]
+ modify_file_dic = modify_file_dic.replace("/", os.sep)
+ range_directory[modify_file_dic] = []
+ elif line.startswith('--- '):
+ StartCheck = False
+ elif re.match(self.LineScopePattern, line, re.I) and not IsDelete and StartCheck:
+ start_line = self.LineNumRange.search(line).group(1)
+ line_range = self.LineNumRange.search(line).group(2)
+ if not line_range:
+ line_range = '1'
+ range_directory[modify_file_dic].append((int(start_line), int(start_line) + int(line_range) - 1))
+ for i in modify_file_comment_dic:
+ if int(i[0]) <= int(start_line) <= int(i[1]):
+ range_directory[modify_file_dic].append(i)
+ return range_directory
+
+ def GetCommentRange(self, modify_file: str, workingdir: str) -> List[Tuple[int, int]]:
+ modify_file_path = os.path.join(workingdir, modify_file)
+ with open(modify_file_path) as f:
+ line_no = 1
+ comment_range: List[Tuple[int, int]] = []
+ Start = False
+ for line in f:
+ if line.startswith('/**'):
+ start_no = line_no
+ Start = True
+ if line.startswith('**/') and Start:
+ end_no = line_no
+ Start = False
+ comment_range.append((int(start_no), int(end_no)))
+ line_no += 1
+
+ if comment_range and comment_range[0][0] == 1:
+ del comment_range[0]
+ return comment_range
+
+ def GenerateEccReport(self, modify_dir_list: List[str], ecc_diff_range: Dict[str, List[Tuple[int, int]]],
+ edk2_path: str) -> None:
+ ecc_need = False
+ ecc_run = True
+ config = os.path.join(edk2_path, "BaseTools", "Source", "Python", "Ecc", "config.ini")
+ exception = os.path.join(edk2_path, "BaseTools", "Source", "Python", "Ecc", "exception.xml")
+ report = os.path.join(edk2_path, "Ecc.csv")
+ for modify_dir in modify_dir_list:
+ target = os.path.join(edk2_path, modify_dir)
+ logging.info('Run ECC tool for the commit in %s' % modify_dir)
+ ecc_need = True
+ ecc_params = "-c {0} -e {1} -t {2} -r {3}".format(config, exception, target, report)
+ return_code = RunCmd("Ecc", ecc_params, workingdir=edk2_path)
+ if return_code != 0:
+ ecc_run = False
+ break
+ if not ecc_run:
+ logging.error('Fail to run ECC tool')
+ self.ParseEccReport(ecc_diff_range, edk2_path)
+
+ if not ecc_need:
+ logging.info("Doesn't need run ECC check")
+
+ revert_params = "checkout -- {}".format(exception)
+ RunCmd("git", revert_params)
+ return
+
+ def ParseEccReport(self, ecc_diff_range: Dict[str, List[Tuple[int, int]]], edk2_path: str) -> None:
+ ecc_log = os.path.join(edk2_path, "Ecc.log")
+ ecc_csv = "Ecc.csv"
+ file = os.listdir(edk2_path)
+ row_lines = []
+ ignore_error_code = self.GetIgnoreErrorCode()
+ if ecc_csv in file:
+ with open(ecc_csv) as csv_file:
+ reader = csv.reader(csv_file)
+ for row in reader:
+ for modify_file in ecc_diff_range:
+ if modify_file in row[3]:
+ for i in ecc_diff_range[modify_file]:
+ line_no = int(row[4])
+ if i[0] <= line_no <= i[1] and row[1] not in ignore_error_code:
+ row[0] = '\nEFI coding style error'
+ row[1] = 'Error code: ' + row[1]
+ row[3] = 'file: ' + row[3]
+ row[4] = 'Line number: ' + row[4]
+ row_line = '\n *'.join(row)
+ row_lines.append(row_line)
+ break
+ break
+ if row_lines:
+ self.ECC_PASS = False
+
+ with open(ecc_log, 'a') as log:
+ all_line = '\n'.join(row_lines)
+ all_line = all_line + '\n'
+ log.writelines(all_line)
+ return
+
+ def ApplyConfig(self, pkgconfig: Dict[str, List[str]], edk2_path: str, pkg: str) -> None:
+ if "IgnoreFiles" in pkgconfig:
+ for a in pkgconfig["IgnoreFiles"]:
+ a = os.path.join(edk2_path, pkg, a)
+ a = a.replace(os.sep, "/")
+
+ logging.info("Ignoring Files {0}".format(a))
+ if os.path.exists(a):
+ if os.path.isfile(a):
+ self.RemoveFile(a)
+ elif os.path.isdir(a):
+ shutil.rmtree(a)
+ else:
+ logging.error("EccCheck.IgnoreInf -> {0} not found in filesystem. Invalid ignore files".format(a))
+
+ if "ExceptionList" in pkgconfig:
+ exception_list = pkgconfig["ExceptionList"]
+ exception_xml = os.path.join(edk2_path, "BaseTools", "Source", "Python", "Ecc", "exception.xml")
+ try:
+ logging.info("Appending exceptions")
+ self.AppendException(exception_list, exception_xml)
+ except Exception as e:
+ logging.error("Fail to apply exceptions")
+ raise e
+ return
+
+ def AppendException(self, exception_list: List[str], exception_xml: str) -> None:
+ error_code_list = exception_list[::2]
+ keyword_list = exception_list[1::2]
+ dom_tree = xml.dom.minidom.parse(exception_xml)
+ root_node = dom_tree.documentElement
+ for error_code, keyword in zip(error_code_list, keyword_list):
+ customer_node = dom_tree.createElement("Exception")
+ keyword_node = dom_tree.createElement("KeyWord")
+ keyword_node_text_value = dom_tree.createTextNode(keyword)
+ keyword_node.appendChild(keyword_node_text_value)
+ customer_node.appendChild(keyword_node)
+ error_code_node = dom_tree.createElement("ErrorID")
+ error_code_text_value = dom_tree.createTextNode(error_code)
+ error_code_node.appendChild(error_code_text_value)
+ customer_node.appendChild(error_code_node)
+ root_node.appendChild(customer_node)
+ with open(exception_xml, 'w') as f:
+ dom_tree.writexml(f, indent='', addindent='', newl='\n', encoding='UTF-8')
+ return
+
+ def GetIgnoreErrorCode(self) -> set:
+ """
+ Below are kinds of error code that are accurate in ecc scanning of edk2 level.
+ But EccCheck plugin is partial scanning so they are always false positive issues.
+ The mapping relationship of error code and error message is listed BaseTools/Sourc/Python/Ecc/EccToolError.py
+ """
+ ignore_error_code = {
+ "10000",
+ "10001",
+ "10002",
+ "10003",
+ "10004",
+ "10005",
+ "10006",
+ "10007",
+ "10008",
+ "10009",
+ "10010",
+ "10011",
+ "10012",
+ "10013",
+ "10015",
+ "10016",
+ "10017",
+ "10022",
+ }
+ return ignore_error_code
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck_plug_in.yaml b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck_plug_in.yaml
new file mode 100644
index 00000000000..bc3ea6e27f4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/EccCheck_plug_in.yaml
@@ -0,0 +1,11 @@
+## @file
+# CiBuildPlugin used to check Ecc issues
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ "scope": "cibuild",
+ "name": "EccCheck Test",
+ "module": "EccCheck"
+}
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/Readme.md b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/Readme.md
new file mode 100644
index 00000000000..02e0c130f24
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/EccCheck/Readme.md
@@ -0,0 +1,15 @@
+# EFI Coding style Check Plugin
+
+This CiBuildPlugin finds the Ecc issues of newly added code in pull request.
+
+## Configuration
+
+The plugin can be configured to ignore certain files and issues.
+
+"EccCheck": {
+ "ExceptionList": [],
+ "IgnoreFiles": []
+ },
+ """
+
+OPTIONAL List of file to ignore.
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck.py b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck.py
new file mode 100644
index 00000000000..e19e164e9b2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck.py
@@ -0,0 +1,115 @@
+# @file LicenseCheck.py
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+import os
+import logging
+import re
+from io import StringIO
+from typing import List, Tuple
+from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
+from edk2toolext.environment.var_dict import VarDict
+from edk2toollib.utility_functions import RunCmd
+
+
+class LicenseCheck(ICiBuildPlugin):
+
+ """
+ A CiBuildPlugin to check the license for new added files.
+
+ Configuration options:
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ """
+
+ license_format_preflix = 'SPDX-License-Identifier'
+
+ bsd2_patent = 'BSD-2-Clause-Patent'
+
+ Readdedfileformat = re.compile(r'\+\+\+ b\/(.*)')
+
+ file_extension_list = [".c", ".h", ".inf", ".dsc", ".dec", ".py", ".bat", ".sh", ".uni", ".yaml",
+ ".fdf", ".inc", "yml", ".asm", ".asm16", ".asl", ".vfr", ".s", ".S", ".aslc",
+ ".nasm", ".nasmb", ".idf", ".Vfr", ".H"]
+
+ def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
+ """ Provide the testcase name and classname for use in reporting
+ testclassname: a descriptive string for the testcase can include whitespace
+ classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>
+
+ Args:
+ packagename: string containing name of package to build
+ environment: The VarDict for the test to run in
+ Returns:
+ a tuple containing the testcase name and the classname
+ (testcasename, classname)
+ """
+ return ("Check for license for " + packagename, packagename + ".LicenseCheck")
+
+ ##
+ # External function of plugin. This function is used to perform the task of the ci_build_plugin Plugin
+ #
+ # - package is the edk2 path to package. This means workspace/packagepath relative.
+ # - edk2path object configured with workspace and packages path
+ # - PkgConfig Object (dict) for the pkg
+ # - EnvConfig Object
+ # - Plugin Manager Instance
+ # - Plugin Helper Obj Instance
+ # - Junit Logger
+ # - output_stream the StringIO output stream from this plugin via logging
+ def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
+ return_buffer = StringIO()
+ params = "diff --unified=0 origin/master HEAD"
+ RunCmd("git", params, outstream=return_buffer)
+ p = return_buffer.getvalue().strip()
+ patch = p.split("\n")
+ return_buffer.close()
+
+ ignore_files = []
+ if "IgnoreFiles" in pkgconfig:
+ ignore_files = pkgconfig["IgnoreFiles"]
+
+ self.ok = True
+ self.startcheck = False
+ self.license = True
+ self.all_file_pass = True
+ count = len(patch)
+ line_index = 0
+ for line in patch:
+ if line.startswith('--- /dev/null'):
+ nextline = patch[line_index + 1]
+ added_file = self.Readdedfileformat.search(nextline).group(1)
+ added_file_extension = os.path.splitext(added_file)[1]
+ if added_file_extension in self.file_extension_list and packagename in added_file:
+ if (self.IsIgnoreFile(added_file, ignore_files)):
+ line_index = line_index + 1
+ continue
+ self.startcheck = True
+ self.license = False
+ if self.startcheck and self.license_format_preflix in line:
+ if self.bsd2_patent in line:
+ self.license = True
+ if line_index + 1 == count or patch[line_index + 1].startswith('diff --') and self.startcheck:
+ if not self.license:
+ self.all_file_pass = False
+ error_message = "Invalid license in: " + added_file + " Hint: Only BSD-2-Clause-Patent is accepted."
+ logging.error(error_message)
+ self.startcheck = False
+ self.license = True
+ line_index = line_index + 1
+
+ if self.all_file_pass:
+ tc.SetSuccess()
+ return 0
+ else:
+ tc.SetFailed("License Check {0} Failed. ".format(packagename), "LICENSE_CHECK_FAILED")
+ return 1
+
+ def IsIgnoreFile(self, file: str, ignore_files: List[str]) -> bool:
+ for f in ignore_files:
+ if f in file:
+ return True
+ return False
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml
new file mode 100644
index 00000000000..6bb8225b9d3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/LicenseCheck_plug_in.yaml
@@ -0,0 +1,11 @@
+## @file
+# CiBuildPlugin used to check license issues for new added files
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ "scope": "cibuild",
+ "name": "License Check Test",
+ "module": "LicenseCheck"
+}
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/Readme.md b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/Readme.md
new file mode 100644
index 00000000000..ddb7670a348
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/LicenseCheck/Readme.md
@@ -0,0 +1,17 @@
+# License Check Plugin
+
+This CiBuildPlugin scans all new added files in a package to make sure code
+is contributed under BSD-2-Clause-Patent.
+
+## Configuration
+
+The plugin can be configured to ignore certain files.
+
+``` yaml
+"LicenseCheck": {
+ "IgnoreFiles": []
+}
+```
+### IgnoreFiles
+
+OPTIONAL List of file to ignore.
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/SpellCheck/cspell.base.yaml b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/SpellCheck/cspell.base.yaml
index 4a94bbf9649..237a59c920c 100644
--- a/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/SpellCheck/cspell.base.yaml
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Plugin/SpellCheck/cspell.base.yaml
@@ -178,5 +178,6 @@
"vcruntimed",
"ucrtd",
"msvcrtd",
+ "XIPFLAGS"
]
}
diff --git a/src/VBox/Devices/EFI/Firmware/.pytool/Readme.md b/src/VBox/Devices/EFI/Firmware/.pytool/Readme.md
index 678629a7275..d79d233ac18 100644
--- a/src/VBox/Devices/EFI/Firmware/.pytool/Readme.md
+++ b/src/VBox/Devices/EFI/Firmware/.pytool/Readme.md
@@ -4,11 +4,11 @@
| Package | Windows VS2019 (IA32/X64)| Ubuntu GCC (IA32/X64/ARM/AARCH64) | Known Issues |
| :---- | :----- | :---- | :--- |
-| ArmPkg |
-| ArmPlatformPkg |
+| ArmPkg | | :heavy_check_mark: |
+| ArmPlatformPkg | | :heavy_check_mark: |
| ArmVirtPkg | SEE PACKAGE README | SEE PACKAGE README |
| CryptoPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode
-| DynamicTablesPkg |
+| DynamicTablesPkg | | :heavy_check_mark: |
| EmbeddedPkg |
| EmulatorPkg | SEE PACKAGE README | SEE PACKAGE README | Spell checking in audit mode
| FatPkg | :heavy_check_mark: | :heavy_check_mark: |
@@ -24,7 +24,7 @@
| ShellPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode, 3 modules are not being built by DSC
| SignedCapsulePkg |
| SourceLevelDebugPkg |
-| StandaloneMmPkg |
+| StandaloneMmPkg | :heavy_check_mark: | :heavy_check_mark: |
| UefiCpuPkg | :heavy_check_mark: | :heavy_check_mark: | Spell checking in audit mode, 2 binary modules not being built by DSC
| UefiPayloadPkg |
| UnitTestFrameworkPkg | :heavy_check_mark: | :heavy_check_mark: |
@@ -254,6 +254,16 @@ Install
More cspell info: https://github.com/streetsidesoftware/cspell
+### License Checking - LicenseCheck
+
+Scans all new added files in a package to make sure code is contributed under
+BSD-2-Clause-Patent.
+
+### Ecc tool - EccCheck
+
+Run the Ecc tool on the package. The Ecc tool is available in the BaseTools
+package. It checks that the code complies to the EDKII coding standard.
+
## PyTool Scopes
Scopes are how the PyTool ext_dep, path_env, and plugins are activated. Meaning
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/AmlToC b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/AmlToC
new file mode 100755
index 00000000000..1dd28e96628
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/AmlToC
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+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")
+exe=$(basename "$full_cmd")
+
+export PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTHONPATH"}"
+exec "${python_exe:-python}" "$dir/../../Source/Python/$exe/$exe.py" "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BPDG b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BPDG
new file mode 100755
index 00000000000..a08cbd8de5c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BPDG
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.EccMain "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BrotliCompress b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BrotliCompress
new file mode 100755
index 00000000000..426f2a2ef19
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/BrotliCompress
@@ -0,0 +1,60 @@
+#!/usr/bin/env bash
+#
+# This script will exec Brotli tool with -e/-d options.
+#
+# Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+QLT="-q 9 -w 22"
+ARGS=
+
+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##*/}
+
+while test $# -gt 0
+do
+ case $1 in
+ -e)
+ ;;
+ -d)
+ ARGS+="$1 "
+ ;;
+ -o|-g)
+ ARGS+="$1 $2 "
+ shift
+ ;;
+ -q)
+ QLT="$1 $2 "
+ shift
+ ;;
+ *)
+ ARGS+="$1 "
+ ;;
+ esac
+ shift
+done
+
+
+if [ -n "$WORKSPACE" ] && [ -e "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" $QLT $ARGS
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" $QLT $ARGS
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/DevicePath b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/DevicePath
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/DevicePath
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Ecc b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Ecc
new file mode 100755
index 00000000000..59872891509
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Ecc
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+export PYTHONPATH="$dir/../../Source/Python${PYTHONPATH:+:"$PYTHONPATH"}"
+exec "${python_exe:-python}" -m $cmd.EccMain "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/EfiRom b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/EfiRom
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/EfiRom
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenCrc32 b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenCrc32
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenCrc32
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenDepex b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenDepex
new file mode 100755
index 00000000000..df75e43f9ec
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenDepex
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.AutoGen.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFds b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFds
new file mode 100755
index 00000000000..b27e84eaa21
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFds
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFfs b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFfs
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFfs
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFv b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFv
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFv
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFw b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFw
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenFw
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenPatchPcdTable b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenPatchPcdTable
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenPatchPcdTable
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenSec b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenSec
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenSec
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenerateCapsule b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenerateCapsule
new file mode 100755
index 00000000000..366a268802c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/GenerateCapsule
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.Capsule.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaCompress b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaCompress
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaCompress
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaF86Compress b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaF86Compress
new file mode 100755
index 00000000000..b55352ae4c7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/LzmaF86Compress
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+#
+# This script will exec LzmaCompress tool with --f86 option that enables converter for x86 code.
+#
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+
+for arg; do
+ case $arg in
+ -e|-d)
+ set -- "$@" --f86
+ break
+ ;;
+ esac
+done
+
+exec LzmaCompress "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/PatchPcdValue b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/PatchPcdValue
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/PatchPcdValue
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Pkcs7Sign b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Pkcs7Sign
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Pkcs7Sign
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256GenerateKeys b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256GenerateKeys
new file mode 100755
index 00000000000..aca2f3a6fe2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256GenerateKeys
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.Rsa2048Sha256Sign.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256Sign b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256Sign
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Rsa2048Sha256Sign
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Split b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Split
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Split
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TargetTool b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TargetTool
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TargetTool
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TianoCompress b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TianoCompress
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/TianoCompress
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Trim b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Trim
new file mode 100755
index 00000000000..0bd14ee0387
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/Trim
@@ -0,0 +1,13 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=$(basename "$full_cmd")
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/UPT b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/UPT
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/UPT
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VfrCompile b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VfrCompile
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VfrCompile
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VolInfo b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VolInfo
new file mode 100755
index 00000000000..0945d86d920
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/VolInfo
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+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 "$WORKSPACE/Conf/BaseToolsCBinaries" ]
+then
+ exec "$WORKSPACE/Conf/BaseToolsCBinaries/$cmd"
+elif [ -n "$WORKSPACE" ] && [ -e "$EDK_TOOLS_PATH/Source/C" ]
+then
+ if [ ! -e "$EDK_TOOLS_PATH/Source/C/bin/$cmd" ]
+ then
+ echo "BaseTools C Tool binary was not found ($cmd)"
+ echo "You may need to run:"
+ echo " make -C $EDK_TOOLS_PATH/Source/C"
+ else
+ exec "$EDK_TOOLS_PATH/Source/C/bin/$cmd" "$@"
+ fi
+elif [ -e "$dir/../../Source/C/bin/$cmd" ]
+then
+ exec "$dir/../../Source/C/bin/$cmd" "$@"
+else
+ echo "Unable to find the real '$cmd' to run"
+ echo "This message was printed by"
+ echo " $0"
+ exit 127
+fi
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/build b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/build
new file mode 100755
index 00000000000..9d143c7fc6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/build
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+#python `dirname $0`/RunToolFromSource.py `basename $0` $*
+
+# If a ${PYTHON_COMMAND} command is available, use it in preference to python
+if command -v ${PYTHON_COMMAND} >/dev/null 2>&1; then
+ python_exe=${PYTHON_COMMAND}
+fi
+
+full_cmd=${BASH_SOURCE:-$0} # see http://mywiki.wooledge.org/BashFAQ/028 for a discussion of why $0 is not a good choice here
+cmd=${full_cmd##*/}
+
+exec "${python_exe:-python}" -m edk2basetools.$cmd.$cmd "$@"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/posix_path_env.yaml b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/posix_path_env.yaml
new file mode 100644
index 00000000000..830670305c0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/PosixLike/posix_path_env.yaml
@@ -0,0 +1,11 @@
+## @file
+# Set this folder on the path for all linux builds
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ "scope": "pipbuild-unix",
+ "override_id": "binwrappers",
+ "flags": ["set_path"]
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/AmlToC.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/AmlToC.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/AmlToC.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/BPDG.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/BPDG.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/BPDG.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Ecc.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Ecc.bat
new file mode 100644
index 00000000000..16a0a799a43
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Ecc.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.EccMain %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenDepex.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenDepex.bat
new file mode 100644
index 00000000000..481b5ac47d2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenDepex.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.AutoGen.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenFds.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenFds.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenFds.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenPatchPcdTable.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenPatchPcdTable.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenPatchPcdTable.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenerateCapsule.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenerateCapsule.bat
new file mode 100644
index 00000000000..34c43ac7fc9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/GenerateCapsule.bat
@@ -0,0 +1 @@
+@%PYTHON_COMMAND% -m edk2basetools.Capsule.GenerateCapsule %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/PatchPcdValue.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/PatchPcdValue.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/PatchPcdValue.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Pkcs7Sign.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Pkcs7Sign.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Pkcs7Sign.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256GenerateKeys.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256GenerateKeys.bat
new file mode 100644
index 00000000000..cdc2e3ea373
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256GenerateKeys.bat
@@ -0,0 +1 @@
+@%PYTHON_COMMAND% -m edk2basetools.Rsa2048Sha256Sign.Rsa2048Sha256GenerateKeys %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256Sign.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256Sign.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Rsa2048Sha256Sign.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Split.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Split.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Split.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/TargetTool.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/TargetTool.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/TargetTool.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Trim.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Trim.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/Trim.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/UPT.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/UPT.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/UPT.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/build.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/build.bat
new file mode 100644
index 00000000000..d347d648446
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/build.bat
@@ -0,0 +1,3 @@
+@setlocal
+@set ToolName=%~n0%
+@%PYTHON_COMMAND% -m edk2basetools.%ToolName%.%ToolName% %*
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/win_build_tools_path_env.yaml b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/win_build_tools_path_env.yaml
new file mode 100644
index 00000000000..fbeede54b42
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BinPipWrappers/WindowsLike/win_build_tools_path_env.yaml
@@ -0,0 +1,11 @@
+## @file
+# Add this folder to the path on Windows
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ "scope": "pipbuild-win",
+ "override_id": "binwrappers",
+ "flags": ["set_path"]
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/BuildEnv b/src/VBox/Devices/EFI/Firmware/BaseTools/BuildEnv
index 4bdf59b26a8..275f4c5901a 100755
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/BuildEnv
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/BuildEnv
@@ -198,7 +198,17 @@ AddEdkToolsToPath() {
EDK_TOOLS_PATH_BIN=`GetEdkToolsPathBinDirectory`
- AddDirToStartOfPath $EDK_TOOLS_PATH/BinWrappers/PosixLike
+ # check if the edk2basetools pip package is available
+ if $PYTHON_COMMAND -c "import edk2basetools" &> /dev/null; then
+ # if it is, use the pip version of the wrappers
+ echo "Using Pip Basetools"
+ AddDirToStartOfPath $EDK_TOOLS_PATH/BinPipWrappers/PosixLike
+ else
+ echo "Using EDK2 in-source Basetools"
+ AddDirToStartOfPath $EDK_TOOLS_PATH/BinWrappers/PosixLike
+ fi
+
+
AddDirToStartOfPath $EDK_TOOLS_PATH_BIN
}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/build_rule.template b/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/build_rule.template
index bfaddf2cb65..ceaaf739c8b 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/build_rule.template
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/build_rule.template
@@ -419,6 +419,7 @@
<OutputFile>
$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml
+ $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.amli
<ExtraDependency>
$(MAKE_FILE)
@@ -428,14 +429,24 @@
"$(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
"$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
- -AmlToHex $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml
+ $(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
"$(ASL)" $(ASL_FLAGS) $(ASL_OUTFLAGS)${dst} $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.iiii
- -AmlToHex $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml
+ $(CP) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.aml $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.amli
+
+[Acpi-Machine-Language-File-to-C.DXE_DRIVER]
+ <InputFile>
+ ?.amli
+
+ <OutputFile>
+ ${s_path}(+)${s_base}.c
+
+ <Command>
+ -AmlToC ${src}
[C-Code-File.AcpiTable]
<InputFile>
@@ -504,7 +515,7 @@
"$(PP)" $(DEPS_FLAGS) $(PP_FLAGS) $(INC) ${src} > ${d_path}(+)${s_base}.ii
Trim --source-code --convert-hex --trim-long -o ${d_path}(+)${s_base}.iii ${d_path}(+)${s_base}.ii
cd $(OUTPUT_DIR)(+)${s_dir}
- "$(ASM16)" /nologo /c /omf $(INC) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj ${d_path}(+)${s_base}.iii
+ "$(ASM16)" /nologo /c /omf $(ASM16_FLAGS) $(INC) /Fo$(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj ${d_path}(+)${s_base}.iii
"$(ASMLINK)" $(ASMLINK_FLAGS) $(OUTPUT_DIR)(+)${s_dir}(+)${s_base}.obj,${dst},,,,
<Command.GCC>
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/diff.order b/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/diff.order
index 4361817012c..f1534f6c187 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/diff.order
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/diff.order
@@ -1,13 +1,13 @@
-#
-# Copyright (c) 2019, Linaro Ltd. All rights reserved.
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-*.dec
-*.dsc.inc
-*.dsc
-*.fdf
-*.inf
-*.h
-*.vfr
-*.c
+#
+# Copyright (c) 2019, Linaro Ltd. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+*.dec
+*.dsc.inc
+*.dsc
+*.fdf
+*.inf
+*.h
+*.vfr
+*.c
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/tools_def.template b/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/tools_def.template
index 21c7ddcf70d..0cb4a90ddcd 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/tools_def.template
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Conf/tools_def.template
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# Portions copyright (c) 2011 - 2019, ARM Ltd. All rights reserved.<BR>
# Copyright (c) 2015, Hewlett-Packard Development Company, L.P.<BR>
@@ -441,7 +441,6 @@ DEFINE DTC_BIN = ENV(DTC_PREFIX)dtc
##################
*_VS2008_IA32_*_DLL = DEF(VS2008_DLL)
-*_VS2008_IA32_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
*_VS2008_IA32_CC_PATH = DEF(VS2008_BIN)\cl.exe
*_VS2008_IA32_VFRPP_PATH = DEF(VS2008_BIN)\cl.exe
*_VS2008_IA32_SLINK_PATH = DEF(VS2008_BIN)\lib.exe
@@ -453,7 +452,6 @@ DEFINE DTC_BIN = ENV(DTC_PREFIX)dtc
*_VS2008_IA32_ASLPP_PATH = DEF(VS2008_BIN)\cl.exe
*_VS2008_IA32_ASLDLINK_PATH = DEF(VS2008_BIN)\link.exe
- *_VS2008_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2008_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm
RELEASE_VS2008_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
NOOPT_VS2008_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
@@ -508,14 +506,12 @@ NOOPT_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2008_EBC_*_FAMILY = INTEL
*_VS2008_EBC_*_DLL = DEF(VS2008_DLL)
-*_VS2008_EBC_MAKE_PATH = DEF(VS2008_BIN)\nmake.exe
*_VS2008_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2008_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2008_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
*_VS2008_EBC_SLINK_PATH = DEF(VS2008_BIN)\link.exe
*_VS2008_EBC_DLINK_PATH = DEF(VS2008_BIN)\link.exe
-*_VS2008_EBC_MAKE_FLAGS = /nologo
*_VS2008_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2008_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2008_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -531,10 +527,9 @@ NOOPT_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2008x86_*_*_FAMILY = MSFT
*_VS2008x86_*_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
-*_VS2008x86_*_MAKE_FLAG = /nologo
+*_VS2008x86_*_MAKE_FLAGS = /nologo
*_VS2008x86_*_RC_PATH = DEF(WINSDK_BIN)\rc.exe
-*_VS2008x86_*_MAKE_FLAGS = /nologo
*_VS2008x86_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2008x86_*_APP_FLAGS = /nologo /E /TC
*_VS2008x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -557,7 +552,6 @@ NOOPT_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
##################
*_VS2008x86_IA32_*_DLL = DEF(VS2008x86_DLL)
-*_VS2008x86_IA32_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
*_VS2008x86_IA32_CC_PATH = DEF(VS2008x86_BIN)\cl.exe
*_VS2008x86_IA32_VFRPP_PATH = DEF(VS2008x86_BIN)\cl.exe
*_VS2008x86_IA32_ASLCC_PATH = DEF(VS2008x86_BIN)\cl.exe
@@ -569,7 +563,6 @@ NOOPT_VS2008_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2008x86_IA32_PP_PATH = DEF(VS2008x86_BIN)\cl.exe
*_VS2008x86_IA32_ASM_PATH = DEF(VS2008x86_BIN)\ml.exe
- *_VS2008x86_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2008x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7
RELEASE_VS2008x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
NOOPT_VS2008x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -623,14 +616,12 @@ NOOPT_VS2008x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2008x86_EBC_*_FAMILY = INTEL
*_VS2008x86_EBC_*_DLL = DEF(VS2008x86_DLL)
-*_VS2008x86_EBC_MAKE_PATH = DEF(VS2008x86_BIN)\nmake.exe
*_VS2008x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2008x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2008x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2008x86_EBC_SLINK_PATH = DEF(VS2008x86_BIN)\link.exe
*_VS2008x86_EBC_DLINK_PATH = DEF(VS2008x86_BIN)\link.exe
-*_VS2008x86_EBC_MAKE_FLAGS = /nologo
*_VS2008x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2008x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2008x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -675,7 +666,6 @@ NOOPT_VS2008x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
##################
*_VS2010_IA32_*_DLL = DEF(VS2010_DLL)
-*_VS2010_IA32_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
*_VS2010_IA32_CC_PATH = DEF(VS2010_BIN)\cl.exe
*_VS2010_IA32_VFRPP_PATH = DEF(VS2010_BIN)\cl.exe
*_VS2010_IA32_SLINK_PATH = DEF(VS2010_BIN)\lib.exe
@@ -687,7 +677,6 @@ NOOPT_VS2008x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2010_IA32_ASLPP_PATH = DEF(VS2010_BIN)\cl.exe
*_VS2010_IA32_ASLDLINK_PATH = DEF(VS2010_BIN)\link.exe
- *_VS2010_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2010_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7
RELEASE_VS2010_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
NOOPT_VS2010_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gm /Od
@@ -742,14 +731,12 @@ NOOPT_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2010_EBC_*_FAMILY = INTEL
*_VS2010_EBC_*_DLL = DEF(VS2010_DLL)
-*_VS2010_EBC_MAKE_PATH = DEF(VS2010_BIN)\nmake.exe
*_VS2010_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2010_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2010_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
*_VS2010_EBC_SLINK_PATH = DEF(VS2010_BIN)\link.exe
*_VS2010_EBC_DLINK_PATH = DEF(VS2010_BIN)\link.exe
-*_VS2010_EBC_MAKE_FLAGS = /nologo
*_VS2010_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2010_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2010_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -765,10 +752,9 @@ NOOPT_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2010x86_*_*_FAMILY = MSFT
*_VS2010x86_*_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
-*_VS2010x86_*_MAKE_FLAG = /nologo
+*_VS2010x86_*_MAKE_FLAGS = /nologo
*_VS2010x86_*_RC_PATH = DEF(WINSDK7x86_BIN)\rc.exe
-*_VS2010x86_*_MAKE_FLAGS = /nologo
*_VS2010x86_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2010x86_*_APP_FLAGS = /nologo /E /TC
*_VS2010x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -791,7 +777,6 @@ NOOPT_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
##################
*_VS2010x86_IA32_*_DLL = DEF(VS2010x86_DLL)
-*_VS2010x86_IA32_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
*_VS2010x86_IA32_CC_PATH = DEF(VS2010x86_BIN)\cl.exe
*_VS2010x86_IA32_VFRPP_PATH = DEF(VS2010x86_BIN)\cl.exe
*_VS2010x86_IA32_ASLCC_PATH = DEF(VS2010x86_BIN)\cl.exe
@@ -803,7 +788,6 @@ NOOPT_VS2010_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2010x86_IA32_PP_PATH = DEF(VS2010x86_BIN)\cl.exe
*_VS2010x86_IA32_ASM_PATH = DEF(VS2010x86_BIN)\ml.exe
- *_VS2010x86_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2010x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7
RELEASE_VS2010x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
NOOPT_VS2010x86_IA32_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -858,14 +842,12 @@ NOOPT_VS2010x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2010x86_EBC_*_FAMILY = INTEL
*_VS2010x86_EBC_*_DLL = DEF(VS2010x86_DLL)
-*_VS2010x86_EBC_MAKE_PATH = DEF(VS2010x86_BIN)\nmake.exe
*_VS2010x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2010x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2010x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2010x86_EBC_SLINK_PATH = DEF(VS2010x86_BIN)\link.exe
*_VS2010x86_EBC_DLINK_PATH = DEF(VS2010x86_BIN)\link.exe
-*_VS2010x86_EBC_MAKE_FLAGS = /nologo
*_VS2010x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2010x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2010x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -909,7 +891,6 @@ NOOPT_VS2010x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
##################
*_VS2012_IA32_*_DLL = DEF(VS2012_DLL)
-*_VS2012_IA32_MAKE_PATH = DEF(VS2012_BIN)\nmake.exe
*_VS2012_IA32_CC_PATH = DEF(VS2012_BIN)\cl.exe
*_VS2012_IA32_VFRPP_PATH = DEF(VS2012_BIN)\cl.exe
*_VS2012_IA32_SLINK_PATH = DEF(VS2012_BIN)\lib.exe
@@ -921,7 +902,6 @@ NOOPT_VS2010x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2012_IA32_ASLPP_PATH = DEF(VS2012_BIN)\cl.exe
*_VS2012_IA32_ASLDLINK_PATH = DEF(VS2012_BIN)\link.exe
- *_VS2012_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2012_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7
RELEASE_VS2012_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
NOOPT_VS2012_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -976,14 +956,12 @@ NOOPT_VS2012_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2012_EBC_*_FAMILY = INTEL
*_VS2012_EBC_*_DLL = DEF(VS2012_DLL)
-*_VS2012_EBC_MAKE_PATH = DEF(VS2012_BIN)\nmake.exe
*_VS2012_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2012_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2012_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
*_VS2012_EBC_SLINK_PATH = DEF(VS2012_BIN)\link.exe
*_VS2012_EBC_DLINK_PATH = DEF(VS2012_BIN)\link.exe
-*_VS2012_EBC_MAKE_FLAGS = /nologo
*_VS2012_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2012_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2012_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -999,10 +977,9 @@ NOOPT_VS2012_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2012x86_*_*_FAMILY = MSFT
*_VS2012x86_*_MAKE_PATH = DEF(VS2012x86_BIN)\nmake.exe
-*_VS2012x86_*_MAKE_FLAG = /nologo
+*_VS2012x86_*_MAKE_FLAGS = /nologo
*_VS2012x86_*_RC_PATH = DEF(WINSDK71x86_BIN)\rc.exe
-*_VS2012x86_*_MAKE_FLAGS = /nologo
*_VS2012x86_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2012x86_*_APP_FLAGS = /nologo /E /TC
*_VS2012x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -1025,7 +1002,6 @@ NOOPT_VS2012_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
##################
*_VS2012x86_IA32_*_DLL = DEF(VS2012x86_DLL)
-*_VS2012x86_IA32_MAKE_PATH = DEF(VS2012x86_BIN)\nmake.exe
*_VS2012x86_IA32_CC_PATH = DEF(VS2012x86_BIN)\cl.exe
*_VS2012x86_IA32_VFRPP_PATH = DEF(VS2012x86_BIN)\cl.exe
*_VS2012x86_IA32_ASLCC_PATH = DEF(VS2012x86_BIN)\cl.exe
@@ -1037,7 +1013,6 @@ NOOPT_VS2012_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2012x86_IA32_PP_PATH = DEF(VS2012x86_BIN)\cl.exe
*_VS2012x86_IA32_ASM_PATH = DEF(VS2012x86_BIN)\ml.exe
- *_VS2012x86_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2012x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7
RELEASE_VS2012x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF
NOOPT_VS2012x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1092,14 +1067,12 @@ NOOPT_VS2012x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2012x86_EBC_*_FAMILY = INTEL
*_VS2012x86_EBC_*_DLL = DEF(VS2012x86_DLL)
-*_VS2012x86_EBC_MAKE_PATH = DEF(VS2012x86_BIN)\nmake.exe
*_VS2012x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2012x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2012x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2012x86_EBC_SLINK_PATH = DEF(VS2012x86_BIN)\link.exe
*_VS2012x86_EBC_DLINK_PATH = DEF(VS2012x86_BIN)\link.exe
-*_VS2012x86_EBC_MAKE_FLAGS = /nologo
*_VS2012x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2012x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2012x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1143,7 +1116,6 @@ NOOPT_VS2012x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
##################
*_VS2013_IA32_*_DLL = DEF(VS2013_DLL)
-*_VS2013_IA32_MAKE_PATH = DEF(VS2013_BIN)\nmake.exe
*_VS2013_IA32_CC_PATH = DEF(VS2013_BIN)\cl.exe
*_VS2013_IA32_VFRPP_PATH = DEF(VS2013_BIN)\cl.exe
*_VS2013_IA32_SLINK_PATH = DEF(VS2013_BIN)\lib.exe
@@ -1155,7 +1127,6 @@ NOOPT_VS2012x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2013_IA32_ASLPP_PATH = DEF(VS2013_BIN)\cl.exe
*_VS2013_IA32_ASLDLINK_PATH = DEF(VS2013_BIN)\link.exe
- *_VS2013_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2013_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw
RELEASE_VS2013_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw
NOOPT_VS2013_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1210,14 +1181,12 @@ NOOPT_VS2013_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2013_EBC_*_FAMILY = INTEL
*_VS2013_EBC_*_DLL = DEF(VS2013_DLL)
-*_VS2013_EBC_MAKE_PATH = DEF(VS2013_BIN)\nmake.exe
*_VS2013_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2013_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2013_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
*_VS2013_EBC_SLINK_PATH = DEF(VS2013_BIN)\link.exe
*_VS2013_EBC_DLINK_PATH = DEF(VS2013_BIN)\link.exe
-*_VS2013_EBC_MAKE_FLAGS = /nologo
*_VS2013_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2013_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2013_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1233,10 +1202,9 @@ NOOPT_VS2013_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2013x86_*_*_FAMILY = MSFT
*_VS2013x86_*_MAKE_PATH = DEF(VS2013x86_BIN)\nmake.exe
-*_VS2013x86_*_MAKE_FLAG = /nologo
+*_VS2013x86_*_MAKE_FLAGS = /nologo
*_VS2013x86_*_RC_PATH = DEF(WINSDK8x86_BIN)\rc.exe
-*_VS2013x86_*_MAKE_FLAGS = /nologo
*_VS2013x86_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2013x86_*_APP_FLAGS = /nologo /E /TC
*_VS2013x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -1259,7 +1227,6 @@ NOOPT_VS2013_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
##################
*_VS2013x86_IA32_*_DLL = DEF(VS2013x86_DLL)
-*_VS2013x86_IA32_MAKE_PATH = DEF(VS2013x86_BIN)\nmake.exe
*_VS2013x86_IA32_CC_PATH = DEF(VS2013x86_BIN)\cl.exe
*_VS2013x86_IA32_VFRPP_PATH = DEF(VS2013x86_BIN)\cl.exe
*_VS2013x86_IA32_ASLCC_PATH = DEF(VS2013x86_BIN)\cl.exe
@@ -1271,7 +1238,6 @@ NOOPT_VS2013_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2013x86_IA32_PP_PATH = DEF(VS2013x86_BIN)\cl.exe
*_VS2013x86_IA32_ASM_PATH = DEF(VS2013x86_BIN)\ml.exe
- *_VS2013x86_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2013x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw
RELEASE_VS2013x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw
NOOPT_VS2013x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1326,14 +1292,12 @@ NOOPT_VS2013x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2013x86_EBC_*_FAMILY = INTEL
*_VS2013x86_EBC_*_DLL = DEF(VS2013x86_DLL)
-*_VS2013x86_EBC_MAKE_PATH = DEF(VS2013x86_BIN)\nmake.exe
*_VS2013x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2013x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2013x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2013x86_EBC_SLINK_PATH = DEF(VS2013x86_BIN)\link.exe
*_VS2013x86_EBC_DLINK_PATH = DEF(VS2013x86_BIN)\link.exe
-*_VS2013x86_EBC_MAKE_FLAGS = /nologo
*_VS2013x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2013x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2013x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1378,7 +1342,6 @@ NOOPT_VS2013x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
##################
*_VS2015_IA32_*_DLL = DEF(VS2015_DLL)
-*_VS2015_IA32_MAKE_PATH = DEF(VS2015_BIN)\nmake.exe
*_VS2015_IA32_CC_PATH = DEF(VS2015_BIN)\cl.exe
*_VS2015_IA32_VFRPP_PATH = DEF(VS2015_BIN)\cl.exe
*_VS2015_IA32_SLINK_PATH = DEF(VS2015_BIN)\lib.exe
@@ -1390,7 +1353,6 @@ NOOPT_VS2013x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2015_IA32_ASLPP_PATH = DEF(VS2015_BIN)\cl.exe
*_VS2015_IA32_ASLDLINK_PATH = DEF(VS2015_BIN)\link.exe
- *_VS2015_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2015_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw
RELEASE_VS2015_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw
NOOPT_VS2015_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1445,14 +1407,12 @@ NOOPT_VS2015_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2015_EBC_*_FAMILY = INTEL
*_VS2015_EBC_*_DLL = DEF(VS2015_DLL)
-*_VS2015_EBC_MAKE_PATH = DEF(VS2015_BIN)\nmake.exe
*_VS2015_EBC_PP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2015_EBC_VFRPP_PATH = DEF(EBC_BIN)\iec.exe
*_VS2015_EBC_CC_PATH = DEF(EBC_BIN)\iec.exe
*_VS2015_EBC_SLINK_PATH = DEF(VS2015_BIN)\link.exe
*_VS2015_EBC_DLINK_PATH = DEF(VS2015_BIN)\link.exe
-*_VS2015_EBC_MAKE_FLAGS = /nologo
*_VS2015_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2015_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2015_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1468,10 +1428,9 @@ NOOPT_VS2015_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2015x86_*_*_FAMILY = MSFT
*_VS2015x86_*_MAKE_PATH = DEF(VS2015x86_BIN)\nmake.exe
-*_VS2015x86_*_MAKE_FLAG = /nologo
+*_VS2015x86_*_MAKE_FLAGS = /nologo
*_VS2015x86_*_RC_PATH = DEF(WINSDK81x86_BIN)\rc.exe
-*_VS2015x86_*_MAKE_FLAGS = /nologo
*_VS2015x86_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2015x86_*_APP_FLAGS = /nologo /E /TC
*_VS2015x86_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -1495,7 +1454,6 @@ NOOPT_VS2015_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
##################
*_VS2015x86_IA32_*_DLL = DEF(VS2015x86_DLL)
-*_VS2015x86_IA32_MAKE_PATH = DEF(VS2015x86_BIN)\nmake.exe
*_VS2015x86_IA32_CC_PATH = DEF(VS2015x86_BIN)\cl.exe
*_VS2015x86_IA32_VFRPP_PATH = DEF(VS2015x86_BIN)\cl.exe
*_VS2015x86_IA32_ASLCC_PATH = DEF(VS2015x86_BIN)\cl.exe
@@ -1507,7 +1465,6 @@ NOOPT_VS2015_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF /OPT
*_VS2015x86_IA32_PP_PATH = DEF(VS2015x86_BIN)\cl.exe
*_VS2015x86_IA32_ASM_PATH = DEF(VS2015x86_BIN)\ml.exe
- *_VS2015x86_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw
RELEASE_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw
NOOPT_VS2015x86_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1562,14 +1519,12 @@ NOOPT_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2015x86_EBC_*_FAMILY = INTEL
*_VS2015x86_EBC_*_DLL = DEF(VS2015x86_DLL)
-*_VS2015x86_EBC_MAKE_PATH = DEF(VS2015x86_BIN)\nmake.exe
*_VS2015x86_EBC_PP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2015x86_EBC_VFRPP_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2015x86_EBC_CC_PATH = DEF(EBC_BINx86)\iec.exe
*_VS2015x86_EBC_SLINK_PATH = DEF(VS2015x86_BIN)\link.exe
*_VS2015x86_EBC_DLINK_PATH = DEF(VS2015x86_BIN)\link.exe
-*_VS2015x86_EBC_MAKE_FLAGS = /nologo
*_VS2015x86_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2015x86_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2015x86_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1586,10 +1541,9 @@ NOOPT_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2017_*_*_DLL = DEF(VS2017_BIN_HOST)
*_VS2017_*_MAKE_PATH = DEF(VS2017_BIN_HOST)\nmake.exe
-*_VS2017_*_MAKE_FLAG = /nologo
+*_VS2017_*_MAKE_FLAGS = /nologo
*_VS2017_*_RC_PATH = DEF(RC_PATH)
-*_VS2017_*_MAKE_FLAGS = /nologo
*_VS2017_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2017_*_APP_FLAGS = /nologo /E /TC
*_VS2017_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -1621,7 +1575,6 @@ NOOPT_VS2015x86_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2017_IA32_PP_PATH = DEF(VS2017_BIN_IA32)\cl.exe
*_VS2017_IA32_ASM_PATH = DEF(VS2017_BIN_IA32)\ml.exe
- *_VS2017_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2017_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw
RELEASE_VS2017_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw
NOOPT_VS2017_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1682,7 +1635,6 @@ NOOPT_VS2017_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:428
*_VS2017_ARM_ASLPP_PATH = DEF(VS2017_BIN_ARM)\cl.exe
*_VS2017_ARM_ASLDLINK_PATH = DEF(VS2017_BIN_ARM)\link.exe
- *_VS2017_ARM_MAKE_FLAGS = /nologo
DEBUG_VS2017_ARM_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gw /Oi-
RELEASE_VS2017_ARM_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw /Oi-
NOOPT_VS2017_ARM_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Od /Oi-
@@ -1709,7 +1661,6 @@ NOOPT_VS2017_ARM_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2017_AARCH64_ASLPP_PATH = DEF(VS2017_BIN_AARCH64)\cl.exe
*_VS2017_AARCH64_ASLDLINK_PATH = DEF(VS2017_BIN_AARCH64)\link.exe
- *_VS2017_AARCH64_MAKE_FLAGS = /nologo
DEBUG_VS2017_AARCH64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gw /Oi-
RELEASE_VS2017_AARCH64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw /Oi-
NOOPT_VS2017_AARCH64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Od /Oi-
@@ -1733,7 +1684,6 @@ NOOPT_VS2017_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2017_EBC_SLINK_PATH = DEF(VS2017_BIN_IA32)\link.exe
*_VS2017_EBC_DLINK_PATH = DEF(VS2017_BIN_IA32)\link.exe
-*_VS2017_EBC_MAKE_FLAGS = /nologo
*_VS2017_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2017_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2017_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1749,10 +1699,9 @@ NOOPT_VS2017_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2019_*_*_DLL = DEF(VS2019_BIN_HOST)
*_VS2019_*_MAKE_PATH = DEF(VS2019_BIN_HOST)\nmake.exe
-*_VS2019_*_MAKE_FLAG = /nologo
+*_VS2019_*_MAKE_FLAGS = /nologo
*_VS2019_*_RC_PATH = DEF(RC_PATH)
-*_VS2019_*_MAKE_FLAGS = /nologo
*_VS2019_*_SLINK_FLAGS = /NOLOGO /LTCG
*_VS2019_*_APP_FLAGS = /nologo /E /TC
*_VS2019_*_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
@@ -1784,7 +1733,6 @@ NOOPT_VS2017_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2019_IA32_PP_PATH = DEF(VS2019_BIN_IA32)\cl.exe
*_VS2019_IA32_ASM_PATH = DEF(VS2019_BIN_IA32)\ml.exe
- *_VS2019_IA32_MAKE_FLAGS = /nologo
DEBUG_VS2019_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Gw
RELEASE_VS2019_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw
NOOPT_VS2019_IA32_CC_FLAGS = /nologo /arch:IA32 /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Z7 /Od
@@ -1845,7 +1793,6 @@ NOOPT_VS2019_X64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /IGNORE:428
*_VS2019_ARM_ASLPP_PATH = DEF(VS2019_BIN_ARM)\cl.exe
*_VS2019_ARM_ASLDLINK_PATH = DEF(VS2019_BIN_ARM)\link.exe
- *_VS2019_ARM_MAKE_FLAGS = /nologo
DEBUG_VS2019_ARM_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gw /Oi-
RELEASE_VS2019_ARM_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw /Oi-
NOOPT_VS2019_ARM_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Od /Oi-
@@ -1872,7 +1819,6 @@ NOOPT_VS2019_ARM_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2019_AARCH64_ASLPP_PATH = DEF(VS2019_BIN_AARCH64)\cl.exe
*_VS2019_AARCH64_ASLDLINK_PATH = DEF(VS2019_BIN_AARCH64)\link.exe
- *_VS2019_AARCH64_MAKE_FLAGS = /nologo
DEBUG_VS2019_AARCH64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Gw /Oi-
RELEASE_VS2019_AARCH64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /O1b2 /GL /FIAutoGen.h /EHs-c- /GR- /GF /Gw /Oi-
NOOPT_VS2019_AARCH64_CC_FLAGS = /nologo /c /WX /GS- /W4 /Gs32768 /D UNICODE /FIAutoGen.h /EHs-c- /GR- /GF /Gy /Zi /Od /Oi-
@@ -1896,7 +1842,6 @@ NOOPT_VS2019_AARCH64_DLINK_FLAGS = /NOLOGO /NODEFAULTLIB /IGNORE:4001 /OPT:REF
*_VS2019_EBC_SLINK_PATH = DEF(VS2019_BIN_IA32)\link.exe
*_VS2019_EBC_DLINK_PATH = DEF(VS2019_BIN_IA32)\link.exe
-*_VS2019_EBC_MAKE_FLAGS = /nologo
*_VS2019_EBC_PP_FLAGS = /nologo /E /TC /FIAutoGen.h
*_VS2019_EBC_CC_FLAGS = /nologo /c /WX /W3 /FIAutoGen.h /D$(MODULE_ENTRY_POINT)=$(ARCH_ENTRY_POINT)
*_VS2019_EBC_VFRPP_FLAGS = /nologo /E /TC /DVFRCOMPILE /FI$(MODULE_NAME)StrDefs.h
@@ -1952,7 +1897,7 @@ DEFINE GCC_RISCV64_RC_FLAGS = -I binary -O elf64-littleriscv -B riscv
# GCC Build Flag for included header file list generation
DEFINE GCC_DEPS_FLAGS = -MMD -MF $@.deps
-DEFINE GCC48_ALL_CC_FLAGS = -g -fshort-wchar -fno-builtin -fno-strict-aliasing -Wall -Werror -Wno-array-bounds -ffunction-sections -fdata-sections -include AutoGen.h -fno-common -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
+DEFINE GCC48_ALL_CC_FLAGS = DEF(GCC_ALL_CC_FLAGS) -ffunction-sections -fdata-sections -DSTRING_ARRAY_NAME=$(BASE_NAME)Strings
DEFINE GCC48_IA32_X64_DLINK_COMMON = -nostdlib -Wl,-n,-q,--gc-sections -z common-page-size=0x20
DEFINE GCC48_IA32_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -m32 -march=i586 -malign-double -fno-stack-protector -D EFI32 -fno-asynchronous-unwind-tables -Wno-address
DEFINE GCC48_X64_CC_FLAGS = DEF(GCC48_ALL_CC_FLAGS) -m64 -fno-stack-protector "-DEFIAPI=__attribute__((ms_abi))" -maccumulate-outgoing-args -mno-red-zone -Wno-address -mcmodel=small -fpie -fno-asynchronous-unwind-tables -Wno-address
@@ -2037,6 +1982,7 @@ DEFINE GCC5_RISCV64_CC_FLAGS = DEF(GCC5_RISCV_ALL_CC_FLAGS) DEF(GC
DEFINE GCC5_RISCV64_DLINK_FLAGS = DEF(GCC5_RISCV_ALL_DLINK_FLAGS) -Wl,-melf64lriscv,--oformat=elf64-littleriscv,--no-relax
DEFINE GCC5_RISCV64_DLINK2_FLAGS = DEF(GCC5_RISCV_ALL_DLINK2_FLAGS)
DEFINE GCC5_RISCV64_ASM_FLAGS = DEF(GCC5_RISCV_ALL_ASM_FLAGS) -march=DEF(GCC5_RISCV64_ARCH) -mcmodel=medany -mabi=lp64
+DEFINE GCC_PP_FLAGS = -E -x assembler-with-cpp -include AutoGen.h DEF(GCC5_RISCV_OPENSBI_TYPES)
####################################################################################
#
@@ -2512,6 +2458,7 @@ RELEASE_GCC5_AARCH64_DLINK_XIPFLAGS = -z common-page-size=0x20
*_GCC5_RISCV64_DLINK2_FLAGS = DEF(GCC5_RISCV64_DLINK2_FLAGS)
*_GCC5_RISCV64_RC_FLAGS = DEF(GCC_RISCV64_RC_FLAGS)
*_GCC5_RISCV64_OBJCOPY_FLAGS =
+*_GCC5_RISCV64_DTCPP_FLAGS = DEF(GCC_DTCPP_FLAGS)
####################################################################################
#
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.rst b/src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.rst
new file mode 100644
index 00000000000..ea0cf364156
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.rst
@@ -0,0 +1,41 @@
+This directory contains the EDK II build tools and template files.
+Templates are located in the Conf directory, while the tools executables for
+Microsoft Windows Operating Systems are located in the Bin\\Win32 directory, other
+directory contains tools source.
+
+Build step to generate the binary tools
+---------------------------------------
+
+Windows/Visual Studio Notes
+===========================
+
+To build the BaseTools, you should run the standard vsvars32.bat script
+from your preferred Visual Studio installation or you can run get_vsvars.bat
+to use latest automatically detected version.
+
+In addition to this, you should set the following environment variables::
+
+ * EDK_TOOLS_PATH - Path to the BaseTools sub directory under the edk2 tree
+ * BASE_TOOLS_PATH - The directory where the BaseTools source is located.
+ (It is the same directory where this README.rst is located.)
+
+After this, you can run the toolsetup.bat file, which is in the same
+directory as this file. It should setup the remainder of the environment,
+and build the tools if necessary.
+
+Please also refer to the ``BuildNotes.txt`` file for more information on
+building under Windows.
+
+Unix-like operating systems
+===========================
+
+To build on Unix-like operating systems, you only need to type ``make`` in
+the base directory of the project.
+
+Ubuntu Notes
+============
+
+On Ubuntu, the following command should install all the necessary build
+packages to build all the C BaseTools::
+
+ sudo apt install build-essential uuid-dev
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.txt
deleted file mode 100644
index 2288dcb2855..00000000000
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/ReadMe.txt
+++ /dev/null
@@ -1,47 +0,0 @@
-This directory contains the next generation of EDK II build tools and template files.
-Templates are located in the Conf directory, while the tools executables for
-Microsoft Windows 32-bit Operating Systems are located in the Bin\Win32 directory, other
-directory contains tools source.
-
-1. Build step to generate the binary tools.
-
-=== Windows/Visual Studio Notes ===
-
-To build the BaseTools, you should run the standard vsvars32.bat script
-from your preferred Visual Studio installation or you can run get_vsvars.bat
-to use latest automatically detected version.
-
-In addition to this, you should set the following environment variables:
-
- * EDK_TOOLS_PATH - Path to the BaseTools sub directory under the edk2 tree
- * BASE_TOOLS_PATH - The directory where the BaseTools source is located.
- (It is the same directory where this README.txt is located.)
-
-After this, you can run the toolsetup.bat file, which is in the same
-directory as this file. It should setup the remainder of the environment,
-and build the tools if necessary.
-
-Please also refer to the 'BuildNotes.txt' file for more information on
-building under Windows.
-
-=== Unix-like operating systems ===
-
-To build on Unix-like operating systems, you only need to type 'make' in
-the base directory of the project.
-
-=== Ubuntu Notes ===
-
-On Ubuntu, the following command should install all the necessary build
-packages to build all the C BaseTools:
-
- sudo apt-get install build-essential uuid-dev
-
-=== Python sqlite3 module ===
-On Windows, the cx_freeze will not copy the sqlite3.dll to the frozen
-binary directory (the same directory as build.exe and GenFds.exe).
-Please copy it manually from <PythonHome>\DLLs.
-
-The Python distributed with most recent Linux will have sqlite3 module
-built in. If not, please install sqlit3 package separately.
-
-26-OCT-2011
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertFceToStructurePcd.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertFceToStructurePcd.py
index 93c300c549f..995fcfceb3b 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertFceToStructurePcd.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/ConvertFceToStructurePcd.py
@@ -52,6 +52,7 @@ infstatement = '''[Pcd]
SECTION='PcdsDynamicHii'
PCD_NAME='gStructPcdTokenSpaceGuid.Pcd'
+Max_Pcd_Len = 100
WARNING=[]
ERRORMSG=[]
@@ -196,6 +197,8 @@ class parser_lst(object):
efitxt = efivarstore_format.findall(self.text)
for i in efitxt:
struct = struct_re.findall(i.replace(' ',''))
+ if struct[0] in self._ignore:
+ continue
name = name_re.findall(i.replace(' ',''))
if struct and name:
efivarstore_dict[name[0]]=struct[0]
@@ -276,8 +279,12 @@ class Config(object):
attribute_re=re.compile(r'attribute=(\w+)')
value_re = re.compile(r'(//.*)')
part = []
+ part_without_comment = []
for x in section[1:]:
line=x.split('\n')[0]
+ comment_list = value_re.findall(line) # the string \\... in "Q...." line
+ comment_list[0] = comment_list[0].replace('//', '')
+ comment = comment_list[0].strip()
line=value_re.sub('',line) #delete \\... in "Q...." line
list1=line.split(' ')
value=self.value_parser(list1)
@@ -289,8 +296,18 @@ class Config(object):
if attribute[0] in ['0x3','0x7']:
offset = int(offset[0], 16)
#help = help_re.findall(x)
- text = offset, name[0], guid[0], value, attribute[0]
- part.append(text)
+ text_without_comment = offset, name[0], guid[0], value, attribute[0]
+ if text_without_comment in part_without_comment:
+ # check if exists same Pcd with different comments, add different comments in one line with "|".
+ dupl_index = part_without_comment.index(text_without_comment)
+ part[dupl_index] = list(part[dupl_index])
+ if comment not in part[dupl_index][-1]:
+ part[dupl_index][-1] += " | " + comment
+ part[dupl_index] = tuple(part[dupl_index])
+ else:
+ text = offset, name[0], guid[0], value, attribute[0], comment
+ part_without_comment.append(text_without_comment)
+ part.append(text)
return(part)
def value_parser(self, list1):
@@ -370,7 +387,7 @@ class PATH(object):
def __init__(self,path):
self.path=path
self.rootdir=self.get_root_dir()
- self.usefuldir=[]
+ self.usefuldir=set()
self.lstinf = {}
for path in self.rootdir:
for o_root, o_dir, o_file in os.walk(os.path.join(path, "OUTPUT"), topdown=True, followlinks=False):
@@ -381,7 +398,7 @@ class PATH(object):
for LST in l_file:
if os.path.splitext(LST)[1] == '.lst':
self.lstinf[os.path.join(l_root, LST)] = os.path.join(o_root, INF)
- self.usefuldir.append(path)
+ self.usefuldir.add(path)
def get_root_dir(self):
rootdir=[]
@@ -410,7 +427,7 @@ class PATH(object):
def header(self,struct):
header={}
- head_re = re.compile('typedef.*} %s;[\n]+(.*?)(?:typedef|formset)'%struct,re.M|re.S)
+ head_re = re.compile('typedef.*} %s;[\n]+(.*)(?:typedef|formset)'%struct,re.M|re.S)
head_re2 = re.compile(r'#line[\s\d]+"(\S+h)"')
for i in list(self.lstinf.keys()):
with open(i,'r') as lst:
@@ -421,9 +438,21 @@ class PATH(object):
if head:
format = head[0].replace('\\\\','/').replace('\\','/')
name =format.split('/')[-1]
- head = self.makefile(name).replace('\\','/')
- header[struct] = head
+ head = self.headerfileset.get(name)
+ if head:
+ head = head.replace('\\','/')
+ header[struct] = head
return header
+ @property
+ def headerfileset(self):
+ headerset = dict()
+ for root,dirs,files in os.walk(self.path):
+ for file in files:
+ if os.path.basename(file) == 'deps.txt':
+ with open(os.path.join(root,file),"r") as fr:
+ for line in fr.readlines():
+ headerset[os.path.basename(line).strip()] = line.strip()
+ return headerset
def makefile(self,filename):
re_format = re.compile(r'DEBUG_DIR.*(?:\S+Pkg)\\(.*\\%s)'%filename)
@@ -433,6 +462,7 @@ class PATH(object):
dir = re_format.findall(read)
if dir:
return dir[0]
+ return None
class mainprocess(object):
@@ -466,7 +496,7 @@ class mainprocess(object):
tmp_id=[id_key] #['0_0',[(struct,[name...]),(struct,[name...])]]
tmp_info={} #{name:struct}
for section in config_dict[id_key]:
- c_offset,c_name,c_guid,c_value,c_attribute = section
+ c_offset,c_name,c_guid,c_value,c_attribute,c_comment = section
if c_name in efi_dict:
struct = efi_dict[c_name]
title='%s%s|L"%s"|%s|0x00||%s\n'%(PCD_NAME,c_name,c_name,self.guid.guid_parser(c_guid),self.attribute_dict[c_attribute])
@@ -479,16 +509,21 @@ class mainprocess(object):
WARNING.append("Warning: No <HeaderFiles> for struct %s"%struct)
title2 = '%s%s|{0}|%s|0xFCD00000{\n <HeaderFiles>\n %s\n <Packages>\n%s\n}\n' % (PCD_NAME, c_name, struct, '', self.LST.package()[self.lst_dict[lstfile]])
header_list.append(title2)
- else:
+ elif struct not in lst._ignore:
struct_dict ={}
print("ERROR: Struct %s can't found in lst file" %struct)
ERRORMSG.append("ERROR: Struct %s can't found in lst file" %struct)
if c_offset in struct_dict:
offset_name=struct_dict[c_offset]
info = "%s%s.%s|%s\n"%(PCD_NAME,c_name,offset_name,c_value)
+ blank_length = Max_Pcd_Len - len(info)
+ if blank_length <= 0:
+ info_comment = "%s%s.%s|%s%s# %s\n"%(PCD_NAME,c_name,offset_name,c_value," ",c_comment)
+ else:
+ info_comment = "%s%s.%s|%s%s# %s\n"%(PCD_NAME,c_name,offset_name,c_value,blank_length*" ",c_comment)
inf = "%s%s\n"%(PCD_NAME,c_name)
inf_list.append(inf)
- tmp_info[info]=title
+ tmp_info[info_comment]=title
else:
print("ERROR: Can't find offset %s with struct name %s"%(c_offset,struct))
ERRORMSG.append("ERROR: Can't find offset %s with name %s"%(c_offset,struct))
@@ -510,6 +545,18 @@ class mainprocess(object):
i.sort()
return keys,title_all,info_list,header_list,inf_list
+ def correct_sort(self, PcdString):
+ # sort the Pcd list with two rules:
+ # First sort through Pcd name;
+ # Second if the Pcd exists several elements, sort them through index value.
+ if ("]|") in PcdString:
+ Pcdname = PcdString.split("[")[0]
+ Pcdindex = int(PcdString.split("[")[1].split("]")[0])
+ else:
+ Pcdname = PcdString.split("|")[0]
+ Pcdindex = 0
+ return Pcdname, Pcdindex
+
def remove_bracket(self,List):
for i in List:
for j in i:
@@ -521,7 +568,7 @@ class mainprocess(object):
List[List.index(i)][i.index(j)] = j
for i in List:
if type(i) == type([0,0]):
- i.sort()
+ i.sort(key = lambda x:(self.correct_sort(x)[0], self.correct_sort(x)[1]))
return List
def write_all(self):
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PatchCheck.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PatchCheck.py
index 2a69a116acd..c587922936e 100755
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PatchCheck.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PatchCheck.py
@@ -3,6 +3,7 @@
#
# Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
# Copyright (C) 2020, Red Hat, Inc.<BR>
+# Copyright (c) 2020, ARM Ltd. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -19,6 +20,8 @@ import re
import subprocess
import sys
+import email.header
+
class Verbose:
SILENT, ONELINE, NORMAL = range(3)
level = NORMAL
@@ -265,7 +268,14 @@ class CommitMessageCheck:
for i in range(2, count):
if (len(lines[i]) >= 76 and
len(lines[i].split()) > 1 and
- not lines[i].startswith('git-svn-id:')):
+ not lines[i].startswith('git-svn-id:') and
+ not lines[i].startswith('Reviewed-by') and
+ not lines[i].startswith('Acked-by:') and
+ not lines[i].startswith('Tested-by:') and
+ not lines[i].startswith('Reported-by:') and
+ not lines[i].startswith('Suggested-by:') and
+ not lines[i].startswith('Signed-off-by:') and
+ not lines[i].startswith('Cc:')):
#
# Print a warning if body line is longer than 75 characters
#
@@ -347,16 +357,23 @@ class GitDiffCheck:
self.is_newfile = False
self.force_crlf = True
self.force_notabs = True
- if self.filename.endswith('.sh'):
+ if self.filename.endswith('.sh') or \
+ self.filename.startswith('BaseTools/BinWrappers/PosixLike/') or \
+ self.filename.startswith('BaseTools/BinPipWrappers/PosixLike/') or \
+ self.filename.startswith('BaseTools/Bin/CYGWIN_NT-5.1-i686/') or \
+ self.filename == 'BaseTools/BuildEnv':
#
# Do not enforce CR/LF line endings for linux shell scripts.
+ # Some linux shell scripts don't end with the ".sh" extension,
+ # they are identified by their path.
#
self.force_crlf = False
- if self.filename == '.gitmodules':
+ if self.filename == '.gitmodules' or \
+ self.filename == 'BaseTools/Conf/diff.order':
#
- # .gitmodules is updated by git and uses tabs and LF line
- # endings. Do not enforce no tabs and do not enforce
- # CR/LF line endings.
+ # .gitmodules and diff orderfiles are used internally by git
+ # use tabs and LF line endings. Do not enforce no tabs and
+ # do not enforce CR/LF line endings.
#
self.force_crlf = False
self.force_notabs = False
@@ -449,7 +466,7 @@ class GitDiffCheck:
stripped = line.rstrip()
- if self.force_crlf and eol != '\r\n':
+ if self.force_crlf and eol != '\r\n' and (line.find('Subproject commit') == -1):
self.added_line_error('Line ending (%s) is not CRLF' % repr(eol),
line)
if self.force_notabs and '\t' in line:
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c
new file mode 100644
index 00000000000..e32b0c6b279
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c
@@ -0,0 +1,587 @@
+/** @file
+ BrotliCompress Compress/Decompress tool (BrotliCompress)
+
+ Copyright (c) 2020, ByoSoft Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/* Command line interface for Brotli library. */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <time.h>
+
+#include "./brotli/c/common/constants.h"
+#include "./brotli/c/common/version.h"
+#include <brotli/decode.h>
+#include <brotli/encode.h>
+
+#if !defined(_WIN32)
+#include <unistd.h>
+#include <utime.h>
+#else
+#include <io.h>
+#include <share.h>
+#include <sys/utime.h>
+
+#if !defined(__MINGW32__)
+#define STDIN_FILENO _fileno(stdin)
+#define STDOUT_FILENO _fileno(stdout)
+#define S_IRUSR S_IREAD
+#define S_IWUSR S_IWRITE
+#endif
+
+#define fopen ms_fopen
+#define open ms_open
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+#define fseek _fseeki64
+#define ftell _ftelli64
+#endif
+
+static FILE* ms_fopen(const char* FileName, const char* Mode) {
+ FILE* Result;
+ Result = NULL;
+ fopen_s(&Result, FileName, Mode);
+ return Result;
+}
+
+static int ms_open(const char* FileName, int Oflag, int Pmode) {
+ int Result;
+ Result = -1;
+ _sopen_s(&Result, FileName, Oflag | O_BINARY, _SH_DENYNO, Pmode);
+ return Result;
+}
+#endif /* WIN32 */
+
+
+#ifndef _MAX_PATH
+#define _MAX_PATH 500
+#endif
+
+#define DEFAULT_LGWIN 22
+#define DECODE_HEADER_SIZE 0x10
+#define GAP_MEM_BLOCK 0x1000
+size_t ScratchBufferSize = 0;
+static const size_t kFileBufferSize = 1 << 19;
+
+static void Version(void) {
+ int Major;
+ int Minor;
+ int Patch;
+ Major = BROTLI_VERSION >> 24;
+ Minor = (BROTLI_VERSION >> 12) & 0xFFF;
+ Patch = BROTLI_VERSION & 0xFFF;
+ printf("BrotliCompress %d.%d.%d\n", Major, Minor, Patch);
+}
+
+static void Usage() {
+ printf("Usage: %s [OPTION]... [FILE]...\n", __FILE__);
+ printf(
+"Options:\n"
+" -e, --compress compress\n"
+" -d, --decompress decompress\n"
+" -h, --help display this help and exit\n");
+ printf(
+" -o FILE, --output=FILE output file (only if 1 input file)\n");
+ printf(
+" -g NUM, --gap=NUM scratch memory gap level (1-16)\n");
+ printf(
+" -q NUM, --quality=NUM compression level (%d-%d)\n",
+ BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY);
+ printf(
+" -v, --version display version and exit\n");
+}
+
+static int64_t FileSize(const char* Path) {
+ FILE *FileHandle;
+ int64_t RetVal;
+ FileHandle = fopen(Path, "rb");
+
+ if (FileHandle == NULL) {
+ printf ("Failed to open file [%s]\n", Path);
+ return -1;
+ }
+ if (fseek(FileHandle, 0L, SEEK_END) != 0) {
+ printf ("Failed to seek file [%s]\n", Path);
+ fclose(FileHandle);
+ return -1;
+ }
+ RetVal = ftell(FileHandle);
+ if (fclose(FileHandle) != 0) {
+ printf ("Failed to close file [%s]\n", Path);
+ return -1;
+ }
+ return RetVal;
+}
+
+static BROTLI_BOOL HasMoreInput(FILE *FileHandle) {
+ return feof(FileHandle) ? BROTLI_FALSE : BROTLI_TRUE;
+}
+
+int OpenFiles(char *InputFile, FILE **InHandle, char *OutputFile, FILE **OutHandle) {
+ *InHandle = NULL;
+ *OutHandle = NULL;
+ *InHandle = fopen(InputFile, "rb");
+ if (*InHandle == NULL) {
+ printf("Failed to open input file [%s]\n", InputFile);
+ return BROTLI_FALSE;
+ }
+
+ *OutHandle = fopen(OutputFile, "wb+");
+ if (*OutHandle == NULL) {
+ printf("Failed to open output file [%s]\n", OutputFile);
+ fclose(*InHandle);
+ return BROTLI_FALSE;
+ }
+ return BROTLI_TRUE;
+}
+
+int CompressFile(char *InputFile, uint8_t *InputBuffer, char *OutputFile, uint8_t *OutputBuffer, int Quality, int Gap) {
+ int64_t InputFileSize;
+ FILE *InputFileHandle;
+ FILE *OutputFileHandle;
+ BrotliEncoderState *EncodeState;
+ uint32_t LgWin;
+ BROTLI_BOOL IsEof;
+ size_t AvailableIn;
+ const uint8_t *NextIn;
+ size_t AvailableOut;
+ uint8_t *NextOut;
+ uint8_t *Input;
+ uint8_t *Output;
+ size_t TotalOut;
+ size_t OutSize;
+ uint32_t SizeHint;
+ BROTLI_BOOL IsOk;
+ AvailableIn = 0;
+ IsEof = BROTLI_FALSE;
+ Input = InputBuffer;
+ Output = OutputBuffer;
+ IsOk = BROTLI_TRUE;
+ LgWin = DEFAULT_LGWIN;
+
+ InputFileSize = FileSize(InputFile);
+
+ IsOk = OpenFiles(InputFile, &InputFileHandle, OutputFile, &OutputFileHandle);
+ if (!IsOk) {
+ return IsOk;
+ }
+
+ fseek (OutputFileHandle, DECODE_HEADER_SIZE, SEEK_SET);
+
+ EncodeState = BrotliEncoderCreateInstance(NULL, NULL, NULL);
+ if (!EncodeState) {
+ printf("Out of memory\n");
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_QUALITY, (uint32_t)Quality);
+
+ if (InputFileSize >= 0) {
+ LgWin = BROTLI_MIN_WINDOW_BITS;
+ while (BROTLI_MAX_BACKWARD_LIMIT(LgWin) < InputFileSize) {
+ LgWin++;
+ if (LgWin == BROTLI_MAX_WINDOW_BITS) {
+ break;
+ }
+ }
+ }
+ BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_LGWIN, LgWin);
+ if (InputFileSize > 0) {
+ SizeHint = InputFileSize < (1 << 30)? (uint32_t)InputFileSize : (1u << 30);
+ BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_SIZE_HINT, SizeHint);
+ }
+
+ AvailableIn = 0;
+ NextIn = NULL;
+ AvailableOut = kFileBufferSize;
+ NextOut = Output;
+ for (;;) {
+ if (AvailableIn == 0 && !IsEof) {
+ AvailableIn = fread(Input, 1, kFileBufferSize, InputFileHandle);
+ NextIn = Input;
+ if (ferror(InputFileHandle)) {
+ printf("Failed to read input [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ IsEof = !HasMoreInput(InputFileHandle);
+ }
+
+ if (!IsEof){
+ do{
+ if (!BrotliEncoderCompressStream(EncodeState,
+ BROTLI_OPERATION_FLUSH,
+ &AvailableIn, &NextIn, &AvailableOut, &NextOut, &TotalOut)) {
+ printf("Failed to compress data [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ OutSize = (size_t)(NextOut - Output);
+ if (OutSize > 0) {
+ fwrite(Output, 1, OutSize, OutputFileHandle);
+ if (ferror(OutputFileHandle)) {
+ printf("Failed to write output [%s]\n", OutputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ }
+ NextOut = Output;
+ AvailableOut = kFileBufferSize;
+ }
+ while (AvailableIn > 0 || BrotliEncoderHasMoreOutput(EncodeState));
+ }
+ else{
+ do{
+ if (!BrotliEncoderCompressStream(EncodeState,
+ BROTLI_OPERATION_FINISH,
+ &AvailableIn, &NextIn, &AvailableOut, &NextOut, &TotalOut)) {
+ printf("Failed to compress data [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ OutSize = (size_t)(NextOut - Output);
+ if (OutSize > 0) {
+ fwrite(Output, 1, OutSize, OutputFileHandle);
+ if (ferror(OutputFileHandle)) {
+ printf("Failed to write output [%s]\n", OutputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ }
+ NextOut = Output;
+ AvailableOut = kFileBufferSize;
+ }
+ while (AvailableIn > 0 || BrotliEncoderHasMoreOutput(EncodeState));
+ }
+ if (BrotliEncoderIsFinished(EncodeState)){
+ break;
+ }
+ }
+
+Finish:
+ if (EncodeState) {
+ BrotliEncoderDestroyInstance(EncodeState);
+ }
+ if (InputFileHandle) {
+ fclose(InputFileHandle);
+ }
+ if (OutputFileHandle) {
+ fclose(OutputFileHandle);
+ }
+ return IsOk;
+}
+
+/* Default BrotliAllocFunc */
+void* BrotliAllocFunc(void* Opaque, size_t Size) {
+ *(size_t *)Opaque = *(size_t *) Opaque + Size;
+ return malloc(Size);
+}
+
+/* Default BrotliFreeFunc */
+void BrotliFreeFunc(void* Opaque, void* Address) {
+ free(Address);
+}
+
+int DecompressFile(char *InputFile, uint8_t *InputBuffer, char *OutputFile, uint8_t *OutputBuffer, int Quality, int Gap) {
+ FILE *InputFileHandle;
+ FILE *OutputFileHandle;
+ BrotliDecoderState *DecoderState;
+ BrotliDecoderResult Result;
+ size_t AvailableIn;
+ const uint8_t *NextIn;
+ size_t AvailableOut;
+ uint8_t *NextOut;
+ uint8_t *Input;
+ uint8_t *Output;
+ size_t OutSize;
+ BROTLI_BOOL IsOk;
+ AvailableIn = 0;
+ Input = InputBuffer;
+ Output = OutputBuffer;
+ IsOk = BROTLI_TRUE;
+
+ IsOk = OpenFiles(InputFile, &InputFileHandle, OutputFile, &OutputFileHandle);
+ if (!IsOk) {
+ return IsOk;
+ }
+ fseek(InputFileHandle, DECODE_HEADER_SIZE, SEEK_SET);
+
+ DecoderState = BrotliDecoderCreateInstance(BrotliAllocFunc, BrotliFreeFunc, &ScratchBufferSize);
+ if (!DecoderState) {
+ printf("Out of memory\n");
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ /* This allows decoding "large-window" streams. Though it creates
+ fragmentation (new builds decode streams that old builds don't),
+ it is better from used experience perspective. */
+ BrotliDecoderSetParameter(DecoderState, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1u);
+
+ AvailableIn = 0;
+ NextIn = NULL;
+ AvailableOut = kFileBufferSize;
+ NextOut = Output;
+ Result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;
+ for (;;) {
+ if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) {
+ if (!HasMoreInput(InputFileHandle)) {
+ printf("Corrupt input [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ AvailableIn = fread(Input, 1, kFileBufferSize, InputFileHandle);
+ NextIn = Input;
+ if (ferror(InputFileHandle)) {
+ printf("Failed to read input [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ } else if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) {
+ OutSize = (size_t) (NextOut - Output);
+ if (OutSize > 0) {
+ fwrite(Output, 1, OutSize, OutputFileHandle);
+ if (ferror(OutputFileHandle)) {
+ printf("Failed to write output [%s]\n", OutputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ }
+ AvailableOut = kFileBufferSize;
+ NextOut = Output;
+ } else if (Result == BROTLI_DECODER_RESULT_SUCCESS) {
+ OutSize = (size_t) (NextOut - Output);
+ if (OutSize > 0) {
+ fwrite(Output, 1, OutSize, OutputFileHandle);
+ if (ferror(OutputFileHandle)) {
+ printf("Failed to write output [%s]\n", OutputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ }
+ AvailableOut = 0;
+ if (AvailableIn != 0 || HasMoreInput(InputFileHandle)) {
+ printf("Corrupt input [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ } else {
+ printf("Corrupt input [%s]\n", InputFile);
+ IsOk = BROTLI_FALSE;
+ goto Finish;
+ }
+ if (!HasMoreInput(InputFileHandle) && Result == BROTLI_DECODER_RESULT_SUCCESS ) {
+ break;
+ }
+ Result = BrotliDecoderDecompressStream(DecoderState, &AvailableIn, &NextIn, &AvailableOut, &NextOut, 0);
+ }
+Finish:
+ if (DecoderState) {
+ BrotliDecoderDestroyInstance(DecoderState);
+ }
+ if (InputFileHandle) {
+ fclose(InputFileHandle);
+ }
+ if (OutputFileHandle) {
+ fclose(OutputFileHandle);
+ }
+ return IsOk;
+}
+
+int main(int argc, char** argv) {
+ BROTLI_BOOL CompressBool;
+ BROTLI_BOOL DecompressBool;
+ char *OutputFile;
+ char *InputFile;
+ char OutputTmpFile[_MAX_PATH];
+ FILE *OutputHandle;
+ int Quality;
+ int Gap;
+ int OutputFileLength;
+ int InputFileLength;
+ int Ret;
+ size_t InputFileSize;
+ uint8_t *Buffer;
+ uint8_t *InputBuffer;
+ uint8_t *OutputBuffer;
+ int64_t Size;
+
+ InputFile = NULL;
+ OutputFile = NULL;
+ CompressBool = BROTLI_FALSE;
+ DecompressBool = BROTLI_FALSE;
+ //
+ //Set default Quality and Gap
+ //
+ Quality = 9;
+ Gap = 1;
+ InputFileSize = 0;
+ Ret = 0;
+
+ if (argc < 2) {
+ Usage();
+ return 1;
+ }
+ if (strcmp(argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0 ) {
+ Usage();
+ return 0;
+ }
+ if (strcmp(argv[1], "-v") == 0 || strcmp (argv[1], "--version") == 0 ) {
+ Version();
+ return 0;
+ }
+ while (argc > 1) {
+ if (strcmp(argv[1], "-e") == 0 || strcmp(argv[1], "--compress") == 0 ) {
+ CompressBool = BROTLI_TRUE;
+ if (DecompressBool) {
+ printf("Can't use -e/--compress with -d/--decompess on the same time\n");
+ return 1;
+ }
+ argc--;
+ argv++;
+ continue;
+ }
+ if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--decompress") == 0 ) {
+ DecompressBool = BROTLI_TRUE;
+ if (CompressBool) {
+ printf("Can't use -e/--compress with -d/--decompess on the same time\n");
+ return 1;
+ }
+ argc--;
+ argv++;
+ continue;
+ }
+ if (strcmp(argv[1], "-o") == 0 || strncmp(argv[1], "--output", 8) == 0) {
+ if (strcmp(argv[1], "-o") == 0) {
+ OutputFileLength = strlen(argv[2]);
+ if (OutputFileLength > _MAX_PATH) {
+ printf ("The file path %s is too long\n", argv[2]);
+ return 1;
+ }
+ OutputFile = argv[2];
+ if (OutputFile == NULL) {
+ fprintf(stderr, "Input file can't be null\n");
+ return 1;
+ }
+ argc--;
+ argv++;
+ } else {
+ OutputFileLength = strlen(argv[1] - 9);
+ OutputFile = (char *)argv[1] + 9;
+ }
+ argc--;
+ argv++;
+ continue;
+ }
+ if (strcmp(argv[1], "-q") == 0 || strncmp(argv[1], "--quality", 9) == 0) {
+ if (strcmp(argv[1], "-q") == 0) {
+ Quality = strtol(argv[2], NULL, 16);
+ argc--;
+ argv++;
+ } else {
+ Quality = strtol((char *)argv[1] + 10, NULL, 16);
+ }
+ argc--;
+ argv++;
+ continue;
+ }
+ if (strcmp(argv[1], "-g") == 0 || strncmp(argv[1], "--gap", 5) == 0) {
+ if (strcmp(argv[1], "-g") == 0) {
+ Gap = strtol(argv[2], NULL, 16);
+ argc--;
+ argv++;
+ } else {
+ Gap = strtol((char *)argv[1] + 6, NULL, 16);
+ }
+ argc--;
+ argv++;
+ continue;
+ }
+ if (argc > 1) {
+ InputFileLength = strlen(argv[1]);
+ if (InputFileLength > _MAX_PATH - 1) {
+ printf ("The file path %s is too long\n", argv[2]);
+ return 1;
+ }
+ InputFile = argv[1];
+ if (InputFile == NULL) {
+ printf("Input file can't be null\n");
+ return 1;
+ }
+ argc--;
+ argv++;
+ }
+ }
+
+ Buffer = (uint8_t*)malloc(kFileBufferSize * 2);
+ if (!Buffer) {
+ printf("Out of memory\n");
+ goto Finish;
+ }
+ memset(Buffer, 0, kFileBufferSize*2);
+ InputBuffer = Buffer;
+ OutputBuffer = Buffer + kFileBufferSize;
+ if (CompressBool) {
+ //
+ // Compress file
+ //
+ Ret = CompressFile(InputFile, InputBuffer, OutputFile, OutputBuffer, Quality, Gap);
+ if (!Ret) {
+ printf ("Failed to compress file [%s]\n", InputFile);
+ goto Finish;
+ }
+ //
+ // Decompress file for get Outputfile size
+ //
+ strcpy (OutputTmpFile, OutputFile);
+ if (strlen(InputFile) + strlen(".tmp") < _MAX_PATH) {
+ strcat(OutputTmpFile, ".tmp");
+ } else {
+ printf ("Output file path is too long[%s]\n", OutputFile);
+ Ret = BROTLI_FALSE;
+ goto Finish;
+ }
+ memset(Buffer, 0, kFileBufferSize*2);
+ Ret = DecompressFile(OutputFile, InputBuffer, OutputTmpFile, OutputBuffer, Quality, Gap);
+ if (!Ret) {
+ printf ("Failed to decompress file [%s]\n", OutputFile);
+ goto Finish;
+ }
+ remove (OutputTmpFile);
+
+ //
+ // fill decoder header
+ //
+ InputFileSize = FileSize(InputFile);
+ Size = (int64_t)InputFileSize;
+ OutputHandle = fopen(OutputFile, "rb+"); /* open output_path file and add in head info */
+ fwrite(&Size, 1, sizeof(int64_t), OutputHandle);
+ ScratchBufferSize += Gap * GAP_MEM_BLOCK; /* there is a memory gap between IA32 and X64 environment*/
+ ScratchBufferSize += kFileBufferSize * 2;
+ Size = (int64_t) ScratchBufferSize;
+ fwrite(&Size, 1, sizeof(int64_t), OutputHandle);
+ if (fclose(OutputHandle) != 0) {
+ printf("Failed to close output file [%s]\n", OutputFile);
+ Ret = BROTLI_FALSE;
+ goto Finish;
+ }
+ } else {
+ Ret = DecompressFile(InputFile, InputBuffer, OutputFile, OutputBuffer, Quality, Gap);
+ if (!Ret) {
+ printf ("Failed to decompress file [%s]\n", InputFile);
+ goto Finish;
+ }
+ }
+ Finish:
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+ return !Ret;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile
index cf27d1360f5..1a1c1bb6578 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile
@@ -6,10 +6,10 @@
#
MAKEROOT ?= ..
-APPNAME = Brotli
+APPNAME = BrotliCompress
OBJECTS = \
- brotli/c/tools/brotli.o \
+ BrotliCompress.o \
brotli/c/common/dictionary.o \
brotli/c/common/transform.o \
brotli/c/dec/bit_reader.o \
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile
index 3d5151f4c97..30d329b6463 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile
@@ -9,7 +9,7 @@
INC = -I .\brotli\c\include $(INC)
CFLAGS = $(CFLAGS) /W2
-APPNAME = Brotli
+APPNAME = BrotliCompress
#LIBS = $(LIB_PATH)\Common.lib
@@ -40,7 +40,7 @@ ENC_OBJ = \
brotli\c\enc\utf8_util.obj
OBJECTS = \
- brotli\c\tools\brotli.obj \
+ BrotliCompress.obj \
$(COMMON_OBJ) \
$(DEC_OBJ) \
$(ENC_OBJ)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h
index 47db64b59e4..2fa4b576409 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h
@@ -12,9 +12,17 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Common/UefiBaseTypes.h>
#include <Common/BuildVersion.h>
#include <assert.h>
+#ifndef _WIN32
+#include <limits.h>
+#endif
+
#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination
+#ifdef PATH_MAX
+#define MAX_LONG_FILE_PATH PATH_MAX
+#else
#define MAX_LONG_FILE_PATH 500
+#endif
#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL)
#define MAX_UINT32 ((UINT32)0xFFFFFFFF)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h
index 6c53f6e877d..f53d8a4be20 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h
@@ -14,7 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define __FIELD_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field)
#define __ARRAY_ELEMENT_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field[0])
-#define __OFFSET_OF(TYPE, Field) ((UINT32) &(((TYPE *)0)->Field))
+#define __OFFSET_OF(TYPE, Field) ((UINT32)(size_t) &(((TYPE *)0)->Field))
#define __FLEXIBLE_SIZE(Size, TYPE, Field, MaxIndex) if (__FIELD_SIZE(TYPE, Field) == 0) Size = MAX((__OFFSET_OF(TYPE, Field) + __ARRAY_ELEMENT_SIZE(TYPE, Field) * (MaxIndex)), Size)
#define __ARRAY_SIZE(Array) (sizeof(Array)/sizeof(Array[0]))
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c
index 10d52032720..b7492998a9d 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c
@@ -127,10 +127,7 @@ PeCoffLoaderRelocateRiscVImage (
{
UINT32 Value;
UINT32 Value2;
- UINT32 OrgValue;
- OrgValue = *(UINT32 *) Fixup;
- OrgValue = OrgValue;
switch ((*Reloc) >> 12) {
case EFI_IMAGE_REL_BASED_RISCV_HI20:
RiscVHi20Fixup = (UINT32 *) Fixup;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c
index a62e0b4e14b..61e47a6ae64 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c
@@ -1014,7 +1014,7 @@ Returns:
// Device IDs specified with -i
// Make sure there's at least one more parameter
//
- if (Argc < 1) {
+ if (Argc == 1) {
Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName);
ReturnStatus = 1;
goto Done;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile
index ed7e777a1f1..34031a4b6b9 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile
@@ -26,6 +26,9 @@ ifndef HOST_ARCH
else ifneq (,$(findstring arm,$(uname_m)))
HOST_ARCH=ARM
endif
+ ifneq (,$(findstring riscv64,$(uname_m)))
+ HOST_ARCH=RISCV64
+ endif
ifndef HOST_ARCH
$(info Could not detected HOST_ARCH from uname results)
$(error HOST_ARCH is not defined!)
@@ -54,7 +57,6 @@ APPLICATIONS = \
GenSec \
GenCrc32 \
LzmaCompress \
- Split \
TianoCompress \
VolInfo \
DevicePath
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c
index ba849912736..28066c2bca3 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c
@@ -825,12 +825,11 @@ Returns:
if (Alignment < 0x400){
sprintf (AlignmentBuffer, "%d", Alignment);
}
- else if (Alignment >= 0x400) {
- if (Alignment >= 0x100000) {
- sprintf (AlignmentBuffer, "%dM", Alignment/0x100000);
- } else {
- sprintf (AlignmentBuffer, "%dK", Alignment/0x400);
- }
+ else if (Alignment >= 0x100000) {
+ sprintf (AlignmentBuffer, "%dM", Alignment/0x100000);
+ }
+ else {
+ sprintf (AlignmentBuffer, "%dK", Alignment/0x400);
}
Status = StringtoAlignment (AlignmentBuffer, &(InputFileAlign[InputFileNum]));
}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c
index 9abee0fe2b1..85ea51eb52a 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c
@@ -903,7 +903,12 @@ Returns:
fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset));
}
- fprintf (FvMapFile, "EntryPoint=0x%010llx", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
+ fprintf (FvMapFile, "EntryPoint=0x%010llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint));
+ if (!pImageContext->IsTeImage) {
+ fprintf (FvMapFile, "Type=PE");
+ } else {
+ fprintf (FvMapFile, "Type=TE");
+ }
fprintf (FvMapFile, ")\n");
fprintf (FvMapFile, "(GUID=%s", FileGuidName);
@@ -3140,6 +3145,7 @@ Returns:
--*/
{
UINTN CurrentOffset;
+ UINTN OrigOffset;
UINTN Index;
FILE *fpin;
UINTN FfsFileSize;
@@ -3148,8 +3154,10 @@ Returns:
UINT32 FfsHeaderSize;
EFI_FFS_FILE_HEADER FfsHeader;
UINTN VtfFileSize;
+ UINTN MaxPadFileSize;
FvExtendHeaderSize = 0;
+ MaxPadFileSize = 0;
VtfFileSize = 0;
fpin = NULL;
Index = 0;
@@ -3258,8 +3266,12 @@ Returns:
//
// Only EFI_FFS_FILE_HEADER is needed for a pad section.
//
+ OrigOffset = CurrentOffset;
CurrentOffset = (CurrentOffset + FfsHeaderSize + sizeof(EFI_FFS_FILE_HEADER) + FfsAlignment - 1) & ~(FfsAlignment - 1);
CurrentOffset -= FfsHeaderSize;
+ if ((CurrentOffset - OrigOffset) > MaxPadFileSize) {
+ MaxPadFileSize = CurrentOffset - OrigOffset;
+ }
}
}
@@ -3303,6 +3315,12 @@ Returns:
//
mFvTotalSize = FvInfoPtr->Size;
mFvTakenSize = CurrentOffset;
+ if ((mFvTakenSize == mFvTotalSize) && (MaxPadFileSize > 0)) {
+ //
+ // This FV means TOP FFS has been taken. Then, check whether there is padding data for use.
+ //
+ mFvTakenSize = mFvTakenSize - MaxPadFileSize;
+ }
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c
index 3ec75a6e887..f93eeb47bf1 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c
@@ -1,7 +1,7 @@
/** @file
Elf32 Convert solution
-Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2013, ARM Ltd. All rights reserved.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -143,8 +143,7 @@ InitializeElf32 (
return FALSE;
}
if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM) || (mEhdr->e_machine == EM_RISCV))) {
- Error (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf32 machine.");
- return FALSE;
+ Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf32 machine.");
}
if (mEhdr->e_version != EV_CURRENT) {
Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c
index 00c1277e05f..989c1fa8ea7 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c
@@ -1,7 +1,7 @@
/** @file
Elf64 convert solution
-Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -162,8 +162,7 @@ InitializeElf64 (
return FALSE;
}
if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64) || (mEhdr->e_machine == EM_RISCV64))) {
- Error (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine.");
- return FALSE;
+ Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine.");
}
if (mEhdr->e_version != EV_CURRENT) {
Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT);
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c
index 638e23e4ecf..01719a7c662 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c
@@ -184,7 +184,7 @@ Returns:
fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\
GuidHeaderLength is the size of header of guided data\n");
fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\
- GuidAttr is guid section atttributes, which may be\n\
+ GuidAttr is guid section attributes, which may be\n\
PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\
if -r option is not given, default PROCESSING_REQUIRED\n");
fprintf (stdout, " -n String, --name String\n\
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h
index 0c05c8d93a7..18d202e04de 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h
@@ -57,6 +57,16 @@
#define NULL ((VOID *) 0)
#endif
+#ifdef __CC_ARM
+ //
+ // Older RVCT ARM compilers don't fully support #pragma pack and require __packed
+ // as a prefix for the structure.
+ //
+ #define PACKED __packed
+#else
+ #define PACKED
+#endif
+
//
// Support for variable length argument lists using the ANSI standard.
//
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h
new file mode 100644
index 00000000000..3446334dea3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h
@@ -0,0 +1,85 @@
+/** @file
+ Processor or Compiler specific defines and types for RISC-V.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __PROCESSOR_BIND_H__
+#define __PROCESSOR_BIND_H__
+
+//
+// Define the processor type so other code can make processor based choices
+//
+#define MDE_CPU_RISCV64
+
+//
+// Make sure we are using the correct packing rules per EFI specification
+//
+#ifndef __GNUC__
+#pragma pack()
+#endif
+
+//
+// Use ANSI C 2000 stdint.h integer width declarations
+//
+#include <stdint.h>
+typedef uint8_t BOOLEAN;
+typedef int8_t INT8;
+typedef uint8_t UINT8;
+typedef int16_t INT16;
+typedef uint16_t UINT16;
+typedef int32_t INT32;
+typedef uint32_t UINT32;
+typedef int64_t INT64;
+typedef uint64_t UINT64;
+typedef char CHAR8;
+typedef uint16_t CHAR16;
+
+//
+// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,
+// 8 bytes on supported 64-bit processor instructions)
+//
+typedef UINT64 UINTN;
+
+//
+// Signed value of native width. (4 bytes on supported 32-bit processor instructions,
+// 8 bytes on supported 64-bit processor instructions)
+//
+typedef INT64 INTN;
+
+//
+// Processor specific defines
+//
+
+//
+// A value of native width with the highest bit set.
+//
+#define MAX_BIT 0x8000000000000000
+
+//
+// A value of native width with the two highest bits set.
+//
+#define MAX_2_BITS 0xC000000000000000
+
+//
+// The stack alignment required for RISC-V
+//
+#define CPU_STACK_ALIGNMENT 16
+
+//
+// Modifier to ensure that all protocol member functions and EFI intrinsics
+// use the correct C calling convention. All protocol member functions and
+// EFI intrinsics are required to modify their member functions with EFIAPI.
+//
+#define EFIAPI
+
+#if defined(__GNUC__)
+ //
+ // For GNU assembly code, .global or .globl can declare global symbols.
+ // Define this macro to unify the usage.
+ //
+ #define ASM_GLOBAL .globl
+#endif
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt
index 6d3b9eece06..553eacea717 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt
@@ -1,3 +1,3 @@
-LzmaCompress is based on the LZMA SDK 18.05. LZMA SDK 18.05
-was placed in the public domain on 2018-04-30. It was
+LzmaCompress is based on the LZMA SDK 19.00. LZMA SDK 19.00
+was placed in the public domain on 2019-02-21. It was
released on the http://www.7-zip.org/sdk.html website.
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c
index 0ff23a5cdb0..1ecc51c52f4 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c
@@ -1,9 +1,9 @@
/** @file
LZMA Compress/Decompress tool (LzmaCompress)
- Based on LZMA SDK 18.05:
+ Based on LZMA SDK 19.00:
LzmaUtil.c -- Test application for LZMA compression
- 2018-04-30 : Igor Pavlov : Public domain
+ 2019-02-21 : Igor Pavlov : Public domain
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -39,7 +39,7 @@ const char *kCantAllocateMessage = "Can not allocate memory";
const char *kDataErrorMessage = "Data error";
const char *kInvalidParamValMessage = "Invalid parameter value";
-static Bool mQuietMode = False;
+static BoolInt mQuietMode = False;
static CONVERTER_TYPE mConType = NoConverter;
UINT64 mDictionarySize = 28;
@@ -244,7 +244,7 @@ int main2(int numArgs, const char *args[], char *rs)
CFileOutStream outStream;
int res;
int encodeMode = 0;
- Bool modeWasSet = False;
+ BoolInt modeWasSet = False;
const char *inputFile = NULL;
const char *outputFile = "file.tmp";
int param;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h
index 8678a8d6fef..7a9cadb9426 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h
@@ -1,5 +1,5 @@
/* 7zTypes.h -- Basic types
-2017-07-17 : Igor Pavlov : Public domain */
+2018-08-04 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
@@ -103,7 +103,8 @@ typedef UInt32 SizeT;
typedef size_t SizeT;
#endif
-typedef int Bool;
+typedef int BoolInt;
+/* typedef BoolInt Bool; */
#define True 1
#define False 0
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h
index f3fb623aa6c..c176823a4dd 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h
@@ -1,7 +1,7 @@
-#define MY_VER_MAJOR 18
-#define MY_VER_MINOR 05
+#define MY_VER_MAJOR 19
+#define MY_VER_MINOR 00
#define MY_VER_BUILD 0
-#define MY_VERSION_NUMBERS "18.05"
+#define MY_VERSION_NUMBERS "19.00"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@@ -10,7 +10,7 @@
#define MY_VERSION_CPU MY_VERSION
#endif
-#define MY_DATE "2018-04-30"
+#define MY_DATE "2019-02-21"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h
index 056116dde34..bd429388024 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h
@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
-2017-09-04 : Igor Pavlov : Public domain */
+2018-02-18 : Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@@ -318,15 +318,16 @@ enum
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
-Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
+BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
#define x86cpuid_GetStepping(ver) (ver & 0xF)
-Bool CPU_Is_InOrder();
-Bool CPU_Is_Aes_Supported();
+BoolInt CPU_Is_InOrder();
+BoolInt CPU_Is_Aes_Supported();
+BoolInt CPU_IsSupported_PageGB();
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c
index 19d2dcce08c..92264c7af46 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c
@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
-2017-06-10 : Igor Pavlov : Public domain */
+2018-07-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -138,7 +138,7 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p)
{
- UInt32 i;
+ unsigned i;
p->bufferBase = NULL;
p->directInput = 0;
p->hash = NULL;
@@ -147,7 +147,7 @@ void MatchFinder_Construct(CMatchFinder *p)
for (i = 0; i < 256; i++)
{
- UInt32 r = i;
+ UInt32 r = (UInt32)i;
unsigned j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
@@ -368,6 +368,8 @@ static void MatchFinder_Normalize(CMatchFinder *p)
MatchFinder_ReduceOffsets(p, subValue);
}
+
+MY_NO_INLINE
static void MatchFinder_CheckLimits(CMatchFinder *p)
{
if (p->pos == kMaxValForNormalize)
@@ -379,10 +381,16 @@ static void MatchFinder_CheckLimits(CMatchFinder *p)
MatchFinder_SetLimits(p);
}
-static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+
+/*
+ (lenLimit > maxLen)
+*/
+MY_FORCE_INLINE
+static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
- UInt32 *distances, UInt32 maxLen)
+ UInt32 *distances, unsigned maxLen)
{
+ /*
son[_cyclicBufferPos] = curMatch;
for (;;)
{
@@ -400,7 +408,8 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
break;
if (maxLen < len)
{
- *distances++ = maxLen = len;
+ maxLen = len;
+ *distances++ = len;
*distances++ = delta - 1;
if (len == lenLimit)
return distances;
@@ -408,15 +417,58 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
}
}
}
+ */
+
+ const Byte *lim = cur + lenLimit;
+ son[_cyclicBufferPos] = curMatch;
+ do
+ {
+ UInt32 delta = pos - curMatch;
+ if (delta >= _cyclicBufferSize)
+ break;
+ {
+ ptrdiff_t diff;
+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+ diff = (ptrdiff_t)0 - delta;
+ if (cur[maxLen] == cur[maxLen + diff])
+ {
+ const Byte *c = cur;
+ while (*c == c[diff])
+ {
+ if (++c == lim)
+ {
+ distances[0] = (UInt32)(lim - cur);
+ distances[1] = delta - 1;
+ return distances + 2;
+ }
+ }
+ {
+ unsigned len = (unsigned)(c - cur);
+ if (maxLen < len)
+ {
+ maxLen = len;
+ distances[0] = (UInt32)len;
+ distances[1] = delta - 1;
+ distances += 2;
+ }
+ }
+ }
+ }
+ }
+ while (--cutValue);
+
+ return distances;
}
+
+MY_FORCE_INLINE
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
- CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
- UInt32 len0 = 0, len1 = 0;
+ CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+ unsigned len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
@@ -426,9 +478,10 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
return distances;
}
{
- CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
- UInt32 len = (len0 < len1 ? len0 : len1);
+ unsigned len = (len0 < len1 ? len0 : len1);
+ UInt32 pair0 = pair[0];
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
@@ -437,11 +490,12 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
break;
if (maxLen < len)
{
- *distances++ = maxLen = len;
+ maxLen = (UInt32)len;
+ *distances++ = (UInt32)len;
*distances++ = delta - 1;
if (len == lenLimit)
{
- *ptr1 = pair[0];
+ *ptr1 = pair0;
*ptr0 = pair[1];
return distances;
}
@@ -468,9 +522,9 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
{
- CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
- UInt32 len0 = 0, len1 = 0;
+ CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+ unsigned len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
@@ -480,9 +534,9 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
return;
}
{
- CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
- UInt32 len = (len0 < len1 ? len0 : len1);
+ unsigned len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
while (++len != lenLimit)
@@ -520,13 +574,13 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
p->buffer++; \
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
-#define MOVE_POS_RET MOVE_POS return offset;
+#define MOVE_POS_RET MOVE_POS return (UInt32)offset;
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \
- UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
- lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+ unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
+ lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
@@ -535,22 +589,22 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define GET_MATCHES_FOOTER(offset, maxLen) \
- offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
- distances + offset, maxLen) - distances); MOVE_POS_RET;
+ offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
+ distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
#define SKIP_FOOTER \
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+ SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
#define UPDATE_maxLen { \
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
const Byte *c = cur + maxLen; \
const Byte *lim = cur + lenLimit; \
for (; c != lim; c++) if (*(c + diff) != *c) break; \
- maxLen = (UInt32)(c - cur); }
+ maxLen = (unsigned)(c - cur); }
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 offset;
+ unsigned offset;
GET_MATCHES_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hv];
@@ -561,7 +615,7 @@ static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 offset;
+ unsigned offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hv];
@@ -572,7 +626,8 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 h2, d2, maxLen, offset, pos;
+ UInt32 h2, d2, pos;
+ unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(3)
@@ -594,12 +649,12 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
UPDATE_maxLen
- distances[0] = maxLen;
+ distances[0] = (UInt32)maxLen;
distances[1] = d2 - 1;
offset = 2;
if (maxLen == lenLimit)
{
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
@@ -609,7 +664,8 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 h2, h3, d2, d3, maxLen, offset, pos;
+ UInt32 h2, h3, d2, d3, pos;
+ unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(4)
@@ -618,12 +674,12 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
- d2 = pos - hash[ h2];
+ d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
curMatch = (hash + kFix4HashSize)[hv];
- hash[ h2] = pos;
+ hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[hv] = pos;
@@ -632,7 +688,8 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
- distances[0] = maxLen = 2;
+ maxLen = 2;
+ distances[0] = 2;
distances[1] = d2 - 1;
offset = 2;
}
@@ -648,10 +705,10 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[(size_t)offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit)
{
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
@@ -674,13 +731,13 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
- d2 = pos - hash[ h2];
+ d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = (hash + kFix5HashSize)[hv];
- hash[ h2] = pos;
+ hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[h4] = pos;
(hash + kFix5HashSize)[hv] = pos;
@@ -741,7 +798,8 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 h2, h3, d2, d3, maxLen, offset, pos;
+ UInt32 h2, h3, d2, d3, pos;
+ unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(4)
@@ -750,12 +808,11 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
- d2 = pos - hash[ h2];
+ d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
-
curMatch = (hash + kFix4HashSize)[hv];
- hash[ h2] = pos;
+ hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[hv] = pos;
@@ -764,7 +821,8 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
- distances[0] = maxLen = 2;
+ maxLen = 2;
+ distances[0] = 2;
distances[1] = d2 - 1;
offset = 2;
}
@@ -780,7 +838,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[(size_t)offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
@@ -791,7 +849,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (maxLen < 3)
maxLen = 3;
- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
@@ -808,13 +866,13 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
hash = p->hash;
pos = p->pos;
- d2 = pos - hash[ h2];
+ d2 = pos - hash [h2];
d3 = pos - (hash + kFix3HashSize)[h3];
d4 = pos - (hash + kFix4HashSize)[h4];
curMatch = (hash + kFix5HashSize)[hv];
- hash[ h2] = pos;
+ hash [h2] = pos;
(hash + kFix3HashSize)[h3] = pos;
(hash + kFix4HashSize)[h4] = pos;
(hash + kFix5HashSize)[hv] = pos;
@@ -877,12 +935,12 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 offset;
+ unsigned offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hv];
p->hash[hv] = p->pos;
- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances));
MOVE_POS_RET
}
@@ -940,7 +998,7 @@ static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH4_CALC;
hash = p->hash;
curMatch = (hash + kFix4HashSize)[hv];
- hash[ h2] =
+ hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[hv] = p->pos;
SKIP_FOOTER
@@ -959,7 +1017,7 @@ static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH5_CALC;
hash = p->hash;
curMatch = (hash + kFix5HashSize)[hv];
- hash[ h2] =
+ hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[h4] =
(hash + kFix5HashSize)[hv] = p->pos;
@@ -979,7 +1037,7 @@ static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH4_CALC;
hash = p->hash;
curMatch = (hash + kFix4HashSize)[hv];
- hash[ h2] =
+ hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[hv] = p->pos;
p->son[p->cyclicBufferPos] = curMatch;
@@ -999,7 +1057,7 @@ static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
HASH5_CALC;
hash = p->hash;
curMatch = hash + kFix5HashSize)[hv];
- hash[ h2] =
+ hash [h2] =
(hash + kFix3HashSize)[h3] =
(hash + kFix4HashSize)[h4] =
(hash + kFix5HashSize)[hv] = p->pos;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c
index 448fc4be724..2d170d66c0f 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c
@@ -1,5 +1,5 @@
/* LzFindMt.c -- multithreaded Match finder for LZ algorithms
-2017-06-10 : Igor Pavlov : Public domain */
+2018-12-29 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -232,38 +232,57 @@ static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p)
#define kEmptyHashValue 0
-/* #define MFMT_GM_INLINE */
+#define MFMT_GM_INLINE
#ifdef MFMT_GM_INLINE
-#define NO_INLINE MY_FAST_CALL
+/*
+ we use size_t for _cyclicBufferPos instead of UInt32
+ to eliminate "movsx" BUG in old MSVC x64 compiler.
+*/
-static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
- UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
- UInt32 *_distances, UInt32 _maxLen, const UInt32 *hash, Int32 limit, UInt32 size, UInt32 *posRes)
+MY_NO_INLINE
+static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son,
+ size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
+ UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes)
{
do
{
- UInt32 *distances = _distances + 1;
- UInt32 curMatch = pos - *hash++;
+ UInt32 *_distances = ++distances;
+ UInt32 delta = *hash++;
- CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
- UInt32 len0 = 0, len1 = 0;
+ CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+ unsigned len0 = 0, len1 = 0;
UInt32 cutValue = _cutValue;
- UInt32 maxLen = _maxLen;
- for (;;)
+ unsigned maxLen = (unsigned)_maxLen;
+
+ /*
+ if (size > 1)
{
- UInt32 delta = pos - curMatch;
- if (cutValue-- == 0 || delta >= _cyclicBufferSize)
+ UInt32 delta = *hash;
+ if (delta < _cyclicBufferSize)
{
- *ptr0 = *ptr1 = kEmptyHashValue;
- break;
+ UInt32 cyc1 = _cyclicBufferPos + 1;
+ CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1);
+ Byte b = *(cur + 1 - delta);
+ _distances[0] = pair[0];
+ _distances[1] = b;
}
+ }
+ */
+ if (cutValue == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ }
+ else
+ for(;;)
+ {
{
- CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
- UInt32 len = (len0 < len1 ? len0 : len1);
+ unsigned len = (len0 < len1 ? len0 : len1);
+ UInt32 pair0 = *pair;
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
@@ -272,54 +291,66 @@ static Int32 NO_INLINE GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *
break;
if (maxLen < len)
{
- *distances++ = maxLen = len;
+ maxLen = len;
+ *distances++ = (UInt32)len;
*distances++ = delta - 1;
if (len == lenLimit)
{
- *ptr1 = pair[0];
- *ptr0 = pair[1];
+ UInt32 pair1 = pair[1];
+ *ptr1 = pair0;
+ *ptr0 = pair1;
break;
}
}
}
- if (pb[len] < cur[len])
- {
- *ptr1 = curMatch;
- ptr1 = pair + 1;
- curMatch = *ptr1;
- len1 = len;
- }
- else
{
- *ptr0 = curMatch;
- ptr0 = pair;
- curMatch = *ptr0;
- len0 = len;
+ UInt32 curMatch = pos - delta;
+ // delta = pos - *pair;
+ // delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31];
+ if (pb[len] < cur[len])
+ {
+ delta = pos - pair[1];
+ *ptr1 = curMatch;
+ ptr1 = pair + 1;
+ len1 = len;
+ }
+ else
+ {
+ delta = pos - *pair;
+ *ptr0 = curMatch;
+ ptr0 = pair;
+ len0 = len;
+ }
}
}
+ if (--cutValue == 0 || delta >= _cyclicBufferSize)
+ {
+ *ptr0 = *ptr1 = kEmptyHashValue;
+ break;
+ }
}
pos++;
_cyclicBufferPos++;
cur++;
{
UInt32 num = (UInt32)(distances - _distances);
- *_distances = num - 1;
- _distances += num;
- limit -= num;
+ _distances[-1] = num;
}
}
- while (limit > 0 && --size != 0);
+ while (distances < limit && --size != 0);
*posRes = pos;
- return limit;
+ return distances;
}
#endif
+
+
static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
{
UInt32 numProcessed = 0;
UInt32 curPos = 2;
- UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2);
+ UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2
distances[1] = p->hashNumAvail;
@@ -369,8 +400,10 @@ static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances)
#else
{
UInt32 posRes;
- curPos = limit - GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
- distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, (Int32)(limit - curPos), size, &posRes);
+ curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue,
+ distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos,
+ distances + limit,
+ size, &posRes) - distances);
p->hashBufPos += posRes - pos;
cyclicBufferPos += posRes - pos;
p->buffer += posRes - pos;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h
index 0529b6b5fc4..708157ecafa 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h
@@ -1,5 +1,5 @@
/* LzFindMt.h -- multithreaded Match finder for LZ algorithms
-2017-04-03 : Igor Pavlov : Public domain */
+2018-07-04 : Igor Pavlov : Public domain */
#ifndef __LZ_FIND_MT_H
#define __LZ_FIND_MT_H
@@ -19,10 +19,10 @@ EXTERN_C_BEGIN
typedef struct _CMtSync
{
- Bool wasCreated;
- Bool needStart;
- Bool exit;
- Bool stopWriting;
+ BoolInt wasCreated;
+ BoolInt needStart;
+ BoolInt exit;
+ BoolInt stopWriting;
CThread thread;
CAutoResetEvent canStart;
@@ -30,8 +30,8 @@ typedef struct _CMtSync
CAutoResetEvent wasStopped;
CSemaphore freeSemaphore;
CSemaphore filledSemaphore;
- Bool csWasInitialized;
- Bool csWasEntered;
+ BoolInt csWasInitialized;
+ BoolInt csWasEntered;
CCriticalSection cs;
UInt32 numProcessedBlocks;
} CMtSync;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c
index ea381f1c3cb..9749efe973b 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c
@@ -1,13 +1,13 @@
/* LzmaDec.c -- LZMA Decoder
-2018-02-28 : Igor Pavlov : Public domain */
+2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
+#include <string.h>
+
/* #include "CpuArch.h" */
#include "LzmaDec.h"
-#include <string.h>
-
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
@@ -19,7 +19,7 @@
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
-#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
@@ -66,7 +66,7 @@
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
-#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0_CHECK range = bound;
#define UPDATE_1_CHECK range -= bound; code -= bound;
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
@@ -539,7 +539,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
curLen = ((rem < len) ? (unsigned)rem : len);
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
- processedPos += curLen;
+ processedPos += (UInt32)curLen;
len -= curLen;
if (curLen <= dicBufSize - pos)
@@ -547,7 +547,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
Byte *dest = dic + dicPos;
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
const Byte *lim = dest + curLen;
- dicPos += curLen;
+ dicPos += (SizeT)curLen;
do
*(dest) = (Byte)*(dest + src);
while (++dest != lim);
@@ -572,14 +572,14 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
p->buf = buf;
p->range = range;
p->code = code;
- p->remainLen = len;
+ p->remainLen = (UInt32)len;
p->dicPos = dicPos;
p->processedPos = processedPos;
p->reps[0] = rep0;
p->reps[1] = rep1;
p->reps[2] = rep2;
p->reps[3] = rep3;
- p->state = state;
+ p->state = (UInt32)state;
return SZ_OK;
}
@@ -601,8 +601,8 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
p->checkDicSize = p->prop.dicSize;
- p->processedPos += len;
- p->remainLen -= len;
+ p->processedPos += (UInt32)len;
+ p->remainLen -= (UInt32)len;
while (len != 0)
{
len--;
@@ -850,7 +850,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
}
-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
{
p->remainLen = kMatchSpecLenStart + 1;
p->tempBufSize = 0;
@@ -979,10 +979,10 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->tempBufSize = rem;
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
{
- int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem);
if (dummyRes == DUMMY_ERROR)
{
- (*srcLen) += lookAhead;
+ (*srcLen) += (SizeT)lookAhead;
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
@@ -1005,9 +1005,9 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
return SZ_ERROR_FAIL; /* some internal error */
lookAhead -= rem;
}
- (*srcLen) += lookAhead;
+ (*srcLen) += (SizeT)lookAhead;
src += lookAhead;
- inSize -= lookAhead;
+ inSize -= (SizeT)lookAhead;
p->tempBufSize = 0;
}
}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
index c619ef7a27e..68e97c95480 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c
@@ -1,5 +1,5 @@
/* LzmaEnc.c -- LZMA Encoder
-2018-04-29 : Igor Pavlov : Public domain */
+2019-01-10: Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -38,6 +38,8 @@ static unsigned g_STAT_OFFSET = 0;
#define kNumBitPriceShiftBits 4
#define kBitPrice (1 << kNumBitPriceShiftBits)
+#define REP_LEN_COUNT 64
+
void LzmaEncProps_Init(CLzmaEncProps *p)
{
p->level = 5;
@@ -183,8 +185,11 @@ typedef struct
} COptimal;
-#define kNumOpts (1 << 12)
-#define kPackReserve (1 + kNumOpts * 2)
+// 18.06
+#define kNumOpts (1 << 11)
+#define kPackReserve (kNumOpts * 8)
+// #define kNumOpts (1 << 12)
+// #define kPackReserve (1 + kNumOpts * 2)
#define kNumLenToPosStates 4
#define kNumPosSlotBits 6
@@ -236,10 +241,18 @@ typedef struct
typedef struct
{
unsigned tableSize;
- unsigned counters[LZMA_NUM_PB_STATES_MAX];
UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
+ // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2];
+ // UInt32 prices2[kLenNumSymbolsTotal];
} CLenPriceEnc;
+#define GET_PRICE_LEN(p, posState, len) \
+ ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN])
+
+/*
+#define GET_PRICE_LEN(p, posState, len) \
+ ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9)))
+*/
typedef struct
{
@@ -308,16 +321,18 @@ typedef struct
unsigned lc, lp, pb;
unsigned lclp;
- Bool fastMode;
- Bool writeEndMark;
- Bool finished;
- Bool multiThread;
- Bool needInit;
+ BoolInt fastMode;
+ BoolInt writeEndMark;
+ BoolInt finished;
+ BoolInt multiThread;
+ BoolInt needInit;
+ // BoolInt _maxMode;
UInt64 nowPos64;
unsigned matchPriceCount;
- unsigned alignPriceCount;
+ // unsigned alignPriceCount;
+ int repLenEncCounter;
unsigned distTableSize;
@@ -325,7 +340,7 @@ typedef struct
SRes result;
#ifndef _7ZIP_ST
- Bool mtMode;
+ BoolInt mtMode;
// begin of CMatchFinderMt is used in LZ thread
CMatchFinderMt matchFinderMt;
// end of CMatchFinderMt is used in BT and HASH threads
@@ -458,6 +473,7 @@ SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
p->lp = props.lp;
p->pb = props.pb;
p->fastMode = (props.algo == 0);
+ // p->_maxMode = True;
p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0);
{
unsigned numHashBytes = 4;
@@ -618,9 +634,9 @@ static void RangeEnc_FlushData(CRangeEnc *p)
#ifdef _LZMA_ENC_USE_BRANCH
-#define RC_BIT(p, prob, symbol) { \
+#define RC_BIT(p, prob, bit) { \
RC_BIT_PRE(p, prob) \
- if (symbol == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
+ if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \
else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \
*(prob) = (CLzmaProb)ttt; \
RC_NORM(p) \
@@ -628,15 +644,15 @@ static void RangeEnc_FlushData(CRangeEnc *p)
#else
-#define RC_BIT(p, prob, symbol) { \
+#define RC_BIT(p, prob, bit) { \
UInt32 mask; \
RC_BIT_PRE(p, prob) \
- mask = 0 - (UInt32)symbol; \
+ mask = 0 - (UInt32)bit; \
range &= mask; \
mask &= newBound; \
range -= mask; \
(p)->low += mask; \
- mask = (UInt32)symbol - 1; \
+ mask = (UInt32)bit - 1; \
range += newBound & mask; \
mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \
mask += ((1 << kNumMoveBits) - 1); \
@@ -673,42 +689,42 @@ static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob)
p->range = range;
}
-static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym)
{
UInt32 range = p->range;
- symbol |= 0x100;
+ sym |= 0x100;
do
{
UInt32 ttt, newBound;
- // RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
- CLzmaProb *prob = probs + (symbol >> 8);
- UInt32 bit = (symbol >> 7) & 1;
- symbol <<= 1;
+ // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1);
+ CLzmaProb *prob = probs + (sym >> 8);
+ UInt32 bit = (sym >> 7) & 1;
+ sym <<= 1;
RC_BIT(p, prob, bit);
}
- while (symbol < 0x10000);
+ while (sym < 0x10000);
p->range = range;
}
-static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte)
{
UInt32 range = p->range;
UInt32 offs = 0x100;
- symbol |= 0x100;
+ sym |= 0x100;
do
{
UInt32 ttt, newBound;
CLzmaProb *prob;
UInt32 bit;
matchByte <<= 1;
- // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
- prob = probs + (offs + (matchByte & offs) + (symbol >> 8));
- bit = (symbol >> 7) & 1;
- symbol <<= 1;
- offs &= ~(matchByte ^ symbol);
+ // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1);
+ prob = probs + (offs + (matchByte & offs) + (sym >> 8));
+ bit = (sym >> 7) & 1;
+ sym <<= 1;
+ offs &= ~(matchByte ^ sym);
RC_BIT(p, prob, bit);
}
- while (symbol < 0x10000);
+ while (sym < 0x10000);
p->range = range;
}
@@ -739,11 +755,11 @@ static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
}
-#define GET_PRICE(prob, symbol) \
- p->ProbPrices[((prob) ^ (unsigned)(((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+#define GET_PRICE(prob, bit) \
+ p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
-#define GET_PRICEa(prob, symbol) \
- ProbPrices[((prob) ^ (unsigned)((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
+#define GET_PRICEa(prob, bit) \
+ ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
@@ -752,48 +768,48 @@ static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices)
#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
-static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, const CProbPrice *ProbPrices)
+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices)
{
UInt32 price = 0;
- symbol |= 0x100;
+ sym |= 0x100;
do
{
- unsigned bit = symbol & 1;
- symbol >>= 1;
- price += GET_PRICEa(probs[symbol], bit);
+ unsigned bit = sym & 1;
+ sym >>= 1;
+ price += GET_PRICEa(probs[sym], bit);
}
- while (symbol >= 2);
+ while (sym >= 2);
return price;
}
-static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, const CProbPrice *ProbPrices)
+static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices)
{
UInt32 price = 0;
UInt32 offs = 0x100;
- symbol |= 0x100;
+ sym |= 0x100;
do
{
matchByte <<= 1;
- price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
- symbol <<= 1;
- offs &= ~(matchByte ^ symbol);
+ price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1);
+ sym <<= 1;
+ offs &= ~(matchByte ^ sym);
}
- while (symbol < 0x10000);
+ while (sym < 0x10000);
return price;
}
-static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, UInt32 symbol)
+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym)
{
UInt32 range = rc->range;
unsigned m = 1;
do
{
UInt32 ttt, newBound;
- unsigned bit = symbol & 1;
+ unsigned bit = sym & 1;
// RangeEnc_EncodeBit(rc, probs + m, bit);
- symbol >>= 1;
+ sym >>= 1;
RC_BIT(rc, probs + m, bit);
m = (m << 1) | bit;
}
@@ -812,37 +828,37 @@ static void LenEnc_Init(CLenEnc *p)
p->high[i] = kProbInitValue;
}
-static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned symbol, unsigned posState)
+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState)
{
UInt32 range, ttt, newBound;
CLzmaProb *probs = p->low;
range = rc->range;
RC_BIT_PRE(rc, probs);
- if (symbol >= kLenNumLowSymbols)
+ if (sym >= kLenNumLowSymbols)
{
RC_BIT_1(rc, probs);
probs += kLenNumLowSymbols;
RC_BIT_PRE(rc, probs);
- if (symbol >= kLenNumLowSymbols * 2)
+ if (sym >= kLenNumLowSymbols * 2)
{
RC_BIT_1(rc, probs);
rc->range = range;
- // RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols * 2);
- LitEnc_Encode(rc, p->high, symbol - kLenNumLowSymbols * 2);
+ // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2);
+ LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2);
return;
}
- symbol -= kLenNumLowSymbols;
+ sym -= kLenNumLowSymbols;
}
- // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
+ // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym);
{
unsigned m;
unsigned bit;
RC_BIT_0(rc, probs);
probs += (posState << (1 + kLenNumLowBits));
- bit = (symbol >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
- bit = (symbol >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
- bit = symbol & 1; RC_BIT(rc, probs + m, bit);
+ bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit;
+ bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit;
+ bit = sym & 1; RC_BIT(rc, probs + m, bit);
rc->range = range;
}
}
@@ -863,50 +879,93 @@ static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *price
}
-MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTable(
- CLenPriceEnc *p, unsigned posState,
+MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables(
+ CLenPriceEnc *p,
+ unsigned numPosStates,
const CLenEnc *enc,
const CProbPrice *ProbPrices)
{
- // int y; for (y = 0; y < 100; y++) {
- UInt32 a;
- unsigned i, numSymbols;
+ UInt32 b;
+
+ {
+ unsigned prob = enc->low[0];
+ UInt32 a, c;
+ unsigned posState;
+ b = GET_PRICEa_1(prob);
+ a = GET_PRICEa_0(prob);
+ c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
+ for (posState = 0; posState < numPosStates; posState++)
+ {
+ UInt32 *prices = p->prices[posState];
+ const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
+ SetPrices_3(probs, a, prices, ProbPrices);
+ SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices);
+ }
+ }
- UInt32 *prices = p->prices[posState];
+ /*
{
- const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits));
- SetPrices_3(probs, GET_PRICEa_0(enc->low[0]), prices, ProbPrices);
+ unsigned i;
+ UInt32 b;
+ a = GET_PRICEa_0(enc->low[0]);
+ for (i = 0; i < kLenNumLowSymbols; i++)
+ p->prices2[i] = a;
a = GET_PRICEa_1(enc->low[0]);
- SetPrices_3(probs + kLenNumLowSymbols, a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]), prices + kLenNumLowSymbols, ProbPrices);
+ b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]);
+ for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++)
+ p->prices2[i] = b;
a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
}
- numSymbols = p->tableSize;
- p->counters[posState] = numSymbols;
- for (i = kLenNumLowSymbols * 2; i < numSymbols; i += 1)
+ */
+
+ // p->counter = numSymbols;
+ // p->counter = 64;
+
{
- prices[i] = a +
- // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
- LitEnc_GetPrice(enc->high, i - kLenNumLowSymbols * 2, ProbPrices);
- /*
- unsigned sym = (i - kLenNumLowSymbols * 2) >> 1;
- UInt32 price = a + RcTree_GetPrice(enc->high, kLenNumHighBits - 1, sym, ProbPrices);
- UInt32 prob = enc->high[(1 << 7) + sym];
- prices[i ] = price + GET_PRICEa_0(prob);
- prices[i + 1] = price + GET_PRICEa_1(prob);
- */
- }
- // }
-}
+ unsigned i = p->tableSize;
-static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates,
- const CLenEnc *enc,
- const CProbPrice *ProbPrices)
-{
- unsigned posState;
- for (posState = 0; posState < numPosStates; posState++)
- LenPriceEnc_UpdateTable(p, posState, enc, ProbPrices);
-}
+ if (i > kLenNumLowSymbols * 2)
+ {
+ const CLzmaProb *probs = enc->high;
+ UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2;
+ i -= kLenNumLowSymbols * 2 - 1;
+ i >>= 1;
+ b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]);
+ do
+ {
+ /*
+ p->prices2[i] = a +
+ // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices);
+ LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices);
+ */
+ // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices);
+ unsigned sym = --i + (1 << (kLenNumHighBits - 1));
+ UInt32 price = b;
+ do
+ {
+ unsigned bit = sym & 1;
+ sym >>= 1;
+ price += GET_PRICEa(probs[sym], bit);
+ }
+ while (sym >= 2);
+ {
+ unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))];
+ prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob);
+ prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob);
+ }
+ }
+ while (i);
+
+ {
+ unsigned posState;
+ size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]);
+ for (posState = 1; posState < numPosStates; posState++)
+ memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num);
+ }
+ }
+ }
+}
/*
#ifdef SHOW_STAT
@@ -917,7 +976,7 @@ static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, unsigned numPosStates,
#define MOVE_POS(p, num) { \
p->additionalOffset += (num); \
- p->matchFinder.Skip(p->matchFinderObj, (num)); }
+ p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); }
static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
@@ -954,7 +1013,8 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
const Byte *p2 = p1 + len;
ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1];
const Byte *lim = p1 + numAvail;
- for (; p2 != lim && *p2 == p2[dif]; p2++);
+ for (; p2 != lim && *p2 == p2[dif]; p2++)
+ {}
return (unsigned)(p2 - p1);
}
}
@@ -977,7 +1037,7 @@ static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes)
+ GET_PRICE_1(p->isRep[state]) \
+ GET_PRICE_0(p->isRepG0[state])
-
+MY_FORCE_INLINE
static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState)
{
UInt32 price;
@@ -1011,14 +1071,14 @@ static unsigned Backward(CLzmaEnc *p, unsigned cur)
for (;;)
{
UInt32 dist = p->opt[cur].dist;
- UInt32 len = p->opt[cur].len;
- UInt32 extra = p->opt[cur].extra;
+ unsigned len = (unsigned)p->opt[cur].len;
+ unsigned extra = (unsigned)p->opt[cur].extra;
cur -= len;
if (extra)
{
wr--;
- p->opt[wr].len = len;
+ p->opt[wr].len = (UInt32)len;
cur -= extra;
len = extra;
if (extra == 1)
@@ -1045,7 +1105,7 @@ static unsigned Backward(CLzmaEnc *p, unsigned cur)
wr--;
p->opt[wr].dist = dist;
- p->opt[wr].len = len;
+ p->opt[wr].len = (UInt32)len;
}
}
@@ -1102,7 +1162,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
repLens[i] = 0;
continue;
}
- for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++)
+ {}
repLens[i] = len;
if (len > repLens[repMaxIndex])
repMaxIndex = i;
@@ -1111,7 +1172,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
if (repLens[repMaxIndex] >= p->numFastBytes)
{
unsigned len;
- p->backRes = repMaxIndex;
+ p->backRes = (UInt32)repMaxIndex;
len = repLens[repMaxIndex];
MOVE_POS(p, len - 1)
return len;
@@ -1129,7 +1190,11 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
curByte = *data;
matchByte = *(data - reps[0]);
- if (mainLen < 2 && curByte != matchByte && repLens[repMaxIndex] < 2)
+ last = repLens[repMaxIndex];
+ if (last <= mainLen)
+ last = mainLen;
+
+ if (last < 2 && curByte != matchByte)
{
p->backRes = MARK_LIT;
return 1;
@@ -1152,7 +1217,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
- if (matchByte == curByte)
+ // 18.06
+ if (matchByte == curByte && repLens[0] == 0)
{
UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState);
if (shortRepPrice < p->opt[1].price)
@@ -1160,14 +1226,11 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
p->opt[1].price = shortRepPrice;
MakeAs_ShortRep(&p->opt[1]);
}
- }
-
- last = (mainLen >= repLens[repMaxIndex] ? mainLen : repLens[repMaxIndex]);
-
- if (last < 2)
- {
- p->backRes = p->opt[1].dist;
- return 1;
+ if (last < 2)
+ {
+ p->backRes = p->opt[1].dist;
+ return 1;
+ }
}
p->opt[1].len = 1;
@@ -1177,13 +1240,6 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
p->opt[0].reps[2] = reps[2];
p->opt[0].reps[3] = reps[3];
- {
- unsigned len = last;
- do
- p->opt[len--].price = kInfinityPrice;
- while (len >= 2);
- }
-
// ---------- REP ----------
for (i = 0; i < LZMA_NUM_REPS; i++)
@@ -1195,13 +1251,13 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState);
do
{
- UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)repLen - 2];
+ UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen);
COptimal *opt = &p->opt[repLen];
if (price2 < opt->price)
{
opt->price = price2;
- opt->len = repLen;
- opt->dist = i;
+ opt->len = (UInt32)repLen;
+ opt->dist = (UInt32)i;
opt->extra = 0;
}
}
@@ -1211,38 +1267,41 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
// ---------- MATCH ----------
{
- unsigned len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
+ unsigned len = repLens[0] + 1;
if (len <= mainLen)
{
unsigned offs = 0;
UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
- while (len > matches[offs])
- offs += 2;
+ if (len < 2)
+ len = 2;
+ else
+ while (len > matches[offs])
+ offs += 2;
for (; ; len++)
{
COptimal *opt;
UInt32 dist = matches[(size_t)offs + 1];
- UInt32 price2 = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
+ UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
unsigned lenToPosState = GetLenToPosState(len);
if (dist < kNumFullDistances)
- price2 += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
+ price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
else
{
unsigned slot;
GetPosSlot2(dist, slot);
- price2 += p->alignPrices[dist & kAlignMask];
- price2 += p->posSlotPrices[lenToPosState][slot];
+ price += p->alignPrices[dist & kAlignMask];
+ price += p->posSlotPrices[lenToPosState][slot];
}
opt = &p->opt[len];
- if (price2 < opt->price)
+ if (price < opt->price)
{
- opt->price = price2;
- opt->len = len;
+ opt->price = price;
+ opt->len = (UInt32)len;
opt->dist = dist + LZMA_NUM_REPS;
opt->extra = 0;
}
@@ -1277,16 +1336,43 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
for (;;)
{
- UInt32 numAvail, numAvailFull;
+ unsigned numAvail;
+ UInt32 numAvailFull;
unsigned newLen, numPairs, prev, state, posState, startLen;
- UInt32 curPrice, litPrice, matchPrice, repMatchPrice;
- Bool nextIsLit;
+ UInt32 litPrice, matchPrice, repMatchPrice;
+ BoolInt nextIsLit;
Byte curByte, matchByte;
const Byte *data;
COptimal *curOpt, *nextOpt;
if (++cur == last)
- return Backward(p, cur);
+ break;
+
+ // 18.06
+ if (cur >= kNumOpts - 64)
+ {
+ unsigned j, best;
+ UInt32 price = p->opt[cur].price;
+ best = cur;
+ for (j = cur + 1; j <= last; j++)
+ {
+ UInt32 price2 = p->opt[j].price;
+ if (price >= price2)
+ {
+ price = price2;
+ best = j;
+ }
+ }
+ {
+ unsigned delta = best - cur;
+ if (delta != 0)
+ {
+ MOVE_POS(p, delta);
+ }
+ }
+ cur = best;
+ break;
+ }
newLen = ReadMatchDistances(p, &numPairs);
@@ -1294,15 +1380,24 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
{
p->numPairs = numPairs;
p->longestMatchLen = newLen;
- return Backward(p, cur);
+ break;
}
curOpt = &p->opt[cur];
+
+ position++;
+
+ // we need that check here, if skip_items in p->opt are possible
+ /*
+ if (curOpt->price >= kInfinityPrice)
+ continue;
+ */
+
prev = cur - curOpt->len;
if (curOpt->len == 1)
{
- state = p->opt[prev].state;
+ state = (unsigned)p->opt[prev].state;
if (IsShortRep(curOpt))
state = kShortRepNextStates[state];
else
@@ -1316,14 +1411,14 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
if (curOpt->extra)
{
- prev -= curOpt->extra;
+ prev -= (unsigned)curOpt->extra;
state = kState_RepAfterLit;
if (curOpt->extra == 1)
- state = (dist < LZMA_NUM_REPS) ? kState_RepAfterLit : kState_MatchAfterLit;
+ state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit);
}
else
{
- state = p->opt[prev].state;
+ state = (unsigned)p->opt[prev].state;
if (dist < LZMA_NUM_REPS)
state = kRepNextStates[state];
else
@@ -1379,7 +1474,6 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
curByte = *data;
matchByte = *(data - reps[0]);
- position++;
posState = (position & p->pbMask);
/*
@@ -1391,13 +1485,25 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
< MATCH [ : LIT : REP_0 ]
*/
- curPrice = curOpt->price;
- litPrice = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
+ {
+ UInt32 curPrice = curOpt->price;
+ unsigned prob = p->isMatch[state][posState];
+ matchPrice = curPrice + GET_PRICE_1(prob);
+ litPrice = curPrice + GET_PRICE_0(prob);
+ }
nextOpt = &p->opt[(size_t)cur + 1];
nextIsLit = False;
- // if (litPrice >= nextOpt->price) litPrice = 0; else // 18.new
+ // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice)
+ // 18.new.06
+ if ((nextOpt->price < kInfinityPrice
+ // && !IsLitState(state)
+ && matchByte == curByte)
+ || litPrice > nextOpt->price
+ )
+ litPrice = 0;
+ else
{
const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
litPrice += (!IsLitState(state) ?
@@ -1413,21 +1519,32 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
}
}
- matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
+ numAvailFull = p->numAvail;
+ {
+ unsigned temp = kNumOpts - 1 - cur;
+ if (numAvailFull > temp)
+ numAvailFull = (UInt32)temp;
+ }
+
+ // 18.06
// ---------- SHORT_REP ----------
- // if (IsLitState(state)) // 18.new
+ if (IsLitState(state)) // 18.new
if (matchByte == curByte)
- // if (repMatchPrice < nextOpt->price) // 18.new
- if (nextOpt->len < 2
+ if (repMatchPrice < nextOpt->price) // 18.new
+ // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1))
+ if (
+ // nextOpt->price >= kInfinityPrice ||
+ nextOpt->len < 2 // we can check nextOpt->len, if skip items are not allowed in p->opt
|| (nextOpt->dist != 0
- && nextOpt->extra <= 1 // 17.old
- ))
+ // && nextOpt->extra <= 1 // 17.old
+ )
+ )
{
UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState);
- if (shortRepPrice <= nextOpt->price) // 17.old
- // if (shortRepPrice < nextOpt->price) // 18.new
+ // if (shortRepPrice <= nextOpt->price) // 17.old
+ if (shortRepPrice < nextOpt->price) // 18.new
{
nextOpt->price = shortRepPrice;
nextOpt->len = 1;
@@ -1436,13 +1553,6 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
}
}
- numAvailFull = p->numAvail;
- {
- UInt32 temp = kNumOpts - 1 - cur;
- if (numAvailFull > temp)
- numAvailFull = temp;
- }
-
if (numAvailFull < 2)
continue;
numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes);
@@ -1451,9 +1561,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
// ---------- LIT : REP_0 ----------
- if (
- // litPrice != 0 && // 18.new
- !nextIsLit
+ if (!nextIsLit
+ && litPrice != 0 // 18.new
&& matchByte != curByte
&& numAvailFull > 2)
{
@@ -1465,8 +1574,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
if (limit > numAvailFull)
limit = numAvailFull;
for (len = 3; len < limit && data[len] == data2[len]; len++)
- {
- }
+ {}
{
unsigned state2 = kLiteralNextStates[state];
@@ -1474,8 +1582,9 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2);
{
unsigned offset = cur + len;
- while (last < offset)
- p->opt[++last].price = kInfinityPrice;
+
+ if (last < offset)
+ last = offset;
// do
{
@@ -1483,14 +1592,14 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
COptimal *opt;
len--;
// price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2);
- price2 = price + p->repLenEnc.prices[posState2][len - LZMA_MATCH_LEN_MIN];
+ price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len);
opt = &p->opt[offset];
// offset--;
if (price2 < opt->price)
{
opt->price = price2;
- opt->len = len;
+ opt->len = (UInt32)len;
opt->dist = 0;
opt->extra = 1;
}
@@ -1502,6 +1611,7 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
}
startLen = 2; /* speed optimization */
+
{
// ---------- REP ----------
unsigned repIndex = 0; // 17.old
@@ -1514,24 +1624,28 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
if (data[0] != data2[0] || data[1] != data2[1])
continue;
- for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++)
+ {}
// if (len < startLen) continue; // 18.new: speed optimization
- while (last < cur + len)
- p->opt[++last].price = kInfinityPrice;
+ {
+ unsigned offset = cur + len;
+ if (last < offset)
+ last = offset;
+ }
{
unsigned len2 = len;
price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState);
do
{
- UInt32 price2 = price + p->repLenEnc.prices[posState][(size_t)len2 - 2];
+ UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2);
COptimal *opt = &p->opt[cur + len2];
if (price2 < opt->price)
{
opt->price = price2;
- opt->len = len2;
- opt->dist = repIndex;
+ opt->len = (UInt32)len2;
+ opt->dist = (UInt32)repIndex;
opt->extra = 0;
}
}
@@ -1551,15 +1665,14 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
if (limit > numAvailFull)
limit = numAvailFull;
- for (; len2 < limit && data[len2] == data2[len2]; len2++);
-
- len2 -= len;
- if (len2 >= 3)
+ len2 += 2;
+ if (len2 <= limit)
+ if (data[len2 - 2] == data2[len2 - 2])
+ if (data[len2 - 1] == data2[len2 - 1])
{
unsigned state2 = kRepNextStates[state];
unsigned posState2 = (position + len) & p->pbMask;
- price +=
- p->repLenEnc.prices[posState][(size_t)len - 2]
+ price += GET_PRICE_LEN(&p->repLenEnc, posState, len)
+ GET_PRICE_0(p->isMatch[state2][posState2])
+ LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]),
data[len], data2[len], p->ProbPrices);
@@ -1570,31 +1683,40 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
price += GetPrice_Rep_0(p, state2, posState2);
+
+ for (; len2 < limit && data[len2] == data2[len2]; len2++)
+ {}
+
+ len2 -= len;
+ // if (len2 >= 3)
+ {
{
unsigned offset = cur + len + len2;
- while (last < offset)
- p->opt[++last].price = kInfinityPrice;
+
+ if (last < offset)
+ last = offset;
// do
{
- unsigned price2;
+ UInt32 price2;
COptimal *opt;
len2--;
// price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
- price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
+ price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
opt = &p->opt[offset];
// offset--;
if (price2 < opt->price)
{
opt->price = price2;
- opt->len = len2;
+ opt->len = (UInt32)len2;
opt->extra = (CExtra)(len + 1);
- opt->dist = repIndex;
+ opt->dist = (UInt32)repIndex;
}
}
// while (len2 >= 3);
}
}
+ }
}
}
}
@@ -1606,17 +1728,23 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
{
newLen = numAvail;
for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2);
- matches[numPairs] = newLen;
+ matches[numPairs] = (UInt32)newLen;
numPairs += 2;
}
+ // startLen = 2; /* speed optimization */
+
if (newLen >= startLen)
{
UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
UInt32 dist;
unsigned offs, posSlot, len;
- while (last < cur + newLen)
- p->opt[++last].price = kInfinityPrice;
+
+ {
+ unsigned offset = cur + newLen;
+ if (last < offset)
+ last = offset;
+ }
offs = 0;
while (startLen > matches[offs])
@@ -1628,27 +1756,29 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
for (len = /*2*/ startLen; ; len++)
{
- UInt32 price = normalMatchPrice + p->lenEnc.prices[posState][(size_t)len - LZMA_MATCH_LEN_MIN];
+ UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len);
{
COptimal *opt;
- unsigned lenToPosState = len - 2; lenToPosState = GetLenToPosState2(lenToPosState);
+ unsigned lenNorm = len - 2;
+ lenNorm = GetLenToPosState2(lenNorm);
if (dist < kNumFullDistances)
- price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)];
+ price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)];
else
- price += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[dist & kAlignMask];
+ price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask];
opt = &p->opt[cur + len];
if (price < opt->price)
{
opt->price = price;
- opt->len = len;
+ opt->len = (UInt32)len;
opt->dist = dist + LZMA_NUM_REPS;
opt->extra = 0;
}
}
- if (/*_maxMode && */ len == matches[offs])
+ if (len == matches[offs])
{
+ // if (p->_maxMode) {
// MATCH : LIT : REP_0
const Byte *data2 = data - dist - 1;
@@ -1657,11 +1787,17 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
if (limit > numAvailFull)
limit = numAvailFull;
- for (; len2 < limit && data[len2] == data2[len2]; len2++);
+ len2 += 2;
+ if (len2 <= limit)
+ if (data[len2 - 2] == data2[len2 - 2])
+ if (data[len2 - 1] == data2[len2 - 1])
+ {
+ for (; len2 < limit && data[len2] == data2[len2]; len2++)
+ {}
len2 -= len;
- if (len2 >= 3)
+ // if (len2 >= 3)
{
unsigned state2 = kMatchNextStates[state];
unsigned posState2 = (position + len) & p->pbMask;
@@ -1677,21 +1813,22 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
price += GetPrice_Rep_0(p, state2, posState2);
offset = cur + len + len2;
- while (last < offset)
- p->opt[++last].price = kInfinityPrice;
+
+ if (last < offset)
+ last = offset;
// do
{
UInt32 price2;
COptimal *opt;
len2--;
// price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2);
- price2 = price + p->repLenEnc.prices[posState2][len2 - LZMA_MATCH_LEN_MIN];
+ price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2);
opt = &p->opt[offset];
// offset--;
if (price2 < opt->price)
{
opt->price = price2;
- opt->len = len2;
+ opt->len = (UInt32)len2;
opt->extra = (CExtra)(len + 1);
opt->dist = dist + LZMA_NUM_REPS;
}
@@ -1699,6 +1836,8 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
// while (len2 >= 3);
}
+ }
+
offs += 2;
if (offs == numPairs)
break;
@@ -1709,6 +1848,12 @@ static unsigned GetOptimum(CLzmaEnc *p, UInt32 position)
}
}
}
+
+ do
+ p->opt[last].price = kInfinityPrice;
+ while (--last);
+
+ return Backward(p, cur);
}
@@ -1735,6 +1880,7 @@ static unsigned GetOptimumFast(CLzmaEnc *p)
p->backRes = MARK_LIT;
if (numAvail < 2)
return 1;
+ // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused
if (numAvail > LZMA_MATCH_LEN_MAX)
numAvail = LZMA_MATCH_LEN_MAX;
data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
@@ -1746,10 +1892,11 @@ static unsigned GetOptimumFast(CLzmaEnc *p)
const Byte *data2 = data - p->reps[i];
if (data[0] != data2[0] || data[1] != data2[1])
continue;
- for (len = 2; len < numAvail && data[len] == data2[len]; len++);
+ for (len = 2; len < numAvail && data[len] == data2[len]; len++)
+ {}
if (len >= p->numFastBytes)
{
- p->backRes = i;
+ p->backRes = (UInt32)i;
MOVE_POS(p, len - 1)
return len;
}
@@ -1793,7 +1940,7 @@ static unsigned GetOptimumFast(CLzmaEnc *p)
|| (repLen + 2 >= mainLen && mainDist >= (1 << 9))
|| (repLen + 3 >= mainLen && mainDist >= (1 << 15)))
{
- p->backRes = repIndex;
+ p->backRes = (UInt32)repIndex;
MOVE_POS(p, repLen - 1)
return repLen;
}
@@ -1932,23 +2079,22 @@ MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
}
-
-static void FillAlignPrices(CLzmaEnc *p)
+MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p)
{
unsigned i;
const CProbPrice *ProbPrices = p->ProbPrices;
const CLzmaProb *probs = p->posAlignEncoder;
- p->alignPriceCount = 0;
+ // p->alignPriceCount = 0;
for (i = 0; i < kAlignTableSize / 2; i++)
{
UInt32 price = 0;
- unsigned symbol = i;
+ unsigned sym = i;
unsigned m = 1;
unsigned bit;
UInt32 prob;
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit;
prob = probs[m];
p->alignPrices[i ] = price + GET_PRICEa_0(prob);
p->alignPrices[i + 8] = price + GET_PRICEa_1(prob);
@@ -1957,78 +2103,97 @@ static void FillAlignPrices(CLzmaEnc *p)
}
-static void FillDistancesPrices(CLzmaEnc *p)
+MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p)
{
+ // int y; for (y = 0; y < 100; y++) {
+
UInt32 tempPrices[kNumFullDistances];
- unsigned i, lenToPosState;
+ unsigned i, lps;
const CProbPrice *ProbPrices = p->ProbPrices;
p->matchPriceCount = 0;
- for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
+ for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++)
{
unsigned posSlot = GetPosSlot1(i);
- unsigned footerBits = ((posSlot >> 1) - 1);
+ unsigned footerBits = (posSlot >> 1) - 1;
unsigned base = ((2 | (posSlot & 1)) << footerBits);
+ const CLzmaProb *probs = p->posEncoders + (size_t)base * 2;
// tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices);
-
- const CLzmaProb *probs = p->posEncoders + base;
UInt32 price = 0;
unsigned m = 1;
- unsigned symbol = i - base;
+ unsigned sym = i;
+ unsigned offset = (unsigned)1 << footerBits;
+ base += i;
+
+ if (footerBits)
do
{
- unsigned bit = symbol & 1;
- symbol >>= 1;
+ unsigned bit = sym & 1;
+ sym >>= 1;
price += GET_PRICEa(probs[m], bit);
m = (m << 1) + bit;
}
while (--footerBits);
- tempPrices[i] = price;
+
+ {
+ unsigned prob = probs[m];
+ tempPrices[base ] = price + GET_PRICEa_0(prob);
+ tempPrices[base + offset] = price + GET_PRICEa_1(prob);
+ }
}
- for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
+ for (lps = 0; lps < kNumLenToPosStates; lps++)
{
- unsigned posSlot;
- const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
- UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
- unsigned distTableSize = p->distTableSize;
- const CLzmaProb *probs = encoder;
- for (posSlot = 0; posSlot < distTableSize; posSlot += 2)
+ unsigned slot;
+ unsigned distTableSize2 = (p->distTableSize + 1) >> 1;
+ UInt32 *posSlotPrices = p->posSlotPrices[lps];
+ const CLzmaProb *probs = p->posSlotEncoder[lps];
+
+ for (slot = 0; slot < distTableSize2; slot++)
{
- // posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
- UInt32 price = 0;
+ // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices);
+ UInt32 price;
unsigned bit;
- unsigned symbol = (posSlot >> 1) + (1 << (kNumPosSlotBits - 1));
- UInt32 prob;
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
- bit = symbol & 1; symbol >>= 1; price += GET_PRICEa(probs[symbol], bit);
- prob = probs[(posSlot >> 1) + (1 << (kNumPosSlotBits - 1))];
- posSlotPrices[posSlot ] = price + GET_PRICEa_0(prob);
- posSlotPrices[posSlot + 1] = price + GET_PRICEa_1(prob);
+ unsigned sym = slot + (1 << (kNumPosSlotBits - 1));
+ unsigned prob;
+ bit = sym & 1; sym >>= 1; price = GET_PRICEa(probs[sym], bit);
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
+ bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit);
+ prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))];
+ posSlotPrices[(size_t)slot * 2 ] = price + GET_PRICEa_0(prob);
+ posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob);
}
- for (posSlot = kEndPosModelIndex; posSlot < distTableSize; posSlot++)
- posSlotPrices[posSlot] += ((UInt32)(((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
{
- UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
+ UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
+ for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++)
{
- distancesPrices[0] = posSlotPrices[0];
- distancesPrices[1] = posSlotPrices[1];
- distancesPrices[2] = posSlotPrices[2];
- distancesPrices[3] = posSlotPrices[3];
+ posSlotPrices[(size_t)slot * 2 ] += delta;
+ posSlotPrices[(size_t)slot * 2 + 1] += delta;
+ delta += ((UInt32)1 << kNumBitPriceShiftBits);
}
+ }
+
+ {
+ UInt32 *dp = p->distancesPrices[lps];
+
+ dp[0] = posSlotPrices[0];
+ dp[1] = posSlotPrices[1];
+ dp[2] = posSlotPrices[2];
+ dp[3] = posSlotPrices[3];
+
for (i = 4; i < kNumFullDistances; i += 2)
{
UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)];
- distancesPrices[i ] = slotPrice + tempPrices[i];
- distancesPrices[i + 1] = slotPrice + tempPrices[i + 1];
+ dp[i ] = slotPrice + tempPrices[i];
+ dp[i + 1] = slotPrice + tempPrices[i + 1];
}
}
}
+ // }
}
@@ -2245,10 +2410,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
if (len != 1)
{
LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
- if (!p->fastMode)
- if (--p->repLenEnc.counters[posState] == 0)
- LenPriceEnc_UpdateTable(&p->repLenEnc, posState, &p->repLenProbs, p->ProbPrices);
-
+ --p->repLenEncCounter;
p->state = kRepNextStates[p->state];
}
}
@@ -2260,9 +2422,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
p->state = kMatchNextStates[p->state];
LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState);
- if (!p->fastMode)
- if (--p->lenEnc.counters[posState] == 0)
- LenPriceEnc_UpdateTable(&p->lenEnc, posState, &p->lenProbs, p->ProbPrices);
+ // --p->lenEnc.counter;
dist -= LZMA_NUM_REPS;
p->reps[3] = p->reps[2];
@@ -2274,17 +2434,17 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
GetPosSlot(dist, posSlot);
// RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot);
{
- UInt32 symbol = posSlot + (1 << kNumPosSlotBits);
+ UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits);
range = p->rc.range;
probs = p->posSlotEncoder[GetLenToPosState(len)];
do
{
- CLzmaProb *prob = probs + (symbol >> kNumPosSlotBits);
- UInt32 bit = (symbol >> (kNumPosSlotBits - 1)) & 1;
- symbol <<= 1;
+ CLzmaProb *prob = probs + (sym >> kNumPosSlotBits);
+ UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1;
+ sym <<= 1;
RC_BIT(&p->rc, prob, bit);
}
- while (symbol < (1 << kNumPosSlotBits * 2));
+ while (sym < (1 << kNumPosSlotBits * 2));
p->rc.range = range;
}
@@ -2295,7 +2455,7 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
if (dist < kNumFullDistances)
{
unsigned base = ((2 | (posSlot & 1)) << footerBits);
- RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, dist - base);
+ RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */));
}
else
{
@@ -2331,14 +2491,14 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit;
bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit);
p->rc.range = range;
- p->alignPriceCount++;
+ // p->alignPriceCount++;
}
}
}
}
}
- nowPos32 += len;
+ nowPos32 += (UInt32)len;
p->additionalOffset -= len;
if (p->additionalOffset == 0)
@@ -2347,10 +2507,27 @@ static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpa
if (!p->fastMode)
{
- if (p->matchPriceCount >= (1 << 7))
+ /*
+ if (p->alignPriceCount >= 16) // kAlignTableSize
+ FillAlignPrices(p);
+ if (p->matchPriceCount >= 128)
FillDistancesPrices(p);
- if (p->alignPriceCount >= kAlignTableSize)
+ if (p->lenEnc.counter <= 0)
+ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
+ */
+ if (p->matchPriceCount >= 64)
+ {
FillAlignPrices(p);
+ // { int y; for (y = 0; y < 100; y++) {
+ FillDistancesPrices(p);
+ // }}
+ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
+ }
+ if (p->repLenEncCounter <= 0)
+ {
+ p->repLenEncCounter = REP_LEN_COUNT;
+ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
+ }
}
if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
@@ -2490,12 +2667,19 @@ void LzmaEnc_Init(CLzmaEnc *p)
p->optEnd = 0;
p->optCur = 0;
+
+ {
+ for (i = 0; i < kNumOpts; i++)
+ p->opt[i].price = kInfinityPrice;
+ }
+
p->additionalOffset = 0;
p->pbMask = (1 << p->pb) - 1;
p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc);
}
+
void LzmaEnc_InitPrices(CLzmaEnc *p)
{
if (!p->fastMode)
@@ -2507,6 +2691,9 @@ void LzmaEnc_InitPrices(CLzmaEnc *p)
p->lenEnc.tableSize =
p->repLenEnc.tableSize =
p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
+
+ p->repLenEncCounter = REP_LEN_COUNT;
+
LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices);
LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices);
}
@@ -2583,7 +2770,7 @@ typedef struct
ISeqOutStream vt;
Byte *data;
SizeT rem;
- Bool overflow;
+ BoolInt overflow;
} CLzmaEnc_SeqOutStreamBuf;
static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size)
@@ -2615,7 +2802,7 @@ const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
}
-SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
+SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit,
Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
{
CLzmaEnc *p = (CLzmaEnc *)pp;
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt
index 422a09d9d29..e82fd33c0a6 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt
@@ -1,6 +1,28 @@
HISTORY of the LZMA SDK
-----------------------
+19.00 2019-02-21
+-------------------------
+- Encryption strength for 7z archives was increased:
+ the size of random initialization vector was increased from 64-bit to 128-bit,
+ and the pseudo-random number generator was improved.
+- The bug in 7zIn.c code was fixed.
+
+
+18.06 2018-12-30
+-------------------------
+- The speed for LZMA/LZMA2 compressing was increased by 3-10%,
+ and there are minor changes in compression ratio.
+- Some bugs were fixed.
+- The bug in 7-Zip 18.02-18.05 was fixed:
+ There was memory leak in multithreading xz decoder - XzDecMt_Decode(),
+ if xz stream contains only one block.
+- The changes for MSVS compiler makefiles:
+ - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64)
+ instead of "CPU" macroname with values (AMD64, ARM64).
+ - the makefiles by default now use static version of the run-time library.
+
+
18.05 2018-04-30
-------------------------
- The speed for LZMA/LZMA2 compressing was increased
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt
index fb7424b66e7..abe578ff6d4 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt
@@ -1,4 +1,4 @@
-LZMA SDK 18.05
+LZMA SDK 19.00
--------------
LZMA SDK provides the documentation, samples, header files,
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile
index 038a4e2f0c8..25875fe7791 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile
@@ -19,7 +19,6 @@ APPLICATIONS = \
GenFw \
GenSec \
LzmaCompress \
- Split \
TianoCompress \
VolInfo \
DevicePath
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk
index d20959a8db5..c8d249e4cfb 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk
@@ -34,7 +34,6 @@ include $(PATH_SUB_CURRENT)/LzmaCompress/Makefile.kmk
include $(PATH_SUB_CURRENT)/GenFw/Makefile.kmk
include $(PATH_SUB_CURRENT)/TianoCompress/Makefile.kmk
include $(PATH_SUB_CURRENT)/EfiRom/Makefile.kmk
-include $(PATH_SUB_CURRENT)/Split/Makefile.kmk
include $(PATH_SUB_CURRENT)/GenSec/Makefile.kmk
include $(PATH_SUB_CURRENT)/GenFfs/Makefile.kmk
include $(PATH_SUB_CURRENT)/GenCrc32/Makefile.kmk
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py
index 56bc37a3897..155eb2235f9 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py
@@ -45,7 +45,10 @@ def RunCommand(WorkDir=None, *Args, **kwargs):
output_lock.acquire(True)
print("execute command \"{0}\" in directory {1}".format(" ".join(Args), WorkDir))
- print(message)
+ try:
+ print(message)
+ except:
+ pass
output_lock.release()
return p.returncode, stdout
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile
index ed5d75af868..45c935958ac 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile
@@ -28,6 +28,9 @@ ifndef HOST_ARCH
else ifneq (,$(findstring arm,$(uname_m)))
HOST_ARCH=ARM
endif
+ ifneq (,$(findstring riscv64,$(uname_m)))
+ HOST_ARCH=RISCV64
+ endif
ifndef HOST_ARCH
$(info Could not detected HOST_ARCH from uname results)
$(error HOST_ARCH is not defined!)
@@ -38,12 +41,19 @@ endif
CYGWIN:=$(findstring CYGWIN, $(shell uname -s))
LINUX:=$(findstring Linux, $(shell uname -s))
DARWIN:=$(findstring Darwin, $(shell uname -s))
-
+ifeq ($(CXX), llvm)
+BUILD_CC ?= $(CLANG_BIN)clang
+BUILD_CXX ?= $(CLANG_BIN)clang++
+BUILD_AS ?= $(CLANG_BIN)clang
+BUILD_AR ?= $(CLANG_BIN)llvm-ar
+BUILD_LD ?= $(CLANG_BIN)llvm-ld
+else
BUILD_CC ?= gcc
BUILD_CXX ?= g++
BUILD_AS ?= gcc
BUILD_AR ?= ar
BUILD_LD ?= ld
+endif
LINKER ?= $(BUILD_CC)
ifeq ($(HOST_ARCH), IA32)
ARCH_INCLUDE = -I $(MAKEROOT)/Include/Ia32/
@@ -57,6 +67,9 @@ ARCH_INCLUDE = -I $(MAKEROOT)/Include/Arm/
else ifeq ($(HOST_ARCH), AARCH64)
ARCH_INCLUDE = -I $(MAKEROOT)/Include/AArch64/
+else ifeq ($(HOST_ARCH), RISCV64)
+ARCH_INCLUDE = -I $(MAKEROOT)/Include/RiscV64/
+
else
$(error Bad HOST_ARCH)
endif
@@ -72,14 +85,25 @@ ifeq ($(DARWIN),Darwin)
BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror \
-Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g
else
+ifeq ($(CXX), llvm)
+BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
+-fno-delete-null-pointer-checks -Wall -Werror \
+-Wno-deprecated-declarations -Wno-self-assign \
+-Wno-unused-result -nostdlib -g
+else
BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \
-fno-delete-null-pointer-checks -Wall -Werror \
-Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict \
-Wno-unused-result -nostdlib -g
endif
+endif
+ifeq ($(CXX), llvm)
+BUILD_LFLAGS =
+BUILD_CXXFLAGS = -Wno-deprecated-register -Wno-unused-result
+else
BUILD_LFLAGS =
BUILD_CXXFLAGS = -Wno-unused-result
-
+endif
ifeq ($(HOST_ARCH), IA32)
#
# Snow Leopard is a 32-bit and 64-bit environment. uname -m returns i386, but gcc defaults
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common
index 9db6f46636e..695da7a3d1b 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common
@@ -55,7 +55,7 @@ AR = lib.exe
LD = link.exe
LINKER = $(LD)
-INC = -I . -I $(SOURCE_PATH)\Include -I $(ARCH_INCLUDE) -I $(SOURCE_PATH)\Common $(INC)
+INC = $(INC) -I . -I $(SOURCE_PATH)\Include -I $(ARCH_INCLUDE) -I $(SOURCE_PATH)\Common
CFLAGS = $(CFLAGS) /nologo /Zi /c /O2 /MT /W4 /WX /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE
CPPFLAGS = $(CPPFLAGS) /EHsc /nologo /Zi /c /O2 /MT /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/GNUmakefile
deleted file mode 100644
index 225e7da78a5..00000000000
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/GNUmakefile
+++ /dev/null
@@ -1,17 +0,0 @@
-## @file
-# GNU/Linux makefile for 'Split' module build.
-#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-MAKEROOT ?= ..
-
-APPNAME = Split
-
-OBJECTS = Split.o
-
-include $(MAKEROOT)/Makefiles/app.makefile
-
-LIBS = -lCommon
-
-
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile
deleted file mode 100644
index 1975f983fa9..00000000000
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-## @file
-# Windows makefile for 'Split' module build.
-#
-# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-!INCLUDE ..\Makefiles\ms.common
-
-APPNAME = Split
-
-LIBS = $(LIB_PATH)\Common.lib
-
-OBJECTS = Split.obj
-
-!INCLUDE ..\Makefiles\ms.app
-
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile.kmk
deleted file mode 100644
index 80632ce7e65..00000000000
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Makefile.kmk
+++ /dev/null
@@ -1,35 +0,0 @@
-# $Id$
-## @file
-# Sub-makefile for the EFI Split build tool.
-#
-
-#
-# Copyright (C) 2013-2020 Oracle Corporation
-#
-# This file is part of VirtualBox Open Source Edition (OSE), as
-# available from http://www.virtualbox.org. This file is free software;
-# you can redistribute it and/or modify it under the terms of the GNU
-# General Public License (GPL) as published by the Free Software
-# Foundation, in version 2 as it comes in the "COPYING" file of the
-# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
-# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
-#
-# The contents of this file may alternatively be used under the terms
-# of the Common Development and Distribution License Version 1.0
-# (CDDL) only, as it comes in the "COPYING.CDDL" file of the
-# VirtualBox OSE distribution, in which case the provisions of the
-# CDDL are applicable instead of those of the GPL.
-#
-# You may elect to license modified versions of this file under the
-# terms and conditions of either the GPL or the CDDL or both.
-#
-
-SUB_DEPTH = ../../../../../../../../..
-include $(KBUILD_PATH)/subheader.kmk
-
-BLDPROGS += Split
-Split_TEMPLATE = VBoxEfiBldProg
-Split_SOURCES = Split.c
-
-include $(FILE_KBUILD_SUB_FOOTER)
-
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Split.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Split.c
deleted file mode 100644
index 016aeeb79f0..00000000000
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Split/Split.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/** @file
-
- Split a file into two pieces at the request offset.
-
-Copyright (c) 1999 - 2017, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-// GC_TODO: fix comment to start with /*++
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#ifdef __GNUC__
-#include <unistd.h>
-#else
-#include <direct.h>
-#endif
-#include <ctype.h>
-#include "ParseInf.h"
-#include "CommonLib.h"
-#include "EfiUtilityMsgs.h"
-//
-// Utility Name
-//
-#define UTILITY_NAME "Split"
-
-//
-// Utility version information
-//
-#define UTILITY_MAJOR_VERSION 1
-#define UTILITY_MINOR_VERSION 0
-
-void
-Version (
- void
- )
-/*++
-
-Routine Description:
-
- Displays the standard utility information to SDTOUT
-
-Arguments:
-
- None
-
-Returns:
-
- None
-
---*/
-{
- printf ("%s Version %d.%d Build %s\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
-}
-
-void
-Usage (
- void
- )
-/*++
-
-Routine Description:
-
- GC_TODO: Add function description
-
-Arguments:
-
-
-Returns:
-
- GC_TODO: add return values
-
---*/
-{
- Version();
- printf ("Copyright (c) 1999-2017 Intel Corporation. All rights reserved.\n");
- printf ("\n SplitFile creates two Binary files either in the same directory as the current working\n");
- printf (" directory or in the specified directory.\n");
- printf ("\nUsage: \n\
- Split\n\
- -f, --filename inputFile to split\n\
- -s, --split VALUE the number of bytes in the first file\n\
- [-p, --prefix OutputDir]\n\
- [-o, --firstfile Filename1]\n\
- [-t, --secondfile Filename2]\n\
- [-v, --verbose]\n\
- [--version]\n\
- [-q, --quiet disable all messages except fatal errors]\n\
- [-d, --debug[#]\n\
- [-h, --help]\n");
-}
-
-EFI_STATUS
-GetSplitValue (
- IN CONST CHAR8* SplitValueString,
- OUT UINT64 *ReturnValue
-)
-{
- UINT64 len = 0;
- UINT64 base = 1;
- UINT64 index = 0;
- UINT64 number = 0;
- CHAR8 lastCHAR = 0;
- EFI_STATUS Status = EFI_SUCCESS;
-
- if (SplitValueString != NULL){
- len = strlen(SplitValueString);
- }
-
- if (len == 0) {
- return EFI_ABORTED;
- }
-
- Status = AsciiStringToUint64 (SplitValueString, FALSE, ReturnValue);
- if (!EFI_ERROR (Status)) {
- return Status;
- }
-
- if (SplitValueString[0] == '0' && (SplitValueString[1] == 'x' || SplitValueString[1] == 'X')) {
- Status = AsciiStringToUint64 (SplitValueString, TRUE, ReturnValue);
- if (!EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- lastCHAR = (CHAR8)toupper((int)SplitValueString[len - 1]);
-
- if (lastCHAR != 'K' && lastCHAR != 'M' && lastCHAR != 'G') {
- return STATUS_ERROR;
- }
-
- for (;index < len - 1; ++index) {
- if (!isdigit((int)SplitValueString[index])) {
- return EFI_ABORTED;
- }
- }
-
- number = atol (SplitValueString);
- if (lastCHAR == 'K')
- base = 1024;
- else if (lastCHAR == 'M')
- base = 1024*1024;
- else
- base = 1024*1024*1024;
-
- *ReturnValue = number*base;
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-CountVerboseLevel (
- IN CONST CHAR8* VerboseLevelString,
- IN CONST UINT64 Length,
- OUT UINT64 *ReturnValue
-)
-{
- UINT64 i = 0;
- for (;i < Length; ++i) {
- if (VerboseLevelString[i] != 'v' && VerboseLevelString[i] != 'V') {
- return EFI_ABORTED;
- }
- ++(*ReturnValue);
- }
-
- return EFI_SUCCESS;
-}
-
-EFI_STATUS
-CreateDir (
- IN OUT CHAR8** FullFileName
-)
-{
- CHAR8* temp = *FullFileName;
- CHAR8* start = temp;
- CHAR8 tempchar;
- UINT64 index = 0;
-
- for (;index < strlen(temp); ++index) {
- if (temp[index] == '\\' || temp[index] == '/') {
- if (temp[index + 1] != '\0') {
- tempchar = temp[index + 1];
- temp[index + 1] = 0;
- if (chdir(start)) {
- if (mkdir(start, S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
- return EFI_ABORTED;
- }
- chdir(start);
- }
- start = temp + index + 1;
- temp[index] = '/';
- temp[index + 1] = tempchar;
- }
- }
- }
-
- return EFI_SUCCESS;
-}
-
-int
-main (
- int argc,
- char*argv[]
- )
-/*++
-
-Routine Description:
-
- GC_TODO: Add function description
-
-Arguments:
-
- argc - GC_TODO: add argument description
- ] - GC_TODO: add argument description
-
-Returns:
-
- GC_TODO: add return values
-
---*/
-{
- EFI_STATUS Status = EFI_SUCCESS;
- INTN ReturnStatus = STATUS_SUCCESS;
- FILE *In;
- CHAR8 *InputFileName = NULL;
- CHAR8 *OutputDir = NULL;
- CHAR8 *OutFileName1 = NULL;
- CHAR8 *OutFileName2 = NULL;
- UINT64 SplitValue = (UINT64) -1;
- FILE *Out1 = NULL;
- FILE *Out2 = NULL;
- CHAR8 *OutName1 = NULL;
- CHAR8 *OutName2 = NULL;
- CHAR8 *CurrentDir = NULL;
- UINT64 Index;
- CHAR8 CharC;
- UINT64 DebugLevel = 0;
- UINT64 VerboseLevel = 0;
-
- SetUtilityName(UTILITY_NAME);
- if (argc == 1) {
- Usage();
- return STATUS_ERROR;
- }
-
- argc --;
- argv ++;
-
- if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
- Usage();
- return STATUS_SUCCESS;
- }
-
- if (stricmp (argv[0], "--version") == 0) {
- Version();
- return STATUS_SUCCESS;
- }
-
- while (argc > 0) {
- if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--prefix") == 0)) {
- OutputDir = argv[1];
- if (OutputDir == NULL) {
- Warning (NULL, 0, 0, "NO output directory specified.", NULL);
- return STATUS_ERROR;
- }
- argc -= 2;
- argv += 2;
- continue;
- }
-
- if ((stricmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--filename") == 0)) {
- InputFileName = argv[1];
- if (InputFileName == NULL) {
- Error (NULL, 0, 0x1001, "NO Input file specified.", NULL);
- return STATUS_ERROR;
- }
- argc -= 2;
- argv += 2;
- continue;
- }
-
- if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--split") == 0)) {
- Status = GetSplitValue(argv[1], &SplitValue);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 0x1003, "Input split value is not one valid integer.", NULL);
- return STATUS_ERROR;
- }
- argc -= 2;
- argv += 2;
- continue;
- }
-
- if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--firstfile") == 0)) {
- OutFileName1 = argv[1];
- if (OutFileName1 == NULL) {
- Warning (NULL, 0, 0, NULL, "No output file1 specified.");
- }
- argc -= 2;
- argv += 2;
- continue;
- }
-
- if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--secondfile") == 0)) {
- OutFileName2 = argv[1];
- if (OutFileName2 == NULL) {
- Warning (NULL, 0, 0, NULL, "No output file2 specified.");
- }
- argc -= 2;
- argv += 2;
- continue;
- }
-
- if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
- argc --;
- argv ++;
- continue;
- }
-
- if ((strlen(argv[0]) >= 2 && argv[0][0] == '-' && (argv[0][1] == 'v' || argv[0][1] == 'V')) || (stricmp (argv[0], "--verbose") == 0)) {
- VerboseLevel = 1;
- if (strlen(argv[0]) > 2) {
- Status = CountVerboseLevel (&argv[0][2], strlen(argv[0]) - 2, &VerboseLevel);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 0x1003, NULL, "%s is invalid parameter!", argv[0]);
- return STATUS_ERROR;
- }
- }
-
- argc --;
- argv ++;
- continue;
- }
-
- if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
- Status = AsciiStringToUint64 (argv[1], FALSE, &DebugLevel);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 0x1003, "Input debug level is not one valid integrator.", NULL);
- return STATUS_ERROR;
- }
- argc -= 2;
- argv += 2;
- continue;
- }
- //
- // Don't recognize the parameter.
- //
- Error (NULL, 0, 0x1003, NULL, "%s is invalid parameter!", argv[0]);
- return STATUS_ERROR;
- }
-
- if (InputFileName == NULL) {
- Error (NULL, 0, 0x1001, "NO Input file specified.", NULL);
- return STATUS_ERROR;
- }
-
- In = fopen (LongFilePath (InputFileName), "rb");
- if (In == NULL) {
- // ("Unable to open file \"%s\"\n", InputFileName);
- Error (InputFileName, 0, 1, "File open failure", NULL);
- return STATUS_ERROR;
- }
-
- if (OutFileName1 == NULL) {
- OutName1 = (CHAR8*)malloc(strlen(InputFileName) + 16);
- if (OutName1 == NULL) {
- Warning (NULL, 0, 0, NULL, "Memory Allocation Fail.");
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
- strcpy (OutName1, InputFileName);
- strcat (OutName1, "1");
- OutFileName1 = OutName1;
-
- }
- if (OutFileName2 == NULL) {
- OutName2 = (CHAR8*)malloc(strlen(InputFileName) + 16);
- if (OutName2 == NULL) {
- Warning (NULL, 0, 0, NULL, "Memory Allocation Fail.");
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
- strcpy (OutName2, InputFileName);
- strcat (OutName2, "2");
- OutFileName2 = OutName2;
-
- }
-
- if (OutputDir != NULL) {
- //OutputDirSpecified = TRUE;
- if (chdir(OutputDir) != 0) {
- Warning (NULL, 0, 0, NULL, "Change dir to OutputDir Fail.");
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
- }
-
- CurrentDir = (CHAR8*)getcwd((CHAR8*)0, 0);
- if (EFI_ERROR(CreateDir(&OutFileName1))) {
- Error (OutFileName1, 0, 5, "Create Dir for File1 Fail.", NULL);
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
- chdir(CurrentDir);
-
- if (EFI_ERROR(CreateDir(&OutFileName2))) {
- Error (OutFileName2, 0, 5, "Create Dir for File2 Fail.", NULL);
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
- chdir(CurrentDir);
- free(CurrentDir);
-
- Out1 = fopen (LongFilePath (OutFileName1), "wb");
- if (Out1 == NULL) {
- // ("Unable to open file \"%s\"\n", OutFileName1);
- Error (OutFileName1, 0, 1, "File open failure", NULL);
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
-
- Out2 = fopen (LongFilePath (OutFileName2), "wb");
- if (Out2 == NULL) {
- // ("Unable to open file \"%s\"\n", OutFileName2);
- Error (OutFileName2, 0, 1, "File open failure", NULL);
- ReturnStatus = STATUS_ERROR;
- goto Finish;
- }
-
- for (Index = 0; Index < SplitValue; Index++) {
- CharC = (CHAR8) fgetc (In);
- if (feof (In)) {
- break;
- }
-
- fputc (CharC, Out1);
- }
-
- for (;;) {
- CharC = (CHAR8) fgetc (In);
- if (feof (In)) {
- break;
- }
-
- fputc (CharC, Out2);
- }
-
-Finish:
- if (OutName1 != NULL) {
- free(OutName1);
- }
- if (OutName2 != NULL) {
- free(OutName2);
- }
- if (In != NULL) {
- fclose (In);
- }
- if (Out1 != NULL) {
- fclose (Out1);
- }
- if (Out2 != NULL) {
- fclose (Out2);
- }
-
- return ReturnStatus;
-}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile
index 4d5b5050dee..5cf434aee0a 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile
@@ -16,9 +16,11 @@ TOOL_INCLUDE = -I Pccts/h
#OBJECTS = VfrSyntax.o VfrServices.o DLGLexer.o EfiVfrParser.o ATokenBuffer.o DLexerBase.o AParser.o
OBJECTS = AParser.o DLexerBase.o ATokenBuffer.o EfiVfrParser.o VfrLexer.o VfrSyntax.o \
VfrFormPkg.o VfrError.o VfrUtilityLib.o VfrCompiler.o
-
+ifeq ($(CXX), llvm)
+VFR_CPPFLAGS = -Wno-deprecated-register -DPCCTS_USE_NAMESPACE_STD $(BUILD_CPPFLAGS)
+else
VFR_CPPFLAGS = -DPCCTS_USE_NAMESPACE_STD $(BUILD_CPPFLAGS)
-
+endif
# keep BUILD_OPTFLAGS last
VFR_CXXFLAGS = $(BUILD_OPTFLAGS)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile
index 08e68f67a3d..b5b4eb4054c 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile
@@ -164,7 +164,11 @@ PCCTS_H=../h
#
# UNIX (default)
#
+ifeq ($(CXX), llvm)
+BUILD_CC?=$(CLANG_BIN)clang
+else
BUILD_CC?=gcc
+endif
COPT=-O
ANTLR=${BIN_DIR}/antlr
DLG=${BIN_DIR}/dlg
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile
index 47ae93e4fa7..a82a952ac53 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile
@@ -114,7 +114,11 @@ PCCTS_H=../h
#
# UNIX
#
+ifeq ($(CXX), llvm)
+BUILD_CC?=$(CLANG_BIN)clang
+else
BUILD_CC?=cc
+endif
COPT=-O
ANTLR=${BIN_DIR}/antlr
DLG=${BIN_DIR}/dlg
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g
index 7d8d2fa9aad..21bf1cbe133 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g
@@ -192,6 +192,7 @@ VfrParserStart (
#token LateCheckFlag("LATE_CHECK") "LATE_CHECK"
#token ReadOnlyFlag("READ_ONLY") "READ_ONLY"
#token OptionOnlyFlag("OPTIONS_ONLY") "OPTIONS_ONLY"
+#token RestStyleFlag("REST_STYLE") "REST_STYLE"
#token Class("class") "class"
#token Subclass("subclass") "subclass"
#token ClassGuid("classguid") "classguid"
@@ -584,7 +585,7 @@ vfrFormSetDefinition :
<<
EFI_GUID Guid;
EFI_GUID DefaultClassGuid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID;
- EFI_GUID ClassGuid1, ClassGuid2, ClassGuid3;
+ EFI_GUID ClassGuid1, ClassGuid2, ClassGuid3, ClassGuid4;
UINT8 ClassGuidNum = 0;
CIfrFormSet *FSObj = NULL;
UINT16 C, SC;
@@ -600,13 +601,16 @@ vfrFormSetDefinition :
"\|" guidDefinition[ClassGuid2] << ++ClassGuidNum; >>
{
"\|" guidDefinition[ClassGuid3] << ++ClassGuidNum; >>
+ {
+ "\|" guidDefinition[ClassGuid4] << ++ClassGuidNum; >>
+ }
}
}
","
}
<<
- if (mOverrideClassGuid != NULL && ClassGuidNum >= 3) {
- _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "Already has 3 class guids, can't add extra class guid!");
+ if (mOverrideClassGuid != NULL && ClassGuidNum >= 4) {
+ _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "Already has 4 class guids, can't add extra class guid!");
}
switch (ClassGuidNum) {
case 0:
@@ -643,10 +647,23 @@ vfrFormSetDefinition :
}
break;
case 3:
+ if (mOverrideClassGuid != NULL) {
+ ClassGuidNum ++;
+ }
+ FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID));
+ FSObj->SetClassGuid(&ClassGuid1);
+ FSObj->SetClassGuid(&ClassGuid2);
+ FSObj->SetClassGuid(&ClassGuid3);
+ if (mOverrideClassGuid != NULL) {
+ FSObj->SetClassGuid(mOverrideClassGuid);
+ }
+ break;
+ case 4:
FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID));
FSObj->SetClassGuid(&ClassGuid1);
FSObj->SetClassGuid(&ClassGuid2);
FSObj->SetClassGuid(&ClassGuid3);
+ FSObj->SetClassGuid(&ClassGuid4);
break;
default:
break;
@@ -1321,6 +1338,7 @@ questionheaderFlagsField[UINT8 & Flags] :
ReadOnlyFlag << $Flags |= 0x01; >>
| InteractiveFlag << $Flags |= 0x04; >>
| ResetRequiredFlag << $Flags |= 0x10; >>
+ | RestStyleFlag << $Flags |= 0x20; >>
| ReconnectRequiredFlag << $Flags |= 0x40; >>
| O:OptionOnlyFlag <<
gCVfrErrorHandle.HandleWarning (
@@ -3766,6 +3784,7 @@ oneofoptionFlagsField [UINT8 & HFlags, UINT8 & LFlags] :
| "OPTION_DEFAULT_MFG" << $LFlags |= 0x20; >>
| InteractiveFlag << $HFlags |= 0x04; >>
| ResetRequiredFlag << $HFlags |= 0x10; >>
+ | RestStyleFlag << $HFlags |= 0x20; >>
| ReconnectRequiredFlag << $HFlags |= 0x40; >>
| ManufacturingFlag << $LFlags |= 0x20; >>
| DefaultFlag << $LFlags |= 0x10; >>
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c
index 0500f81adef..9f9d92f4568 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c
@@ -1086,7 +1086,7 @@ Returns:
}
if (VolumeHeader.FvLength != Size) {
- printf ("ERROR: Volume Size not consistant with Block Maps!\n");
+ printf ("ERROR: Volume Size not consistent with Block Maps!\n");
return EFI_ABORTED;
}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AmlToHex/AmlToHex.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AmlToC/AmlToC.py
index 88d5df1142d..25477426beb 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AmlToHex/AmlToHex.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AmlToC/AmlToC.py
@@ -1,9 +1,9 @@
## @file
#
-# Convert an AML file to a .hex file containing the AML bytecode stored in a
+# Convert an AML file to a .c file containing the AML bytecode stored in a
# C array.
-# By default, "Tables\Dsdt.aml" will generate "Tables\Dsdt.hex".
-# "Tables\Dsdt.hex" will contain a C array named "dsdt_aml_code" that contains
+# By default, "Tables\Dsdt.aml" will generate "Tables\Dsdt.c".
+# "Tables\Dsdt.c" will contain a C array named "dsdt_aml_code" that contains
# the AML bytecode.
#
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
@@ -17,31 +17,26 @@ from Common.BuildToolError import *
import sys
import os
+__description__ = """
+Convert an AML file to a .c file containing the AML bytecode stored in a C
+array. By default, Tables\Dsdt.aml will generate Tables\Dsdt.c.
+Tables\Dsdt.c will contain a C array named "dsdt_aml_code" that contains
+the AML bytecode.
+"""
+
## Parse the command line arguments.
#
# @retval A argparse.NameSpace instance, containing parsed values.
#
def ParseArgs():
# Initialize the parser.
- Parser = argparse.ArgumentParser(
- description="Convert an AML file to a .hex file containing the AML " + \
- "bytecode stored in a C array. By default, " + \
- "\"Tables\\Dsdt.aml\" will generate" + \
- "\"Tables\\Dsdt.hex\". \"Tables\\Dsdt.hex\" will " + \
- "contain a C array named \"dsdt_aml_code\" that " + \
- "contains the AML bytecode."
- )
+ Parser = argparse.ArgumentParser(description=__description__)
# Define the possible arguments.
- Parser.add_argument(
- dest="InputFile",
- help="Path to an input AML file to generate a .hex file from."
- )
- Parser.add_argument(
- "-o", "--out-dir", dest="OutDir",
- help="Output directory where the .hex file will be generated. " + \
- "Default is the input file's directory."
- )
+ Parser.add_argument(dest="InputFile",
+ help="Path to an input AML file to generate a .c file from.")
+ Parser.add_argument("-o", "--out-dir", dest="OutDir",
+ help="Output directory where the .c file will be generated. Default is the input file's directory.")
# Parse the input arguments.
Args = Parser.parse_args()
@@ -55,9 +50,7 @@ def ParseArgs():
with open(Args.InputFile, "rb") as fIn:
Signature = str(fIn.read(4))
if ("DSDT" not in Signature) and ("SSDT" not in Signature):
- EdkLogger.info("Invalid file type. " + \
- "File does not have a valid " + \
- "DSDT or SSDT signature: %s" % Args.InputFile)
+ EdkLogger.info("Invalid file type. File does not have a valid DSDT or SSDT signature: {}".format(Args.InputFile))
return None
# Get the basename of the input file.
@@ -66,42 +59,39 @@ def ParseArgs():
# If no output directory is specified, output to the input directory.
if not Args.OutDir:
- Args.OutputFile = os.path.join(
- os.path.dirname(Args.InputFile),
- BaseName + ".hex"
- )
+ Args.OutputFile = os.path.join(os.path.dirname(Args.InputFile),
+ BaseName + ".c")
else:
if not os.path.exists(Args.OutDir):
os.mkdir(Args.OutDir)
- Args.OutputFile = os.path.join(Args.OutDir, BaseName + ".hex")
+ Args.OutputFile = os.path.join(Args.OutDir, BaseName + ".c")
Args.BaseName = BaseName
return Args
-## Convert an AML file to a .hex file containing the AML bytecode stored
+## Convert an AML file to a .c file containing the AML bytecode stored
# in a C array.
#
# @param InputFile Path to the input AML file.
-# @param OutputFile Path to the output .hex file to generate.
+# @param OutputFile Path to the output .c file to generate.
# @param BaseName Base name of the input file.
-# This is also the name of the generated .hex file.
+# This is also the name of the generated .c file.
#
-def AmlToHex(InputFile, OutputFile, BaseName):
+def AmlToC(InputFile, OutputFile, BaseName):
- MacroName = "__{}_HEX__".format(BaseName.upper())
ArrayName = BaseName.lower() + "_aml_code"
+ FileHeader =\
+"""
+// This file has been generated from:
+// -Python script: {}
+// -Input AML file: {}
+
+"""
with open(InputFile, "rb") as fIn, open(OutputFile, "w") as fOut:
# Write header.
- fOut.write("// This file has been generated from:\n" + \
- "// \tPython script: " + \
- os.path.abspath(__file__) + "\n" + \
- "// \tInput AML file: " + \
- os.path.abspath(InputFile) + "\n\n" + \
- "#ifndef {}\n".format(MacroName) + \
- "#define {}\n\n".format(MacroName)
- )
+ fOut.write(FileHeader.format(os.path.abspath(InputFile), os.path.abspath(__file__)))
# Write the array and its content.
fOut.write("unsigned char {}[] = {{\n ".format(ArrayName))
@@ -115,15 +105,12 @@ def AmlToHex(InputFile, OutputFile, BaseName):
byte = fIn.read(1)
fOut.write("\n};\n")
- # Write footer.
- fOut.write("#endif // {}\n".format(MacroName))
-
## Main method
#
# This method:
# 1- Initialize an EdkLogger instance.
# 2- Parses the input arguments.
-# 3- Converts an AML file to a .hex file containing the AML bytecode stored
+# 3- Converts an AML file to a .c file containing the AML bytecode stored
# in a C array.
#
# @retval 0 Success.
@@ -139,10 +126,9 @@ def Main():
if not CommandArguments:
return 1
- # Convert an AML file to a .hex file containing the AML bytecode stored
+ # Convert an AML file to a .c file containing the AML bytecode stored
# in a C array.
- AmlToHex(CommandArguments.InputFile, CommandArguments.OutputFile,
- CommandArguments.BaseName)
+ AmlToC(CommandArguments.InputFile, CommandArguments.OutputFile, CommandArguments.BaseName)
except Exception as e:
print(e)
return 1
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGenWorker.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGenWorker.py
index 9221ee23276..d392ffb224e 100755
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGenWorker.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/AutoGenWorker.py
@@ -24,6 +24,7 @@ import traceback
import sys
from AutoGen.DataPipe import MemoryDataPipe
import logging
+import time
def clearQ(q):
try:
@@ -111,7 +112,11 @@ class AutoGenManager(threading.Thread):
break
if badnews == "Done":
fin_num += 1
+ elif badnews == "QueueEmpty":
+ EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), badnews))
+ self.TerminateWorkers()
else:
+ EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), badnews))
self.Status = False
self.TerminateWorkers()
if fin_num == len(self.autogen_workers):
@@ -227,12 +232,21 @@ class AutoGenWorkerInProcess(mp.Process):
PlatformMetaFile = self.GetPlatformMetaFile(self.data_pipe.Get("P_Info").get("ActivePlatform"),
self.data_pipe.Get("P_Info").get("WorkspaceDir"))
while True:
- if self.module_queue.empty():
- break
if self.error_event.is_set():
break
module_count += 1
- module_file,module_root,module_path,module_basename,module_originalpath,module_arch,IsLib = self.module_queue.get_nowait()
+ try:
+ module_file,module_root,module_path,module_basename,module_originalpath,module_arch,IsLib = self.module_queue.get_nowait()
+ except Empty:
+ EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), "Fake Empty."))
+ time.sleep(0.01)
+ continue
+ if module_file is None:
+ EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), "Worker get the last item in the queue."))
+ self.feedback_q.put("QueueEmpty")
+ time.sleep(0.01)
+ continue
+
modulefullpath = os.path.join(module_root,module_file)
taskname = " : ".join((modulefullpath,module_arch))
module_metafile = PathClass(module_file,module_root)
@@ -266,7 +280,7 @@ class AutoGenWorkerInProcess(mp.Process):
Ma.CreateCodeFile(False)
Ma.CreateMakeFile(False,GenFfsList=FfsCmd.get((Ma.MetaFile.Path, Ma.Arch),[]))
-
+ Ma.CreateAsBuiltInf()
if GlobalData.gBinCacheSource and CommandTarget in [None, "", "all"]:
try:
CacheResult = Ma.CanSkipbyMakeCache()
@@ -280,11 +294,11 @@ class AutoGenWorkerInProcess(mp.Process):
else:
self.cache_q.put((Ma.MetaFile.Path, Ma.Arch, "MakeCache", False))
- except Empty:
- pass
- except:
+ except Exception as e:
+ EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), str(e)))
self.feedback_q.put(taskname)
finally:
+ EdkLogger.debug(EdkLogger.DEBUG_9, "Worker %s: %s" % (os.getpid(), "Done"))
self.feedback_q.put("Done")
self.cache_q.put("CacheDone")
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py
index f41b2733f39..8a321bf898e 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/BuildEngine.py
@@ -172,7 +172,7 @@ class FileBuildRule:
def __str__(self):
SourceString = ""
SourceString += " %s %s %s" % (self.SourceFileType, " ".join(self.SourceFileExtList), self.ExtraSourceFileList)
- DestString = ", ".join(self.DestFileList)
+ DestString = ", ".join([str(i) for i in self.DestFileList])
CommandString = "\n\t".join(self.CommandList)
return "%s : %s\n\t%s" % (DestString, SourceString, CommandString)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/DataPipe.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/DataPipe.py
index 6ea9d607725..d5028f3910c 100755
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/DataPipe.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/DataPipe.py
@@ -72,9 +72,10 @@ class MemoryDataPipe(DataPipe):
#Platform Module Pcds
ModulePcds = {}
for m in PlatformInfo.Platform.Modules:
- m_pcds = PlatformInfo.Platform.Modules[m].Pcds
+ module = PlatformInfo.Platform.Modules[m]
+ m_pcds = module.Pcds
if m_pcds:
- ModulePcds[(m.File,m.Root,m.Arch)] = [PCD_DATA(
+ ModulePcds[module.Guid] = [PCD_DATA(
pcd.TokenCName,pcd.TokenSpaceGuidCName,pcd.Type,
pcd.DatumType,pcd.SkuInfoList,pcd.DefaultValue,
pcd.MaxDatumSize,pcd.UserDefinedDefaultStoresFlag,pcd.validateranges,
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py
index c9cb15de337..7c7a7d53048 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenC.py
@@ -1980,12 +1980,14 @@ def CreateHeaderCode(Info, AutoGenC, AutoGenH):
AutoGenH.Append("#include <Library/PcdLib.h>\n")
AutoGenH.Append('\nextern GUID gEfiCallerIdGuid;')
+ AutoGenH.Append('\nextern GUID gEdkiiDscPlatformGuid;')
AutoGenH.Append('\nextern CHAR8 *gEfiCallerBaseName;\n\n')
if Info.IsLibrary:
return
AutoGenH.Append("#define EFI_CALLER_ID_GUID \\\n %s\n" % GuidStringToGuidStructureString(Info.Guid))
+ AutoGenH.Append("#define EDKII_DSC_PLATFORM_GUID \\\n %s\n" % GuidStringToGuidStructureString(Info.PlatformInfo.Guid))
if Info.IsLibrary:
return
@@ -2002,6 +2004,7 @@ def CreateHeaderCode(Info, AutoGenC, AutoGenH):
# Publish the CallerId Guid
#
AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED GUID gEfiCallerIdGuid = %s;\n' % GuidStringToGuidStructureString(Info.Guid))
+ AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED GUID gEdkiiDscPlatformGuid = %s;\n' % GuidStringToGuidStructureString(Info.PlatformInfo.Guid))
AutoGenC.Append('\nGLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *gEfiCallerBaseName = "%s";\n' % Info.Name)
## Create common code for header file
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py
index 190d0d64e54..130557de0d5 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenMake.py
@@ -1,7 +1,7 @@
## @file
# Create makefile for MS nmake and GNU make
#
-# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -519,13 +519,15 @@ cleanlib:
# tools definitions
ToolsDef = []
IncPrefix = self._INC_FLAG_[MyAgo.ToolChainFamily]
- for Tool in MyAgo.BuildOption:
- for Attr in MyAgo.BuildOption[Tool]:
+ for Tool in sorted(list(MyAgo.BuildOption)):
+ Appended = False
+ for Attr in sorted(list(MyAgo.BuildOption[Tool])):
Value = MyAgo.BuildOption[Tool][Attr]
if Attr == "FAMILY":
continue
elif Attr == "PATH":
ToolsDef.append("%s = %s" % (Tool, Value))
+ Appended = True
else:
# Don't generate MAKE_FLAGS in makefile. It's put in environment variable.
if Tool == "MAKE":
@@ -542,7 +544,9 @@ cleanlib:
Value = ' '.join(ValueList)
ToolsDef.append("%s_%s = %s" % (Tool, Attr, Value))
- ToolsDef.append("")
+ Appended = True
+ if Appended:
+ ToolsDef.append("")
# generate the Response file and Response flag
RespDict = self.CommandExceedLimit()
@@ -576,7 +580,7 @@ cleanlib:
EdkLogger.error("build", AUTOGEN_ERROR, "Nothing to build",
ExtraData="[%s]" % str(MyAgo))
- self.ProcessBuildTargetList()
+ self.ProcessBuildTargetList(MyAgo.OutputDir, ToolsDef)
self.ParserGenerateFfsCmd()
# Generate macros used to represent input files
@@ -786,8 +790,10 @@ cleanlib:
def ReplaceMacro(self, str):
for Macro in self.MacroList:
- if self._AutoGenObject.Macros[Macro] and self._AutoGenObject.Macros[Macro] in str:
- str = str.replace(self._AutoGenObject.Macros[Macro], '$(' + Macro + ')')
+ if self._AutoGenObject.Macros[Macro] and os.path.normcase(self._AutoGenObject.Macros[Macro]) in os.path.normcase(str):
+ replace_dir = str[os.path.normcase(str).index(os.path.normcase(self._AutoGenObject.Macros[Macro])): os.path.normcase(str).index(
+ os.path.normcase(self._AutoGenObject.Macros[Macro])) + len(self._AutoGenObject.Macros[Macro])]
+ str = str.replace(replace_dir, '$(' + Macro + ')')
return str
def CommandExceedLimit(self):
@@ -901,7 +907,7 @@ cleanlib:
BuildTargets[Target].Commands[i] = SingleCommand.replace('$(INC)', '').replace(FlagDict[Flag]['Macro'], RespMacro)
return RespDict
- def ProcessBuildTargetList(self):
+ def ProcessBuildTargetList(self, RespFile, ToolsDef):
#
# Search dependency file list for each source file
#
@@ -1002,6 +1008,7 @@ cleanlib:
self.ObjTargetDict[T.Target.SubDir] = set()
self.ObjTargetDict[T.Target.SubDir].add(NewFile)
for Type in self._AutoGenObject.Targets:
+ resp_file_number = 0
for T in self._AutoGenObject.Targets[Type]:
# Generate related macros if needed
if T.GenFileListMacro and T.FileListMacro not in self.FileListMacros:
@@ -1058,7 +1065,10 @@ cleanlib:
# VBox - end.
if self._AutoGenObject.BuildRuleFamily == TAB_COMPILER_MSFT and Type == TAB_C_CODE_FILE:
- T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict)
+ T, CmdTarget, CmdTargetDict, CmdCppDict = self.ParserCCodeFile(T, Type, CmdSumDict, CmdTargetDict,
+ CmdCppDict, DependencyDict, RespFile,
+ ToolsDef, resp_file_number)
+ resp_file_number += 1
TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": "\n\t".join(T.Commands),"deps": CCodeDeps}
# VBox: Original: TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": sAllCmds,"deps": CCodeDeps}
CmdLine = self._BUILD_TARGET_TEMPLATE.Replace(TargetDict).rstrip().replace('\t$(OBJLIST', '$(OBJLIST')
@@ -1071,7 +1081,15 @@ cleanlib:
# VBox: Original: TargetDict = {"target": self.PlaceMacro(T.Target.Path, self.Macros), "cmd": sAllCmds,"deps": Deps}
self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(TargetDict))
- def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict):
+ # Add a Makefile rule for targets generating multiple files.
+ # The main output is a prerequisite for the other output files.
+ for i in T.Outputs[1:]:
+ AnnexeTargetDict = {"target": self.PlaceMacro(i.Path, self.Macros), "cmd": "", "deps": self.PlaceMacro(T.Target.Path, self.Macros)}
+ self.BuildTargetList.append(self._BUILD_TARGET_TEMPLATE.Replace(AnnexeTargetDict))
+
+ def ParserCCodeFile(self, T, Type, CmdSumDict, CmdTargetDict, CmdCppDict, DependencyDict, RespFile, ToolsDef,
+ resp_file_number):
+ SaveFilePath = os.path.join(RespFile, "cc_resp_%s.txt" % resp_file_number)
if not CmdSumDict:
for item in self._AutoGenObject.Targets[Type]:
CmdSumDict[item.Target.SubDir] = item.Target.BaseName
@@ -1098,17 +1116,36 @@ cleanlib:
if Temp.startswith('/Fo'):
CmdSign = '%s%s' % (Temp.rsplit(TAB_SLASH, 1)[0], TAB_SLASH)
break
- else: continue
+ else:
+ continue
if CmdSign not in list(CmdTargetDict.keys()):
- CmdTargetDict[CmdSign] = Item.replace(Temp, CmdSign)
+ cmd = Item.replace(Temp, CmdSign)
+ if SingleCommandList[-1] in cmd:
+ CmdTargetDict[CmdSign] = [cmd.replace(SingleCommandList[-1], "").rstrip(), SingleCommandList[-1]]
else:
- CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
+ # CmdTargetDict[CmdSign] = "%s %s" % (CmdTargetDict[CmdSign], SingleCommandList[-1])
+ CmdTargetDict[CmdSign].append(SingleCommandList[-1])
Index = CommandList.index(Item)
CommandList.pop(Index)
if SingleCommandList[-1].endswith("%s%s.c" % (TAB_SLASH, CmdSumDict[CmdSign[3:].rsplit(TAB_SLASH, 1)[0]])):
Cpplist = CmdCppDict[T.Target.SubDir]
Cpplist.insert(0, '$(OBJLIST_%d): ' % list(self.ObjTargetDict.keys()).index(T.Target.SubDir))
- T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign])
+ source_files = CmdTargetDict[CmdSign][1:]
+ source_files.insert(0, " ")
+ if len(source_files)>2:
+ SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
+ T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
+ ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
+ ToolsDef.append("cc_resp_%s = @%s" % (resp_file_number, SaveFilePath))
+
+ elif len(source_files)<=2 and len(" ".join(CmdTargetDict[CmdSign][:2]))>GlobalData.gCommandMaxLength:
+ SaveFileOnChange(SaveFilePath, " ".join(source_files), False)
+ T.Commands[Index] = '%s\n\t%s $(cc_resp_%s)' % (
+ ' \\\n\t'.join(Cpplist), CmdTargetDict[CmdSign][0], resp_file_number)
+ ToolsDef.append("cc_resp_%s = @%s" % (resp_file_number, SaveFilePath))
+
+ else:
+ T.Commands[Index] = '%s\n\t%s' % (' \\\n\t'.join(Cpplist), " ".join(CmdTargetDict[CmdSign]))
else:
T.Commands.pop(Index)
return T, CmdSumDict, CmdTargetDict, CmdCppDict
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py
index e48ebca4bec..8b2cbebc57d 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/GenPcdDb.py
@@ -894,7 +894,7 @@ def CreatePcdDataBase(PcdDBData):
delta = {}
for skuname, skuid in PcdDBData:
if len(PcdDBData[(skuname, skuid)][1]) != len(PcdDBData[(TAB_DEFAULT, "0")][1]):
- EdkLogger.ERROR("The size of each sku in one pcd are not same")
+ EdkLogger.error("build", AUTOGEN_ERROR, "The size of each sku in one pcd are not same")
for skuname, skuid in PcdDBData:
if skuname == TAB_DEFAULT:
continue
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py
index 532ee940c19..29169f67199 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/IncludesAutoGen.py
@@ -103,7 +103,7 @@ ${END}
if os.path.normpath(dependency_file +".deps") == abspath:
continue
filename = os.path.basename(dependency_file).strip()
- if filename not in self.SourceFileList and filename not in targetname:
+ if filename not in targetname:
includes.add(dependency_file.strip())
for item in lines[1:]:
@@ -116,8 +116,6 @@ ${END}
if os.path.normpath(dependency_file +".deps") == abspath:
continue
filename = os.path.basename(dependency_file).strip()
- if filename in self.SourceFileList:
- continue
if filename in targetname:
continue
includes.add(dependency_file.strip())
@@ -203,7 +201,17 @@ ${END}
cc_options = line[len(cc_cmd)+2:].split()
else:
cc_options = line[len(cc_cmd):].split()
- SourceFileAbsPathMap = {os.path.basename(item):item for item in cc_options if not item.startswith("/") and os.path.exists(item)}
+ for item in cc_options:
+ if not item.startswith("/"):
+ if item.endswith(".txt") and item.startswith("@"):
+ with open(item[1:], "r") as file:
+ source_files = file.readlines()[0].split()
+ SourceFileAbsPathMap = {os.path.basename(file): file for file in source_files if
+ os.path.exists(file)}
+ else:
+ if os.path.exists(item):
+ SourceFileAbsPathMap.update({os.path.basename(item): item.strip()})
+ # SourceFileAbsPathMap = {os.path.basename(item):item for item in cc_options if not item.startswith("/") and os.path.exists(item)}
if line in SourceFileAbsPathMap:
current_source = line
if current_source not in ModuleDepDict:
@@ -283,7 +291,8 @@ ${END}
targetitem = self.GetRealTarget(source_abs.strip(" :"))
targetitem += ": "
- targetitem += lines[1]
+ if len(lines)>=2:
+ targetitem += lines[1]
newcontent.append(targetitem)
newcontent.extend(lines[2:])
newcontent.append("\n")
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py
index 3a7b19fe14b..2bf2cf1a80e 100755
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGen.py
@@ -860,7 +860,8 @@ class ModuleAutoGen(AutoGen):
SubDirectory = os.path.join(self.OutputDir, File.SubDir)
if not os.path.exists(SubDirectory):
CreateDirectory(SubDirectory)
- LastTarget = None
+ TargetList = set()
+ FinalTargetName = set()
RuleChain = set()
SourceList = [File]
Index = 0
@@ -870,6 +871,9 @@ class ModuleAutoGen(AutoGen):
self.BuildOption
while Index < len(SourceList):
+ # Reset the FileType if not the first iteration.
+ if Index > 0:
+ FileType = TAB_UNKNOWN_FILE
Source = SourceList[Index]
Index = Index + 1
@@ -886,29 +890,25 @@ class ModuleAutoGen(AutoGen):
elif Source.Ext in self.BuildRules:
RuleObject = self.BuildRules[Source.Ext]
else:
- # stop at no more rules
- if LastTarget:
- self._FinalBuildTargetList.add(LastTarget)
- break
+ # No more rule to apply: Source is a final target.
+ FinalTargetName.add(Source)
+ continue
FileType = RuleObject.SourceFileType
self._FileTypes[FileType].add(Source)
# stop at STATIC_LIBRARY for library
if self.IsLibrary and FileType == TAB_STATIC_LIBRARY:
- if LastTarget:
- self._FinalBuildTargetList.add(LastTarget)
- break
+ FinalTargetName.add(Source)
+ continue
Target = RuleObject.Apply(Source, self.BuildRuleOrder)
if not Target:
- if LastTarget:
- self._FinalBuildTargetList.add(LastTarget)
- break
- elif not Target.Outputs:
- # Only do build for target with outputs
- self._FinalBuildTargetList.add(Target)
+ # No Target: Source is a final target.
+ FinalTargetName.add(Source)
+ continue
+ TargetList.add(Target)
self._BuildTargets[FileType].add(Target)
if not Source.IsBinary and Source == File:
@@ -916,12 +916,16 @@ class ModuleAutoGen(AutoGen):
# to avoid cyclic rule
if FileType in RuleChain:
- break
+ EdkLogger.error("build", ERROR_STATEMENT, "Cyclic dependency detected while generating rule for %s" % str(Source))
RuleChain.add(FileType)
SourceList.extend(Target.Outputs)
- LastTarget = Target
- FileType = TAB_UNKNOWN_FILE
+
+ # For each final target name, retrieve the corresponding TargetDescBlock instance.
+ for FTargetName in FinalTargetName:
+ for Target in TargetList:
+ if FTargetName == Target.Target:
+ self._FinalBuildTargetList.add(Target)
@cached_property
def Targets(self):
@@ -1028,7 +1032,7 @@ class ModuleAutoGen(AutoGen):
@cached_property
def ModulePcdList(self):
# apply PCD settings from platform
- RetVal = self.PlatformInfo.ApplyPcdSetting(self.Module, self.Module.Pcds)
+ RetVal = self.PlatformInfo.ApplyPcdSetting(self, self.Module.Pcds)
return RetVal
@cached_property
@@ -1059,7 +1063,7 @@ class ModuleAutoGen(AutoGen):
continue
Pcds.add(Key)
PcdsInLibrary[Key] = copy.copy(Library.Pcds[Key])
- RetVal.extend(self.PlatformInfo.ApplyPcdSetting(self.Module, PcdsInLibrary, Library=Library))
+ RetVal.extend(self.PlatformInfo.ApplyPcdSetting(self, PcdsInLibrary, Library=Library))
return RetVal
## Get the GUID value mapping
@@ -1818,9 +1822,6 @@ class ModuleAutoGen(AutoGen):
for LibraryAutoGen in self.LibraryAutoGenList:
LibraryAutoGen.CreateCodeFile()
- # CanSkip uses timestamps to determine build skipping
- if self.CanSkip():
- return
self.LibraryAutoGenList
AutoGenList = []
IgoredAutoGenList = []
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
index c839c99b4f7..09168047e1b 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/ModuleAutoGenHelper.py
@@ -1,7 +1,7 @@
## @file
# Create makefile for MS nmake and GNU make
#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
from __future__ import absolute_import
@@ -173,14 +173,22 @@ class AutoGenInfo(object):
Family = Key[0]
Target, Tag, Arch, Tool, Attr = Key[1].split("_")
# if tool chain family doesn't match, skip it
- if Tool in ToolDef and Family != "":
- FamilyIsNull = False
- if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
- if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
- continue
- elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
+ if Family != "":
+ Found = False
+ if Tool in ToolDef:
+ FamilyIsNull = False
+ if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[Tool]:
+ if Family == ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
+ FamilyMatch = True
+ Found = True
+ if TAB_STAR in ToolDef:
+ FamilyIsNull = False
+ if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[TAB_STAR]:
+ if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
+ FamilyMatch = True
+ Found = True
+ if not Found:
continue
- FamilyMatch = True
# expand any wildcard
if Target == TAB_STAR or Target == self.BuildTarget:
if Tag == TAB_STAR or Tag == self.ToolChain:
@@ -210,10 +218,19 @@ class AutoGenInfo(object):
Family = Key[0]
Target, Tag, Arch, Tool, Attr = Key[1].split("_")
# if tool chain family doesn't match, skip it
- if Tool not in ToolDef or Family == "":
+ if Family == "":
continue
# option has been added before
- if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
+ Found = False
+ if Tool in ToolDef:
+ if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:
+ if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
+ Found = True
+ if TAB_STAR in ToolDef:
+ if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:
+ if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:
+ Found = True
+ if not Found:
continue
# expand any wildcard
@@ -479,8 +496,9 @@ class PlatformInfo(AutoGenInfo):
SkuName : SkuInfoClass(SkuName, self.Platform.SkuIds[SkuName][0], '', '', '', '', '', ToPcd.DefaultValue)
}
- def ApplyPcdSetting(self, Module, Pcds, Library=""):
+ def ApplyPcdSetting(self, Ma, Pcds, Library=""):
# for each PCD in module
+ Module=Ma.Module
for Name, Guid in Pcds:
PcdInModule = Pcds[Name, Guid]
# find out the PCD setting in platform
@@ -507,9 +525,12 @@ class PlatformInfo(AutoGenInfo):
)
# override PCD settings with module specific setting
+ ModuleScopePcds = self.DataPipe.Get("MOL_PCDS")
if Module in self.Platform.Modules:
PlatformModule = self.Platform.Modules[str(Module)]
- for Key in PlatformModule.Pcds:
+ PCD_DATA = ModuleScopePcds.get(Ma.Guid,{})
+ mPcds = {(pcd.TokenCName,pcd.TokenSpaceGuidCName): pcd for pcd in PCD_DATA}
+ for Key in mPcds:
if self.BuildOptionPcd:
for pcd in self.BuildOptionPcd:
(TokenSpaceGuidCName, TokenCName, FieldName, pcdvalue, _) = pcd
@@ -528,7 +549,7 @@ class PlatformInfo(AutoGenInfo):
Flag = True
break
if Flag:
- self._OverridePcd(ToPcd, PlatformModule.Pcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
+ self._OverridePcd(ToPcd, mPcds[Key], Module, Msg="DSC Components Module scoped PCD section", Library=Library)
# use PCD value to calculate the MaxDatumSize when it is not specified
for Name, Guid in Pcds:
Pcd = Pcds[Name, Guid]
@@ -611,14 +632,19 @@ class PlatformInfo(AutoGenInfo):
if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
continue
Value = Options[Tool][Attr]
- # check if override is indicated
- if Value.startswith('='):
- BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
- else:
- if Attr != 'PATH':
- BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
+ ToolList = [Tool]
+ if Tool == TAB_STAR:
+ ToolList = list(AllTools)
+ ToolList.remove(TAB_STAR)
+ for ExpandedTool in ToolList:
+ # check if override is indicated
+ if Value.startswith('='):
+ BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value[1:])
else:
- BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
+ if Attr != 'PATH':
+ BuildOptions[ExpandedTool][Attr] += " " + mws.handleWsMacro(Value)
+ else:
+ BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value)
return BuildOptions, BuildRuleOrder
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
index 23de3d6b507..29bc543987f 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/PlatformAutoGen.py
@@ -1,7 +1,7 @@
## @file
# Create makefile for MS nmake and GNU make
#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -253,7 +253,7 @@ class PlatformAutoGen(AutoGen):
VariableInfo.SetVpdRegionMaxSize(VpdRegionSize)
VariableInfo.SetVpdRegionOffset(VpdRegionBase)
Index = 0
- for Pcd in DynamicPcdSet:
+ for Pcd in sorted(DynamicPcdSet):
pcdname = ".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName))
for SkuName in Pcd.SkuInfoList:
Sku = Pcd.SkuInfoList[SkuName]
@@ -805,22 +805,55 @@ class PlatformAutoGen(AutoGen):
#
@cached_property
def BuildCommand(self):
- RetVal = []
- if "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
- RetVal += _SplitOption(self.ToolDefinition["MAKE"]["PATH"])
- if "FLAGS" in self.ToolDefinition["MAKE"]:
- NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
- if NewOption != '':
- RetVal += _SplitOption(NewOption)
- if "MAKE" in self.EdkIIBuildOption:
- if "FLAGS" in self.EdkIIBuildOption["MAKE"]:
- Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
- if Flags.startswith('='):
- RetVal = [RetVal[0]] + [Flags[1:]]
- else:
- RetVal.append(Flags)
+ if "MAKE" in self.EdkIIBuildOption and "PATH" in self.EdkIIBuildOption["MAKE"]:
+ # MAKE_PATH in DSC [BuildOptions] section is higher priority
+ Path = self.EdkIIBuildOption["MAKE"]["PATH"]
+ if Path.startswith('='):
+ Path = Path[1:].strip()
+ RetVal = _SplitOption(Path)
+ elif "MAKE" in self.ToolDefinition and "PATH" in self.ToolDefinition["MAKE"]:
+ RetVal = _SplitOption(self.ToolDefinition["MAKE"]["PATH"])
+ else:
+ return []
+ if "MAKE" in self.ToolDefinition and "FLAGS" in self.ToolDefinition["MAKE"]:
+ NewOption = self.ToolDefinition["MAKE"]["FLAGS"].strip()
+ if NewOption != '':
+ RetVal += _SplitOption(NewOption)
+ if "MAKE" in self.EdkIIBuildOption and "FLAGS" in self.EdkIIBuildOption["MAKE"]:
+ Flags = self.EdkIIBuildOption["MAKE"]["FLAGS"]
+ if Flags.startswith('='):
+ RetVal = [RetVal[0]] + _SplitOption(Flags[1:].strip())
+ else:
+ RetVal = RetVal + _SplitOption(Flags.strip())
return RetVal
+ ## Compute a tool defintion key priority value in range 0..15
+ #
+ # TARGET_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE 15
+ # ******_TOOLCHAIN_ARCH_COMMANDTYPE_ATTRIBUTE 14
+ # TARGET_*********_ARCH_COMMANDTYPE_ATTRIBUTE 13
+ # ******_*********_ARCH_COMMANDTYPE_ATTRIBUTE 12
+ # TARGET_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE 11
+ # ******_TOOLCHAIN_****_COMMANDTYPE_ATTRIBUTE 10
+ # TARGET_*********_****_COMMANDTYPE_ATTRIBUTE 9
+ # ******_*********_****_COMMANDTYPE_ATTRIBUTE 8
+ # TARGET_TOOLCHAIN_ARCH_***********_ATTRIBUTE 7
+ # ******_TOOLCHAIN_ARCH_***********_ATTRIBUTE 6
+ # TARGET_*********_ARCH_***********_ATTRIBUTE 5
+ # ******_*********_ARCH_***********_ATTRIBUTE 4
+ # TARGET_TOOLCHAIN_****_***********_ATTRIBUTE 3
+ # ******_TOOLCHAIN_****_***********_ATTRIBUTE 2
+ # TARGET_*********_****_***********_ATTRIBUTE 1
+ # ******_*********_****_***********_ATTRIBUTE 0
+ #
+ def ToolDefinitionPriority (self,Key):
+ KeyList = Key.split('_')
+ Priority = 0
+ for Index in range (0, min(4, len(KeyList))):
+ if KeyList[Index] != '*':
+ Priority += (1 << Index)
+ return Priority
+
## Get tool chain definition
#
# Get each tool definition for given tool chain from tools_def.txt and platform
@@ -833,8 +866,16 @@ class PlatformAutoGen(AutoGen):
ExtraData="[%s]" % self.MetaFile)
RetVal = OrderedDict()
DllPathList = set()
- for Def in ToolDefinition:
+
+ PrioritizedDefList = sorted(ToolDefinition.keys(), key=self.ToolDefinitionPriority, reverse=True)
+ for Def in PrioritizedDefList:
Target, Tag, Arch, Tool, Attr = Def.split("_")
+ if Target == TAB_STAR:
+ Target = self.BuildTarget
+ if Tag == TAB_STAR:
+ Tag = self.ToolChain
+ if Arch == TAB_STAR:
+ Arch = self.Arch
if Target != self.BuildTarget or Tag != self.ToolChain or Arch != self.Arch:
continue
@@ -844,9 +885,14 @@ class PlatformAutoGen(AutoGen):
DllPathList.add(Value)
continue
+ #
+ # ToolDefinition is sorted from highest priority to lowest priority.
+ # Only add the first(highest priority) match to RetVal
+ #
if Tool not in RetVal:
RetVal[Tool] = OrderedDict()
- RetVal[Tool][Attr] = Value
+ if Attr not in RetVal[Tool]:
+ RetVal[Tool][Attr] = Value
ToolsDef = ''
if GlobalData.gOptions.SilentMode and "MAKE" in RetVal:
@@ -854,24 +900,35 @@ class PlatformAutoGen(AutoGen):
RetVal["MAKE"]["FLAGS"] = ""
RetVal["MAKE"]["FLAGS"] += " -s"
MakeFlags = ''
- for Tool in RetVal:
- for Attr in RetVal[Tool]:
- Value = RetVal[Tool][Attr]
+
+ ToolList = list(RetVal.keys())
+ ToolList.sort()
+ for Tool in ToolList:
+ if Tool == TAB_STAR:
+ continue
+ AttrList = list(RetVal[Tool].keys())
+ if TAB_STAR in ToolList:
+ AttrList += list(RetVal[TAB_STAR])
+ AttrList.sort()
+ for Attr in AttrList:
+ if Attr in RetVal[Tool]:
+ Value = RetVal[Tool][Attr]
+ else:
+ Value = RetVal[TAB_STAR][Attr]
if Tool in self._BuildOptionWithToolDef(RetVal) and Attr in self._BuildOptionWithToolDef(RetVal)[Tool]:
# check if override is indicated
if self._BuildOptionWithToolDef(RetVal)[Tool][Attr].startswith('='):
- Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:]
+ Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr][1:].strip()
else:
- if Attr != 'PATH':
+ # Do not append PATH or GUID
+ if Attr != 'PATH' and Attr != 'GUID':
Value += " " + self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
else:
Value = self._BuildOptionWithToolDef(RetVal)[Tool][Attr]
- Def = '_'.join([self.BuildTarget, self.ToolChain, self.Arch, Tool, Attr])
- self.Workspace.ToolDef.ToolsDefTxtDictionary[Def] = Value
if Attr == "PATH":
# Don't put MAKE definition in the file
if Tool != "MAKE":
- ToolsDef += "%s = %s\n" % (Tool, Value)
+ ToolsDef += "%s_%s = %s\n" % (Tool, Attr, Value)
elif Attr != "DLL":
# Don't put MAKE definition in the file
if Tool == "MAKE":
@@ -1037,13 +1094,18 @@ class PlatformAutoGen(AutoGen):
TokenNumber += 1
for Pcd in self.NonDynamicPcdList:
- RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = TokenNumber
- TokenNumber += 1
+ RetVal[Pcd.TokenCName, Pcd.TokenSpaceGuidCName] = 0
return RetVal
@cached_property
def _MbList(self):
- return [self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain] for m in self.Platform.Modules]
+ ModuleList = []
+ for m in self.Platform.Modules:
+ component = self.Platform.Modules[m]
+ module = self.BuildDatabase[m, self.Arch, self.BuildTarget, self.ToolChain]
+ module.Guid = component.Guid
+ ModuleList.append(module)
+ return ModuleList
@cached_property
def _MaList(self):
@@ -1328,14 +1390,19 @@ class PlatformAutoGen(AutoGen):
if Attr == TAB_TOD_DEFINES_BUILDRULEORDER:
continue
Value = Options[Tool][Attr]
- # check if override is indicated
- if Value.startswith('='):
- BuildOptions[Tool][Attr] = mws.handleWsMacro(Value[1:])
- else:
- if Attr != 'PATH':
- BuildOptions[Tool][Attr] += " " + mws.handleWsMacro(Value)
+ ToolList = [Tool]
+ if Tool == TAB_STAR:
+ ToolList = list(AllTools)
+ ToolList.remove(TAB_STAR)
+ for ExpandedTool in ToolList:
+ # check if override is indicated
+ if Value.startswith('='):
+ BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value[1:])
else:
- BuildOptions[Tool][Attr] = mws.handleWsMacro(Value)
+ if Attr != 'PATH':
+ BuildOptions[ExpandedTool][Attr] += " " + mws.handleWsMacro(Value)
+ else:
+ BuildOptions[ExpandedTool][Attr] = mws.handleWsMacro(Value)
return BuildOptions, BuildRuleOrder
@@ -1458,14 +1525,23 @@ class PlatformAutoGen(AutoGen):
Family = Key[0]
Target, Tag, Arch, Tool, Attr = Key[1].split("_")
# if tool chain family doesn't match, skip it
- if Tool in ToolDef and Family != "":
- FamilyIsNull = False
- if ToolDef[Tool].get(TAB_TOD_DEFINES_BUILDRULEFAMILY, "") != "":
- if Family != ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
- continue
- elif Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
+ if Family != "":
+ Found = False
+ if Tool in ToolDef:
+ FamilyIsNull = False
+ if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[Tool]:
+ if Family == ToolDef[Tool][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
+ FamilyMatch = True
+ Found = True
+ if TAB_STAR in ToolDef:
+ FamilyIsNull = False
+ if TAB_TOD_DEFINES_BUILDRULEFAMILY in ToolDef[TAB_STAR]:
+ if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_BUILDRULEFAMILY]:
+ FamilyMatch = True
+ Found = True
+ if not Found:
continue
- FamilyMatch = True
+
# expand any wildcard
if Target == TAB_STAR or Target == self.BuildTarget:
if Tag == TAB_STAR or Tag == self.ToolChain:
@@ -1495,10 +1571,19 @@ class PlatformAutoGen(AutoGen):
Family = Key[0]
Target, Tag, Arch, Tool, Attr = Key[1].split("_")
# if tool chain family doesn't match, skip it
- if Tool not in ToolDef or Family == "":
+ if Family == "":
continue
# option has been added before
- if Family != ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
+ Found = False
+ if Tool in ToolDef:
+ if TAB_TOD_DEFINES_FAMILY in ToolDef[Tool]:
+ if Family == ToolDef[Tool][TAB_TOD_DEFINES_FAMILY]:
+ Found = True
+ if TAB_STAR in ToolDef:
+ if TAB_TOD_DEFINES_FAMILY in ToolDef[TAB_STAR]:
+ if Family == ToolDef[TAB_STAR][TAB_TOD_DEFINES_FAMILY]:
+ Found = True
+ if not Found:
continue
# expand any wildcard
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py
index efc77d91356..a13a27b52f6 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/UniClassObject.py
@@ -152,7 +152,7 @@ class Ucs2Codec(codecs.Codec):
TheUcs2Codec = Ucs2Codec()
def Ucs2Search(name):
- if name == 'ucs-2':
+ if name in ['ucs-2', 'ucs_2']:
return codecs.CodecInfo(
name=name,
encode=TheUcs2Codec.encode,
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
index 9eac3d99578..93624d0f721 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/AutoGen/WorkspaceAutoGen.py
@@ -108,6 +108,10 @@ class WorkspaceAutoGen(AutoGen):
#
# Mark now build in AutoGen Phase
#
+ #
+ # Collect Platform Guids to support Guid name in Fdfparser.
+ #
+ self.CollectPlatformGuids()
GlobalData.gAutoGenPhase = True
self.ProcessModuleFromPdf()
self.ProcessPcdType()
@@ -153,6 +157,26 @@ class WorkspaceAutoGen(AutoGen):
EdkLogger.error("build", PARAMETER_INVALID,
ExtraData="Build target [%s] is not supported by the platform. [Valid target: %s]"
% (self.BuildTarget, " ".join(self.Platform.BuildTargets)))
+
+ def CollectPlatformGuids(self):
+ oriInfList = []
+ oriPkgSet = set()
+ PlatformPkg = set()
+ for Arch in self.ArchList:
+ Platform = self.BuildDatabase[self.MetaFile, Arch, self.BuildTarget, self.ToolChain]
+ oriInfList = Platform.Modules
+ for ModuleFile in oriInfList:
+ ModuleData = self.BuildDatabase[ModuleFile, Platform._Arch, Platform._Target, Platform._Toolchain]
+ oriPkgSet.update(ModuleData.Packages)
+ for Pkg in oriPkgSet:
+ Guids = Pkg.Guids
+ GlobalData.gGuidDict.update(Guids)
+ if Platform.Packages:
+ PlatformPkg.update(Platform.Packages)
+ for Pkg in PlatformPkg:
+ Guids = Pkg.Guids
+ GlobalData.gGuidDict.update(Guids)
+
@cached_property
def FdfProfile(self):
if not self.FdfFile:
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Capsule/GenerateCapsule.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Capsule/GenerateCapsule.py
index ba35bc6b949..f8d85bca067 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Capsule/GenerateCapsule.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Capsule/GenerateCapsule.py
@@ -561,6 +561,7 @@ if __name__ == '__main__':
print ('GenerateCapsule: error:' + str(Msg))
sys.exit (1)
for SinglePayloadDescriptor in PayloadDescriptorList:
+ ImageCapsuleSupport = 0x0000000000000000
Result = SinglePayloadDescriptor.Payload
try:
FmpPayloadHeader.FwVersion = SinglePayloadDescriptor.FwVersion
@@ -575,6 +576,7 @@ if __name__ == '__main__':
if SinglePayloadDescriptor.UseDependency:
CapsuleDependency.Payload = Result
CapsuleDependency.DepexExp = SinglePayloadDescriptor.DepexExp
+ ImageCapsuleSupport |= FmpCapsuleHeader.CAPSULE_SUPPORT_DEPENDENCY
Result = CapsuleDependency.Encode ()
if args.Verbose:
CapsuleDependency.DumpInfo ()
@@ -607,13 +609,14 @@ if __name__ == '__main__':
FmpAuthHeader.MonotonicCount = SinglePayloadDescriptor.MonotonicCount
FmpAuthHeader.CertData = CertData
FmpAuthHeader.Payload = Result
+ ImageCapsuleSupport |= FmpCapsuleHeader.CAPSULE_SUPPORT_AUTHENTICATION
Result = FmpAuthHeader.Encode ()
if args.Verbose:
FmpAuthHeader.DumpInfo ()
except:
print ('GenerateCapsule: error: can not encode FMP Auth Header')
sys.exit (1)
- FmpCapsuleHeader.AddPayload (SinglePayloadDescriptor.Guid, Result, HardwareInstance = SinglePayloadDescriptor.HardwareInstance, UpdateImageIndex = SinglePayloadDescriptor.UpdateImageIndex)
+ FmpCapsuleHeader.AddPayload (SinglePayloadDescriptor.Guid, Result, HardwareInstance = SinglePayloadDescriptor.HardwareInstance, UpdateImageIndex = SinglePayloadDescriptor.UpdateImageIndex, CapsuleSupport = ImageCapsuleSupport)
try:
for EmbeddedDriver in EmbeddedDriverDescriptorList:
FmpCapsuleHeader.AddEmbeddedDriver(EmbeddedDriver)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/GlobalData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/GlobalData.py
index 6a8f50a0f6f..13248d9457b 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/GlobalData.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/GlobalData.py
@@ -29,6 +29,7 @@ gProcessingFile = ''
gBuildingModule = ''
gSkuids = []
gDefaultStores = []
+gGuidDict = {}
# definition for a MACRO name. used to create regular expressions below.
_MacroNamePattern = "[A-Z][A-Z0-9_]*"
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py
index 149e8e6e2ab..980fa8394d0 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Misc.py
@@ -1635,7 +1635,7 @@ class PeImageClass():
ByteArray = array.array('B')
ByteArray.fromfile(PeObject, 4)
# PE signature should be 'PE\0\0'
- if ByteArray.tostring() != b'PE\0\0':
+ if ByteArray.tolist() != [ord('P'), ord('E'), 0, 0]:
self.ErrorInfo = self.FileName + ' has no valid PE signature PE00'
return
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py
index e12fb2d061f..2319a7c4126 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/ToolDefClassObject.py
@@ -1,7 +1,7 @@
## @file
# This file is used to define each component of tools_def.txt file
#
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -86,23 +86,6 @@ class ToolDefClassObject(object):
self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TARGET_ARCH].sort()
self.ToolsDefTxtDatabase[TAB_TOD_DEFINES_COMMAND_TYPE].sort()
- KeyList = [TAB_TOD_DEFINES_TARGET, TAB_TOD_DEFINES_TOOL_CHAIN_TAG, TAB_TOD_DEFINES_TARGET_ARCH, TAB_TOD_DEFINES_COMMAND_TYPE]
- for Index in range(3, -1, -1):
- # make a copy of the keys to enumerate over to prevent issues when
- # adding/removing items from the original dict.
- for Key in list(self.ToolsDefTxtDictionary.keys()):
- List = Key.split('_')
- if List[Index] == TAB_STAR:
- for String in self.ToolsDefTxtDatabase[KeyList[Index]]:
- List[Index] = String
- NewKey = '%s_%s_%s_%s_%s' % tuple(List)
- if NewKey not in self.ToolsDefTxtDictionary:
- self.ToolsDefTxtDictionary[NewKey] = self.ToolsDefTxtDictionary[Key]
- del self.ToolsDefTxtDictionary[Key]
- elif List[Index] not in self.ToolsDefTxtDatabase[KeyList[Index]]:
- del self.ToolsDefTxtDictionary[Key]
-
-
## IncludeToolDefFile
#
# Load target.txt file and parse it as if its contents were inside the main file
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
index 5dfe6fbf3f4..44bdcbc4345 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/Uefi/Capsule/FmpCapsuleHeader.py
@@ -47,14 +47,19 @@ class FmpCapsuleImageHeaderClass (object):
# /// therefore can be modified without changing the Auth data.
# ///
# UINT64 UpdateHardwareInstance;
+ #
+ # ///
+ # /// Bits which indicate authentication and depex information for the image that follows this structure
+ # ///
+ # UINT64 ImageCapsuleSupport
# } EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER;
#
- # #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000002
+ # #define EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION 0x00000003
- _StructFormat = '<I16sB3BIIQ'
+ _StructFormat = '<I16sB3BIIQQ'
_StructSize = struct.calcsize (_StructFormat)
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000002
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION = 0x00000003
def __init__ (self):
self._Valid = False
@@ -64,6 +69,7 @@ class FmpCapsuleImageHeaderClass (object):
self.UpdateImageSize = 0
self.UpdateVendorCodeSize = 0
self.UpdateHardwareInstance = 0x0000000000000000
+ self.ImageCapsuleSupport = 0x0000000000000000
self.Payload = b''
self.VendorCodeBytes = b''
@@ -78,7 +84,8 @@ class FmpCapsuleImageHeaderClass (object):
0,0,0,
self.UpdateImageSize,
self.UpdateVendorCodeSize,
- self.UpdateHardwareInstance
+ self.UpdateHardwareInstance,
+ self.ImageCapsuleSupport
)
self._Valid = True
return FmpCapsuleImageHeader + self.Payload + self.VendorCodeBytes
@@ -86,7 +93,7 @@ class FmpCapsuleImageHeaderClass (object):
def Decode (self, Buffer):
if len (Buffer) < self._StructSize:
raise ValueError
- (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance) = \
+ (Version, UpdateImageTypeId, UpdateImageIndex, r0, r1, r2, UpdateImageSize, UpdateVendorCodeSize, UpdateHardwareInstance, ImageCapsuleSupport) = \
struct.unpack (
self._StructFormat,
Buffer[0:self._StructSize]
@@ -105,6 +112,7 @@ class FmpCapsuleImageHeaderClass (object):
self.UpdateImageSize = UpdateImageSize
self.UpdateVendorCodeSize = UpdateVendorCodeSize
self.UpdateHardwareInstance = UpdateHardwareInstance
+ self.ImageCapsuleSupport = ImageCapsuleSupport
self.Payload = Buffer[self._StructSize:self._StructSize + UpdateImageSize]
self.VendorCodeBytes = Buffer[self._StructSize + UpdateImageSize:]
self._Valid = True
@@ -119,6 +127,7 @@ class FmpCapsuleImageHeaderClass (object):
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateImageSize = {UpdateImageSize:08X}'.format (UpdateImageSize = self.UpdateImageSize))
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateVendorCodeSize = {UpdateVendorCodeSize:08X}'.format (UpdateVendorCodeSize = self.UpdateVendorCodeSize))
print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.UpdateHardwareInstance = {UpdateHardwareInstance:016X}'.format (UpdateHardwareInstance = self.UpdateHardwareInstance))
+ print ('EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.ImageCapsuleSupport = {ImageCapsuleSupport:016X}'.format (ImageCapsuleSupport = self.ImageCapsuleSupport))
print ('sizeof (Payload) = {Size:08X}'.format (Size = len (self.Payload)))
print ('sizeof (VendorCodeBytes) = {Size:08X}'.format (Size = len (self.VendorCodeBytes)))
@@ -153,6 +162,8 @@ class FmpCapsuleHeaderClass (object):
_ItemOffsetSize = struct.calcsize (_ItemOffsetFormat)
EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION = 0x00000001
+ CAPSULE_SUPPORT_AUTHENTICATION = 0x0000000000000001
+ CAPSULE_SUPPORT_DEPENDENCY = 0x0000000000000002
def __init__ (self):
self._Valid = False
@@ -172,8 +183,8 @@ class FmpCapsuleHeaderClass (object):
raise ValueError
return self._EmbeddedDriverList[Index]
- def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0, UpdateImageIndex = 1):
- self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex))
+ def AddPayload (self, UpdateImageTypeId, Payload = b'', VendorCodeBytes = b'', HardwareInstance = 0, UpdateImageIndex = 1, CapsuleSupport = 0):
+ self._PayloadList.append ((UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex, CapsuleSupport))
def GetFmpCapsuleImageHeader (self, Index):
if Index >= len (self._FmpCapsuleImageHeaderList):
@@ -198,13 +209,14 @@ class FmpCapsuleHeaderClass (object):
self._ItemOffsetList.append (Offset)
Offset = Offset + len (EmbeddedDriver)
Index = 1
- for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex) in self._PayloadList:
+ for (UpdateImageTypeId, Payload, VendorCodeBytes, HardwareInstance, UpdateImageIndex, CapsuleSupport) in self._PayloadList:
FmpCapsuleImageHeader = FmpCapsuleImageHeaderClass ()
FmpCapsuleImageHeader.UpdateImageTypeId = UpdateImageTypeId
FmpCapsuleImageHeader.UpdateImageIndex = UpdateImageIndex
FmpCapsuleImageHeader.Payload = Payload
FmpCapsuleImageHeader.VendorCodeBytes = VendorCodeBytes
FmpCapsuleImageHeader.UpdateHardwareInstance = HardwareInstance
+ FmpCapsuleImageHeader.ImageCapsuleSupport = CapsuleSupport
FmpCapsuleImage = FmpCapsuleImageHeader.Encode ()
FmpCapsuleData = FmpCapsuleData + FmpCapsuleImage
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py
index f0d5ec7d58b..3967fa2f513 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/Check.py
@@ -1,6 +1,7 @@
## @file
# This file is used to define checkpoints used by ECC tool
#
+# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
# Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -1103,11 +1104,11 @@ class Check(object):
InfPathList.append(Item[0])
SqlCommand = """
select ID, Path, FullPath from File where upper(FullPath) not in
- (select upper(A.Path) || '\\' || upper(B.Value1) from File as A, INF as B
+ (select upper(A.Path) || '%s' || upper(B.Value1) from File as A, INF as B
where A.ID in (select BelongsToFile from INF where Model = %s group by BelongsToFile) and
B.BelongsToFile = A.ID and B.Model = %s)
and (Model = %s or Model = %s)
- """ % (MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H)
+ """ % (os.sep, MODEL_EFI_SOURCE_FILE, MODEL_EFI_SOURCE_FILE, MODEL_FILE_C, MODEL_FILE_H)
RecordSet = EccGlobalData.gDb.TblInf.Exec(SqlCommand)
for Record in RecordSet:
Path = Record[1]
@@ -1132,9 +1133,9 @@ class Check(object):
BelongsToFile = Pcd[4]
SqlCommand = """
select ID from File where FullPath in
- (select B.Path || '\\' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s
+ (select B.Path || '%s' || A.Value1 from INF as A, File as B where A.Model = %s and A.BelongsToFile = %s
and B.ID = %s and (B.Model = %s or B.Model = %s))
- """ % (MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile, MODEL_FILE_C, MODEL_FILE_H)
+ """ % (os.sep, MODEL_EFI_SOURCE_FILE, BelongsToFile, BelongsToFile, MODEL_FILE_C, MODEL_FILE_H)
TableSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
for Tbl in TableSet:
TblName = 'Identifier' + str(Tbl[0])
@@ -1436,11 +1437,13 @@ class Check(object):
SqlCommand = """select ID, Value from %s where Model = %s""" % (FileTable, MODEL_IDENTIFIER_MACRO_IFNDEF)
RecordSet = EccGlobalData.gDb.TblFile.Exec(SqlCommand)
- for Record in RecordSet:
- Name = Record[1].replace('#ifndef', '').strip()
- if Name[-1] != '_':
+ if RecordSet:
+ # Only check the first ifndef statement of the file
+ FirstDefine = sorted(RecordSet, key=lambda Record: Record[0])[0]
+ Name = FirstDefine[1].replace('#ifndef', '').strip()
+ if Name[0] == '_' or Name[-1] != '_' or Name[-2] == '_':
if not EccGlobalData.gException.IsException(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, Name):
- EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, OtherMsg="The #ifndef name [%s] does not follow the rules" % (Name), BelongsToTable=FileTable, BelongsToItem=Record[0])
+ EccGlobalData.gDb.TblReport.Insert(ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT, OtherMsg="The #ifndef name [%s] does not follow the rules" % (Name), BelongsToTable=FileTable, BelongsToItem=FirstDefine[0])
# Rule for path name, variable name and function name
# 1. First character should be upper case
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/EccToolError.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/EccToolError.py
index 5b5e7e6d899..7765f0e5ff6 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/EccToolError.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/EccToolError.py
@@ -1,6 +1,7 @@
## @file
# Standardized Error Handling infrastructures.
#
+# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -161,7 +162,7 @@ gEccErrorMessage = {
ERROR_NAMING_CONVENTION_CHECK_ALL : "",
ERROR_NAMING_CONVENTION_CHECK_DEFINE_STATEMENT : "Only capital letters are allowed to be used for #define declarations",
ERROR_NAMING_CONVENTION_CHECK_TYPEDEF_STATEMENT : "Only capital letters are allowed to be used for typedef declarations",
- ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT : "The #ifndef at the start of an include file should use both prefix and postfix underscore characters, '_'",
+ ERROR_NAMING_CONVENTION_CHECK_IFNDEF_STATEMENT : "The #ifndef at the start of an include file should have one postfix underscore, and no prefix underscore character '_'",
ERROR_NAMING_CONVENTION_CHECK_PATH_NAME : """Path name does not follow the rules: 1. First character should be upper case 2. Must contain lower case characters 3. No white space characters""",
ERROR_NAMING_CONVENTION_CHECK_VARIABLE_NAME : """Variable name does not follow the rules: 1. First character should be upper case 2. Must contain lower case characters 3. No white space characters 4. Global variable name must start with a 'g'""",
ERROR_NAMING_CONVENTION_CHECK_FUNCTION_NAME : """Function name does not follow the rules: 1. First character should be upper case 2. Must contain lower case characters 3. No white space characters""",
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py
index 1c788702bab..ed2668196d6 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/MetaDataParser.py
@@ -214,8 +214,12 @@ def _IsCopyrightLine (LineContent):
LineContent = LineContent.upper()
Result = False
+ #Support below Copyright format
+ # Copyright (C) 2020 Hewlett Packard Enterprise Development LP<BR>
+ # (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
ReIsCopyrightRe = re.compile(r"""(^|\s)COPYRIGHT *\(""", re.DOTALL)
- if ReIsCopyrightRe.search(LineContent):
+ ReIsCopyrightTypeB = re.compile(r"""(^|\s)\(C\)\s*COPYRIGHT""", re.DOTALL)
+ if ReIsCopyrightRe.search(LineContent) or ReIsCopyrightTypeB.search(LineContent):
Result = True
return Result
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py
index f01f777492c..9c9c7dd0040 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/c.py
@@ -2,6 +2,7 @@
# This file is used to be the c coding style checking of ECC tool
#
# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -64,7 +65,9 @@ def GetIdType(Str):
Type = DataClass.MODEL_UNKNOWN
Str = Str.replace('#', '# ')
List = Str.split()
- if List[1] == 'include':
+ if len(List) < 2:
+ pass
+ elif List[1] == 'include':
Type = DataClass.MODEL_IDENTIFIER_INCLUDE
elif List[1] == 'define':
Type = DataClass.MODEL_IDENTIFIER_MACRO_DEFINE
@@ -1557,7 +1560,7 @@ def CheckFuncLayoutLocalVariable(FullFileName):
continue
for Result in ResultSet:
- if len(Result[1]) > 0 and 'CONST' not in Result[3]:
+ if len(Result[1]) > 0 and 'CONST' not in Result[3] and 'STATIC' not in Result[3]:
PrintErrorMsg(ERROR_C_FUNCTION_LAYOUT_CHECK_NO_INIT_OF_VARIABLE, 'Variable Name: %s' % Result[0], FileTable, Result[2])
def CheckMemberVariableFormat(Name, Value, FileTable, TdId, ModelId):
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/exception.xml b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/exception.xml
index 434ec0140e2..2bd25a9692a 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/exception.xml
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Ecc/exception.xml
@@ -1,3 +1,4 @@
+<<<<<<< .working
<?xml version="1.0" encoding="UTF-8"?>
<ExceptionList xmlns="http://www.uefi.org/2008/2.1" xmlns:xsi="http:/www.w3.org/2001/XMLSchema-instance">
<Copyright>Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.</Copyright>
@@ -312,4 +313,639 @@
<KeyWord>REPORT_STATUS_CODE_WITH_DEVICE_PATH</KeyWord>
<ErrorID>10015</ErrorID>
</Exception>
+||||||| .merge-left.r145445
+<?xml version="1.0" encoding="UTF-8"?>
+<ExceptionList xmlns="http://www.uefi.org/2008/2.1" xmlns:xsi="http:/www.w3.org/2001/XMLSchema-instance">
+ <Copyright>Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.</Copyright>
+ <License>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ </License>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_break</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>InternalX86DisablePaging32</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>InternalX86EnablePaging32</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>InternalLongJump</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>SetJump</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoRead8</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoWrite8</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoRead16</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoWrite16</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoRead32</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoWrite32</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@R1</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@R2</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@Rx</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@R2.</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_DriverUnloadHandler</KeyWord>
+ <ErrorID>8006</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>ASSERT</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>REPORT_STATUS_CODE</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>REPORT_STATUS_CODE_WITH_EXTENDED_DATA</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>REPORT_STATUS_CODE_WITH_DEVICE_PATH</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+=======
+<?xml version="1.0" encoding="UTF-8"?>
+<ExceptionList xmlns="http://www.uefi.org/2008/2.1" xmlns:xsi="http:/www.w3.org/2001/XMLSchema-instance">
+ <Copyright>Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.</Copyright>
+ <License>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ </License>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_break</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>InternalX86DisablePaging32</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>InternalX86EnablePaging32</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>InternalLongJump</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>SetJump</KeyWord>
+ <ErrorID>4002</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoRead8</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoWrite8</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoRead16</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoWrite16</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoRead32</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>IoWrite32</KeyWord>
+ <ErrorID>5001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>5003</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__debugbreak</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__readmsr</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>__writemsr</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedCompareExchange64</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedDecrement</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_InterlockedIncrement</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inp</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpw</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_inpd</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outp</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpw</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_outpd</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ReadWriteBarrier</KeyWord>
+ <ErrorID>7001</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@R1</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@R2</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@Rx</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>@R2.</KeyWord>
+ <ErrorID>9005</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_DriverUnloadHandler</KeyWord>
+ <ErrorID>8006</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>_ModuleEntryPoint</KeyWord>
+ <ErrorID>8006</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>ASSERT</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>REPORT_STATUS_CODE</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>REPORT_STATUS_CODE_WITH_EXTENDED_DATA</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+ <Exception>
+ <KeyWord>REPORT_STATUS_CODE_WITH_DEVICE_PATH</KeyWord>
+ <ErrorID>10015</ErrorID>
+ </Exception>
+>>>>>>> .merge-right.r145445
</ExceptionList> \ No newline at end of file
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py
index 9660f3881b1..4391d333c1f 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/DataSection.py
@@ -80,14 +80,7 @@ class DataSection (DataSectionClassObject):
#Get PE Section alignment when align is set to AUTO
if self.Alignment == 'Auto' and self.SecType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
- ImageObj = PeImageClass (Filename)
- if ImageObj.SectionAlignment < 0x400:
- self.Alignment = str (ImageObj.SectionAlignment)
- elif ImageObj.SectionAlignment < 0x100000:
- self.Alignment = str (ImageObj.SectionAlignment // 0x400) + 'K'
- else:
- self.Alignment = str (ImageObj.SectionAlignment // 0x100000) + 'M'
-
+ self.Alignment = "0"
NoStrip = True
if self.SecType in (BINARY_FILE_TYPE_TE, BINARY_FILE_TYPE_PE32):
if self.KeepReloc is not None:
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py
index f300bdf118a..0e0c0dffa35 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/EfiSection.py
@@ -260,15 +260,8 @@ class EfiSection (EfiSectionClassObject):
#Get PE Section alignment when align is set to AUTO
if self.Alignment == 'Auto' and (SectionType == BINARY_FILE_TYPE_PE32 or SectionType == BINARY_FILE_TYPE_TE):
- ImageObj = PeImageClass (File)
- if ImageObj.SectionAlignment < 0x400:
- Align = str (ImageObj.SectionAlignment)
- elif ImageObj.SectionAlignment < 0x100000:
- Align = str (ImageObj.SectionAlignment // 0x400) + 'K'
- else:
- Align = str (ImageObj.SectionAlignment // 0x100000) + 'M'
-
- if File[(len(File)-4):] == '.efi':
+ Align = "0"
+ if File[(len(File)-4):] == '.efi' and FfsInf.InfModule.BaseName == os.path.basename(File)[:-4]:
MapFile = File.replace('.efi', '.map')
CopyMapFile = os.path.join(OutputPath, ModuleName + '.map')
if IsMakefile:
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
index 49c3adaf739..73ae5b32ab8 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FdfParser.py
@@ -1,7 +1,7 @@
## @file
# parse FDF file
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2015, Hewlett Packard Enterprise Development, L.P.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -18,7 +18,7 @@ from uuid import UUID
from Common.BuildToolError import *
from Common import EdkLogger
-from Common.Misc import PathClass, tdict, ProcessDuplicatedInf
+from Common.Misc import PathClass, tdict, ProcessDuplicatedInf, GuidStructureStringToGuidString
from Common.StringUtils import NormPath, ReplaceMacro
from Common import GlobalData
from Common.Expression import *
@@ -1087,6 +1087,8 @@ class FdfParser:
return False
if GlobalData.gGuidPattern.match(self._Token) is not None:
return True
+ elif self._Token in GlobalData.gGuidDict:
+ return True
else:
self._UndoToken()
return False
@@ -2248,6 +2250,8 @@ class FdfParser:
if not self._GetNextGuid():
raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
FvObj.FvNameGuid = self._Token
@@ -2459,6 +2463,8 @@ class FdfParser:
raise Warning.ExpectedEquals(self.FileName, self.CurrentLineNumber)
if not self._GetNextGuid():
raise Warning.Expected("GUID value", self.FileName, self.CurrentLineNumber)
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
FfsInfObj.OverrideGuid = self._Token
if self._IsKeyword("RuleOverride"):
@@ -2550,6 +2556,8 @@ class FdfParser:
raise Warning.Expected("')'", self.FileName, self.CurrentLineNumber)
self._Token = 'PCD('+PcdPair[1]+TAB_SPLIT+PcdPair[0]+')'
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
FfsFileObj.NameGuid = self._Token
self._GetFilePart(FfsFileObj)
@@ -2980,6 +2988,8 @@ class FdfParser:
elif self._IsKeyword("GUIDED"):
GuidValue = None
if self._GetNextGuid():
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
GuidValue = self._Token
AttribDict = self._GetGuidAttrib()
@@ -3494,8 +3504,6 @@ class FdfParser:
raise Warning.Expected("'.'", self.FileName, self.CurrentLineNumber)
Arch = self._SkippedChars.rstrip(TAB_SPLIT)
- if Arch.upper() not in ARCH_SET_FULL:
- raise Warning("Unknown Arch '%s'" % Arch, self.FileName, self.CurrentLineNumber)
ModuleType = self._GetModuleType()
@@ -4049,6 +4057,8 @@ class FdfParser:
elif self._IsKeyword("GUIDED"):
GuidValue = None
if self._GetNextGuid():
+ if self._Token in GlobalData.gGuidDict:
+ self._Token = GuidStructureStringToGuidString(GlobalData.gGuidDict[self._Token]).upper()
GuidValue = self._Token
if self._IsKeyword("$(NAMED_GUID)"):
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py
index dab45a7a547..7ab1507d04d 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/FfsFileStatement.py
@@ -21,6 +21,7 @@ from .GuidSection import GuidSection
from .FvImageSection import FvImageSection
from .Ffs import FdfFvFileTypeToFileType
from .GenFdsGlobalVariable import GenFdsGlobalVariable
+import shutil
## generate FFS from FILE
#
@@ -67,6 +68,8 @@ class FileStatement (FileStatementClassObject):
if FvName:
Str += FvName
OutputDir = os.path.join(GenFdsGlobalVariable.FfsDir, Str)
+ if os.path.exists(OutputDir):
+ shutil.rmtree(OutputDir)
if not os.path.exists(OutputDir):
os.makedirs(OutputDir)
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py
index 0150688fa54..74dca772a5a 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFds.py
@@ -633,7 +633,10 @@ class GenFds(object):
else:
Percentage = str((UsedSizeValue + 0.0) / TotalSizeValue)[0:4].lstrip('0.')
- GenFdsGlobalVariable.QuietLogger(Name + ' ' + '[' + Percentage + '%Full] ' + str(TotalSizeValue) + ' total, ' + str(UsedSizeValue) + ' used, ' + str(FreeSizeValue) + ' free') # VBox: Same as above.
+ GenFdsGlobalVariable.QuietLogger(Name + ' ' + '[' + Percentage + '%Full] '\
+ + str(TotalSizeValue) + ' (' + hex(TotalSizeValue) + ')' + ' total, '\
+ + str(UsedSizeValue) + ' (' + hex(UsedSizeValue) + ')' + ' used, '\
+ + str(FreeSizeValue) + ' (' + hex(FreeSizeValue) + ')' + ' free') # VBox: Same as above
## PreprocessImage()
#
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
index 935a6925e5a..7454359c5bc 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/GenFdsGlobalVariable.py
@@ -1,7 +1,7 @@
## @file
# Global variables for GenFds
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -27,10 +27,12 @@ from Common.TargetTxtClassObject import TargetTxtDict
from Common.ToolDefClassObject import ToolDefDict
from AutoGen.BuildEngine import ToolBuildRule
import Common.DataType as DataType
-from Common.Misc import PathClass
+from Common.Misc import PathClass,CreateDirectory
from Common.LongFilePathSupport import OpenLongFilePath as open
from Common.MultipleWorkspace import MultipleWorkspace as mws
import Common.GlobalData as GlobalData
+from Common.BuildToolError import *
+from AutoGen.AutoGen import CalculatePriorityValue
## Global variables
#
@@ -463,12 +465,28 @@ class GenFdsGlobalVariable:
GenFdsGlobalVariable.SecCmdList.append(' '.join(Cmd).strip())
else:
SectionData = array('B', [0, 0, 0, 0])
- SectionData.fromstring(Ui.encode("utf_16_le"))
+ SectionData.fromlist(array('B',Ui.encode('utf-16-le')).tolist())
SectionData.append(0)
SectionData.append(0)
Len = len(SectionData)
GenFdsGlobalVariable.SectionHeader.pack_into(SectionData, 0, Len & 0xff, (Len >> 8) & 0xff, (Len >> 16) & 0xff, 0x15)
- SaveFileOnChange(Output, SectionData.tostring())
+
+
+ DirName = os.path.dirname(Output)
+ if not CreateDirectory(DirName):
+ EdkLogger.error(None, FILE_CREATE_FAILURE, "Could not create directory %s" % DirName)
+ else:
+ if DirName == '':
+ DirName = os.getcwd()
+ if not os.access(DirName, os.W_OK):
+ EdkLogger.error(None, PERMISSION_FAILURE, "Do not have write permission on directory %s" % DirName)
+
+ try:
+ with open(Output, "wb") as Fd:
+ SectionData.tofile(Fd)
+ Fd.flush()
+ except IOError as X:
+ EdkLogger.error(None, FILE_CREATE_FAILURE, ExtraData='IOError %s' % X)
elif Ver:
Cmd += ("-n", Ver)
@@ -839,6 +857,10 @@ class GenFdsGlobalVariable:
# @param NameGuid The Guid name
#
def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
+ if GenFdsGlobalVariable.GuidToolDefinition:
+ if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
+ return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
+
ToolDefObj = ToolDefDict((os.path.join(os.getenv("WORKSPACE"), "Conf")))
ToolDef = ToolDefObj.ToolDef
ToolDb = ToolDef.ToolsDefTxtDatabase
@@ -853,73 +875,159 @@ def FindExtendTool(KeyStringList, CurrentArchList, NameGuid):
if Target + '_' + ToolChain + '_' + Arch not in KeyStringList:
KeyStringList.append(Target + '_' + ToolChain + '_' + Arch)
- if GenFdsGlobalVariable.GuidToolDefinition:
- if NameGuid in GenFdsGlobalVariable.GuidToolDefinition:
- return GenFdsGlobalVariable.GuidToolDefinition[NameGuid]
-
- ToolDefinition = ToolDef.ToolsDefTxtDictionary
ToolPathTmp = None
ToolOption = None
- ToolPathKey = None
- ToolOptionKey = None
- KeyList = None
- for tool_def in ToolDefinition.items():
- if NameGuid.lower() == tool_def[1].lower():
- KeyList = tool_def[0].split('_')
- Key = KeyList[0] + \
- '_' + \
- KeyList[1] + \
- '_' + \
- KeyList[2]
- if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
- ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
- ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
- ToolPath = ToolDefinition.get(ToolPathKey)
- ToolOption = ToolDefinition.get(ToolOptionKey)
- if ToolPathTmp is None:
- ToolPathTmp = ToolPath
- else:
- if ToolPathTmp != ToolPath:
- EdkLogger.error("GenFds", GENFDS_ERROR, "Don't know which tool to use, %s or %s ?" % (ToolPathTmp, ToolPath))
-
- BuildOption = {}
for Arch in CurrentArchList:
- Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]
- # key is (ToolChainFamily, ToolChain, CodeBase)
- for item in Platform.BuildOptions:
- if '_PATH' in item[1] or '_FLAGS' in item[1] or '_GUID' in item[1]:
- if not item[0] or (item[0] and GenFdsGlobalVariable.ToolChainFamily== item[0]):
- if item[1] not in BuildOption:
- BuildOption[item[1]] = Platform.BuildOptions[item]
- if BuildOption:
- ToolList = [DataType.TAB_TOD_DEFINES_TARGET, DataType.TAB_TOD_DEFINES_TOOL_CHAIN_TAG, DataType.TAB_TOD_DEFINES_TARGET_ARCH]
- for Index in range(2, -1, -1):
- for Key in list(BuildOption.keys()):
- List = Key.split('_')
- if List[Index] == DataType.TAB_STAR:
- for String in ToolDb[ToolList[Index]]:
- if String in [Arch, GenFdsGlobalVariable.TargetName, GenFdsGlobalVariable.ToolChainTag]:
- List[Index] = String
- NewKey = '%s_%s_%s_%s_%s' % tuple(List)
- if NewKey not in BuildOption:
- BuildOption[NewKey] = BuildOption[Key]
- continue
- del BuildOption[Key]
- elif List[Index] not in ToolDb[ToolList[Index]]:
- del BuildOption[Key]
- if BuildOption:
- if not KeyList:
- for Op in BuildOption:
- if NameGuid == BuildOption[Op]:
- KeyList = Op.split('_')
- Key = KeyList[0] + '_' + KeyList[1] +'_' + KeyList[2]
- if Key in KeyStringList and KeyList[4] == DataType.TAB_GUID:
- ToolPathKey = Key + '_' + KeyList[3] + '_PATH'
- ToolOptionKey = Key + '_' + KeyList[3] + '_FLAGS'
- if ToolPathKey in BuildOption:
- ToolPathTmp = BuildOption[ToolPathKey]
- if ToolOptionKey in BuildOption:
- ToolOption = BuildOption[ToolOptionKey]
+ MatchItem = None
+ MatchPathItem = None
+ MatchOptionsItem = None
+ for KeyString in KeyStringList:
+ KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_')
+ if KeyStringArch != Arch:
+ continue
+ for Item in ToolDef.ToolsDefTxtDictionary:
+ if len(Item.split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemAttr != DataType.TAB_GUID:
+ # Not GUID attribute
+ continue
+ if ToolDef.ToolsDefTxtDictionary[Item].lower() != NameGuid.lower():
+ # No GUID value match
+ continue
+ if MatchItem:
+ if MatchItem.split('_')[3] == ItemTool:
+ # Tool name is the same
+ continue
+ if CalculatePriorityValue(MatchItem) > CalculatePriorityValue(Item):
+ # Current MatchItem is higher priority than new match item
+ continue
+ MatchItem = Item
+ if not MatchItem:
+ continue
+ ToolName = MatchItem.split('_')[3]
+ for Item in ToolDef.ToolsDefTxtDictionary:
+ if len(Item.split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item.split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemTool != ToolName:
+ continue
+ if ItemAttr == 'PATH':
+ if MatchPathItem:
+ if CalculatePriorityValue(MatchPathItem) <= CalculatePriorityValue(Item):
+ MatchPathItem = Item
+ else:
+ MatchPathItem = Item
+ if ItemAttr == 'FLAGS':
+ if MatchOptionsItem:
+ if CalculatePriorityValue(MatchOptionsItem) <= CalculatePriorityValue(Item):
+ MatchOptionsItem = Item
+ else:
+ MatchOptionsItem = Item
+ if MatchPathItem:
+ ToolPathTmp = ToolDef.ToolsDefTxtDictionary[MatchPathItem]
+ if MatchOptionsItem:
+ ToolOption = ToolDef.ToolsDefTxtDictionary[MatchOptionsItem]
+ for Arch in CurrentArchList:
+ MatchItem = None
+ MatchPathItem = None
+ MatchOptionsItem = None
+ for KeyString in KeyStringList:
+ KeyStringBuildTarget, KeyStringToolChain, KeyStringArch = KeyString.split('_')
+ if KeyStringArch != Arch:
+ continue
+ Platform = GenFdsGlobalVariable.WorkSpace.BuildObject[GenFdsGlobalVariable.ActivePlatform, Arch, KeyStringBuildTarget, KeyStringToolChain]
+ for Item in Platform.BuildOptions:
+ if len(Item[1].split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemAttr != DataType.TAB_GUID:
+ # Not GUID attribute match
+ continue
+ if Platform.BuildOptions[Item].lower() != NameGuid.lower():
+ # No GUID value match
+ continue
+ if MatchItem:
+ if MatchItem[1].split('_')[3] == ItemTool:
+ # Tool name is the same
+ continue
+ if CalculatePriorityValue(MatchItem[1]) > CalculatePriorityValue(Item[1]):
+ # Current MatchItem is higher priority than new match item
+ continue
+ MatchItem = Item
+ if not MatchItem:
+ continue
+ ToolName = MatchItem[1].split('_')[3]
+ for Item in Platform.BuildOptions:
+ if len(Item[1].split('_')) < 5:
+ continue
+ ItemTarget, ItemToolChain, ItemArch, ItemTool, ItemAttr = Item[1].split('_')
+ if ItemTarget == DataType.TAB_STAR:
+ ItemTarget = KeyStringBuildTarget
+ if ItemToolChain == DataType.TAB_STAR:
+ ItemToolChain = KeyStringToolChain
+ if ItemArch == DataType.TAB_STAR:
+ ItemArch = KeyStringArch
+ if ItemTarget != KeyStringBuildTarget:
+ continue
+ if ItemToolChain != KeyStringToolChain:
+ continue
+ if ItemArch != KeyStringArch:
+ continue
+ if ItemTool != ToolName:
+ continue
+ if ItemAttr == 'PATH':
+ if MatchPathItem:
+ if CalculatePriorityValue(MatchPathItem[1]) <= CalculatePriorityValue(Item[1]):
+ MatchPathItem = Item
+ else:
+ MatchPathItem = Item
+ if ItemAttr == 'FLAGS':
+ if MatchOptionsItem:
+ if CalculatePriorityValue(MatchOptionsItem[1]) <= CalculatePriorityValue(Item[1]):
+ MatchOptionsItem = Item
+ else:
+ MatchOptionsItem = Item
+ if MatchPathItem:
+ ToolPathTmp = Platform.BuildOptions[MatchPathItem]
+ if MatchOptionsItem:
+ ToolOption = Platform.BuildOptions[MatchOptionsItem]
GenFdsGlobalVariable.GuidToolDefinition[NameGuid] = (ToolPathTmp, ToolOption)
return ToolPathTmp, ToolOption
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py
index 3bda2001722..a338cffe28f 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/GenFds/Section.py
@@ -140,22 +140,6 @@ class Section (SectionClassObject):
FileList.append(File.Path)
if (not IsMakefile and Suffix is not None and os.path.exists(FfsInf.EfiOutputPath)) or (IsMakefile and Suffix is not None):
- #
- # Get Makefile path and time stamp
- #
- MakefileDir = FfsInf.EfiOutputPath[:-len('OUTPUT')]
- Makefile = os.path.join(MakefileDir, 'Makefile')
- if not os.path.exists(Makefile):
- Makefile = os.path.join(MakefileDir, 'GNUmakefile')
- if os.path.exists(Makefile):
- # Update to search files with suffix in all sub-dirs.
- Tuple = os.walk(FfsInf.EfiOutputPath)
- for Dirpath, Dirnames, Filenames in Tuple:
- for F in Filenames:
- if os.path.splitext(F)[1] == Suffix:
- FullName = os.path.join(Dirpath, F)
- if os.path.getmtime(FullName) > os.path.getmtime(Makefile):
- FileList.append(FullName)
if not FileList:
SuffixMap = FfsInf.GetFinalTargetSuffixMap()
if Suffix in SuffixMap:
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/README.md b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/README.md
new file mode 100644
index 00000000000..7266b8f84f8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/README.md
@@ -0,0 +1,29 @@
+# Edk2 Basetools
+
+This folder has traditionally held the source of Python based tools used by EDK2.
+The official repo this source has moved to https://github.com/tianocore/edk2-basetools.
+This folder will remain in the tree until the next stable release (expected 202102).
+There is a new folder under Basetools `BinPipWrappers` that uses the pip module rather than this tree for Basetools.
+By adding the scope `pipbuild-win` or `pipbuild-unix` (depending on your host system), the SDE will use the
+`BinPipWrappers` instead of the regular `BinWrappers`.
+
+## Why Move It?
+
+The discussion is on the mailing list. The RFC is here: https://edk2.groups.io/g/rfc/topic/74009714#270
+The benefits allow for the Basetools project to be used separately from EDK2 itself as well as offering it in a
+globally accessible manner.
+This makes it much easier to build a module using Basetools.
+Separating the Basetools into their own repo allows for easier CI and contribution process.
+Additional pros, cons, and process can be found on the mailing list.
+
+## How Do I Install It?
+
+By default, EDK2 is tied to and tested with a specific version of the Basetools through `pip-requirements.txt`.
+You can simply run:
+
+```bash
+pip install -r pip-requirements.txt
+```
+
+This will install the required module, thought we strongly suggest setting up a virtual environment.
+Additionally, you can also install a local clone of the Basetools as well as a specific git commit.
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/Split.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/Split.py
new file mode 100644
index 00000000000..e0d91e4e1e6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/Split.py
@@ -0,0 +1,210 @@
+# @file
+# Split a file into two pieces at the request offset.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
+#
+import argparse
+import os
+import io
+import shutil
+import logging
+import sys
+import tempfile
+
+parser = argparse.ArgumentParser(description='''
+SplitFile creates two Binary files either in the same directory as the current working directory or in the specified directory.
+''')
+parser.add_argument("-f", "--filename", dest="inputfile",
+ required=True, help="The input file to split tool.")
+parser.add_argument("-s", "--split", dest="position",
+ required=True, help="The number of bytes in the first file. The valid format are HEX, Decimal and Decimal[KMG].")
+parser.add_argument("-p", "--prefix", dest="output",
+ help="The output folder.")
+parser.add_argument("-o", "--firstfile", help="The first file name")
+parser.add_argument("-t", "--secondfile", help="The second file name")
+parser.add_argument("--version", action="version", version='%(prog)s Version 2.0',
+ help="Print debug information.")
+
+group = parser.add_mutually_exclusive_group()
+group.add_argument("-v", "--verbose", action="store_true",
+ help="Print debug information.")
+group.add_argument("-q", "--quiet", action="store_true",
+ help="Disable all messages except fatal errors")
+
+SizeDict = {
+ "K": 1024,
+ "M": 1024*1024,
+ "G": 1024*1024*1024
+}
+
+
+def GetPositionValue(position):
+ '''
+ Parse the string of the argument position and return a decimal number.
+ The valid position formats are
+ 1. HEX
+ e.g. 0x1000 or 0X1000
+ 2. Decimal
+ e.g. 100
+ 3. Decimal[KMG]
+ e.g. 100K or 100M or 100G or 100k or 100m or 100g
+ '''
+ logger = logging.getLogger('Split')
+ PosVal = 0
+ header = position[:2].upper()
+ tailer = position[-1].upper()
+
+ try:
+ if tailer in SizeDict:
+ PosVal = int(position[:-1]) * SizeDict[tailer]
+ else:
+ if header == "0X":
+ PosVal = int(position, 16)
+ else:
+ PosVal = int(position)
+ except Exception as e:
+ logger.error(
+ "The parameter %s format is incorrect. The valid format is HEX, Decimal and Decimal[KMG]." % position)
+ raise(e)
+
+ return PosVal
+
+
+def getFileSize(filename):
+ '''
+ Read the input file and return the file size.
+ '''
+ logger = logging.getLogger('Split')
+ length = 0
+ try:
+ with open(filename, "rb") as fin:
+ fin.seek(0, io.SEEK_END)
+ length = fin.tell()
+ except Exception as e:
+ logger.error("Access file failed: %s", filename)
+ raise(e)
+
+ return length
+
+def getoutputfileabs(inputfile, prefix, outputfile,index):
+ inputfile = os.path.abspath(inputfile)
+ if outputfile is None:
+ if prefix is None:
+ outputfileabs = os.path.join(os.path.dirname(inputfile), "{}{}".format(os.path.basename(inputfile),index))
+ else:
+ if os.path.isabs(prefix):
+ outputfileabs = os.path.join(prefix, "{}{}".format(os.path.basename(inputfile),index))
+ else:
+ outputfileabs = os.path.join(os.getcwd(), prefix, "{}{}".format(os.path.basename(inputfile),index))
+ elif not os.path.isabs(outputfile):
+ if prefix is None:
+ outputfileabs = os.path.join(os.getcwd(), outputfile)
+ else:
+ if os.path.isabs(prefix):
+ outputfileabs = os.path.join(prefix, outputfile)
+ else:
+ outputfileabs = os.path.join(os.getcwd(), prefix, outputfile)
+ else:
+ outputfileabs = outputfile
+ return outputfileabs
+
+def splitFile(inputfile, position, outputdir=None, outputfile1=None, outputfile2=None):
+ '''
+ Split the inputfile into outputfile1 and outputfile2 from the position.
+ '''
+ logger = logging.getLogger('Split')
+
+ if not os.path.exists(inputfile):
+ logger.error("File Not Found: %s" % inputfile)
+ raise(Exception)
+
+ if outputfile1 and outputfile2 and outputfile1 == outputfile2:
+ logger.error(
+ "The firstfile and the secondfile can't be the same: %s" % outputfile1)
+ raise(Exception)
+
+ # Create dir for the output files
+ try:
+
+ outputfile1 = getoutputfileabs(inputfile, outputdir, outputfile1,1)
+ outputfolder = os.path.dirname(outputfile1)
+ if not os.path.exists(outputfolder):
+ os.makedirs(outputfolder)
+
+ outputfile2 = getoutputfileabs(inputfile, outputdir, outputfile2,2)
+ outputfolder = os.path.dirname(outputfile2)
+ if not os.path.exists(outputfolder):
+ os.makedirs(outputfolder)
+
+ except Exception as e:
+ logger.error("Can't make dir: %s" % outputfolder)
+ raise(e)
+
+ if position <= 0:
+ if outputfile2 != os.path.abspath(inputfile):
+ shutil.copy2(os.path.abspath(inputfile), outputfile2)
+ with open(outputfile1, "wb") as fout:
+ fout.write(b'')
+ else:
+ inputfilesize = getFileSize(inputfile)
+ if position >= inputfilesize:
+ if outputfile1 != os.path.abspath(inputfile):
+ shutil.copy2(os.path.abspath(inputfile), outputfile1)
+ with open(outputfile2, "wb") as fout:
+ fout.write(b'')
+ else:
+ try:
+ tempdir = tempfile.mkdtemp()
+ tempfile1 = os.path.join(tempdir, "file1.bin")
+ tempfile2 = os.path.join(tempdir, "file2.bin")
+ with open(inputfile, "rb") as fin:
+ content1 = fin.read(position)
+ with open(tempfile1, "wb") as fout1:
+ fout1.write(content1)
+
+ content2 = fin.read(inputfilesize - position)
+ with open(tempfile2, "wb") as fout2:
+ fout2.write(content2)
+ shutil.copy2(tempfile1, outputfile1)
+ shutil.copy2(tempfile2, outputfile2)
+ except Exception as e:
+ logger.error("Split file failed")
+ raise(e)
+ finally:
+ if os.path.exists(tempdir):
+ shutil.rmtree(tempdir)
+
+
+def main():
+ args = parser.parse_args()
+ status = 0
+
+ logger = logging.getLogger('Split')
+ if args.quiet:
+ logger.setLevel(logging.CRITICAL)
+ if args.verbose:
+ logger.setLevel(logging.DEBUG)
+
+ lh = logging.StreamHandler(sys.stdout)
+ lf = logging.Formatter("%(levelname)-8s: %(message)s")
+ lh.setFormatter(lf)
+ logger.addHandler(lh)
+
+ try:
+ position = GetPositionValue(args.position)
+ splitFile(args.inputfile, position, args.output,
+ args.firstfile, args.secondfile)
+ except Exception as e:
+ status = 1
+
+ return status
+
+
+if __name__ == "__main__":
+ exit(main())
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/__init__.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/__init__.py
new file mode 100644
index 00000000000..c05ffbbd8d4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Split/__init__.py
@@ -0,0 +1,10 @@
+# @file
+# Split a file into two pieces at the request offset.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py
index ef102b911b5..28801389fcd 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/TargetTool/TargetTool.py
@@ -1,7 +1,7 @@
## @file
# Target Tool Parser
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -197,7 +197,7 @@ def RangeCheckCallback(option, opt_str, value, parser):
def MyOptionParser():
parser = OptionParser(version=__version__, prog="TargetTool.exe", usage=__usage__, description=__copyright__)
- parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64', '0'], dest="TARGET_ARCH",
+ parser.add_option("-a", "--arch", action="append", dest="TARGET_ARCH",
help="ARCHS is one of list: IA32, X64, ARM, AARCH64 or EBC, which replaces target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option. 0 will clear this setting in target.txt and can't combine with other value.")
parser.add_option("-p", "--platform", action="callback", type="string", dest="DSCFILE", callback=SingleCheckCallback,
help="Specify a DSC file, which replace target.txt's ACTIVE_PLATFORM definition. 0 will clear this setting in target.txt and can't combine with other value.")
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py
index d7479324cae..548f53a2d7d 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Trim/Trim.py
@@ -281,9 +281,11 @@ def DoInclude(Source, Indent='', IncludePathList=[], LocalSearchPath=None, Inclu
F = File.readlines()
break
else:
- EdkLogger.error("Trim", "Failed to find include file %s" % Source)
+ EdkLogger.warn("Trim", "Failed to find include file %s" % Source)
+ return []
except:
- EdkLogger.error("Trim", FILE_OPEN_FAILURE, ExtraData=Source)
+ EdkLogger.warn("Trim", FILE_OPEN_FAILURE, ExtraData=Source)
+ return []
# avoid A "include" B and B "include" A
@@ -370,8 +372,7 @@ def TrimAslFile(Source, Target, IncludePathFile,AslDeps = False):
AslIncludes = []
Lines = DoInclude(Source, '', IncludePathList,IncludeFileList=AslIncludes,filetype='ASL')
AslIncludes = [item for item in AslIncludes if item !=Source]
- if AslDeps and AslIncludes:
- SaveFileOnChange(os.path.join(os.path.dirname(Target),os.path.basename(Source))+".trim.deps", " \\\n".join([Source+":"] +AslIncludes),False)
+ SaveFileOnChange(os.path.join(os.path.dirname(Target),os.path.basename(Source))+".trim.deps", " \\\n".join([Source+":"] +AslIncludes),False)
#
# Undef MIN and MAX to avoid collision in ASL source code
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py
index 8692e80369a..a4be167de31 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/BuildClassObject.py
@@ -70,6 +70,7 @@ class PcdClassObject(object):
self.DscDefaultValue = Value
self.PcdValueFromComm = ""
self.PcdValueFromFdf = ""
+ self.PcdValueFromComponents = {} #{ModuleGuid:value, file_path,lineNo}
self.CustomAttribute = {}
self.UserDefinedDefaultStoresFlag = UserDefinedDefaultStoresFlag
self._Capacity = None
@@ -298,6 +299,7 @@ class StructurePcd(PcdClassObject):
self.PcdFieldValueFromComm = OrderedDict()
self.PcdFieldValueFromFdf = OrderedDict()
self.DefaultFromDSC=None
+ self.PcdFiledValueFromDscComponent = OrderedDict()
def __repr__(self):
return self.TypeName
@@ -324,6 +326,12 @@ class StructurePcd(PcdClassObject):
self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr][FieldName] = [Value.strip(), FileName, LineNo]
return self.SkuOverrideValues[SkuName][DefaultStoreName][DimensionAttr][FieldName]
+ def AddComponentOverrideValue(self,FieldName, Value, ModuleGuid, FileName="", LineNo=0, DimensionAttr = '-1'):
+ self.PcdFiledValueFromDscComponent.setdefault(ModuleGuid, OrderedDict())
+ self.PcdFiledValueFromDscComponent[ModuleGuid].setdefault(DimensionAttr,OrderedDict())
+ self.PcdFiledValueFromDscComponent[ModuleGuid][DimensionAttr][FieldName] = [Value.strip(), FileName, LineNo]
+ return self.PcdFiledValueFromDscComponent[ModuleGuid][DimensionAttr][FieldName]
+
def SetPcdMode (self, PcdMode):
self.PcdMode = PcdMode
@@ -365,6 +373,7 @@ class StructurePcd(PcdClassObject):
self.ValueChain = PcdObject.ValueChain if PcdObject.ValueChain else self.ValueChain
self.PcdFieldValueFromComm = PcdObject.PcdFieldValueFromComm if PcdObject.PcdFieldValueFromComm else self.PcdFieldValueFromComm
self.PcdFieldValueFromFdf = PcdObject.PcdFieldValueFromFdf if PcdObject.PcdFieldValueFromFdf else self.PcdFieldValueFromFdf
+ self.PcdFiledValueFromDscComponent = PcdObject.PcdFiledValueFromDscComponent if PcdObject.PcdFiledValueFromDscComponent else self.PcdFiledValueFromDscComponent
def __deepcopy__(self,memo):
new_pcd = StructurePcd()
@@ -383,6 +392,7 @@ class StructurePcd(PcdClassObject):
new_pcd.SkuOverrideValues = CopyDict(self.SkuOverrideValues)
new_pcd.PcdFieldValueFromComm = CopyDict(self.PcdFieldValueFromComm)
new_pcd.PcdFieldValueFromFdf = CopyDict(self.PcdFieldValueFromFdf)
+ new_pcd.PcdFiledValueFromDscComponent = CopyDict(self.PcdFiledValueFromDscComponent)
new_pcd.ValueChain = {item for item in self.ValueChain}
return new_pcd
@@ -463,6 +473,8 @@ class ModuleBuildClassObject(object):
self.Pcds = {}
self.BuildOptions = {}
self.Depex = {}
+ self.StrPcdSet = []
+ self.StrPcdOverallValue = {}
## Convert the class to a string
#
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py
index 6b66cd75771..eeefc9f57b8 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/DscBuildData.py
@@ -755,9 +755,10 @@ class DscBuildData(PlatformBuildClassObject):
EdkLogger.error('build', ErrorCode, File=self.MetaFile, Line=LineNo,
ExtraData=ErrorInfo)
+ ModuleBuildData = self._Bdb[ModuleFile, self._Arch, self._Target, self._Toolchain]
Module = ModuleBuildClassObject()
Module.MetaFile = ModuleFile
-
+ Module.Guid = ModuleBuildData.Guid
# get module private library instance
RecordList = self._RawData[MODEL_EFI_LIBRARY_CLASS, self._Arch, None, ModuleId]
for Record in RecordList:
@@ -778,7 +779,7 @@ class DscBuildData(PlatformBuildClassObject):
Module.LibraryClasses[LibraryClass] = LibraryPath
if LibraryPath not in self.LibraryInstances:
self.LibraryInstances.append(LibraryPath)
-
+ S_PcdSet = []
# get module private PCD setting
for Type in [MODEL_PCD_FIXED_AT_BUILD, MODEL_PCD_PATCHABLE_IN_MODULE, \
MODEL_PCD_FEATURE_FLAG, MODEL_PCD_DYNAMIC, MODEL_PCD_DYNAMIC_EX]:
@@ -792,20 +793,31 @@ class DscBuildData(PlatformBuildClassObject):
else:
MaxDatumSize = ''
TypeString = self._PCD_TYPE_STRING_[Type]
- Pcd = PcdClassObject(
- PcdCName,
- TokenSpaceGuid,
- TypeString,
- '',
- DefaultValue,
- '',
- MaxDatumSize,
- {},
- False,
- None
- )
- Module.Pcds[PcdCName, TokenSpaceGuid] = Pcd
+ TCName,PCName,DimensionAttr,Field = self.ParsePcdNameStruct(TokenSpaceGuid, PcdCName)
+
+ if ("." in TokenSpaceGuid or "[" in PcdCName):
+ S_PcdSet.append([ TCName,PCName,DimensionAttr,Field, ModuleBuildData.Guid, "", Dummy5, AnalyzePcdExpression(Setting)[0]])
+ DefaultValue = ''
+ if ( PCName,TCName) not in Module.Pcds:
+ Pcd = PcdClassObject(
+ PCName,
+ TCName,
+ TypeString,
+ '',
+ DefaultValue,
+ '',
+ MaxDatumSize,
+ {},
+ False,
+ None,
+ IsDsc=True)
+ Module.Pcds[PCName, TCName] = Pcd
+
+ Module.StrPcdSet = S_PcdSet
+ for TCName,PCName, _,_,_,_,_,_ in S_PcdSet:
+ if (PCName,TCName) in Module.Pcds:
+ Module.StrPcdOverallValue[(PCName,TCName)] = Module.Pcds[(PCName,TCName)].DefaultValue, self.MetaFile,Dummy5
# get module private build options
RecordList = self._RawData[MODEL_META_DATA_BUILD_OPTION, self._Arch, None, ModuleId]
for ToolChainFamily, ToolChain, Option, Dummy1, Dummy2, Dummy3, Dummy4, Dummy5 in RecordList:
@@ -822,7 +834,9 @@ class DscBuildData(PlatformBuildClassObject):
File=self.MetaFile, ExtraData=str(ModuleFile), Line=LineNo)
ModuleFile = ProcessDuplicatedInf(ModuleFile, RecordList[0][2], GlobalData.gWorkspace)
ModuleFile.Arch = self._Arch
-
+ Module.Guid = RecordList[0][2]
+ for item in Module.StrPcdSet:
+ item[4] = RecordList[0][2]
self._Modules[ModuleFile] = Module
return self._Modules
@@ -1499,7 +1513,15 @@ class DscBuildData(PlatformBuildClassObject):
File=self.MetaFile, Line = Dummy5)
S_PcdSet.append([ TCName,PCName,DimensionAttr,Field, SkuName, default_store, Dummy5, AnalyzePcdExpression(Setting)[0]])
-
+ ModuleScopeOverallValue = {}
+ for m in self.Modules.values():
+ mguid = m.Guid
+ if m.StrPcdSet:
+ S_PcdSet.extend(m.StrPcdSet)
+ mguid = m.StrPcdSet[0][4]
+ for (PCName,TCName) in m.StrPcdOverallValue:
+ Value, dsc_file, lineNo = m.StrPcdOverallValue[(PCName,TCName)]
+ ModuleScopeOverallValue.setdefault((PCName,TCName),{})[mguid] = Value, dsc_file, lineNo
# handle pcd value override
StrPcdSet = DscBuildData.GetStructurePcdInfo(S_PcdSet)
S_pcd_set = OrderedDict()
@@ -1517,6 +1539,11 @@ class DscBuildData(PlatformBuildClassObject):
for str_pcd_data in StrPcdSet[str_pcd]:
if str_pcd_data[4] in SkuIds:
str_pcd_obj_str.AddOverrideValue(str_pcd_data[3], str(str_pcd_data[7]), TAB_DEFAULT if str_pcd_data[4] == TAB_COMMON else str_pcd_data[4], TAB_DEFAULT_STORES_DEFAULT if str_pcd_data[5] == TAB_COMMON else str_pcd_data[5], self.MetaFile.File if self.WorkspaceDir not in self.MetaFile.File else self.MetaFile.File[len(self.WorkspaceDir) if self.WorkspaceDir.endswith(os.path.sep) else len(self.WorkspaceDir)+1:], LineNo=str_pcd_data[6],DimensionAttr = str_pcd_data[2])
+ elif GlobalData.gGuidPattern.match(str_pcd_data[4]):
+ str_pcd_obj_str.AddComponentOverrideValue(str_pcd_data[3], str(str_pcd_data[7]), str_pcd_data[4].replace("-","S"), self.MetaFile.File if self.WorkspaceDir not in self.MetaFile.File else self.MetaFile.File[len(self.WorkspaceDir) if self.WorkspaceDir.endswith(os.path.sep) else len(self.WorkspaceDir)+1:], LineNo=str_pcd_data[6],DimensionAttr = str_pcd_data[2])
+ PcdComponentValue = ModuleScopeOverallValue.get((str_pcd_obj_str.TokenCName,str_pcd_obj_str.TokenSpaceGuidCName))
+ for module_guid in PcdComponentValue:
+ str_pcd_obj_str.PcdValueFromComponents[module_guid.replace("-","S")] = PcdComponentValue[module_guid]
S_pcd_set[str_pcd[1], str_pcd[0]] = str_pcd_obj_str
# Add the Structure PCD that only defined in DEC, don't have override in DSC file
@@ -1575,7 +1602,10 @@ class DscBuildData(PlatformBuildClassObject):
stru_pcd.ValueChain.add((skuid, defaultstoreid))
S_pcd_set = DscBuildData.OverrideByFdf(S_pcd_set,self.WorkspaceDir)
S_pcd_set = DscBuildData.OverrideByComm(S_pcd_set)
+
+ # Create a tool to caculate structure pcd value
Str_Pcd_Values = self.GenerateByteArrayValue(S_pcd_set)
+
if Str_Pcd_Values:
for (skuname, StoreName, PcdGuid, PcdName, PcdValue) in Str_Pcd_Values:
str_pcd_obj = S_pcd_set.get((PcdName, PcdGuid))
@@ -1593,6 +1623,14 @@ class DscBuildData(PlatformBuildClassObject):
self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
if skuname in (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT, TAB_COMMON):
str_pcd_obj.DefaultValue = PcdValue
+ else:
+ #Module Scope Structure Pcd
+ moduleguid = skuname.replace("S","-")
+ if GlobalData.gGuidPattern.match(moduleguid):
+ for component in self.Modules.values():
+ if component.Guid == moduleguid:
+ component.Pcds[(PcdName, PcdGuid)].DefaultValue = PcdValue
+
else:
if skuname not in str_pcd_obj.SkuInfoList:
nextskuid = self.SkuIdMgr.GetNextSkuId(skuname)
@@ -2341,6 +2379,75 @@ class DscBuildData(PlatformBuildClassObject):
CApp = CApp + "}\n"
return CApp
+ def GenerateModuleScopeValue(self, Pcd):
+ CApp = "// Value in Dsc Module scope \n"
+ for ModuleGuid in Pcd.PcdFiledValueFromDscComponent:
+
+ CApp = CApp + "void Assign_%s_%s_%s_Value(%s *Pcd){\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, ModuleGuid,Pcd.BaseDatumType)
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ pcddefaultvalue, file_path,lineNo = Pcd.PcdValueFromComponents.get(ModuleGuid,(None,None,None))
+
+ if pcddefaultvalue:
+ IsArray = _IsFieldValueAnArray(pcddefaultvalue)
+ if IsArray:
+ try:
+ FieldList = ValueExpressionEx(pcddefaultvalue, TAB_VOID)(True)
+ except BadExpression:
+ EdkLogger.error("Build", FORMAT_INVALID, "Invalid value format for %s.%s, from %s Line %s: %s" %
+ (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, file_path, lineNo, FieldList))
+ Value, ValueSize = ParseFieldValue (FieldList)
+
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd = %s; // From %s Line %s \n' % (Value, file_path, lineNo)
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' Value = %s; // From %s Line %s.\n' % (DscBuildData.IntToCString(Value, ValueSize), file_path, lineNo)
+ CApp = CApp + ' memcpy (Pcd, Value, %d);\n' % (ValueSize)
+
+
+ PcdFiledValue = Pcd.PcdFiledValueFromDscComponent.get(ModuleGuid)
+ for index in PcdFiledValue:
+ FieldList = PcdFiledValue[index]
+ if not FieldList:
+ continue
+ for FieldName in FieldList:
+ IsArray = _IsFieldValueAnArray(FieldList[FieldName][0])
+ if IsArray:
+ try:
+ FieldList[FieldName][0] = ValueExpressionEx(FieldList[FieldName][0], TAB_VOID, self._GuidDict)(True)
+ except BadExpression:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " %
+ (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ except:
+ print("error")
+ try:
+ Value, ValueSize = ParseFieldValue (FieldList[FieldName][0])
+ except Exception:
+ EdkLogger.error('Build', FORMAT_INVALID, "Invalid value format for %s. From %s Line %d " % (".".join((Pcd.TokenSpaceGuidCName, Pcd.TokenCName, FieldName)), FieldList[FieldName][1], FieldList[FieldName][2]))
+ if isinstance(Value, str):
+ CApp = CApp + ' Pcd->%s = %s; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ elif IsArray:
+ #
+ # Use memcpy() to copy value into field
+ #
+ CApp = CApp + ' FieldSize = __FIELD_SIZE(%s, %s);\n' % (Pcd.BaseDatumType, FieldName)
+ CApp = CApp + ' Value = %s; // From %s Line %d Value %s\n' % (DscBuildData.IntToCString(Value, ValueSize), FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' __STATIC_ASSERT((__FIELD_SIZE(%s, %s) >= %d) || (__FIELD_SIZE(%s, %s) == 0), "Input buffer exceeds the buffer array"); // From %s Line %d Value %s\n' % (Pcd.BaseDatumType, FieldName, ValueSize, Pcd.BaseDatumType, FieldName, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + ' memcpy (&Pcd->%s, Value, (FieldSize > 0 && FieldSize < %d) ? FieldSize : %d);\n' % (FieldName, ValueSize, ValueSize)
+ else:
+ if '[' in FieldName and ']' in FieldName:
+ Index = int(FieldName.split('[')[1].split(']')[0])
+ CApp = CApp + ' __STATIC_ASSERT((%d < __ARRAY_SIZE(Pcd->%s)) || (__ARRAY_SIZE(Pcd->%s) == 0), "array index exceeds the array number"); // From %s Line %d Index of %s\n' % (Index, FieldName.split('[')[0], FieldName.split('[')[0], FieldList[FieldName][1], FieldList[FieldName][2], FieldName)
+ if ValueSize > 4:
+ CApp = CApp + ' Pcd->%s = %dULL; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ else:
+ CApp = CApp + ' Pcd->%s = %d; // From %s Line %d Value %s\n' % (FieldName, Value, FieldList[FieldName][1], FieldList[FieldName][2], FieldList[FieldName][0])
+ CApp = CApp + "}\n"
+ return CApp
+
@staticmethod
def GenerateCommandLineValueStatement(Pcd):
CApp = ' Assign_%s_%s_CommandLine_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
@@ -2414,6 +2521,85 @@ class DscBuildData(PlatformBuildClassObject):
CApp = ' Assign_%s_%s_Fdf_Value(Pcd);\n' % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
return CApp
+ @staticmethod
+ def GenerateModuleValueStatement(module_guid, Pcd):
+ CApp = " Assign_%s_%s_%s_Value(Pcd);\n" % (Pcd.TokenSpaceGuidCName, Pcd.TokenCName, module_guid)
+ return CApp
+ def GenerateModuleScopeInitializeFunc(self,SkuName, Pcd, InitByteValue, CApp):
+ for module_guid in Pcd.PcdFiledValueFromDscComponent:
+ CApp = CApp + 'void\n'
+ CApp = CApp + 'Initialize_%s_%s_%s_%s(\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ CApp = CApp + ' void\n'
+ CApp = CApp + ' )\n'
+ CApp = CApp + '{\n'
+ CApp = CApp + ' UINT32 Size;\n'
+ CApp = CApp + ' UINT32 FieldSize;\n'
+ CApp = CApp + ' CHAR8 *Value;\n'
+ CApp = CApp + ' UINT32 OriginalSize;\n'
+ CApp = CApp + ' VOID *OriginalPcd;\n'
+
+ CApp = CApp + ' %s *Pcd; // From %s Line %d \n' % (Pcd.BaseDatumType,Pcd.PkgPath, Pcd.PcdDefineLineNo)
+
+ CApp = CApp + '\n'
+
+ PcdDefaultValue = StringToArray(Pcd.DefaultValueFromDec.strip())
+ InitByteValue += '%s.%s.%s.%s|%s|%s\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName, Pcd.DatumType, PcdDefaultValue)
+ #
+ # Get current PCD value and size
+ #
+ CApp = CApp + ' OriginalPcd = PcdGetPtr (%s, %s, %s, %s, &OriginalSize);\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ #
+ # Determine the size of the PCD. For simple structures, sizeof(TYPE) provides
+ # the correct value. For structures with a flexible array member, the flexible
+ # array member is detected, and the size is based on the highest index used with
+ # the flexible array member. The flexible array member must be the last field
+ # in a structure. The size formula for this case is:
+ # OFFSET_OF(FlexbleArrayField) + sizeof(FlexibleArray[0]) * (HighestIndex + 1)
+ #
+ CApp = CApp + DscBuildData.GenerateSizeStatments(Pcd,SkuName,TAB_DEFAULT_STORES_DEFAULT)
+ if Pcd.IsArray() and Pcd.Capacity[-1] != "-1":
+ CApp = CApp + ' OriginalSize = OriginalSize < sizeof(%s) * %d? OriginalSize:sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize(),Pcd.BaseDatumType,Pcd.PcdArraySize())
+ CApp = CApp + ' Size = sizeof(%s) * %d; \n' % (Pcd.BaseDatumType,Pcd.PcdArraySize())
+
+ #
+ # Allocate and zero buffer for the PCD
+ # Must handle cases where current value is smaller, larger, or same size
+ # Always keep that larger one as the current size
+ #
+ CApp = CApp + ' Size = (OriginalSize > Size ? OriginalSize : Size);\n'
+ CApp = CApp + ' Pcd = (%s *)malloc (Size);\n' % (Pcd.BaseDatumType,)
+ CApp = CApp + ' memset (Pcd, 0, Size);\n'
+
+ #
+ # Copy current PCD value into allocated buffer.
+ #
+ CApp = CApp + ' memcpy (Pcd, OriginalPcd, OriginalSize);\n'
+
+ #
+ # Assign field values in PCD
+ #
+ CApp = CApp + DscBuildData.GenerateDefaultValueAssignStatement(Pcd)
+
+ CApp = CApp + "// SkuName: %s, DefaultStoreName: STANDARD \n" % self.SkuIdMgr.SystemSkuId
+ CApp = CApp + DscBuildData.GenerateInitValueStatement(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
+ CApp = CApp + DscBuildData.GenerateModuleValueStatement(module_guid,Pcd)
+ CApp = CApp + DscBuildData.GenerateFdfValueStatement(Pcd)
+ CApp = CApp + DscBuildData.GenerateCommandLineValueStatement(Pcd)
+
+ #
+ # Set new PCD value and size
+ #
+ CApp = CApp + ' PcdSetPtr (%s, %s, %s, %s, Size, (void *)Pcd);\n' % (module_guid, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+
+ #
+ # Free PCD
+ #
+ CApp = CApp + ' free (Pcd);\n'
+ CApp = CApp + '}\n'
+ CApp = CApp + '\n'
+ return InitByteValue,CApp
+
def GenerateInitializeFunc(self, SkuName, DefaultStore, Pcd, InitByteValue, CApp):
OverrideValues = {DefaultStore:{}}
if Pcd.SkuOverrideValues:
@@ -2584,12 +2770,22 @@ class DscBuildData(PlatformBuildClassObject):
CApp = CApp + '\n'
for Pcd in StructuredPcds.values():
CApp = CApp + self.GenerateArrayAssignment(Pcd)
- for PcdName in StructuredPcds:
+ for PcdName in sorted(StructuredPcds.keys()):
Pcd = StructuredPcds[PcdName]
+
+ #create void void Cal_tocken_cname_Size functions
CApp = CApp + self.GenerateSizeFunction(Pcd)
+
+ #create void Assign_ functions
+
+ # From DEC
CApp = CApp + self.GenerateDefaultValueAssignFunction(Pcd)
+ # From Fdf
CApp = CApp + self.GenerateFdfValue(Pcd)
+ # From CommandLine
CApp = CApp + self.GenerateCommandLineValue(Pcd)
+
+ # From Dsc Global setting
if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
CApp = CApp + self.GenerateInitValueFunction(Pcd, self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT)
@@ -2599,9 +2795,15 @@ class DscBuildData(PlatformBuildClassObject):
continue
for DefaultStoreName in Pcd.SkuOverrideValues[SkuName]:
CApp = CApp + self.GenerateInitValueFunction(Pcd, SkuName, DefaultStoreName)
+
+ # From Dsc module scope setting
+ CApp = CApp + self.GenerateModuleScopeValue(Pcd)
+
+ #create Initialize_ functions
if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD],
self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
InitByteValue, CApp = self.GenerateInitializeFunc(self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT, Pcd, InitByteValue, CApp)
+ InitByteValue, CApp = self.GenerateModuleScopeInitializeFunc(self.SkuIdMgr.SystemSkuId,Pcd,InitByteValue,CApp)
else:
for SkuName in self.SkuIdMgr.SkuOverrideOrder():
if SkuName not in Pcd.SkuOverrideValues:
@@ -2618,6 +2820,8 @@ class DscBuildData(PlatformBuildClassObject):
for Pcd in StructuredPcds.values():
if self.SkuOverrideValuesEmpty(Pcd.SkuOverrideValues) or Pcd.Type in [self._PCD_TYPE_STRING_[MODEL_PCD_FIXED_AT_BUILD], self._PCD_TYPE_STRING_[MODEL_PCD_PATCHABLE_IN_MODULE]]:
CApp = CApp + ' Initialize_%s_%s_%s_%s();\n' % (self.SkuIdMgr.SystemSkuId, TAB_DEFAULT_STORES_DEFAULT, Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
+ for ModuleGuid in Pcd.PcdFiledValueFromDscComponent:
+ CApp += " Initialize_%s_%s_%s_%s();\n" % (ModuleGuid,TAB_DEFAULT_STORES_DEFAULT ,Pcd.TokenSpaceGuidCName, Pcd.TokenCName)
else:
for SkuName in self.SkuIdMgr.SkuOverrideOrder():
if SkuName not in self.SkuIdMgr.AvailableSkuIdSet:
@@ -2633,13 +2837,14 @@ class DscBuildData(PlatformBuildClassObject):
CAppBaseFileName = os.path.join(self.OutputPath, PcdValueInitName)
SaveFileOnChange(CAppBaseFileName + '.c', CApp, False)
+ # start generating makefile
MakeApp = PcdMakefileHeader
if sys.platform == "win32":
MakeApp = MakeApp + 'APPFILE = %s\%s.exe\n' % (self.OutputPath, PcdValueInitName) + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s\%s.obj %s.obj\n' % (self.OutputPath, PcdValueInitName, os.path.join(self.OutputPath, PcdValueCommonName)) + 'INC = '
else:
MakeApp = MakeApp + PcdGccMakefile
MakeApp = MakeApp + 'APPFILE = %s/%s\n' % (self.OutputPath, PcdValueInitName) + 'APPNAME = %s\n' % (PcdValueInitName) + 'OBJECTS = %s/%s.o %s.o\n' % (self.OutputPath, PcdValueInitName, os.path.join(self.OutputPath, PcdValueCommonName)) + \
- 'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'INCLUDE +='
+ 'include $(MAKEROOT)/Makefiles/app.makefile\n' + 'TOOL_INCLUDE +='
IncSearchList = []
PlatformInc = OrderedDict()
@@ -2755,6 +2960,7 @@ class DscBuildData(PlatformBuildClassObject):
MakeApp += "$(OBJECTS) : %s\n" % MakeFileName
SaveFileOnChange(MakeFileName, MakeApp, False)
+ # start generating input file
InputValueFile = os.path.join(self.OutputPath, 'Input.txt')
OutputValueFile = os.path.join(self.OutputPath, 'Output.txt')
SaveFileOnChange(InputValueFile, InitByteValue, False)
@@ -2764,6 +2970,8 @@ class DscBuildData(PlatformBuildClassObject):
Dest_PcdValueInitExe = os.path.join(self.OutputPath, PcdValueInitName)
else:
Dest_PcdValueInitExe = os.path.join(self.OutputPath, PcdValueInitName) +".exe"
+
+ #start building the structure pcd value tool
Messages = ''
if sys.platform == "win32":
MakeCommand = 'nmake -f %s' % (MakeFileName)
@@ -2826,6 +3034,7 @@ class DscBuildData(PlatformBuildClassObject):
else:
EdkLogger.error('Build', COMMAND_FAILURE, 'Can not execute command: %s\n%s\n%s' % (MakeCommand, StdOut, StdErr))
+ #start executing the structure pcd value tool
if DscBuildData.NeedUpdateOutput(OutputValueFile, Dest_PcdValueInitExe, InputValueFile):
Command = Dest_PcdValueInitExe + ' -i %s -o %s' % (InputValueFile, OutputValueFile)
returncode, StdOut, StdErr = DscBuildData.ExecuteCommand (Command)
@@ -2833,6 +3042,7 @@ class DscBuildData(PlatformBuildClassObject):
if returncode != 0:
EdkLogger.warn('Build', COMMAND_FAILURE, 'Can not collect output from command: %s\n%s\n' % (Command, StdOut, StdErr))
+ #start update structure pcd final value
File = open (OutputValueFile, 'r')
FileBuffer = File.readlines()
File.close()
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py
index 0a0139a2ab6..7635d893322 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/MetaFileTable.py
@@ -46,25 +46,17 @@ class MetaFileTable():
self.TableName = "_%s_%s" % (FileType, len(DB.TblFile))
def IsIntegrity(self):
+ Result = False
try:
TimeStamp = self.MetaFile.TimeStamp
if not self.CurrentContent:
Result = False
else:
Result = self.CurrentContent[-1][0] < 0
- if not Result:
- # update the timestamp in database
- self.DB.SetFileTimeStamp(self.FileId, TimeStamp)
- return False
-
- if TimeStamp != self.DB.GetFileTimeStamp(self.FileId):
- # update the timestamp in database
- self.DB.SetFileTimeStamp(self.FileId, TimeStamp)
- return False
except Exception as Exc:
EdkLogger.debug(EdkLogger.DEBUG_5, str(Exc))
return False
- return True
+ return Result
def SetEndFlag(self):
self.CurrentContent.append(self._DUMMY_)
@@ -162,7 +154,7 @@ class ModuleTable(MetaFileTable):
if BelongsToItem is not None:
result = [item for item in result if item[7] == BelongsToItem]
- result = [ [r[2],r[3],r[4],r[5],r[6],r[0],r[9]] for r in result ]
+ result = [ [r[2],r[3],r[4],r[5],r[6],r[0],r[8]] for r in result ]
return result
## Python class representation of table storing package data
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
index b467a24a2e1..c888e6fc447 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceCommon.py
@@ -1,7 +1,7 @@
## @file
# Common routines used by workspace
#
-# Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -100,7 +100,7 @@ def GetModuleLibInstances(Module, Platform, BuildDatabase, Arch, Target, Toolcha
# If a module has a MODULE_TYPE of USER_DEFINED,
# do not link in NULL library class instances from the global [LibraryClasses.*] sections.
#
- if Module.ModuleType != SUP_MODULE_USER_DEFINED and Module.ModuleType != SUP_MODULE_HOST_APPLICATION:
+ if Module.ModuleType != SUP_MODULE_USER_DEFINED:
for LibraryClass in Platform.LibraryClasses.GetKeys():
if LibraryClass.startswith("NULL") and Platform.LibraryClasses[LibraryClass, Module.ModuleType]:
Module.LibraryClasses[LibraryClass] = Platform.LibraryClasses[LibraryClass, Module.ModuleType]
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
index 7b6d31763f1..0764e272436 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Workspace/WorkspaceDatabase.py
@@ -158,12 +158,6 @@ class WorkspaceDatabase(object):
self.BuildObject = WorkspaceDatabase.BuildObjectFactory(self)
self.TransformObject = WorkspaceDatabase.TransformObjectFactory(self)
- def SetFileTimeStamp(self,FileId,TimeStamp):
- self.TblFile[FileId-1][6] = TimeStamp
-
- def GetFileTimeStamp(self,FileId):
- return self.TblFile[FileId-1][6]
-
## Summarize all packages in the database
def GetPackageList(self, Platform, Arch, TargetName, ToolChainTag):
@@ -193,16 +187,6 @@ class WorkspaceDatabase(object):
return PackageList
- ## Summarize all platforms in the database
- def PlatformList(self):
- RetVal = []
- for PlatformFile in [item[3] for item in self.TblFile if item[5] == MODEL_FILE_DSC]:
- try:
- RetVal.append(self.BuildObject[PathClass(PlatformFile), TAB_COMMON])
- except:
- pass
- return RetVal
-
def MapPlatform(self, Dscfile):
Platform = self.BuildObject[PathClass(Dscfile), TAB_COMMON]
if Platform is None:
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py
index e4ffeaa5a16..45edeabd838 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/BuildReport.py
@@ -60,7 +60,7 @@ gPcdGuidPattern = re.compile(r"PCD\((\w+)[.](\w+)\)")
gOffsetGuidPattern = re.compile(r"(0x[0-9A-Fa-f]+) ([-A-Fa-f0-9]+)")
## Pattern to find module base address and entry point in fixed flash map file
-gModulePattern = r"\n[-\w]+\s*\(([^,]+),\s*BaseAddress=%(Address)s,\s*EntryPoint=%(Address)s\)\s*\(GUID=([-0-9A-Fa-f]+)[^)]*\)"
+gModulePattern = r"\n[-\w]+\s*\(([^,]+),\s*BaseAddress=%(Address)s,\s*EntryPoint=%(Address)s,\s*Type=\w+\)\s*\(GUID=([-0-9A-Fa-f]+)[^)]*\)"
gMapFileItemPattern = re.compile(gModulePattern % {"Address" : "(-?0[xX][0-9A-Fa-f]+)"})
## Pattern to find all module referenced header files in source files
@@ -696,7 +696,7 @@ class ModuleReport(object):
FileWrite(File, gSectionSep)
if "PCD" in ReportType:
- GlobalPcdReport.GenerateReport(File, self.ModulePcdSet)
+ GlobalPcdReport.GenerateReport(File, self.ModulePcdSet,self.FileGuid)
if "LIBRARY" in ReportType:
self.LibraryReport.GenerateReport(File)
@@ -881,7 +881,7 @@ class PcdReport(object):
if DscDefaultValue:
self.DscPcdDefault[(TokenCName, TokenSpaceGuidCName)] = DscDefaultValue
- def GenerateReport(self, File, ModulePcdSet):
+ def GenerateReport(self, File, ModulePcdSet,ModuleGuid=None):
if not ModulePcdSet:
if self.ConditionalPcds:
self.GenerateReportDetail(File, ModulePcdSet, 1)
@@ -897,7 +897,7 @@ class PcdReport(object):
break
if not IsEmpty:
self.GenerateReportDetail(File, ModulePcdSet, 2)
- self.GenerateReportDetail(File, ModulePcdSet)
+ self.GenerateReportDetail(File, ModulePcdSet,ModuleGuid = ModuleGuid)
##
# Generate report for PCD information
@@ -913,7 +913,7 @@ class PcdReport(object):
# directives section report, 2 means Unused Pcds section report
# @param DscOverridePcds Module DSC override PCDs set
#
- def GenerateReportDetail(self, File, ModulePcdSet, ReportSubType = 0):
+ def GenerateReportDetail(self, File, ModulePcdSet, ReportSubType = 0,ModuleGuid=None):
PcdDict = self.AllPcds
if ReportSubType == 1:
PcdDict = self.ConditionalPcds
@@ -993,10 +993,12 @@ class PcdReport(object):
#The DefaultValue of StructurePcd already be the latest, no need to update.
if not self.IsStructurePcd(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):
Pcd.DefaultValue = PcdValue
+ PcdComponentValue = None
if ModulePcdSet is not None:
if (Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type) not in ModulePcdSet:
continue
- InfDefaultValue, PcdValue = ModulePcdSet[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type]
+ InfDefaultValue, PcdComponentValue = ModulePcdSet[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type]
+ PcdValue = PcdComponentValue
#The DefaultValue of StructurePcd already be the latest, no need to update.
if not self.IsStructurePcd(Pcd.TokenCName, Pcd.TokenSpaceGuidCName):
Pcd.DefaultValue = PcdValue
@@ -1081,6 +1083,11 @@ class PcdReport(object):
if TypeName in ('DYNVPD', 'DEXVPD'):
SkuInfoList = Pcd.SkuInfoList
Pcd = GlobalData.gStructurePcd[self.Arch][(Pcd.TokenCName, Pcd.TokenSpaceGuidCName)]
+ if ModulePcdSet and ModulePcdSet.get((Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type)):
+ InfDefaultValue, PcdComponentValue = ModulePcdSet[Pcd.TokenCName, Pcd.TokenSpaceGuidCName, Type]
+ DscDefaultValBak = Pcd.DefaultValue
+ Pcd.DefaultValue = PcdComponentValue
+
Pcd.DatumType = Pcd.StructName
if TypeName in ('DYNVPD', 'DEXVPD'):
Pcd.SkuInfoList = SkuInfoList
@@ -1091,48 +1098,54 @@ class PcdReport(object):
DscDefaultValue = True
DscMatch = True
DecMatch = False
- elif Pcd.SkuOverrideValues:
- DscOverride = False
- if Pcd.DefaultFromDSC:
- DscOverride = True
- else:
- DictLen = 0
- for item in Pcd.SkuOverrideValues:
- DictLen += len(Pcd.SkuOverrideValues[item])
- if not DictLen:
- DscOverride = False
+ else:
+ if Pcd.Type in PCD_DYNAMIC_TYPE_SET | PCD_DYNAMIC_EX_TYPE_SET:
+ DscOverride = False
+ if Pcd.DefaultFromDSC:
+ DscOverride = True
else:
- if not Pcd.SkuInfoList:
- OverrideValues = Pcd.SkuOverrideValues
- if OverrideValues:
- for Data in OverrideValues.values():
- Struct = list(Data.values())
- if Struct:
- DscOverride = self.ParseStruct(Struct[0])
- break
+ DictLen = 0
+ for item in Pcd.SkuOverrideValues:
+ DictLen += len(Pcd.SkuOverrideValues[item])
+ if not DictLen:
+ DscOverride = False
else:
- SkuList = sorted(Pcd.SkuInfoList.keys())
- for Sku in SkuList:
- SkuInfo = Pcd.SkuInfoList[Sku]
- if SkuInfo.DefaultStoreDict:
- DefaultStoreList = sorted(SkuInfo.DefaultStoreDict.keys())
- for DefaultStore in DefaultStoreList:
- OverrideValues = Pcd.SkuOverrideValues[Sku]
- DscOverride = self.ParseStruct(OverrideValues[DefaultStore])
- if DscOverride:
+ if not Pcd.SkuInfoList:
+ OverrideValues = Pcd.SkuOverrideValues
+ if OverrideValues:
+ for Data in OverrideValues.values():
+ Struct = list(Data.values())
+ if Struct:
+ DscOverride = self.ParseStruct(Struct[0])
break
- if DscOverride:
- break
- if DscOverride:
- DscDefaultValue = True
- DscMatch = True
- DecMatch = False
+ else:
+ SkuList = sorted(Pcd.SkuInfoList.keys())
+ for Sku in SkuList:
+ SkuInfo = Pcd.SkuInfoList[Sku]
+ if SkuInfo.DefaultStoreDict:
+ DefaultStoreList = sorted(SkuInfo.DefaultStoreDict.keys())
+ for DefaultStore in DefaultStoreList:
+ OverrideValues = Pcd.SkuOverrideValues.get(Sku)
+ if OverrideValues:
+ DscOverride = self.ParseStruct(OverrideValues[DefaultStore])
+ if DscOverride:
+ break
+ if DscOverride:
+ break
+ if DscOverride:
+ DscDefaultValue = True
+ DscMatch = True
+ DecMatch = False
+ else:
+ DecMatch = True
else:
- DecMatch = True
- else:
- DscDefaultValue = True
- DscMatch = True
- DecMatch = False
+ if Pcd.DscRawValue or (ModuleGuid and ModuleGuid.replace("-","S") in Pcd.PcdValueFromComponents):
+ DscDefaultValue = True
+ DscMatch = True
+ DecMatch = False
+ else:
+ DscDefaultValue = False
+ DecMatch = True
#
# Report PCD item according to their override relationship
@@ -1153,13 +1166,14 @@ class PcdReport(object):
elif BuildOptionMatch:
self.PrintPcdValue(File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValBak, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue, '*B')
else:
- if DscDefaultValue and DscMatch:
+ if PcdComponentValue:
+ self.PrintPcdValue(File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValBak, InfMatch, PcdComponentValue, DecMatch, DecDefaultValue, '*M', ModuleGuid)
+ elif DscDefaultValue and DscMatch:
if (Pcd.TokenCName, Key, Field) in self.FdfPcdSet:
self.PrintPcdValue(File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValBak, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue, '*F')
else:
self.PrintPcdValue(File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValBak, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue, '*P')
- else:
- self.PrintPcdValue(File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValBak, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue, '*M')
+
if ModulePcdSet is None:
if IsStructure:
@@ -1265,7 +1279,7 @@ class PcdReport(object):
for filedvalues in Pcd.DefaultValues.values():
self.PrintStructureInfo(File, filedvalues)
- def PrintPcdValue(self, File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValue, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue, Flag = ' '):
+ def PrintPcdValue(self, File, Pcd, PcdTokenCName, TypeName, IsStructure, DscMatch, DscDefaultValue, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue, Flag = ' ',ModuleGuid=None):
if not Pcd.SkuInfoList:
Value = Pcd.DefaultValue
IsByteArray, ArrayList = ByteArrayForamt(Value)
@@ -1288,14 +1302,20 @@ class PcdReport(object):
OverrideValues = GlobalData.gPcdSkuOverrides[(Pcd.TokenCName,Pcd.TokenSpaceGuidCName)]
else:
OverrideValues = Pcd.SkuOverrideValues
+ FieldOverrideValues = None
if OverrideValues:
for Data in OverrideValues.values():
Struct = list(Data.values())
if Struct:
- OverrideFieldStruct = self.OverrideFieldValue(Pcd, Struct[0])
- self.PrintStructureInfo(File, OverrideFieldStruct)
+ FieldOverrideValues = Struct[0]
FiledOverrideFlag = True
break
+ if Pcd.PcdFiledValueFromDscComponent and ModuleGuid and ModuleGuid.replace("-","S") in Pcd.PcdFiledValueFromDscComponent:
+ FieldOverrideValues = Pcd.PcdFiledValueFromDscComponent[ModuleGuid.replace("-","S")]
+ if FieldOverrideValues:
+ OverrideFieldStruct = self.OverrideFieldValue(Pcd, FieldOverrideValues)
+ self.PrintStructureInfo(File, OverrideFieldStruct)
+
if not FiledOverrideFlag and (Pcd.PcdFieldValueFromComm or Pcd.PcdFieldValueFromFdf):
OverrideFieldStruct = self.OverrideFieldValue(Pcd, {})
self.PrintStructureInfo(File, OverrideFieldStruct)
@@ -1369,9 +1389,10 @@ class PcdReport(object):
FileWrite(File, ' %-*s : %6s %10s %10s %10s = %s' % (self.MaxLen, ' ', TypeName, '(' + Pcd.DatumType + ')', '(' + SkuIdName + ')', '(' + DefaultStore + ')', Value))
FileWrite(File, '%*s: %s: %s' % (self.MaxLen + 4, SkuInfo.VariableGuid, SkuInfo.VariableName, SkuInfo.VariableOffset))
if IsStructure:
- OverrideValues = Pcd.SkuOverrideValues[Sku]
- OverrideFieldStruct = self.OverrideFieldValue(Pcd, OverrideValues[DefaultStore])
- self.PrintStructureInfo(File, OverrideFieldStruct)
+ OverrideValues = Pcd.SkuOverrideValues.get(Sku)
+ if OverrideValues:
+ OverrideFieldStruct = self.OverrideFieldValue(Pcd, OverrideValues[DefaultStore])
+ self.PrintStructureInfo(File, OverrideFieldStruct)
self.PrintPcdDefault(File, Pcd, IsStructure, DscMatch, DscDefaultValue, InfMatch, InfDefaultValue, DecMatch, DecDefaultValue)
else:
Value = SkuInfo.DefaultValue
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py
index 6e80951d6a8..3790fbefade 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/build.py
@@ -2,7 +2,7 @@
# build a platform or a module
#
# Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
-# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2018, Hewlett Packard Enterprise Development, L.P.<BR>
# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
#
@@ -62,6 +62,7 @@ from AutoGen.ModuleAutoGenHelper import WorkSpaceInfo, PlatformInfo
from GenFds.FdfParser import FdfParser
from AutoGen.IncludesAutoGen import IncludesAutoGen
from GenFds.GenFds import resetFdsGlobalVariable
+from AutoGen.AutoGen import CalculatePriorityValue
## standard targets of build command
gSupportedTarget = ['all', 'genc', 'genmake', 'modules', 'libraries', 'fds', 'clean', 'cleanall', 'cleanlib', 'run']
@@ -877,19 +878,65 @@ class Build():
PcdMa.CreateCodeFile(False)
PcdMa.CreateMakeFile(False,GenFfsList = DataPipe.Get("FfsCommand").get((PcdMa.MetaFile.Path, PcdMa.Arch),[]))
-
+ PcdMa.CreateAsBuiltInf()
# Force cache miss for PCD driver
if GlobalData.gBinCacheSource and self.Target in [None, "", "all"]:
cqueue.put((PcdMa.MetaFile.Path, PcdMa.Arch, "MakeCache", False))
self.AutoGenMgr.join()
rt = self.AutoGenMgr.Status
- return rt, 0
+ err = 0
+ if not rt:
+ err = UNKNOWN_ERROR
+ return rt, err
except FatalError as e:
return False, e.args[0]
except:
return False, UNKNOWN_ERROR
+ ## Add TOOLCHAIN and FAMILY declared in DSC [BuildOptions] to ToolsDefTxtDatabase.
+ #
+ # Loop through the set of build targets, tool chains, and archs provided on either
+ # the command line or in target.txt to discover FAMILY and TOOLCHAIN delclarations
+ # in [BuildOptions] sections that may be within !if expressions that may use
+ # $(TARGET), $(TOOLCHAIN), $(TOOLCHAIN_TAG), or $(ARCH) operands.
+ #
+ def GetToolChainAndFamilyFromDsc (self, File):
+ SavedGlobalDefines = GlobalData.gGlobalDefines.copy()
+ for BuildTarget in self.BuildTargetList:
+ GlobalData.gGlobalDefines['TARGET'] = BuildTarget
+ for BuildToolChain in self.ToolChainList:
+ GlobalData.gGlobalDefines['TOOLCHAIN'] = BuildToolChain
+ GlobalData.gGlobalDefines['TOOL_CHAIN_TAG'] = BuildToolChain
+ for BuildArch in self.ArchList:
+ GlobalData.gGlobalDefines['ARCH'] = BuildArch
+ dscobj = self.BuildDatabase[File, BuildArch]
+ for KeyFamily, Key, KeyCodeBase in dscobj.BuildOptions:
+ try:
+ Target, ToolChain, Arch, Tool, Attr = Key.split('_')
+ except:
+ continue
+ if ToolChain == TAB_STAR or Attr != TAB_TOD_DEFINES_FAMILY:
+ continue
+ try:
+ Family = dscobj.BuildOptions[(KeyFamily, Key, KeyCodeBase)]
+ Family = Family.strip().strip('=').strip()
+ except:
+ continue
+ if TAB_TOD_DEFINES_FAMILY not in self.ToolDef.ToolsDefTxtDatabase:
+ self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY] = {}
+ if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY]:
+ self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_FAMILY][ToolChain] = Family
+ if TAB_TOD_DEFINES_BUILDRULEFAMILY not in self.ToolDef.ToolsDefTxtDatabase:
+ self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY] = {}
+ if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY]:
+ self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_BUILDRULEFAMILY][ToolChain] = Family
+ if TAB_TOD_DEFINES_TOOL_CHAIN_TAG not in self.ToolDef.ToolsDefTxtDatabase:
+ self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG] = []
+ if ToolChain not in self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG]:
+ self.ToolDef.ToolsDefTxtDatabase[TAB_TOD_DEFINES_TOOL_CHAIN_TAG].append(ToolChain)
+ GlobalData.gGlobalDefines = SavedGlobalDefines
+
## Load configuration
#
# This method will parse target.txt and get the build configurations.
@@ -911,6 +958,26 @@ class Build():
if self.ToolChainList is None or len(self.ToolChainList) == 0:
EdkLogger.error("build", RESOURCE_NOT_AVAILABLE, ExtraData="No toolchain given. Don't know how to build.\n")
+ if not self.PlatformFile:
+ PlatformFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_ACTIVE_PLATFORM]
+ if not PlatformFile:
+ # Try to find one in current directory
+ WorkingDirectory = os.getcwd()
+ FileList = glob.glob(os.path.normpath(os.path.join(WorkingDirectory, '*.dsc')))
+ FileNum = len(FileList)
+ if FileNum >= 2:
+ EdkLogger.error("build", OPTION_MISSING,
+ ExtraData="There are %d DSC files in %s. Use '-p' to specify one.\n" % (FileNum, WorkingDirectory))
+ elif FileNum == 1:
+ PlatformFile = FileList[0]
+ else:
+ EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
+ ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n")
+
+ self.PlatformFile = PathClass(NormFile(PlatformFile, self.WorkspaceDir), self.WorkspaceDir)
+
+ self.GetToolChainAndFamilyFromDsc (self.PlatformFile)
+
# check if the tool chains are defined or not
NewToolChainList = []
for ToolChain in self.ToolChainList:
@@ -936,23 +1003,6 @@ class Build():
ToolChainFamily.append(ToolDefinition[TAB_TOD_DEFINES_FAMILY][Tool])
self.ToolChainFamily = ToolChainFamily
- if not self.PlatformFile:
- PlatformFile = self.TargetTxt.TargetTxtDictionary[TAB_TAT_DEFINES_ACTIVE_PLATFORM]
- if not PlatformFile:
- # Try to find one in current directory
- WorkingDirectory = os.getcwd()
- FileList = glob.glob(os.path.normpath(os.path.join(WorkingDirectory, '*.dsc')))
- FileNum = len(FileList)
- if FileNum >= 2:
- EdkLogger.error("build", OPTION_MISSING,
- ExtraData="There are %d DSC files in %s. Use '-p' to specify one.\n" % (FileNum, WorkingDirectory))
- elif FileNum == 1:
- PlatformFile = FileList[0]
- else:
- EdkLogger.error("build", RESOURCE_NOT_AVAILABLE,
- ExtraData="No active platform specified in target.txt or command line! Nothing can be built.\n")
-
- self.PlatformFile = PathClass(NormFile(PlatformFile, self.WorkspaceDir), self.WorkspaceDir)
self.ThreadNumber = ThreadNum()
## Initialize build configuration
#
@@ -1218,7 +1268,7 @@ class Build():
mqueue = mp.Queue()
for m in AutoGenObject.GetAllModuleInfo:
mqueue.put(m)
-
+ mqueue.put((None,None,None,None,None,None,None))
AutoGenObject.DataPipe.DataContainer = {"CommandTarget": self.Target}
AutoGenObject.DataPipe.DataContainer = {"Workspace_timestamp": AutoGenObject.Workspace._SrcTimeStamp}
AutoGenObject.CreateLibModuelDirs()
@@ -1266,7 +1316,6 @@ class Build():
if BuildModule:
BuildCommand = BuildCommand + [Target]
LaunchCommand(BuildCommand, AutoGenObject.MakeFileDir)
- self.CreateAsBuiltInf()
if GlobalData.gBinCacheDest:
self.GenDestCache()
elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:
@@ -2175,6 +2224,7 @@ class Build():
data_pipe_file = os.path.join(Pa.BuildDir, "GlobalVar_%s_%s.bin" % (str(Pa.Guid),Pa.Arch))
Pa.DataPipe.dump(data_pipe_file)
+ mqueue.put((None,None,None,None,None,None,None))
autogen_rt, errorcode = self.StartAutoGen(mqueue, Pa.DataPipe, self.SkipAutoGen, PcdMaList, cqueue)
if not autogen_rt:
@@ -2276,7 +2326,6 @@ class Build():
#
ExitFlag.set()
BuildTask.WaitForComplete()
- self.CreateAsBuiltInf()
if GlobalData.gBinCacheDest:
self.GenDestCache()
elif GlobalData.gUseHashCache and not GlobalData.gBinCacheSource:
@@ -2381,26 +2430,42 @@ class Build():
FvDir = Wa.FvDir
if not os.path.exists(FvDir):
continue
-
for Arch in self.ArchList:
- # Build up the list of supported architectures for this build
- prefix = '%s_%s_%s_' % (BuildTarget, ToolChain, Arch)
-
- # Look through the tool definitions for GUIDed tools
+ guidList = []
+ tooldefguidList = []
guidAttribs = []
- for (attrib, value) in self.ToolDef.ToolsDefTxtDictionary.items():
- if attrib.upper().endswith('_GUID'):
- split = attrib.split('_')
- thisPrefix = '_'.join(split[0:3]) + '_'
- if thisPrefix == prefix:
- guid = self.ToolDef.ToolsDefTxtDictionary[attrib]
- guid = guid.lower()
- toolName = split[3]
- path = '_'.join(split[0:4]) + '_PATH'
- path = self.ToolDef.ToolsDefTxtDictionary[path]
- path = self.GetRealPathOfTool(path)
- guidAttribs.append((guid, toolName, path))
-
+ for Platform in Wa.AutoGenObjectList:
+ if Platform.BuildTarget != BuildTarget:
+ continue
+ if Platform.ToolChain != ToolChain:
+ continue
+ if Platform.Arch != Arch:
+ continue
+ if hasattr (Platform, 'BuildOption'):
+ for Tool in Platform.BuildOption:
+ if 'GUID' in Platform.BuildOption[Tool]:
+ if 'PATH' in Platform.BuildOption[Tool]:
+ value = Platform.BuildOption[Tool]['GUID']
+ if value in guidList:
+ EdkLogger.error("build", FORMAT_INVALID, "Duplicate GUID value %s used with Tool %s in DSC [BuildOptions]." % (value, Tool))
+ path = Platform.BuildOption[Tool]['PATH']
+ guidList.append(value)
+ guidAttribs.append((value, Tool, path))
+ for Tool in Platform.ToolDefinition:
+ if 'GUID' in Platform.ToolDefinition[Tool]:
+ if 'PATH' in Platform.ToolDefinition[Tool]:
+ value = Platform.ToolDefinition[Tool]['GUID']
+ if value in tooldefguidList:
+ EdkLogger.error("build", FORMAT_INVALID, "Duplicate GUID value %s used with Tool %s in tools_def.txt." % (value, Tool))
+ tooldefguidList.append(value)
+ if value in guidList:
+ # Already added by platform
+ continue
+ path = Platform.ToolDefinition[Tool]['PATH']
+ guidList.append(value)
+ guidAttribs.append((value, Tool, path))
+ # Sort by GuidTool name
+ guidAttribs = sorted (guidAttribs, key=lambda x: x[1])
# Write out GuidedSecTools.txt
toolsFile = os.path.join(FvDir, 'GuidedSectionTools.txt')
toolsFile = open(toolsFile, 'wt')
@@ -2696,6 +2761,7 @@ def Main():
Conclusion = "Done"
except:
Conclusion = "Failed"
+ ReturnCode = POSTBUILD_ERROR
elif ReturnCode == ABORT_ERROR:
Conclusion = "Aborted"
else:
@@ -2728,4 +2794,3 @@ if __name__ == '__main__':
## 0-127 is a safe return range, and 1 is a standard default error
if r < 0 or r > 127: r = 1
sys.exit(r)
-
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/buildoptions.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/buildoptions.py
index d2758fc590c..729584c7b35 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/buildoptions.py
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/build/buildoptions.py
@@ -2,7 +2,7 @@
# build a platform or a module
#
# Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2018 - 2020, Hewlett Packard Enterprise Development, L.P.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -40,7 +40,7 @@ class MyOptionParser():
def GetOption(self):
Parser = OptionParser(description=__copyright__, version=__version__, prog="build.exe", usage="%prog [options] [all|fds|genc|genmake|clean|cleanall|cleanlib|modules|libraries|run]")
- Parser.add_option("-a", "--arch", action="append", type="choice", choices=['IA32', 'X64', 'EBC', 'ARM', 'AARCH64', 'RISCV64'], dest="TargetArch",
+ Parser.add_option("-a", "--arch", action="append", dest="TargetArch",
help="ARCHS is one of list: IA32, X64, ARM, AARCH64, RISCV64 or EBC, which overrides target.txt's TARGET_ARCH definition. To specify more archs, please repeat this option.")
Parser.add_option("-p", "--platform", action="callback", type="string", dest="PlatformFile", callback=SingleCheckCallback,
help="Build the platform specified by the DSC file name argument, overriding target.txt's ACTIVE_PLATFORM definition.")
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py
new file mode 100644
index 00000000000..4e19e636fc0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py
@@ -0,0 +1,115 @@
+# @file
+# Split a file into two pieces at the request offset.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
+import unittest
+import tempfile
+import os
+import shutil
+import Split.Split as sp
+import struct as st
+
+
+class TestSplit(unittest.TestCase):
+ def setUp(self):
+ self.tmpdir = tempfile.mkdtemp()
+ self.binary_file = os.path.join(self.tmpdir, "Binary.bin")
+ self.create_inputfile()
+
+ def tearDown(self):
+ if os.path.exists(self.tmpdir):
+ shutil.rmtree(self.tmpdir)
+
+ def test_splitFile_position(self):
+ position = [-1, 0, 256, 512, 700, 1024, 2048]
+ result = [(0, 1024), (0, 1024), (256, 768),
+ (512, 512), (700, 324), (1024, 0), (1024, 0)]
+ outputfolder = self.tmpdir
+ for index, po in enumerate(position):
+ try:
+ sp.splitFile(self.binary_file, po)
+ except Exception as e:
+ self.assertTrue(False, msg="splitFile function error")
+
+ output1 = os.path.join(outputfolder, "Binary.bin1")
+ output2 = os.path.join(outputfolder, "Binary.bin2")
+ with open(output1, "rb") as f1:
+ size1 = len(f1.read())
+ with open(output2, "rb") as f2:
+ size2 = len(f2.read())
+
+ ex_result = result[index]
+ self.assertEqual(size1, ex_result[0])
+ self.assertEqual(size2, ex_result[1])
+
+ def create_inputfile(self):
+ with open(self.binary_file, "wb") as fout:
+ for i in range(512):
+ fout.write(st.pack("<H", i))
+
+ def test_splitFile_outputfile(self):
+ output = [
+ None,
+ "Binary.bin",
+ "Binary1.bin",
+ r"output/Binary1.bin",
+ os.path.abspath( r"output/Binary1.bin")
+ ]
+ expected_output = [
+ os.path.join(os.path.dirname(self.binary_file),"Binary.bin1" ),
+ os.path.join(os.getcwd(),"Binary.bin"),
+ os.path.join(os.getcwd(),"Binary1.bin"),
+ os.path.join(os.getcwd(),r"output/Binary1.bin"),
+ os.path.join(os.path.abspath( r"output/Binary1.bin"))
+ ]
+ for index, o in enumerate(output):
+ try:
+ sp.splitFile(self.binary_file, 123, outputfile1=o)
+ except Exception as e:
+ self.assertTrue(False, msg="splitFile function error")
+
+ self.assertTrue(os.path.exists(expected_output[index]))
+ self.create_inputfile()
+
+ def test_splitFile_outputfolder(self):
+ outputfolder = [
+ None,
+ "output",
+ r"output1/output2",
+ os.path.abspath("output"),
+ "output"
+ ]
+ output = [
+ None,
+ None,
+ "Binary1.bin",
+ r"output/Binary1.bin",
+ os.path.abspath( r"output_1/Binary1.bin")
+ ]
+
+ expected_output = [
+ os.path.join(os.path.dirname(self.binary_file),"Binary.bin1" ),
+ os.path.join(os.getcwd(),"output", "Binary.bin1"),
+ os.path.join(os.getcwd(), r"output1/output2" , "Binary1.bin"),
+ os.path.join(os.getcwd(),r"output", "output/Binary1.bin"),
+ os.path.join(os.path.abspath( r"output/Binary1.bin"))
+ ]
+
+ for index, o in enumerate(outputfolder):
+ try:
+ sp.splitFile(self.binary_file, 123, outputdir=o,outputfile1=output[index])
+ except Exception as e:
+ self.assertTrue(False, msg="splitFile function error")
+
+ self.assertTrue(os.path.exists(expected_output[index]))
+ self.create_inputfile()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/set_vsprefix_envs.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/set_vsprefix_envs.bat
index 9966a5a4ed5..d4eb84f0648 100644
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/set_vsprefix_envs.bat
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/set_vsprefix_envs.bat
@@ -3,7 +3,7 @@
@REM however it may be executed directly from the BaseTools project folder
@REM if the file is not executed within a WORKSPACE\BaseTools folder.
@REM
-@REM Copyright (c) 2016-2019, Intel Corporation. All rights reserved.<BR>
+@REM Copyright (c) 2016-2020, Intel Corporation. All rights reserved.<BR>
@REM
@REM SPDX-License-Identifier: BSD-2-Clause-Patent
@REM
@@ -108,45 +108,48 @@ if defined VS140COMNTOOLS (
)
if /I "%1"=="VS2015" goto SetWinDDK
-:SetVS2019
-if not defined VS160COMNTOOLS (
+:SetVS2017
+if not defined VS150COMNTOOLS (
+ @REM clear two envs so that vcvars32.bat can run successfully.
+ set VSINSTALLDIR=
+ set VCToolsVersion=
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" (
- if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\BuildTools" (
- call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 16,17 > vswhereInfo
+ if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\BuildTools" (
+ call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 15,16 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
) else (
- call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version 16,17 > vswhereInfo
+ call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version 15,16 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
)
) else if exist "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" (
- if exist "%ProgramFiles%\Microsoft Visual Studio\2019\BuildTools" (
- call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 16,17 > vswhereInfo
+ if exist "%ProgramFiles%\Microsoft Visual Studio\2017\BuildTools" (
+ call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 15,16 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
) else (
- call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -version 16,17 > vswhereInfo
+ call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -version 15,16 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
)
) else (
- if /I "%1"=="VS2019" goto ToolNotInstall
+ if /I "%1"=="VS2017" goto ToolNotInstall
goto SetWinDDK
)
)
if defined VCToolsInstallDir (
- if not defined VS2019_PREFIX (
- set "VS2019_PREFIX=%VCToolsInstallDir%"
+ if not defined VS2017_PREFIX (
+ set "VS2017_PREFIX=%VCToolsInstallDir%"
)
if not defined WINSDK10_PREFIX (
if defined WindowsSdkVerBinPath (
@@ -164,45 +167,50 @@ if not defined WINSDK_PATH_FOR_RC_EXE (
)
)
-:SetVS2017
-if not defined VS150COMNTOOLS (
+if /I "%1"=="VS2017" goto SetWinDDK
+
+:SetVS2019
+if not defined VS160COMNTOOLS (
+ @REM clear two envs so that vcvars32.bat can run successfully.
+ set VSINSTALLDIR=
+ set VCToolsVersion=
if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" (
- if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\BuildTools" (
- call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 15,16 > vswhereInfo
+ if exist "%ProgramFiles(x86)%\Microsoft Visual Studio\2019\BuildTools" (
+ call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 16,17 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
) else (
- call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version 15,16 > vswhereInfo
+ call "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -version 16,17 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
)
) else if exist "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" (
- if exist "%ProgramFiles%\Microsoft Visual Studio\2017\BuildTools" (
- call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 15,16 > vswhereInfo
+ if exist "%ProgramFiles%\Microsoft Visual Studio\2019\BuildTools" (
+ call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -version 16,17 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
) else (
- call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -version 15,16 > vswhereInfo
+ call "%ProgramFiles%\Microsoft Visual Studio\Installer\vswhere.exe" -version 16,17 > vswhereInfo
for /f "usebackq tokens=1* delims=: " %%i in (vswhereInfo) do (
if /i "%%i"=="installationPath" call "%%j\VC\Auxiliary\Build\vcvars32.bat"
)
del vswhereInfo
)
) else (
- if /I "%1"=="VS2017" goto ToolNotInstall
+ if /I "%1"=="VS2019" goto ToolNotInstall
goto SetWinDDK
)
)
if defined VCToolsInstallDir (
- if not defined VS2017_PREFIX (
- set "VS2017_PREFIX=%VCToolsInstallDir%"
+ if not defined VS2019_PREFIX (
+ set "VS2019_PREFIX=%VCToolsInstallDir%"
)
if not defined WINSDK10_PREFIX (
if defined WindowsSdkVerBinPath (
@@ -220,6 +228,8 @@ if not defined WINSDK_PATH_FOR_RC_EXE (
)
)
+if /I "%1"=="VS2019" goto SetWinDDK
+
:SetWinDDK
if not defined WINDDK3790_PREFIX (
set WINDDK3790_PREFIX=C:\WINDDK\3790.1830\bin\
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/toolsetup.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/toolsetup.bat
index 61ebf4ae09b..4b5256ab6e9 100755
--- a/src/VBox/Devices/EFI/Firmware/BaseTools/toolsetup.bat
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/toolsetup.bat
@@ -393,12 +393,31 @@ goto end
goto check_freezer_path
)
+
+
:check_freezer_path
endlocal
+
+ %PYTHON_COMMAND% -c "import edk2basetools" >NUL 2>NUL
+ if %ERRORLEVEL% EQU 0 (
+ goto use_pip_basetools
+ ) else (
+ goto use_builtin_basetools
+ )
+
+:use_builtin_basetools
+ @echo Using EDK2 in-source Basetools
if defined BASETOOLS_PYTHON_SOURCE goto print_python_info
set "PATH=%BASE_TOOLS_PATH%\BinWrappers\WindowsLike;%PATH%"
set BASETOOLS_PYTHON_SOURCE=%BASE_TOOLS_PATH%\Source\Python
set PYTHONPATH=%BASETOOLS_PYTHON_SOURCE%;%PYTHONPATH%
+ goto print_python_info
+
+:use_pip_basetools
+ @echo Using Pip Basetools
+ set "PATH=%BASE_TOOLS_PATH%\BinPipWrappers\WindowsLike;%PATH%"
+ set BASETOOLS_PYTHON_SOURCE=edk2basetools
+ goto print_python_info
:print_python_info
echo PATH = %PATH%
diff --git a/src/VBox/Devices/EFI/Firmware/CONTRIBUTING.md b/src/VBox/Devices/EFI/Firmware/CONTRIBUTING.md
new file mode 100644
index 00000000000..212c69ce8b7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CONTRIBUTING.md
@@ -0,0 +1,3 @@
+# Contributing to EDK2
+
+Contributor documentation is maintained on the wiki: https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Development-Process
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.ci.yaml
index adadb4de448..f16db42d45c 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.ci.yaml
@@ -2,12 +2,38 @@
# CI configuration for CryptoPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ "Library/OpensslLib/openssl",
+ # The unit testing folder is not to be checked
+ "Test/UnitTest",
+ # This has OpenSSL interfaces that aren't UEFI spec compliant
+ "Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c",
+ # this has OpenSSL interfaces that aren't UEFI spec compliant
+ "Library/OpensslLib/rand_pool.c"
+ ]
+ },
"CompilerPlugin": {
"DscPath": "CryptoPkg.dsc"
},
+ ## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
+ "HostUnitTestCompilerPlugin": {
+ "DscPath": "Test/CryptoPkgHostUnitTest.dsc"
+ },
"CharEncodingCheck": {
"IgnoreFiles": []
},
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dec b/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dec
index a702c1a3d80..1bc409b829e 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dec
@@ -23,7 +23,6 @@
Private
Library/Include
Library/OpensslLib/openssl/include
- Library/OpensslLib/openssl/crypto/include
[LibraryClasses]
## @libraryclass Provides basic library functions for cryptographic primitives.
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dsc b/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dsc
index ff1f5e71742..a59422816e3 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/CryptoPkg.dsc
@@ -2,7 +2,7 @@
# Cryptographic Library Package for UEFI Security Implementation.
# PEIM, DXE Driver, and SMM Driver with all crypto services enabled.
#
-# Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -45,11 +45,16 @@
!error CRYPTO_SERVICES must be set to one of PACKAGE ALL NONE MIN_PEI MIN_DXE_MIN_SMM.
!endif
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
+
################################################################################
#
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
@@ -60,6 +65,7 @@
BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
TlsLib|CryptoPkg/Library/TlsLibNull/TlsLibNull.inf
HashApiLib|CryptoPkg/Library/BaseHashApiLib/BaseHashApiLib.inf
+ RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
@@ -223,6 +229,10 @@
# generated for it, but the binary will not be put into any firmware volume.
#
###################################################################################################
+[Components]
+ CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
+
!if $(CRYPTO_SERVICES) == PACKAGE
[Components]
CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -284,3 +294,9 @@
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+!if $(CRYPTO_SERVICES) IN "PACKAGE ALL"
+ MSFT:*_*_*_CC_FLAGS = /D ENABLE_MD5_DEPRECATED_INTERFACES
+ INTEL:*_*_*_CC_FLAGS = /D ENABLE_MD5_DEPRECATED_INTERFACES
+ GCC:*_*_*_CC_FLAGS = -D ENABLE_MD5_DEPRECATED_INTERFACES
+ RVCT:*_*_*_CC_FLAGS = -DENABLE_MD5_DEPRECATED_INTERFACES
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Driver/Crypto.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Driver/Crypto.c
index 5a20a4a6c03..d17fedac969 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Driver/Crypto.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Driver/Crypto.c
@@ -243,6 +243,154 @@ DeprecatedCryptoServiceMd4HashAll (
return BaseCryptLibServiceDeprecated ("Md4HashAll"), FALSE;
}
+#ifndef ENABLE_MD5_DEPRECATED_INTERFACES
+/**
+ Retrieves the size, in bytes, of the context buffer required for MD5 hash operations.
+
+ If this interface is not supported, then return zero.
+
+ @retval 0 This interface is not supported.
+
+**/
+UINTN
+EFIAPI
+DeprecatedCryptoServiceMd5GetContextSize (
+ VOID
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Md5GetContextSize"), 0;
+}
+
+/**
+ Initializes user-supplied memory pointed by Md5Context as MD5 hash context for
+ subsequent use.
+
+ If Md5Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[out] Md5Context Pointer to MD5 context being initialized.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceMd5Init (
+ OUT VOID *Md5Context
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Md5Init"), FALSE;
+}
+
+/**
+ Makes a copy of an existing MD5 context.
+
+ If Md5Context is NULL, then return FALSE.
+ If NewMd5Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] Md5Context Pointer to MD5 context being copied.
+ @param[out] NewMd5Context Pointer to new MD5 context.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceMd5Duplicate (
+ IN CONST VOID *Md5Context,
+ OUT VOID *NewMd5Context
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Md5Init"), FALSE;
+}
+
+/**
+ Digests the input data and updates MD5 context.
+
+ This function performs MD5 digest on a data buffer of the specified size.
+ It can be called multiple times to compute the digest of long or discontinuous data streams.
+ MD5 context should be already correctly initialized by Md5Init(), and should not be finalized
+ by Md5Final(). Behavior with invalid context is undefined.
+
+ If Md5Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in, out] Md5Context Pointer to the MD5 context.
+ @param[in] Data Pointer to the buffer containing the data to be hashed.
+ @param[in] DataSize Size of Data buffer in bytes.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceMd5Update (
+ IN OUT VOID *Md5Context,
+ IN CONST VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Md5Init"), FALSE;
+}
+
+/**
+ Completes computation of the MD5 digest value.
+
+ This function completes MD5 hash computation and retrieves the digest value into
+ the specified memory. After this function has been called, the MD5 context cannot
+ be used again.
+ MD5 context should be already correctly initialized by Md5Init(), and should not be
+ finalized by Md5Final(). Behavior with invalid MD5 context is undefined.
+
+ If Md5Context is NULL, then return FALSE.
+ If HashValue is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in, out] Md5Context Pointer to the MD5 context.
+ @param[out] HashValue Pointer to a buffer that receives the MD5 digest
+ value (16 bytes).
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceMd5Final (
+ IN OUT VOID *Md5Context,
+ OUT UINT8 *HashValue
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Md5Final"), FALSE;
+}
+
+/**
+ Computes the MD5 message digest of a input data buffer.
+
+ This function performs the MD5 message digest of a given data buffer, and places
+ the digest value into the specified memory.
+
+ If this interface is not supported, then return FALSE.
+
+ @param[in] Data Pointer to the buffer containing the data to be hashed.
+ @param[in] DataSize Size of Data buffer in bytes.
+ @param[out] HashValue Pointer to a buffer that receives the MD5 digest
+ value (16 bytes).
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceMd5HashAll (
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT8 *HashValue
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Md5HashAll"), FALSE;
+}
+#else
/**
Retrieves the size, in bytes, of the context buffer required for MD5 hash operations.
@@ -400,8 +548,159 @@ CryptoServiceMd5HashAll (
{
return CALL_BASECRYPTLIB (Md5.Services.HashAll, Md5HashAll, (Data, DataSize, HashValue), FALSE);
}
+#endif
+
+#ifdef DISABLE_SHA1_DEPRECATED_INTERFACES
+/**
+ Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations.
+
+ If this interface is not supported, then return zero.
+
+ @retval 0 This interface is not supported.
+
+**/
+UINTN
+EFIAPI
+DeprecatedCryptoServiceSha1GetContextSize (
+ VOID
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Sha1GetContextSize"), 0;
+}
+
+/**
+ Initializes user-supplied memory pointed by Sha1Context as SHA-1 hash context for
+ subsequent use.
+
+ If Sha1Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[out] Sha1Context Pointer to SHA-1 context being initialized.
+
+ @retval TRUE SHA-1 context initialization succeeded.
+ @retval FALSE SHA-1 context initialization failed.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceSha1Init (
+ OUT VOID *Sha1Context
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Sha1Init"), FALSE;
+}
+
+/**
+ Makes a copy of an existing SHA-1 context.
+
+ If Sha1Context is NULL, then return FALSE.
+ If NewSha1Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] Sha1Context Pointer to SHA-1 context being copied.
+ @param[out] NewSha1Context Pointer to new SHA-1 context.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceSha1Duplicate (
+ IN CONST VOID *Sha1Context,
+ OUT VOID *NewSha1Context
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Sha1Duplicate"), FALSE;
+}
/**
+ Digests the input data and updates SHA-1 context.
+
+ This function performs SHA-1 digest on a data buffer of the specified size.
+ It can be called multiple times to compute the digest of long or discontinuous data streams.
+ SHA-1 context should be already correctly initialized by Sha1Init(), and should not be finalized
+ by Sha1Final(). Behavior with invalid context is undefined.
+
+ If Sha1Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in, out] Sha1Context Pointer to the SHA-1 context.
+ @param[in] Data Pointer to the buffer containing the data to be hashed.
+ @param[in] DataSize Size of Data buffer in bytes.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceSha1Update (
+ IN OUT VOID *Sha1Context,
+ IN CONST VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Sha1Update"), FALSE;
+}
+
+/**
+ Completes computation of the SHA-1 digest value.
+
+ This function completes SHA-1 hash computation and retrieves the digest value into
+ the specified memory. After this function has been called, the SHA-1 context cannot
+ be used again.
+ SHA-1 context should be already correctly initialized by Sha1Init(), and should not be
+ finalized by Sha1Final(). Behavior with invalid SHA-1 context is undefined.
+
+ If Sha1Context is NULL, then return FALSE.
+ If HashValue is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in, out] Sha1Context Pointer to the SHA-1 context.
+ @param[out] HashValue Pointer to a buffer that receives the SHA-1 digest
+ value (20 bytes).
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceSha1Final (
+ IN OUT VOID *Sha1Context,
+ OUT UINT8 *HashValue
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Sha1Final"), FALSE;
+}
+
+/**
+ Computes the SHA-1 message digest of a input data buffer.
+
+ This function performs the SHA-1 message digest of a given data buffer, and places
+ the digest value into the specified memory.
+
+ If this interface is not supported, then return FALSE.
+
+ @param[in] Data Pointer to the buffer containing the data to be hashed.
+ @param[in] DataSize Size of Data buffer in bytes.
+ @param[out] HashValue Pointer to a buffer that receives the SHA-1 digest
+ value (20 bytes).
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+DeprecatedCryptoServiceSha1HashAll (
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT8 *HashValue
+ )
+{
+ return BaseCryptLibServiceDeprecated ("Sha1HashAll"), FALSE;
+}
+#else
+/**
Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations.
If this interface is not supported, then return zero.
@@ -558,6 +857,7 @@ CryptoServiceSha1HashAll (
{
return CALL_BASECRYPTLIB (Sha1.Services.HashAll, Sha1HashAll, (Data, DataSize, HashValue), FALSE);
}
+#endif
/**
Retrieves the size, in bytes, of the context buffer required for SHA-256 hash operations.
@@ -4194,6 +4494,15 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
DeprecatedCryptoServiceMd4Update,
DeprecatedCryptoServiceMd4Final,
DeprecatedCryptoServiceMd4HashAll,
+#ifndef ENABLE_MD5_DEPRECATED_INTERFACES
+ /// Md5 - deprecated and unsupported
+ DeprecatedCryptoServiceMd5GetContextSize,
+ DeprecatedCryptoServiceMd5Init,
+ DeprecatedCryptoServiceMd5Duplicate,
+ DeprecatedCryptoServiceMd5Update,
+ DeprecatedCryptoServiceMd5Final,
+ DeprecatedCryptoServiceMd5HashAll,
+#else
/// Md5
CryptoServiceMd5GetContextSize,
CryptoServiceMd5Init,
@@ -4201,6 +4510,7 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
CryptoServiceMd5Update,
CryptoServiceMd5Final,
CryptoServiceMd5HashAll,
+#endif
/// Pkcs
CryptoServicePkcs1v2Encrypt,
CryptoServicePkcs5HashPassword,
@@ -4235,6 +4545,15 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
CryptoServiceRsaPkcs1Verify,
CryptoServiceRsaGetPrivateKeyFromPem,
CryptoServiceRsaGetPublicKeyFromX509,
+#ifdef DISABLE_SHA1_DEPRECATED_INTERFACES
+ /// Sha1 - deprecated and unsupported
+ DeprecatedCryptoServiceSha1GetContextSize,
+ DeprecatedCryptoServiceSha1Init,
+ DeprecatedCryptoServiceSha1Duplicate,
+ DeprecatedCryptoServiceSha1Update,
+ DeprecatedCryptoServiceSha1Final,
+ DeprecatedCryptoServiceSha1HashAll,
+#else
/// Sha1
CryptoServiceSha1GetContextSize,
CryptoServiceSha1Init,
@@ -4242,6 +4561,7 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = {
CryptoServiceSha1Update,
CryptoServiceSha1Final,
CryptoServiceSha1HashAll,
+#endif
/// Sha256
CryptoServiceSha256GetContextSize,
CryptoServiceSha256Init,
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Include/Library/BaseCryptLib.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Include/Library/BaseCryptLib.h
index 51d99d15b2b..57c3660f927 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -72,6 +72,7 @@ typedef enum {
// One-Way Cryptographic Hash Primitives
//=====================================================================================
+#ifdef ENABLE_MD5_DEPRECATED_INTERFACES
/**
Retrieves the size, in bytes, of the context buffer required for MD5 hash operations.
@@ -211,7 +212,9 @@ Md5HashAll (
IN UINTN DataSize,
OUT UINT8 *HashValue
);
+#endif
+#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
/**
Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations.
@@ -351,6 +354,7 @@ Sha1HashAll (
IN UINTN DataSize,
OUT UINT8 *HashValue
);
+#endif
/**
Retrieves the size, in bytes, of the context buffer required for SHA-256 hash operations.
@@ -1360,6 +1364,80 @@ RsaPkcs1Verify (
);
/**
+ Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If Message is NULL, then return FALSE.
+ If MsgSize is zero or > INT_MAX, then return FALSE.
+ If DigestLen is NOT 32, 48 or 64, return FALSE.
+ If SaltLen is < DigestLen, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ );
+
+/**
+ Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017.
+ Implementation determines salt length automatically from the signature encoding.
+ Mask generation function is the same as the message digest algorithm.
+ Salt length should atleast be equal to digest length.
+
+ @param[in] RsaContext Pointer to RSA context for signature verification.
+ @param[in] Message Pointer to octet message to be verified.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] Signature Pointer to RSASSA-PSS signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+ @param[in] DigestLen Length of digest for RSA operation.
+ @param[in] SaltLen Salt length for PSS encoding.
+
+ @retval TRUE Valid signature encoded in RSASSA-PSS.
+ @retval FALSE Invalid signature or invalid RSA context.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssVerify (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen
+ );
+
+/**
Retrieve the RSA Private Key from the password-protected PEM key data.
If PemData is NULL, then return FALSE.
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
index 208d0ebb36e..e560479fdd1 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -49,6 +49,8 @@
Pk/CryptX509.c
Pk/CryptAuthenticode.c
Pk/CryptTs.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSign.c
Pem/CryptPem.c
SysCall/CrtWrapper.c
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c
index 87ac702eb50..2625f0494bf 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptMd5.c
@@ -9,7 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "InternalCryptLib.h"
#include <openssl/md5.h>
-
+#ifdef ENABLE_MD5_DEPRECATED_INTERFACES
/**
Retrieves the size, in bytes, of the context buffer required for MD5 hash operations.
@@ -223,3 +223,4 @@ Md5HashAll (
return TRUE;
}
}
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c
index cc215013e26..5e9516219e0 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha1.c
@@ -9,7 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "InternalCryptLib.h"
#include <openssl/sha.h>
-
+#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
/**
Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations.
@@ -222,3 +222,4 @@ Sha1HashAll (
return TRUE;
}
}
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSm3.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSm3.c
index ef3e59ccd8f..470d37ea39a 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSm3.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Hash/CryptSm3.c
@@ -7,7 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "InternalCryptLib.h"
-#include "internal/sm3.h"
+#include "crypto/sm3.h"
/**
Retrieves the size, in bytes, of the context buffer required for SM3 hash operations.
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
index 27c56b5fbd4..d8d965c721f 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
@@ -40,8 +40,8 @@
Hash/CryptSha256.c
Hash/CryptSm3.c
Hash/CryptSha512.c
- Hmac/CryptHmacSha256Null.c
- Kdf/CryptHkdfNull.c
+ Hmac/CryptHmacSha256.c
+ Kdf/CryptHkdf.c
Cipher/CryptAesNull.c
Pk/CryptRsaBasic.c
Pk/CryptRsaExtNull.c
@@ -55,6 +55,8 @@
Pk/CryptX509Null.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSignNull.c
Pem/CryptPemNull.c
Rand/CryptRandNull.c
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
index a6908901b96..6421efebe83 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
@@ -9,7 +9,7 @@
AuthenticodeVerify() will get PE/COFF Authenticode and will do basic check for
data structure.
-Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -100,7 +100,7 @@ AuthenticodeVerify (
//
// Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
//
- if (!PKCS7_type_is_signed (Pkcs7)) {
+ if (!PKCS7_type_is_signed (Pkcs7) || PKCS7_get_detached (Pkcs7)) {
goto _Exit;
}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c
index 98dc85ce801..b5f350b3e92 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c
@@ -15,13 +15,13 @@
#include <openssl/asn1.h>
#include <openssl/x509.h>
#include <openssl/bio.h>
-#include <internal/x509_int.h>
+#include <crypto/x509.h>
#include <openssl/pkcs7.h>
#include <openssl/bn.h>
#include <openssl/x509_vfy.h>
#include <openssl/pem.h>
#include <openssl/evp.h>
-#include <internal/asn1_int.h>
+#include <crypto/asn1.h>
/**
This function will return the leaf signer certificate in a chain. This is
@@ -508,10 +508,6 @@ Exit:
free (SignedData);
}
- if (SignerCert != NULL) {
- X509_free (SignerCert);
- }
-
if (Pkcs7 != NULL) {
PKCS7_free (Pkcs7);
}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c
new file mode 100644
index 00000000000..4c25404c83a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c
@@ -0,0 +1,152 @@
+/** @file
+ RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.
+
+ This file implements following APIs which provide basic capabilities for RSA:
+ 1) RsaPssVerify
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+
+/**
+ Retrieve a pointer to EVP message digest object.
+
+ @param[in] DigestLen Length of the message digest.
+
+**/
+STATIC
+const
+EVP_MD*
+GetEvpMD (
+ IN UINT16 DigestLen
+ )
+{
+ switch (DigestLen){
+ case SHA256_DIGEST_SIZE:
+ return EVP_sha256();
+ break;
+ case SHA384_DIGEST_SIZE:
+ return EVP_sha384();
+ break;
+ case SHA512_DIGEST_SIZE:
+ return EVP_sha512();
+ break;
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017.
+ Implementation determines salt length automatically from the signature encoding.
+ Mask generation function is the same as the message digest algorithm.
+ Salt length should atleast be equal to digest length.
+
+ @param[in] RsaContext Pointer to RSA context for signature verification.
+ @param[in] Message Pointer to octet message to be verified.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] Signature Pointer to RSASSA-PSS signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+ @param[in] DigestLen Length of digest for RSA operation.
+ @param[in] SaltLen Salt length for PSS encoding.
+
+ @retval TRUE Valid signature encoded in RSASSA-PSS.
+ @retval FALSE Invalid signature or invalid RSA context.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssVerify (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen
+ )
+{
+ BOOLEAN Result;
+ EVP_PKEY *EvpRsaKey;
+ EVP_MD_CTX *EvpVerifyCtx;
+ EVP_PKEY_CTX *KeyCtx;
+ CONST EVP_MD *HashAlg;
+
+ Result = FALSE;
+ EvpRsaKey = NULL;
+ EvpVerifyCtx = NULL;
+ KeyCtx = NULL;
+ HashAlg = NULL;
+
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+ if (Message == NULL || MsgSize == 0 || MsgSize > INT_MAX) {
+ return FALSE;
+ }
+ if (Signature == NULL || SigSize == 0 || SigSize > INT_MAX) {
+ return FALSE;
+ }
+ if (SaltLen < DigestLen) {
+ return FALSE;
+ }
+
+ HashAlg = GetEvpMD(DigestLen);
+
+ if (HashAlg == NULL) {
+ return FALSE;
+ }
+
+ EvpRsaKey = EVP_PKEY_new();
+ if (EvpRsaKey == NULL) {
+ goto _Exit;
+ }
+
+ EVP_PKEY_set1_RSA(EvpRsaKey, RsaContext);
+
+ EvpVerifyCtx = EVP_MD_CTX_create();
+ if (EvpVerifyCtx == NULL) {
+ goto _Exit;
+ }
+
+ Result = EVP_DigestVerifyInit(EvpVerifyCtx, &KeyCtx, HashAlg, NULL, EvpRsaKey) > 0;
+ if (KeyCtx == NULL) {
+ goto _Exit;
+ }
+
+ if (Result) {
+ Result = EVP_PKEY_CTX_set_rsa_padding(KeyCtx, RSA_PKCS1_PSS_PADDING) > 0;
+ }
+ if (Result) {
+ Result = EVP_PKEY_CTX_set_rsa_pss_saltlen(KeyCtx, SaltLen) > 0;
+ }
+ if (Result) {
+ Result = EVP_PKEY_CTX_set_rsa_mgf1_md(KeyCtx, HashAlg) > 0;
+ }
+ if (Result) {
+ Result = EVP_DigestVerifyUpdate(EvpVerifyCtx, Message, (UINT32)MsgSize) > 0;
+ }
+ if (Result) {
+ Result = EVP_DigestVerifyFinal(EvpVerifyCtx, Signature, (UINT32)SigSize) > 0;
+ }
+
+_Exit :
+ if (EvpRsaKey != NULL) {
+ EVP_PKEY_free(EvpRsaKey);
+ }
+ if (EvpVerifyCtx != NULL) {
+ EVP_MD_CTX_destroy(EvpVerifyCtx);
+ }
+
+ return Result;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c
new file mode 100644
index 00000000000..ff6d11c8faa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c
@@ -0,0 +1,46 @@
+/** @file
+ RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL.
+
+ This file does not provide real capabilities for following APIs in RSA handling:
+ 1) RsaPssVerify
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+ Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017.
+ Implementation determines salt length automatically from the signature encoding.
+ Mask generation function is the same as the message digest algorithm.
+ Salt length should atleast be equal to digest length.
+
+ @param[in] RsaContext Pointer to RSA context for signature verification.
+ @param[in] Message Pointer to octet message to be verified.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] Signature Pointer to RSASSA-PSS signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+ @param[in] DigestLen Length of digest for RSA operation.
+ @param[in] SaltLen Salt length for PSS encoding.
+
+ @retval TRUE Valid signature encoded in RSASSA-PSS.
+ @retval FALSE Invalid signature or invalid RSA context.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssVerify (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c
new file mode 100644
index 00000000000..369648e088b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c
@@ -0,0 +1,175 @@
+/** @file
+ RSA PSS Asymmetric Cipher Wrapper Implementation over OpenSSL.
+
+ This file implements following APIs which provide basic capabilities for RSA:
+ 1) RsaPssSign
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+#include <openssl/bn.h>
+#include <openssl/rsa.h>
+#include <openssl/objects.h>
+#include <openssl/evp.h>
+
+
+/**
+ Retrieve a pointer to EVP message digest object.
+
+ @param[in] DigestLen Length of the message digest.
+
+**/
+STATIC
+const
+EVP_MD*
+GetEvpMD (
+ IN UINT16 DigestLen
+ )
+{
+ switch (DigestLen){
+ case SHA256_DIGEST_SIZE:
+ return EVP_sha256();
+ break;
+ case SHA384_DIGEST_SIZE:
+ return EVP_sha384();
+ break;
+ case SHA512_DIGEST_SIZE:
+ return EVP_sha512();
+ break;
+ default:
+ return NULL;
+ }
+}
+
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If Message is NULL, then return FALSE.
+ If MsgSize is zero or > INT_MAX, then return FALSE.
+ If DigestLen is NOT 32, 48 or 64, return FALSE.
+ If SaltLen is < DigestLen, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ BOOLEAN Result;
+ UINTN RsaSigSize;
+ EVP_PKEY *EvpRsaKey;
+ EVP_MD_CTX *EvpVerifyCtx;
+ EVP_PKEY_CTX *KeyCtx;
+ CONST EVP_MD *HashAlg;
+
+ Result = FALSE;
+ EvpRsaKey = NULL;
+ EvpVerifyCtx = NULL;
+ KeyCtx = NULL;
+ HashAlg = NULL;
+
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+ if (Message == NULL || MsgSize == 0 || MsgSize > INT_MAX) {
+ return FALSE;
+ }
+
+ RsaSigSize = RSA_size (RsaContext);
+ if (*SigSize < RsaSigSize) {
+ *SigSize = RsaSigSize;
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ return FALSE;
+ }
+
+ if (SaltLen < DigestLen) {
+ return FALSE;
+ }
+
+ HashAlg = GetEvpMD(DigestLen);
+
+ if (HashAlg == NULL) {
+ return FALSE;
+ }
+
+ EvpRsaKey = EVP_PKEY_new();
+ if (EvpRsaKey == NULL) {
+ goto _Exit;
+ }
+
+ EVP_PKEY_set1_RSA(EvpRsaKey, RsaContext);
+
+ EvpVerifyCtx = EVP_MD_CTX_create();
+ if (EvpVerifyCtx == NULL) {
+ goto _Exit;
+ }
+
+ Result = EVP_DigestSignInit(EvpVerifyCtx, &KeyCtx, HashAlg, NULL, EvpRsaKey) > 0;
+ if (KeyCtx == NULL) {
+ goto _Exit;
+ }
+
+ if (Result) {
+ Result = EVP_PKEY_CTX_set_rsa_padding(KeyCtx, RSA_PKCS1_PSS_PADDING) > 0;
+ }
+ if (Result) {
+ Result = EVP_PKEY_CTX_set_rsa_pss_saltlen(KeyCtx, SaltLen) > 0;
+ }
+ if (Result) {
+ Result = EVP_PKEY_CTX_set_rsa_mgf1_md(KeyCtx, HashAlg) > 0;
+ }
+ if (Result) {
+ Result = EVP_DigestSignUpdate(EvpVerifyCtx, Message, (UINT32)MsgSize) > 0;
+ }
+ if (Result) {
+ Result = EVP_DigestSignFinal(EvpVerifyCtx, Signature, SigSize) > 0;
+ }
+
+_Exit :
+ if (EvpRsaKey != NULL) {
+ EVP_PKEY_free(EvpRsaKey);
+ }
+ if (EvpVerifyCtx != NULL) {
+ EVP_MD_CTX_destroy(EvpVerifyCtx);
+ }
+
+ return Result;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c
new file mode 100644
index 00000000000..52cef5eb188
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c
@@ -0,0 +1,60 @@
+/** @file
+ RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL.
+
+ This file does not provide real capabilities for following APIs in RSA handling:
+ 1) RsaPssSign
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If Message is NULL, then return FALSE.
+ If MsgSize is zero or > INT_MAX, then return FALSE.
+ If DigestLen is NOT 32, 48 or 64, return FALSE.
+ If SaltLen is < DigestLen, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
index 6bd3280f044..62d8f60be95 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
@@ -40,9 +40,9 @@
Hash/CryptSha256.c
Hash/CryptSm3.c
Hash/CryptSha512Null.c
- Hmac/CryptHmacSha256Null.c
- Kdf/CryptHkdfNull.c
- Cipher/CryptAesNull.c
+ Hmac/CryptHmacSha256.c
+ Kdf/CryptHkdf.c
+ Cipher/CryptAes.c
Pk/CryptRsaBasic.c
Pk/CryptRsaExtNull.c
Pk/CryptPkcs1OaepNull.c
@@ -55,6 +55,8 @@
Pk/CryptX509.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
+ Pk/CryptRsaPssNull.c
+ Pk/CryptRsaPssSignNull.c
Pem/CryptPem.c
SysCall/CrtWrapper.c
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index f689af517b0..caa66399429 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -53,6 +53,8 @@
Pk/CryptX509.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSignNull.c
Pem/CryptPem.c
SysCall/CrtWrapper.c
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
new file mode 100644
index 00000000000..dee33e8328a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/SysCall/UnitTestHostCrtWrapper.c
@@ -0,0 +1,93 @@
+/** @file
+ C Run-Time Libraries (CRT) Wrapper Implementation for OpenSSL-based
+ Cryptographic Library.
+
+Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+
+/* Convert character to lowercase */
+int tolower (int c)
+{
+ if (('A' <= (c)) && ((c) <= 'Z')) {
+ return (c - ('A' - 'a'));
+ }
+ return (c);
+}
+
+/* Compare first n bytes of string s1 with string s2, ignoring case */
+int strncasecmp (const char *s1, const char *s2, size_t n)
+{
+ int Val;
+
+ ASSERT(s1 != NULL);
+ ASSERT(s2 != NULL);
+
+ if (n != 0) {
+ do {
+ Val = tolower(*s1) - tolower(*s2);
+ if (Val != 0) {
+ return Val;
+ }
+ ++s1;
+ ++s2;
+ if (*s1 == '\0') {
+ break;
+ }
+ } while (--n != 0);
+ }
+ return 0;
+}
+
+/* Read formatted data from a string */
+int sscanf (const char *buffer, const char *format, ...)
+{
+ //
+ // Null sscanf() function implementation to satisfy the linker, since
+ // no direct functionality logic dependency in present UEFI cases.
+ //
+ return 0;
+}
+
+//
+// -- Dummy OpenSSL Support Routines --
+//
+
+int BIO_printf (void *bio, const char *format, ...)
+{
+ return 0;
+}
+
+int BIO_snprintf(char *buf, size_t n, const char *format, ...)
+{
+ return 0;
+}
+
+uid_t getuid (void)
+{
+ return 0;
+}
+
+uid_t geteuid (void)
+{
+ return 0;
+}
+
+gid_t getgid (void)
+{
+ return 0;
+}
+
+gid_t getegid (void)
+{
+ return 0;
+}
+
+int errno = 0;
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
new file mode 100644
index 00000000000..b02e6fef1b8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
@@ -0,0 +1,92 @@
+## @file
+# Cryptographic Library Instance for host based unit tests
+#
+# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCryptLib
+ FILE_GUID = c97d34aa-caf8-42cd-8261-8705f46304b3
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BaseCryptLib|HOST_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+ InternalCryptLib.h
+ Hash/CryptMd5.c
+ Hash/CryptSha1.c
+ Hash/CryptSha256.c
+ Hash/CryptSha512.c
+ Hash/CryptSm3.c
+ Hmac/CryptHmacSha256.c
+ Kdf/CryptHkdf.c
+ Cipher/CryptAes.c
+ Pk/CryptRsaBasic.c
+ Pk/CryptRsaExt.c
+ Pk/CryptPkcs1Oaep.c
+ Pk/CryptPkcs5Pbkdf2.c
+ Pk/CryptPkcs7Sign.c
+ Pk/CryptPkcs7VerifyCommon.c
+ Pk/CryptPkcs7VerifyBase.c
+ Pk/CryptPkcs7VerifyEku.c
+ Pk/CryptDh.c
+ Pk/CryptX509.c
+ Pk/CryptAuthenticode.c
+ Pk/CryptTs.c
+ Pem/CryptPem.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSign.c
+
+ SysCall/UnitTestHostCrtWrapper.c
+
+[Sources.Ia32]
+ Rand/CryptRandTsc.c
+
+[Sources.X64]
+ Rand/CryptRandTsc.c
+
+[Sources.ARM]
+ Rand/CryptRand.c
+
+[Sources.AARCH64]
+ Rand/CryptRand.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ DebugLib
+ OpensslLib
+
+#
+# Remove these [BuildOptions] after this library is cleaned up
+#
+[BuildOptions]
+ #
+ # suppress the following warnings so we do not break the build with warnings-as-errors:
+ # C4090: 'function' : different 'const' qualifiers
+ # C4018: '>': signed/unsigned mismatch
+ MSFT:*_*_*_CC_FLAGS = /wd4090 /wd4018
+
+ # -JCryptoPkg/Include : To disable the use of the system includes provided by RVCT
+ # --diag_remark=1 : Reduce severity of "#1-D: last line of file ends without a newline"
+ RVCT:*_*_ARM_CC_FLAGS = -JCryptoPkg/Include --diag_remark=1
+
+ GCC:*_CLANG35_*_CC_FLAGS = -std=c99
+ GCC:*_CLANG38_*_CC_FLAGS = -std=c99
+
+ XCODE:*_*_*_CC_FLAGS = -std=c99
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
index 07d714a251a..02d1b209108 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -50,6 +50,8 @@
Pk/CryptTsNull.c
Pem/CryptPemNull.c
Rand/CryptRandNull.c
+ Pk/CryptRsaPssNull.c
+ Pk/CryptRsaPssSignNull.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c
new file mode 100644
index 00000000000..ff6d11c8faa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c
@@ -0,0 +1,46 @@
+/** @file
+ RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL.
+
+ This file does not provide real capabilities for following APIs in RSA handling:
+ 1) RsaPssVerify
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+ Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017.
+ Implementation determines salt length automatically from the signature encoding.
+ Mask generation function is the same as the message digest algorithm.
+ Salt length should atleast be equal to digest length.
+
+ @param[in] RsaContext Pointer to RSA context for signature verification.
+ @param[in] Message Pointer to octet message to be verified.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] Signature Pointer to RSASSA-PSS signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+ @param[in] DigestLen Length of digest for RSA operation.
+ @param[in] SaltLen Salt length for PSS encoding.
+
+ @retval TRUE Valid signature encoded in RSASSA-PSS.
+ @retval FALSE Invalid signature or invalid RSA context.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssVerify (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c
new file mode 100644
index 00000000000..52cef5eb188
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c
@@ -0,0 +1,60 @@
+/** @file
+ RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL.
+
+ This file does not provide real capabilities for following APIs in RSA handling:
+ 1) RsaPssSign
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If Message is NULL, then return FALSE.
+ If MsgSize is zero or > INT_MAX, then return FALSE.
+ If DigestLen is NOT 32, 48 or 64, return FALSE.
+ If SaltLen is < DigestLen, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index 62a58ffa6cc..7524006cc34 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -99,6 +99,7 @@ CryptoServiceNotAvailable (
// One-Way Cryptographic Hash Primitives
//=====================================================================================
+#ifdef ENABLE_MD5_DEPRECATED_INTERFACES
/**
Retrieves the size, in bytes, of the context buffer required for MD5 hash operations.
@@ -256,7 +257,9 @@ Md5HashAll (
{
CALL_CRYPTO_SERVICE (Md5HashAll, (Data, DataSize, HashValue), FALSE);
}
+#endif
+#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
/**
Retrieves the size, in bytes, of the context buffer required for SHA-1 hash operations.
@@ -414,6 +417,7 @@ Sha1HashAll (
{
CALL_CRYPTO_SERVICE (Sha1HashAll, (Data, DataSize, HashValue), FALSE);
}
+#endif
/**
Retrieves the size, in bytes, of the context buffer required for SHA-256 hash operations.
@@ -1549,6 +1553,76 @@ RsaPkcs1Verify (
}
/**
+ Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017.
+ Implementation determines salt length automatically from the signature encoding.
+ Mask generation function is the same as the message digest algorithm.
+ Salt length should atleast be equal to digest length.
+
+ @param[in] RsaContext Pointer to RSA context for signature verification.
+ @param[in] Message Pointer to octet message to be verified.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] Signature Pointer to RSASSA-PSS signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+ @param[in] DigestLen Length of digest for RSA operation.
+ @param[in] SaltLen Salt length for PSS encoding.
+
+ @retval TRUE Valid signature encoded in RSASSA-PSS.
+ @retval FALSE Invalid signature or invalid RSA context.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssVerify (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen
+ )
+{
+ CALL_CRYPTO_SERVICE (RsaPssVerify, (RsaContext, Message, MsgSize, Signature, SigSize, DigestLen, SaltLen), FALSE);
+}
+
+/**
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ CALL_CRYPTO_SERVICE (RsaPssSign, (RsaContext, Message, MsgSize, DigestLen, SaltLen, Signature, SigSize), FALSE);
+}
+
+/**
Retrieve the RSA Private Key from the password-protected PEM key data.
If PemData is NULL, then return FALSE.
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/CrtLibSupport.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/CrtLibSupport.h
index b5ee9d530af..fd098c50355 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/CrtLibSupport.h
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/CrtLibSupport.h
@@ -2,7 +2,7 @@
Root include file of C runtime library to support building the third-party
cryptographic library.
-Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -44,6 +44,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define CONFIG_HEADER_BN_H
+#if !defined(SIXTY_FOUR_BIT) && !defined (THIRTY_TWO_BIT)
#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || defined(MDE_CPU_IA64) || defined(MDE_CPU_RISCV64)
//
// With GCC we would normally use SIXTY_FOUR_BIT_LONG, but MSVC needs
@@ -56,6 +57,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#else
#error Unknown target architecture
#endif
+#endif
//
// Map all va_xxxx elements to VA_xxx defined in MdePkg/Include/Base.h
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/internal/dso_conf.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/crypto/dso_conf.h
index 43c891588bc..abbbf62caae 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/internal/dso_conf.h
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/crypto/dso_conf.h
@@ -1,5 +1,5 @@
/* WARNING: do not edit! */
-/* Generated from crypto/include/internal/dso_conf.h.in */
+/* Generated from include/crypto/dso_conf.h.in */
/*
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
@@ -9,8 +9,8 @@
* https://www.openssl.org/source/license.html
*/
-#ifndef HEADER_DSO_CONF_H
-# define HEADER_DSO_CONF_H
+#ifndef OSSL_CRYPTO_DSO_CONF_H
+# define OSSL_CRYPTO_DSO_CONF_H
# define DSO_NONE
# define DSO_EXTENSION ".so"
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/openssl/opensslconf.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/openssl/opensslconf.h
index fc2a7bdec9f..500318c3d0d 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/openssl/opensslconf.h
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/Include/openssl/opensslconf.h
@@ -2,7 +2,7 @@
* WARNING: do not edit!
* Generated from include/openssl/opensslconf.h.in
*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -247,9 +247,6 @@ extern "C" {
#ifndef OPENSSL_NO_DYNAMIC_ENGINE
# define OPENSSL_NO_DYNAMIC_ENGINE
#endif
-#ifndef OPENSSL_NO_AFALGENG
-# define OPENSSL_NO_AFALGENG
-#endif
/*
@@ -271,6 +268,11 @@ extern "C" {
# undef DECLARE_DEPRECATED
# define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
# endif
+#elif defined(__SUNPRO_C)
+#if (__SUNPRO_C >= 0x5130)
+#undef DECLARE_DEPRECATED
+#define DECLARE_DEPRECATED(f) f __attribute__ ((deprecated));
+#endif
# endif
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLib.inf
index d02b9e7e89e..5300ea32642 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLib.inf
@@ -477,45 +477,45 @@
$(OPENSSL_PATH)/crypto/s390x_arch.h
$(OPENSSL_PATH)/crypto/sparc_arch.h
$(OPENSSL_PATH)/crypto/vms_rms.h
- $(OPENSSL_PATH)/crypto/aes/aes_locl.h
+ $(OPENSSL_PATH)/crypto/aes/aes_local.h
$(OPENSSL_PATH)/crypto/asn1/asn1_item_list.h
- $(OPENSSL_PATH)/crypto/asn1/asn1_locl.h
+ $(OPENSSL_PATH)/crypto/asn1/asn1_local.h
$(OPENSSL_PATH)/crypto/asn1/charmap.h
$(OPENSSL_PATH)/crypto/asn1/standard_methods.h
$(OPENSSL_PATH)/crypto/asn1/tbl_standard.h
- $(OPENSSL_PATH)/crypto/async/async_locl.h
+ $(OPENSSL_PATH)/crypto/async/async_local.h
$(OPENSSL_PATH)/crypto/async/arch/async_null.h
$(OPENSSL_PATH)/crypto/async/arch/async_posix.h
$(OPENSSL_PATH)/crypto/async/arch/async_win.h
- $(OPENSSL_PATH)/crypto/bio/bio_lcl.h
- $(OPENSSL_PATH)/crypto/bn/bn_lcl.h
+ $(OPENSSL_PATH)/crypto/bio/bio_local.h
+ $(OPENSSL_PATH)/crypto/bn/bn_local.h
$(OPENSSL_PATH)/crypto/bn/bn_prime.h
$(OPENSSL_PATH)/crypto/bn/rsaz_exp.h
- $(OPENSSL_PATH)/crypto/comp/comp_lcl.h
+ $(OPENSSL_PATH)/crypto/comp/comp_local.h
$(OPENSSL_PATH)/crypto/conf/conf_def.h
- $(OPENSSL_PATH)/crypto/conf/conf_lcl.h
- $(OPENSSL_PATH)/crypto/dh/dh_locl.h
- $(OPENSSL_PATH)/crypto/dso/dso_locl.h
- $(OPENSSL_PATH)/crypto/evp/evp_locl.h
- $(OPENSSL_PATH)/crypto/hmac/hmac_lcl.h
- $(OPENSSL_PATH)/crypto/lhash/lhash_lcl.h
- $(OPENSSL_PATH)/crypto/md5/md5_locl.h
- $(OPENSSL_PATH)/crypto/modes/modes_lcl.h
+ $(OPENSSL_PATH)/crypto/conf/conf_local.h
+ $(OPENSSL_PATH)/crypto/dh/dh_local.h
+ $(OPENSSL_PATH)/crypto/dso/dso_local.h
+ $(OPENSSL_PATH)/crypto/evp/evp_local.h
+ $(OPENSSL_PATH)/crypto/hmac/hmac_local.h
+ $(OPENSSL_PATH)/crypto/lhash/lhash_local.h
+ $(OPENSSL_PATH)/crypto/md5/md5_local.h
+ $(OPENSSL_PATH)/crypto/modes/modes_local.h
$(OPENSSL_PATH)/crypto/objects/obj_dat.h
- $(OPENSSL_PATH)/crypto/objects/obj_lcl.h
+ $(OPENSSL_PATH)/crypto/objects/obj_local.h
$(OPENSSL_PATH)/crypto/objects/obj_xref.h
- $(OPENSSL_PATH)/crypto/ocsp/ocsp_lcl.h
- $(OPENSSL_PATH)/crypto/pkcs12/p12_lcl.h
- $(OPENSSL_PATH)/crypto/rand/rand_lcl.h
- $(OPENSSL_PATH)/crypto/rsa/rsa_locl.h
- $(OPENSSL_PATH)/crypto/sha/sha_locl.h
+ $(OPENSSL_PATH)/crypto/ocsp/ocsp_local.h
+ $(OPENSSL_PATH)/crypto/pkcs12/p12_local.h
+ $(OPENSSL_PATH)/crypto/rand/rand_local.h
+ $(OPENSSL_PATH)/crypto/rsa/rsa_local.h
+ $(OPENSSL_PATH)/crypto/sha/sha_local.h
$(OPENSSL_PATH)/crypto/siphash/siphash_local.h
- $(OPENSSL_PATH)/crypto/sm3/sm3_locl.h
- $(OPENSSL_PATH)/crypto/store/store_locl.h
- $(OPENSSL_PATH)/crypto/ui/ui_locl.h
- $(OPENSSL_PATH)/crypto/x509/x509_lcl.h
+ $(OPENSSL_PATH)/crypto/sm3/sm3_local.h
+ $(OPENSSL_PATH)/crypto/store/store_local.h
+ $(OPENSSL_PATH)/crypto/ui/ui_local.h
+ $(OPENSSL_PATH)/crypto/x509/x509_local.h
$(OPENSSL_PATH)/crypto/x509v3/ext_dat.h
- $(OPENSSL_PATH)/crypto/x509v3/pcy_int.h
+ $(OPENSSL_PATH)/crypto/x509v3/pcy_local.h
$(OPENSSL_PATH)/crypto/x509v3/standard_exts.h
$(OPENSSL_PATH)/crypto/x509v3/v3_admis.h
$(OPENSSL_PATH)/ssl/bio_ssl.c
@@ -562,31 +562,18 @@
$(OPENSSL_PATH)/ssl/t1_trce.c
$(OPENSSL_PATH)/ssl/tls13_enc.c
$(OPENSSL_PATH)/ssl/tls_srp.c
- $(OPENSSL_PATH)/ssl/packet_locl.h
+ $(OPENSSL_PATH)/ssl/packet_local.h
$(OPENSSL_PATH)/ssl/ssl_cert_table.h
- $(OPENSSL_PATH)/ssl/ssl_locl.h
+ $(OPENSSL_PATH)/ssl/ssl_local.h
$(OPENSSL_PATH)/ssl/record/record.h
- $(OPENSSL_PATH)/ssl/record/record_locl.h
+ $(OPENSSL_PATH)/ssl/record/record_local.h
$(OPENSSL_PATH)/ssl/statem/statem.h
- $(OPENSSL_PATH)/ssl/statem/statem_locl.h
+ $(OPENSSL_PATH)/ssl/statem/statem_local.h
# Autogenerated files list ends here
buildinf.h
- rand_pool_noise.h
ossl_store.c
rand_pool.c
-[Sources.Ia32]
- rand_pool_noise_tsc.c
-
-[Sources.X64]
- rand_pool_noise_tsc.c
-
-[Sources.ARM]
- rand_pool_noise.c
-
-[Sources.AARCH64]
- rand_pool_noise.c
-
[Packages]
MdePkg/MdePkg.dec
CryptoPkg/CryptoPkg.dec
@@ -594,7 +581,7 @@
[LibraryClasses]
BaseLib
DebugLib
- TimerLib
+ RngLib
PrintLib
[LibraryClasses.ARM]
@@ -634,7 +621,7 @@
GCC:*_*_X64_CC_FLAGS = -U_WIN32 -U_WIN64 $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-error=format -Wno-format -Wno-error=unused-but-set-variable -DNO_MSABI_VA_FUNCS
GCC:*_*_ARM_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-error=unused-but-set-variable
GCC:*_*_AARCH64_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-format -Wno-error=unused-but-set-variable
- GCC:*_*_RISCV64_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=format -Wno-error=maybe-uninitialized -Wno-format -Wno-error=unused-but-set-variable
+ GCC:*_*_RISCV64_CC_FLAGS = $(OPENSSL_FLAGS) -Wno-error=maybe-uninitialized -Wno-format -Wno-error=unused-but-set-variable
GCC:*_CLANG35_*_CC_FLAGS = -std=c99 -Wno-error=uninitialized
GCC:*_CLANG38_*_CC_FLAGS = -std=c99 -Wno-error=uninitialized
GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99 -Wno-error=uninitialized -Wno-error=incompatible-pointer-types -Wno-error=pointer-sign -Wno-error=implicit-function-declaration -Wno-error=ignored-pragma-optimize
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
index 25e08fe5401..1b1d46b010f 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
@@ -477,65 +477,52 @@
$(OPENSSL_PATH)/crypto/s390x_arch.h
$(OPENSSL_PATH)/crypto/sparc_arch.h
$(OPENSSL_PATH)/crypto/vms_rms.h
- $(OPENSSL_PATH)/crypto/aes/aes_locl.h
+ $(OPENSSL_PATH)/crypto/aes/aes_local.h
$(OPENSSL_PATH)/crypto/asn1/asn1_item_list.h
- $(OPENSSL_PATH)/crypto/asn1/asn1_locl.h
+ $(OPENSSL_PATH)/crypto/asn1/asn1_local.h
$(OPENSSL_PATH)/crypto/asn1/charmap.h
$(OPENSSL_PATH)/crypto/asn1/standard_methods.h
$(OPENSSL_PATH)/crypto/asn1/tbl_standard.h
- $(OPENSSL_PATH)/crypto/async/async_locl.h
+ $(OPENSSL_PATH)/crypto/async/async_local.h
$(OPENSSL_PATH)/crypto/async/arch/async_null.h
$(OPENSSL_PATH)/crypto/async/arch/async_posix.h
$(OPENSSL_PATH)/crypto/async/arch/async_win.h
- $(OPENSSL_PATH)/crypto/bio/bio_lcl.h
- $(OPENSSL_PATH)/crypto/bn/bn_lcl.h
+ $(OPENSSL_PATH)/crypto/bio/bio_local.h
+ $(OPENSSL_PATH)/crypto/bn/bn_local.h
$(OPENSSL_PATH)/crypto/bn/bn_prime.h
$(OPENSSL_PATH)/crypto/bn/rsaz_exp.h
- $(OPENSSL_PATH)/crypto/comp/comp_lcl.h
+ $(OPENSSL_PATH)/crypto/comp/comp_local.h
$(OPENSSL_PATH)/crypto/conf/conf_def.h
- $(OPENSSL_PATH)/crypto/conf/conf_lcl.h
- $(OPENSSL_PATH)/crypto/dh/dh_locl.h
- $(OPENSSL_PATH)/crypto/dso/dso_locl.h
- $(OPENSSL_PATH)/crypto/evp/evp_locl.h
- $(OPENSSL_PATH)/crypto/hmac/hmac_lcl.h
- $(OPENSSL_PATH)/crypto/lhash/lhash_lcl.h
- $(OPENSSL_PATH)/crypto/md5/md5_locl.h
- $(OPENSSL_PATH)/crypto/modes/modes_lcl.h
+ $(OPENSSL_PATH)/crypto/conf/conf_local.h
+ $(OPENSSL_PATH)/crypto/dh/dh_local.h
+ $(OPENSSL_PATH)/crypto/dso/dso_local.h
+ $(OPENSSL_PATH)/crypto/evp/evp_local.h
+ $(OPENSSL_PATH)/crypto/hmac/hmac_local.h
+ $(OPENSSL_PATH)/crypto/lhash/lhash_local.h
+ $(OPENSSL_PATH)/crypto/md5/md5_local.h
+ $(OPENSSL_PATH)/crypto/modes/modes_local.h
$(OPENSSL_PATH)/crypto/objects/obj_dat.h
- $(OPENSSL_PATH)/crypto/objects/obj_lcl.h
+ $(OPENSSL_PATH)/crypto/objects/obj_local.h
$(OPENSSL_PATH)/crypto/objects/obj_xref.h
- $(OPENSSL_PATH)/crypto/ocsp/ocsp_lcl.h
- $(OPENSSL_PATH)/crypto/pkcs12/p12_lcl.h
- $(OPENSSL_PATH)/crypto/rand/rand_lcl.h
- $(OPENSSL_PATH)/crypto/rsa/rsa_locl.h
- $(OPENSSL_PATH)/crypto/sha/sha_locl.h
+ $(OPENSSL_PATH)/crypto/ocsp/ocsp_local.h
+ $(OPENSSL_PATH)/crypto/pkcs12/p12_local.h
+ $(OPENSSL_PATH)/crypto/rand/rand_local.h
+ $(OPENSSL_PATH)/crypto/rsa/rsa_local.h
+ $(OPENSSL_PATH)/crypto/sha/sha_local.h
$(OPENSSL_PATH)/crypto/siphash/siphash_local.h
- $(OPENSSL_PATH)/crypto/sm3/sm3_locl.h
- $(OPENSSL_PATH)/crypto/store/store_locl.h
- $(OPENSSL_PATH)/crypto/ui/ui_locl.h
- $(OPENSSL_PATH)/crypto/x509/x509_lcl.h
+ $(OPENSSL_PATH)/crypto/sm3/sm3_local.h
+ $(OPENSSL_PATH)/crypto/store/store_local.h
+ $(OPENSSL_PATH)/crypto/ui/ui_local.h
+ $(OPENSSL_PATH)/crypto/x509/x509_local.h
$(OPENSSL_PATH)/crypto/x509v3/ext_dat.h
- $(OPENSSL_PATH)/crypto/x509v3/pcy_int.h
+ $(OPENSSL_PATH)/crypto/x509v3/pcy_local.h
$(OPENSSL_PATH)/crypto/x509v3/standard_exts.h
$(OPENSSL_PATH)/crypto/x509v3/v3_admis.h
# Autogenerated files list ends here
buildinf.h
- rand_pool_noise.h
ossl_store.c
rand_pool.c
-[Sources.Ia32]
- rand_pool_noise_tsc.c
-
-[Sources.X64]
- rand_pool_noise_tsc.c
-
-[Sources.ARM]
- rand_pool_noise.c
-
-[Sources.AARCH64]
- rand_pool_noise.c
-
[Packages]
MdePkg/MdePkg.dec
CryptoPkg/CryptoPkg.dec
@@ -543,7 +530,7 @@
[LibraryClasses]
BaseLib
DebugLib
- TimerLib
+ RngLib
PrintLib
[LibraryClasses.ARM]
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl
index e4a075afd1c..5b0749fa1fd 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl
@@ -111,8 +111,8 @@ BEGIN {
# Generate dso_conf.h per config data
system(
"perl -I. -Mconfigdata util/dofile.pl " .
- "crypto/include/internal/dso_conf.h.in " .
- "> include/internal/dso_conf.h"
+ "include/crypto/dso_conf.h.in " .
+ "> include/crypto/dso_conf.h"
) == 0 ||
die "Failed to generate dso_conf.h!\n";
@@ -263,14 +263,21 @@ print "Done!";
# Copy opensslconf.h and dso_conf.h generated from OpenSSL Configuration
#
print "\n--> Duplicating opensslconf.h into Include/openssl ... ";
-copy($OPENSSL_PATH . "/include/openssl/opensslconf.h",
- $OPENSSL_PATH . "/../../Include/openssl/") ||
- die "Cannot copy opensslconf.h!";
+system(
+ "perl -pe 's/\\n/\\r\\n/' " .
+ "< " . $OPENSSL_PATH . "/include/openssl/opensslconf.h " .
+ "> " . $OPENSSL_PATH . "/../../Include/openssl/opensslconf.h"
+ ) == 0 ||
+ die "Cannot copy opensslconf.h!";
print "Done!";
-print "\n--> Duplicating dso_conf.h into Include/internal ... ";
-copy($OPENSSL_PATH . "/include/internal/dso_conf.h",
- $OPENSSL_PATH . "/../../Include/internal/") ||
- die "Cannot copy dso_conf.h!";
+
+print "\n--> Duplicating dso_conf.h into Include/crypto ... ";
+system(
+ "perl -pe 's/\\n/\\r\\n/' " .
+ "< " . $OPENSSL_PATH . "/include/crypto/dso_conf.h" .
+ "> " . $OPENSSL_PATH . "/../../Include/crypto/dso_conf.h"
+ ) == 0 ||
+ die "Cannot copy dso_conf.h!";
print "Done!\n";
print "\nProcessing Files Done!\n";
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool.c
index 49f00712fde..1b0a26a854b 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool.c
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool.c
@@ -2,62 +2,27 @@
OpenSSL_1_1_1b doesn't implement rand_pool_* functions for UEFI.
The file implement these functions.
-Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "internal/rand_int.h"
+#include "crypto/rand.h"
#include <openssl/aes.h>
#include <Uefi.h>
-#include <Library/TimerLib.h>
-
-#include "rand_pool_noise.h"
-
-/**
- Get some randomness from low-order bits of GetPerformanceCounter results.
- And combine them to the 64-bit value
-
- @param[out] Rand Buffer pointer to store the 64-bit random value.
-
- @retval TRUE Random number generated successfully.
- @retval FALSE Failed to generate.
-**/
-STATIC
-BOOLEAN
-EFIAPI
-GetRandNoise64FromPerformanceCounter(
- OUT UINT64 *Rand
- )
-{
- UINT32 Index;
- UINT32 *RandPtr;
-
- if (NULL == Rand) {
- return FALSE;
- }
-
- RandPtr = (UINT32 *) Rand;
-
- for (Index = 0; Index < 2; Index ++) {
- *RandPtr = (UINT32) (GetPerformanceCounter () & 0xFF);
- MicroSecondDelay (10);
- RandPtr++;
- }
-
- return TRUE;
-}
+#include <Library/RngLib.h>
/**
Calls RandomNumber64 to fill
a buffer of arbitrary size with random bytes.
+ This is a shim layer to RngLib.
@param[in] Length Size of the buffer, in bytes, to fill with.
@param[out] RandBuffer Pointer to the buffer to store the random result.
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
+ @retval TRUE Random bytes generation succeeded.
+ @retval FALSE Failed to request random bytes.
**/
STATIC
@@ -65,7 +30,7 @@ BOOLEAN
EFIAPI
RandGetBytes (
IN UINTN Length,
- OUT UINT8 *RandBuffer
+ OUT UINT8 *RandBuffer
)
{
BOOLEAN Ret;
@@ -73,17 +38,17 @@ RandGetBytes (
Ret = FALSE;
+ if (RandBuffer == NULL) {
+ DEBUG((DEBUG_ERROR, "[OPENSSL_RAND_POOL] NULL RandBuffer. No random numbers are generated and your system is not secure\n"));
+ ASSERT (RandBuffer != NULL); // Since we can't generate random numbers, we should assert. Otherwise we will just blow up later.
+ return Ret;
+ }
+
+
while (Length > 0) {
- //
- // Get random noise from platform.
- // If it failed, fallback to PerformanceCounter
- // If you really care about security, you must override
- // GetRandomNoise64FromPlatform.
- //
- Ret = GetRandomNoise64 (&TempRand);
- if (Ret == FALSE) {
- Ret = GetRandNoise64FromPerformanceCounter (&TempRand);
- }
+ // Use RngLib to get random number
+ Ret = GetRandomNumber64 (&TempRand);
+
if (!Ret) {
return Ret;
}
@@ -91,7 +56,8 @@ RandGetBytes (
*((UINT64*) RandBuffer) = TempRand;
RandBuffer += sizeof (UINT64);
Length -= sizeof (TempRand);
- } else {
+ }
+ else {
CopyMem (RandBuffer, &TempRand, Length);
Length = 0;
}
@@ -100,129 +66,6 @@ RandGetBytes (
return Ret;
}
-/**
- Creates a 128bit random value that is fully forward and backward prediction resistant,
- suitable for seeding a NIST SP800-90 Compliant.
- This function takes multiple random numbers from PerformanceCounter to ensure reseeding
- and performs AES-CBC-MAC over the data to compute the seed value.
-
- @param[out] SeedBuffer Pointer to a 128bit buffer to store the random seed.
-
- @retval TRUE Random seed generation succeeded.
- @retval FALSE Failed to request random bytes.
-
-**/
-STATIC
-BOOLEAN
-EFIAPI
-RandGetSeed128 (
- OUT UINT8 *SeedBuffer
- )
-{
-#ifndef VBOX
- BOOLEAN Ret;
-#else
- BOOLEAN Ret = 0; // MSFT thinks it can be used uninitialized
-#endif
- UINT8 RandByte[16];
- UINT8 Key[16];
- UINT8 Ffv[16];
- UINT8 Xored[16];
- UINT32 Index;
- UINT32 Index2;
- AES_KEY AESKey;
-
- //
- // Chose an arbitrary key and zero the feed_forward_value (FFV)
- //
- for (Index = 0; Index < 16; Index++) {
- Key[Index] = (UINT8) Index;
- Ffv[Index] = 0;
- }
-
- AES_set_encrypt_key (Key, 16 * 8, &AESKey);
-
- //
- // Perform CBC_MAC over 32 * 128 bit values, with 10us gaps between 128 bit value
- // The 10us gaps will ensure multiple reseeds within the system time with a large
- // design margin.
- //
- for (Index = 0; Index < 32; Index++) {
- MicroSecondDelay (10);
- Ret = RandGetBytes (16, RandByte);
- if (!Ret) {
- return Ret;
- }
-
- //
- // Perform XOR operations on two 128-bit value.
- //
- for (Index2 = 0; Index2 < 16; Index2++) {
- Xored[Index2] = RandByte[Index2] ^ Ffv[Index2];
- }
-
- AES_encrypt (Xored, Ffv, &AESKey);
- }
-
- for (Index = 0; Index < 16; Index++) {
- SeedBuffer[Index] = Ffv[Index];
- }
-
- return Ret;
-}
-
-/**
- Generate high-quality entropy source.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] Entropy Pointer to the buffer to store the entropy data.
-
- @retval EFI_SUCCESS Entropy generation succeeded.
- @retval EFI_NOT_READY Failed to request random data.
-
-**/
-STATIC
-BOOLEAN
-EFIAPI
-RandGenerateEntropy (
- IN UINTN Length,
- OUT UINT8 *Entropy
- )
-{
- BOOLEAN Ret;
- UINTN BlockCount;
- UINT8 Seed[16];
- UINT8 *Ptr;
-
- BlockCount = Length / 16;
- Ptr = (UINT8 *) Entropy;
-
- //
- // Generate high-quality seed for DRBG Entropy
- //
- while (BlockCount > 0) {
- Ret = RandGetSeed128 (Seed);
- if (!Ret) {
- return Ret;
- }
- CopyMem (Ptr, Seed, 16);
-
- BlockCount--;
- Ptr = Ptr + 16;
- }
-
- //
- // Populate the remained data as request.
- //
- Ret = RandGetSeed128 (Seed);
- if (!Ret) {
- return Ret;
- }
- CopyMem (Ptr, Seed, (Length % 16));
-
- return Ret;
-}
-
/*
* Add random bytes to the pool to acquire requested amount of entropy
*
@@ -231,27 +74,31 @@ RandGenerateEntropy (
*
* This is OpenSSL required interface.
*/
-size_t rand_pool_acquire_entropy(RAND_POOL *pool)
+size_t
+rand_pool_acquire_entropy (
+ RAND_POOL *pool
+ )
{
- BOOLEAN Ret;
- size_t bytes_needed;
- unsigned char * buffer;
+ BOOLEAN Ret;
+ size_t Bytes_needed;
+ unsigned char *Buffer;
- bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
- if (bytes_needed > 0) {
- buffer = rand_pool_add_begin(pool, bytes_needed);
+ Bytes_needed = rand_pool_bytes_needed (pool, 1 /*entropy_factor*/);
+ if (Bytes_needed > 0) {
+ Buffer = rand_pool_add_begin (pool, Bytes_needed);
- if (buffer != NULL) {
- Ret = RandGenerateEntropy(bytes_needed, buffer);
+ if (Buffer != NULL) {
+ Ret = RandGetBytes (Bytes_needed, Buffer);
if (FALSE == Ret) {
- rand_pool_add_end(pool, 0, 0);
- } else {
- rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
+ rand_pool_add_end (pool, 0, 0);
+ }
+ else {
+ rand_pool_add_end (pool, Bytes_needed, 8 * Bytes_needed);
}
}
}
- return rand_pool_entropy_available(pool);
+ return rand_pool_entropy_available (pool);
}
/*
@@ -259,17 +106,15 @@ size_t rand_pool_acquire_entropy(RAND_POOL *pool)
*
* This is OpenSSL required interface.
*/
-int rand_pool_add_nonce_data(RAND_POOL *pool)
+int
+rand_pool_add_nonce_data (
+ RAND_POOL *pool
+ )
{
- struct {
- UINT64 Rand;
- UINT64 TimerValue;
- } data = { 0 };
-
- RandGetBytes(8, (UINT8 *)&(data.Rand));
- data.TimerValue = GetPerformanceCounter();
+ UINT8 data[16];
+ RandGetBytes (sizeof(data), data);
- return rand_pool_add(pool, (unsigned char*)&data, sizeof(data), 0);
+ return rand_pool_add (pool, (unsigned char*)&data, sizeof(data), 0);
}
/*
@@ -277,17 +122,15 @@ int rand_pool_add_nonce_data(RAND_POOL *pool)
*
* This is OpenSSL required interface.
*/
-int rand_pool_add_additional_data(RAND_POOL *pool)
+int
+rand_pool_add_additional_data (
+ RAND_POOL *pool
+ )
{
- struct {
- UINT64 Rand;
- UINT64 TimerValue;
- } data = { 0 };
+ UINT8 data[16];
+ RandGetBytes (sizeof(data), data);
- RandGetBytes(8, (UINT8 *)&(data.Rand));
- data.TimerValue = GetPerformanceCounter();
-
- return rand_pool_add(pool, (unsigned char*)&data, sizeof(data), 0);
+ return rand_pool_add (pool, (unsigned char*)&data, sizeof(data), 0);
}
/*
@@ -295,7 +138,10 @@ int rand_pool_add_additional_data(RAND_POOL *pool)
*
* This is OpenSSL required interface.
*/
-int rand_pool_init(void)
+int
+rand_pool_init (
+ VOID
+ )
{
return 1;
}
@@ -305,7 +151,10 @@ int rand_pool_init(void)
*
* This is OpenSSL required interface.
*/
-void rand_pool_cleanup(void)
+VOID
+rand_pool_cleanup(
+ VOID
+ )
{
}
@@ -314,7 +163,9 @@ void rand_pool_cleanup(void)
*
* This is OpenSSL required interface.
*/
-void rand_pool_keep_random_devices_open(int keep)
+VOID
+rand_pool_keep_random_devices_open (
+ int keep
+ )
{
}
-
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.c
deleted file mode 100644
index 46de64d99d3..00000000000
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/** @file
- Provide rand noise source.
-
-Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Library/BaseLib.h>
-
-/**
- Get 64-bit noise source
-
- @param[out] Rand Buffer pointer to store 64-bit noise source
-
- @retval FALSE Failed to generate
-**/
-BOOLEAN
-EFIAPI
-GetRandomNoise64 (
- OUT UINT64 *Rand
- )
-{
- //
- // Return FALSE will fallback to use PerformanceCounter to
- // generate noise.
- //
- return FALSE;
-}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.h
deleted file mode 100644
index e68c7f3b717..00000000000
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/** @file
- Provide rand noise source.
-
-Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __RAND_POOL_NOISE_H__
-#define __RAND_POOL_NOISE_H__
-
-#include <Uefi/UefiBaseType.h>
-
-/**
- Get 64-bit noise source.
-
- @param[out] Rand Buffer pointer to store 64-bit noise source
-
- @retval TRUE Get randomness successfully.
- @retval FALSE Failed to generate
-**/
-BOOLEAN
-EFIAPI
-GetRandomNoise64 (
- OUT UINT64 *Rand
- );
-
-
-#endif // __RAND_POOL_NOISE_H__
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c
deleted file mode 100644
index eafea8329ae..00000000000
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/rand_pool_noise_tsc.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/** @file
- Provide rand noise source.
-
-Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/TimerLib.h>
-
-/**
- Get 64-bit noise source
-
- @param[out] Rand Buffer pointer to store 64-bit noise source
-
- @retval TRUE Get randomness successfully.
- @retval FALSE Failed to generate
-**/
-BOOLEAN
-EFIAPI
-GetRandomNoise64 (
- OUT UINT64 *Rand
- )
-{
- UINT32 Index;
- UINT32 *RandPtr;
-
- if (NULL == Rand) {
- return FALSE;
- }
-
- RandPtr = (UINT32 *)Rand;
-
- for (Index = 0; Index < 2; Index ++) {
- *RandPtr = (UINT32) ((AsmReadTsc ()) & 0xFF);
- RandPtr++;
- MicroSecondDelay (10);
- }
-
- return TRUE;
-}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Private/Protocol/Crypto.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Private/Protocol/Crypto.h
index 036ddfd065f..fbd2d9637e4 100644
--- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Private/Protocol/Crypto.h
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Private/Protocol/Crypto.h
@@ -2,7 +2,7 @@
This Protocol provides Crypto services to DXE modules
Copyright (C) Microsoft Corporation. All rights reserved.
- Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1107,32 +1107,6 @@ BOOLEAN
);
/**
- Retrieve the RSA Public Key from one DER-encoded X509 certificate.
-
- If Cert is NULL, then return FALSE.
- If RsaContext is NULL, then return FALSE.
- If this interface is not supported, then return FALSE.
-
- @param[in] Cert Pointer to the DER-encoded X509 certificate.
- @param[in] CertSize Size of the X509 certificate in bytes.
- @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
- RSA public key component. Use RsaFree() function to free the
- resource.
-
- @retval TRUE RSA Public Key was retrieved successfully.
- @retval FALSE Fail to retrieve RSA public key from X509 certificate.
- @retval FALSE This interface is not supported.
-
-**/
-typedef
-BOOLEAN
-(EFIAPI *EDKII_CRYPTO_RSA_GET_PUBLIC_KEY_FROM_X509) (
- IN CONST UINT8 *Cert,
- IN UINTN CertSize,
- OUT VOID **RsaContext
- );
-
-/**
Allocates and initializes one RSA context for subsequent use.
@return Pointer to the RSA context that has been initialized.
@@ -3434,6 +3408,81 @@ EFI_STATUS
IN OUT UINTN *DataSize
);
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If Message is NULL, then return FALSE.
+ If MsgSize is zero or > INT_MAX, then return FALSE.
+ If DigestLen is NOT 32, 48 or 64, return FALSE.
+ If SaltLen is < DigestLen, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI* EDKII_CRYPTO_RSA_PSS_SIGN)(
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ );
+
+/**
+ Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017.
+ Implementation determines salt length automatically from the signature encoding.
+ Mask generation function is the same as the message digest algorithm.
+ Salt length should atleast be equal to digest length.
+
+ @param[in] RsaContext Pointer to RSA context for signature verification.
+ @param[in] Message Pointer to octet message to be verified.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] Signature Pointer to RSASSA-PSS signature to be verified.
+ @param[in] SigSize Size of signature in bytes.
+ @param[in] DigestLen Length of digest for RSA operation.
+ @param[in] SaltLen Salt length for PSS encoding.
+
+ @retval TRUE Valid signature encoded in RSASSA-PSS.
+ @retval FALSE Invalid signature or invalid RSA context.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI* EDKII_CRYPTO_RSA_PSS_VERIFY)(
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN CONST UINT8 *Signature,
+ IN UINTN SigSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen
+ );
+
+
///
/// EDK II Crypto Protocol
@@ -3619,6 +3668,9 @@ struct _EDKII_CRYPTO_PROTOCOL {
EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT TlsGetHostPublicCert;
EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY TlsGetHostPrivateKey;
EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST TlsGetCertRevocationList;
+ /// RSA PSS
+ EDKII_CRYPTO_RSA_PSS_SIGN RsaPssSign;
+ EDKII_CRYPTO_RSA_PSS_VERIFY RsaPssVerify;
};
extern GUID gEdkiiCryptoProtocolGuid;
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
new file mode 100644
index 00000000000..9a85d8e2003
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
@@ -0,0 +1,42 @@
+## @file
+# CryptoPkg DSC file used to build host-based unit tests.
+#
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = CryptoPkgHostTest
+ PLATFORM_GUID = C7F97D6D-54AC-45A9-8197-CC99B20CC7EC
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/CryptoPkg/HostTest
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[LibraryClasses]
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
+
+[LibraryClasses.AARCH64, LibraryClasses.ARM]
+ RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
+
+[LibraryClasses.X64, LibraryClasses.IA32]
+ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
+
+[Components]
+ #
+ # Build HOST_APPLICATION that tests the SampleUnitTest
+ #
+ CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
+
+[BuildOptions]
+ *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+ MSFT:*_*_*_CC_FLAGS = /D ENABLE_MD5_DEPRECATED_INTERFACES
+ INTEL:*_*_*_CC_FLAGS = /D ENABLE_MD5_DEPRECATED_INTERFACES
+ GCC:*_*_*_CC_FLAGS = -D ENABLE_MD5_DEPRECATED_INTERFACES
+ RVCT:*_*_*_CC_FLAGS = -DENABLE_MD5_DEPRECATED_INTERFACES
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/AuthenticodeTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/AuthenticodeTests.c
new file mode 100644
index 00000000000..1a2d3d18bc1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/AuthenticodeTests.c
@@ -0,0 +1,1002 @@
+/** @file
+ Sample Implementation for Microsoft Authenticode Verification.
+
+Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// Sample PE/COFF Image Hash Value (Digested by SHA-1).
+// This value should be calculated following MSFT's Authenticode Specification
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 PeSha1Hash[] = {
+ 0x44, 0xFD, 0x4F, 0xA9, 0x17, 0xEE, 0xAC, 0xCF, 0x1F, 0x0B, 0xE3, 0xA1, 0x4D, 0x5B, 0xA6, 0x61,
+ 0x82, 0x97, 0xC4, 0xB6
+ };
+
+//
+// Sample PE/COFF Image Hash Value (Digested by SHA-256).
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 PeSha256Hash[] = {
+ 0x61, 0x82, 0xB7, 0xF8, 0x8C, 0xFF, 0xC2, 0xEB, 0x79, 0x6E, 0x9D, 0xA9, 0xDD, 0x39, 0x52, 0xDD,
+ 0x36, 0xDD, 0xF1, 0x43, 0x27, 0x58, 0x8C, 0xA7, 0xCC, 0xAE, 0xDE, 0xDD, 0x3C, 0x02, 0x12, 0x49
+ };
+
+//
+// Sample Authenticode Data with SHA-1 hash algorithm.
+// This data should be retrieved from signed PE/COFF image according to SECURITY
+// directory in PE/COFF Header.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 AuthenticodeWithSha1[] = {
+ 0x30, 0x82, 0x1C, 0x43, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0,
+ 0x82, 0x1C, 0x34, 0x30, 0x82, 0x1C, 0x30, 0x02, 0x01, 0x01, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x05,
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x30, 0x68, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01,
+ 0x82, 0x37, 0x02, 0x01, 0x04, 0xA0, 0x5A, 0x30, 0x58, 0x30, 0x33, 0x06, 0x0A, 0x2B, 0x06, 0x01,
+ 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0F, 0x30, 0x25, 0x03, 0x01, 0x00, 0xA0, 0x20, 0xA2, 0x1E,
+ 0x80, 0x1C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x4F, 0x00, 0x62, 0x00, 0x73, 0x00, 0x6F,
+ 0x00, 0x6C, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x3E, 0x30, 0x21,
+ 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14, 0x44, 0xFD, 0x4F,
+ 0xA9, 0x17, 0xEE, 0xAC, 0xCF, 0x1F, 0x0B, 0xE3, 0xA1, 0x4D, 0x5B, 0xA6, 0x61, 0x82, 0x97, 0xC4,
+ 0xB6, 0xA0, 0x82, 0x17, 0x18, 0x30, 0x82, 0x04, 0xCA, 0x30, 0x82, 0x03, 0xB2, 0xA0, 0x03, 0x02,
+ 0x01, 0x02, 0x02, 0x0A, 0x61, 0x03, 0xDC, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x0D,
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x77, 0x31,
+ 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11,
+ 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F,
+ 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D,
+ 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69,
+ 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74,
+ 0x69, 0x6F, 0x6E, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4D, 0x69,
+ 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61,
+ 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x38, 0x30, 0x37, 0x32, 0x35,
+ 0x31, 0x39, 0x31, 0x32, 0x35, 0x30, 0x5A, 0x17, 0x0D, 0x31, 0x31, 0x30, 0x37, 0x32, 0x35, 0x31,
+ 0x39, 0x32, 0x32, 0x35, 0x30, 0x5A, 0x30, 0x81, 0xB3, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
+ 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30,
+ 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x0D, 0x30,
+ 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x04, 0x4D, 0x4F, 0x50, 0x52, 0x31, 0x27, 0x30, 0x25,
+ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1E, 0x6E, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x44,
+ 0x53, 0x45, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x31, 0x35, 0x39, 0x43, 0x2D, 0x41, 0x33, 0x46, 0x37,
+ 0x2D, 0x32, 0x35, 0x37, 0x30, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C,
+ 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53,
+ 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x30, 0x82, 0x01, 0x22,
+ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC0, 0xED, 0x81,
+ 0x14, 0xA1, 0x5E, 0x77, 0xC0, 0x5B, 0xF4, 0x76, 0x89, 0x62, 0xFA, 0xAD, 0x7C, 0x68, 0x14, 0xB4,
+ 0xF7, 0xBD, 0x35, 0xD8, 0x13, 0x79, 0x5A, 0x17, 0xCA, 0xD9, 0x6C, 0x51, 0x45, 0x62, 0x26, 0x7A,
+ 0x2F, 0x1F, 0xD8, 0xEA, 0xC1, 0x6E, 0x01, 0x17, 0xF9, 0xC3, 0xA6, 0x1F, 0x67, 0xDB, 0x51, 0xB0,
+ 0x2C, 0xDE, 0x8A, 0x17, 0xED, 0xFF, 0x20, 0xAD, 0x34, 0xEA, 0x98, 0xFB, 0xA5, 0xD6, 0x2A, 0xD2,
+ 0xF1, 0x44, 0x27, 0x07, 0x5A, 0x2D, 0x3A, 0x93, 0xFF, 0x56, 0x53, 0xB0, 0xC8, 0xF5, 0xF3, 0x03,
+ 0xF2, 0x49, 0xCC, 0x16, 0xD0, 0xF5, 0x00, 0x4C, 0x58, 0xF8, 0x9B, 0xF5, 0x07, 0x25, 0xB1, 0x66,
+ 0x17, 0xC0, 0xBD, 0xC8, 0xD2, 0x52, 0x85, 0x8D, 0xC2, 0x2B, 0x38, 0xB2, 0xC3, 0x36, 0xBE, 0xF9,
+ 0x87, 0xDA, 0xF4, 0x8E, 0x5D, 0x43, 0xD7, 0x06, 0xBF, 0x99, 0x05, 0x9F, 0xA4, 0xCE, 0xFE, 0xAB,
+ 0x8D, 0x61, 0x63, 0xE7, 0x39, 0xC5, 0xF3, 0x18, 0xF6, 0xD8, 0xFC, 0x31, 0x36, 0x69, 0x72, 0x5A,
+ 0xA2, 0x1A, 0x4C, 0x3E, 0xEA, 0x87, 0x25, 0x42, 0x9D, 0xD1, 0x3E, 0xF1, 0x97, 0xD2, 0x18, 0x32,
+ 0x93, 0x70, 0x55, 0x53, 0x81, 0x1E, 0xE3, 0x3B, 0x0D, 0xE8, 0xBE, 0x82, 0x78, 0x6D, 0xE6, 0xFA,
+ 0xCD, 0x98, 0xA4, 0x6F, 0xDB, 0xEE, 0x66, 0xF4, 0x95, 0xC8, 0xCD, 0x35, 0xC9, 0x9E, 0xBB, 0x36,
+ 0x0D, 0x83, 0x96, 0x94, 0x26, 0xA7, 0x90, 0xE0, 0xA9, 0x34, 0x3B, 0xD5, 0xC0, 0x9E, 0x3E, 0xF0,
+ 0xD4, 0x47, 0x8D, 0x86, 0x0C, 0x82, 0xA4, 0x58, 0x30, 0x3A, 0x1C, 0x76, 0xE3, 0xAD, 0x95, 0x66,
+ 0xB4, 0xB7, 0xFD, 0x09, 0x8A, 0x05, 0x60, 0x0F, 0xA3, 0x0F, 0xE2, 0x93, 0x96, 0x58, 0x22, 0x9C,
+ 0x9D, 0x2B, 0xDB, 0xA2, 0x94, 0x18, 0x90, 0x95, 0x02, 0xBD, 0x06, 0x40, 0x95, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xA3, 0x82, 0x01, 0x19, 0x30, 0x82, 0x01, 0x15, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D,
+ 0x0E, 0x04, 0x16, 0x04, 0x14, 0xD2, 0xED, 0x0D, 0x1E, 0x24, 0xBB, 0x37, 0xA9, 0xD8, 0x20, 0x6A,
+ 0x4D, 0x1D, 0xD2, 0x16, 0xD5, 0x2E, 0xBE, 0x9E, 0xEB, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x23, 0x34, 0xF8, 0xD9, 0x52, 0x46, 0x70, 0x0A, 0xED, 0x40,
+ 0xFB, 0x76, 0xFB, 0xB3, 0x2B, 0xB0, 0xC3, 0x35, 0xB3, 0x0F, 0x30, 0x54, 0x06, 0x03, 0x55, 0x1D,
+ 0x1F, 0x04, 0x4D, 0x30, 0x4B, 0x30, 0x49, 0xA0, 0x47, 0xA0, 0x45, 0x86, 0x43, 0x68, 0x74, 0x74,
+ 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72,
+ 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
+ 0x54, 0x69, 0x6D, 0x65, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x50, 0x43, 0x41, 0x2E, 0x63, 0x72, 0x6C,
+ 0x30, 0x58, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x4C, 0x30, 0x4A,
+ 0x30, 0x48, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3C, 0x68, 0x74,
+ 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73,
+ 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x54, 0x69, 0x6D, 0x65, 0x53, 0x74,
+ 0x61, 0x6D, 0x70, 0x50, 0x43, 0x41, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D,
+ 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30,
+ 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x06, 0xC0, 0x30,
+ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x9C, 0x0A, 0x55, 0xC8, 0xCC, 0x44, 0x13, 0x34, 0x0C, 0xD8, 0x63, 0x27, 0x76,
+ 0x7D, 0x3E, 0xFA, 0x38, 0x32, 0x83, 0x53, 0x9D, 0xF2, 0x08, 0xF9, 0x32, 0xF5, 0xC5, 0x6E, 0x70,
+ 0xA1, 0xC9, 0xB1, 0x63, 0x6B, 0x19, 0x9D, 0x09, 0x67, 0xD9, 0x9D, 0xEB, 0x8A, 0x6A, 0xDB, 0x60,
+ 0x66, 0xE9, 0xE9, 0x52, 0x26, 0xF3, 0x3B, 0xC6, 0x6A, 0xD3, 0xC2, 0x52, 0xBE, 0xA8, 0xB9, 0xEB,
+ 0x6A, 0xAA, 0x78, 0x8C, 0xC9, 0x16, 0x7D, 0x90, 0x95, 0xA0, 0xCC, 0x21, 0xB3, 0x9E, 0x81, 0xBD,
+ 0xCD, 0xC1, 0x8B, 0x29, 0xBD, 0x62, 0x25, 0xEF, 0x09, 0x57, 0xE7, 0x86, 0x4E, 0x2A, 0xEC, 0x80,
+ 0xCA, 0xBB, 0xFC, 0x21, 0x16, 0xC4, 0x3F, 0x4E, 0x52, 0x19, 0xE6, 0x0E, 0xB1, 0xD8, 0xC1, 0xC2,
+ 0x79, 0x90, 0x64, 0xB4, 0x50, 0x73, 0x10, 0x35, 0x5E, 0x5D, 0x11, 0xC1, 0xB8, 0xBA, 0xAA, 0xCF,
+ 0x52, 0xF6, 0x80, 0x91, 0x00, 0xE6, 0xEF, 0x51, 0x43, 0x46, 0xE9, 0xD0, 0xE8, 0x94, 0xF6, 0x2C,
+ 0x24, 0x0D, 0x8A, 0xC6, 0xB2, 0x31, 0x8A, 0xA3, 0x7E, 0x36, 0x6C, 0xA4, 0x05, 0x4C, 0x67, 0x07,
+ 0x2A, 0xBB, 0xBB, 0x10, 0xA5, 0xA5, 0x30, 0x1A, 0x72, 0xD0, 0x06, 0x20, 0x3B, 0x24, 0x93, 0x5B,
+ 0x15, 0xD9, 0x39, 0x93, 0xD3, 0x73, 0x2D, 0x1A, 0xC4, 0xD4, 0x6C, 0x1E, 0xA1, 0x08, 0xEC, 0xF6,
+ 0x31, 0xB8, 0x6B, 0x4B, 0xEC, 0xEE, 0x5C, 0x33, 0x02, 0x14, 0x32, 0x8C, 0x7C, 0x11, 0x20, 0x2F,
+ 0x20, 0x03, 0x7F, 0xF9, 0x0C, 0x9D, 0xB8, 0xD3, 0x9E, 0x5F, 0xD6, 0x08, 0xFC, 0x81, 0xA0, 0x99,
+ 0xB8, 0xBB, 0x55, 0x6E, 0xCD, 0x42, 0x4B, 0x3A, 0x4D, 0x8C, 0x14, 0x2B, 0xCA, 0xC8, 0x12, 0xD3,
+ 0x62, 0x6E, 0xEA, 0x0D, 0x0A, 0x9D, 0x09, 0xA3, 0x66, 0xD9, 0x79, 0x4F, 0x8E, 0x1A, 0xA2, 0xFF,
+ 0xCC, 0x98, 0x04, 0x30, 0x82, 0x05, 0x96, 0x30, 0x82, 0x04, 0x7E, 0xA0, 0x03, 0x02, 0x01, 0x02,
+ 0x02, 0x0A, 0x61, 0x01, 0xC6, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30, 0x0D, 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81, 0x81, 0x31, 0x0B,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E,
+ 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F,
+ 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63,
+ 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69,
+ 0x6F, 0x6E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D, 0x69, 0x63,
+ 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x56,
+ 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x50, 0x43, 0x41, 0x30,
+ 0x1E, 0x17, 0x0D, 0x30, 0x38, 0x31, 0x30, 0x32, 0x32, 0x32, 0x30, 0x33, 0x39, 0x32, 0x32, 0x5A,
+ 0x17, 0x0D, 0x31, 0x30, 0x30, 0x31, 0x32, 0x32, 0x32, 0x30, 0x34, 0x39, 0x32, 0x32, 0x5A, 0x30,
+ 0x7F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67,
+ 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65,
+ 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15,
+ 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72,
+ 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x04,
+ 0x4D, 0x4F, 0x50, 0x52, 0x31, 0x1A, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x11, 0x4D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73,
+ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01,
+ 0x00, 0xDC, 0x3A, 0xD3, 0x44, 0xF4, 0x6E, 0x20, 0x9F, 0xDD, 0xA4, 0x0E, 0x82, 0x4E, 0xC7, 0x86,
+ 0x5E, 0x63, 0xCC, 0xCA, 0xE5, 0x42, 0x53, 0x4B, 0x85, 0xFA, 0x5D, 0x71, 0x6C, 0xCF, 0x76, 0x0C,
+ 0x18, 0x8B, 0xA6, 0x0D, 0xF5, 0x4A, 0xF7, 0xFE, 0x17, 0xF2, 0x90, 0xCC, 0x62, 0xC7, 0x24, 0xAD,
+ 0x9B, 0x9A, 0xE1, 0x45, 0x3B, 0x61, 0xD8, 0x0D, 0x05, 0x69, 0xC7, 0xCD, 0x88, 0x2A, 0xB8, 0xB9,
+ 0x18, 0x1E, 0x60, 0x10, 0x5F, 0x88, 0xC6, 0xD2, 0x82, 0x4E, 0x6D, 0x49, 0xC5, 0xBE, 0x5C, 0x12,
+ 0x86, 0x48, 0x85, 0x89, 0x91, 0x81, 0xCD, 0x1B, 0xAD, 0x1F, 0xB7, 0x2D, 0x67, 0x79, 0xF1, 0x7B,
+ 0x9F, 0x25, 0x87, 0x14, 0x76, 0x5F, 0xE3, 0x0E, 0x64, 0xA1, 0x72, 0x61, 0x25, 0xE5, 0x75, 0x69,
+ 0xC5, 0x14, 0xF1, 0x5F, 0x07, 0x56, 0xA4, 0x0D, 0x70, 0x06, 0x23, 0xA7, 0x6C, 0xDD, 0x82, 0xAE,
+ 0xD9, 0x9B, 0x47, 0xA4, 0xA5, 0x6C, 0x08, 0xB0, 0x58, 0xF1, 0x53, 0x6A, 0x4F, 0xDA, 0x85, 0x61,
+ 0xCB, 0x02, 0x7B, 0x49, 0xAF, 0x1F, 0xBB, 0xE0, 0xD7, 0xB9, 0x5E, 0xDB, 0x73, 0x89, 0x76, 0xC1,
+ 0x3A, 0xBB, 0x0D, 0xF5, 0x97, 0xF0, 0x88, 0x5D, 0x69, 0x77, 0x80, 0xCF, 0xF1, 0x7E, 0x03, 0x9F,
+ 0x73, 0x6D, 0xDE, 0x05, 0xB8, 0x2F, 0x77, 0xB5, 0x54, 0x55, 0x45, 0xD0, 0xD2, 0x38, 0xBD, 0x96,
+ 0xE3, 0xF7, 0xEA, 0x40, 0xE5, 0xAC, 0x19, 0xFC, 0x71, 0xCB, 0x28, 0x27, 0xAA, 0x71, 0xA1, 0x72,
+ 0xB5, 0x12, 0x27, 0xC1, 0x51, 0xF6, 0x36, 0xC5, 0xC0, 0xC7, 0x7B, 0x3A, 0x3A, 0x93, 0x37, 0x04,
+ 0xCC, 0xEE, 0x0B, 0x69, 0x78, 0x64, 0x75, 0x41, 0xB6, 0x78, 0x22, 0x0F, 0x77, 0x84, 0xF7, 0x4B,
+ 0x8D, 0x46, 0x65, 0x92, 0x5B, 0x4D, 0x56, 0x6B, 0x75, 0x04, 0x46, 0x3F, 0x0B, 0x1B, 0xB4, 0x19,
+ 0xBF, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x02, 0x0F, 0x30, 0x82, 0x02, 0x0B, 0x30, 0x1F,
+ 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x18, 0x30, 0x16, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x03, 0x03, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x03, 0x06, 0x30,
+ 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xA1, 0xE6, 0xC3, 0x65, 0xD0, 0xE6,
+ 0xE8, 0x28, 0x62, 0xC2, 0xF3, 0xC2, 0x23, 0xA6, 0x1C, 0x49, 0x82, 0x0B, 0xD5, 0x53, 0x30, 0x0E,
+ 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x1F,
+ 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x90, 0x8B, 0x11,
+ 0xA5, 0x70, 0xED, 0xE0, 0xF9, 0xA9, 0xC0, 0xAC, 0x08, 0xC7, 0xB5, 0xF4, 0x82, 0xB1, 0x3C, 0xC5,
+ 0x4A, 0x30, 0x7B, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x74, 0x30, 0x72, 0x30, 0x70, 0xA0, 0x6E,
+ 0xA0, 0x6C, 0x86, 0x34, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69,
+ 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x57, 0x69,
+ 0x6E, 0x50, 0x43, 0x41, 0x2E, 0x63, 0x72, 0x6C, 0x86, 0x34, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F,
+ 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63,
+ 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75,
+ 0x63, 0x74, 0x73, 0x2F, 0x57, 0x69, 0x6E, 0x50, 0x43, 0x41, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x52,
+ 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x46, 0x30, 0x44, 0x30, 0x42,
+ 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x36, 0x68, 0x74, 0x74, 0x70,
+ 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
+ 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x57, 0x69, 0x6E, 0x50, 0x43, 0x41, 0x2E, 0x63,
+ 0x72, 0x74, 0x30, 0x81, 0xC6, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x81, 0xBE, 0x30, 0x81, 0xBB,
+ 0x30, 0x81, 0xB8, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x2F, 0x30, 0x81,
+ 0xAA, 0x30, 0x40, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x34, 0x68,
+ 0x74, 0x74, 0x70, 0x73, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F,
+ 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x73, 0x73, 0x6C,
+ 0x2F, 0x63, 0x70, 0x73, 0x2F, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x50, 0x43, 0x41, 0x2E,
+ 0x68, 0x74, 0x6D, 0x30, 0x66, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30,
+ 0x5A, 0x1E, 0x58, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00,
+ 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0xA9, 0x00, 0x20, 0x00, 0x31, 0x00, 0x39, 0x00,
+ 0x39, 0x00, 0x39, 0x00, 0x2D, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x35, 0x00, 0x20, 0x00,
+ 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00,
+ 0x74, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x2E, 0x30, 0x0D, 0x06, 0x09, 0x2A,
+ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x73,
+ 0x5F, 0xCA, 0x80, 0x1C, 0x60, 0x46, 0x6F, 0xB9, 0x34, 0x9D, 0x88, 0xE3, 0xBE, 0x22, 0x8C, 0xFA,
+ 0xE6, 0x58, 0x9A, 0xAB, 0x7B, 0x1A, 0x97, 0xFD, 0xED, 0x2E, 0x39, 0xCC, 0x59, 0x5B, 0x1D, 0x7A,
+ 0x06, 0x8A, 0xBB, 0x43, 0x93, 0x7B, 0x1E, 0xA1, 0x88, 0x53, 0xDF, 0x44, 0xF8, 0x53, 0xA9, 0xEA,
+ 0xF6, 0x67, 0x1B, 0x3A, 0x78, 0x84, 0x11, 0x6A, 0x6F, 0x29, 0x47, 0x90, 0x0A, 0x0C, 0x7B, 0x22,
+ 0x77, 0x4E, 0x6F, 0xB8, 0x64, 0x29, 0xDF, 0x06, 0xC7, 0xC8, 0x73, 0x84, 0xD6, 0x66, 0xA0, 0xCA,
+ 0xD9, 0x5A, 0x26, 0x82, 0x57, 0xF9, 0xE3, 0x4F, 0x39, 0xAF, 0x2E, 0x8E, 0xB1, 0x06, 0x5B, 0x72,
+ 0xF2, 0x37, 0x32, 0xAE, 0x4E, 0xCE, 0x3C, 0x7D, 0xB0, 0x12, 0x2B, 0x9E, 0xA5, 0x75, 0xE3, 0x43,
+ 0xA6, 0x12, 0x8B, 0x06, 0x14, 0x98, 0x77, 0xE3, 0x58, 0x32, 0x25, 0x60, 0x07, 0x8C, 0x59, 0x71,
+ 0xA7, 0x71, 0x41, 0xB3, 0x06, 0x8D, 0x5C, 0xEF, 0x9C, 0x7F, 0x5A, 0x22, 0x6D, 0xB7, 0xD3, 0xD9,
+ 0xF5, 0xA6, 0x1B, 0x52, 0xDE, 0xF5, 0x7E, 0x76, 0x7C, 0xFE, 0xF4, 0xC8, 0x23, 0x1A, 0x4B, 0x25,
+ 0xEB, 0xE4, 0xEE, 0xAF, 0x10, 0x0B, 0x55, 0xC3, 0xD8, 0xC1, 0x17, 0x85, 0x61, 0x6F, 0xD3, 0x3F,
+ 0xB6, 0xE9, 0xEC, 0x84, 0xA5, 0xEE, 0x6D, 0xB2, 0xFF, 0xE8, 0x6C, 0x95, 0xAB, 0x2B, 0x5E, 0xC8,
+ 0x85, 0xC3, 0x11, 0x60, 0xAC, 0xFA, 0x02, 0x05, 0xF1, 0x7B, 0xDA, 0xC3, 0x69, 0x49, 0x96, 0xA5,
+ 0x70, 0xF9, 0x65, 0x66, 0x46, 0x10, 0x8D, 0x34, 0xE9, 0x21, 0x94, 0x3C, 0x0F, 0x71, 0x4A, 0x1C,
+ 0xEA, 0x1F, 0xF7, 0x23, 0xA6, 0x87, 0x60, 0x34, 0xE9, 0x14, 0xE1, 0xDE, 0x03, 0x59, 0xB4, 0x02,
+ 0x1D, 0x3A, 0xAF, 0xE3, 0x55, 0x05, 0xF5, 0xED, 0xC1, 0xF4, 0xE4, 0x5D, 0x0E, 0xD3, 0x97, 0x30,
+ 0x82, 0x06, 0x07, 0x30, 0x82, 0x03, 0xEF, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x61, 0x16,
+ 0x68, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5F, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0A, 0x09,
+ 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x03, 0x63, 0x6F, 0x6D, 0x31, 0x19,
+ 0x30, 0x17, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x09,
+ 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x24, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F,
+ 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41,
+ 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x37, 0x30, 0x34,
+ 0x30, 0x33, 0x31, 0x32, 0x35, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x34, 0x30,
+ 0x33, 0x31, 0x33, 0x30, 0x33, 0x30, 0x39, 0x5A, 0x30, 0x77, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E,
+ 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x21,
+ 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43,
+ 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01,
+ 0x01, 0x00, 0x9F, 0xA1, 0x6C, 0xB1, 0xDF, 0xDB, 0x48, 0x92, 0x2A, 0x7C, 0x6B, 0x2E, 0x19, 0xE1,
+ 0xBD, 0xE2, 0xE3, 0xC5, 0x99, 0x51, 0x23, 0x50, 0xAD, 0xCE, 0xDD, 0x18, 0x4E, 0x24, 0x0F, 0xEE,
+ 0xD1, 0xA7, 0xD1, 0x4C, 0xAD, 0x74, 0x30, 0x20, 0x11, 0xEB, 0x07, 0xD5, 0x54, 0x95, 0x15, 0x49,
+ 0x94, 0x1B, 0x42, 0x92, 0xAE, 0x98, 0x5C, 0x30, 0x26, 0xDA, 0x00, 0x6B, 0xE8, 0x7B, 0xBD, 0xEC,
+ 0x89, 0x07, 0x0F, 0xF7, 0x0E, 0x04, 0x98, 0xF0, 0x89, 0xCC, 0x1F, 0xCB, 0x33, 0x24, 0x87, 0x9D,
+ 0xF2, 0xF4, 0x67, 0x1C, 0x2C, 0xFC, 0x7B, 0xE7, 0x88, 0x1D, 0xEA, 0xE7, 0x4E, 0xA3, 0xA1, 0xC1,
+ 0x23, 0x53, 0xCA, 0x8D, 0xFA, 0x45, 0xCF, 0x09, 0xD0, 0x5E, 0xAF, 0xD0, 0xB0, 0x42, 0x04, 0xA2,
+ 0xF9, 0xA6, 0x6C, 0x93, 0x67, 0xD7, 0x28, 0xDC, 0x46, 0x53, 0xB0, 0x86, 0xD0, 0xE5, 0x28, 0x46,
+ 0x2E, 0x27, 0xAC, 0x86, 0x4F, 0x55, 0x52, 0x0C, 0xE4, 0x03, 0x2C, 0xFB, 0x6A, 0x90, 0x90, 0x30,
+ 0x6E, 0x87, 0xF3, 0x59, 0x30, 0x9D, 0xFA, 0x7E, 0xD6, 0x97, 0xB3, 0xE8, 0x21, 0x97, 0x7E, 0xF8,
+ 0xD2, 0x13, 0xF3, 0x08, 0xB7, 0x53, 0x6D, 0x52, 0xB4, 0x45, 0x90, 0x9F, 0x48, 0x00, 0x4A, 0x47,
+ 0x66, 0x11, 0x27, 0x29, 0x66, 0xA8, 0x97, 0xE4, 0xD3, 0x06, 0x81, 0x4A, 0xA2, 0xF9, 0x84, 0xA7,
+ 0x11, 0x47, 0x14, 0x09, 0x82, 0x9F, 0x84, 0xED, 0x55, 0x78, 0xFE, 0x01, 0x9A, 0x1D, 0x50, 0x08,
+ 0x85, 0x00, 0x10, 0x30, 0x46, 0xED, 0xB7, 0xDE, 0x23, 0x46, 0xBB, 0xC4, 0x2D, 0x54, 0x9F, 0xAF,
+ 0x1E, 0x78, 0x41, 0x31, 0x77, 0xCC, 0x9B, 0xDF, 0x3B, 0x83, 0x93, 0xA1, 0x61, 0x02, 0xB5, 0x1D,
+ 0x0D, 0xB1, 0xFC, 0xF7, 0x9B, 0xB2, 0x01, 0xCE, 0x22, 0x4B, 0x54, 0xFF, 0xF9, 0x05, 0xC3, 0xC2,
+ 0x20, 0x0B, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0xAB, 0x30, 0x82, 0x01, 0xA7, 0x30,
+ 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF,
+ 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x23, 0x34, 0xF8, 0xD9, 0x52,
+ 0x46, 0x70, 0x0A, 0xED, 0x40, 0xFB, 0x76, 0xFB, 0xB3, 0x2B, 0xB0, 0xC3, 0x35, 0xB3, 0x0F, 0x30,
+ 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x10, 0x06, 0x09,
+ 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x81,
+ 0x98, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0x90, 0x30, 0x81, 0x8D, 0x80, 0x14, 0x0E, 0xAC,
+ 0x82, 0x60, 0x40, 0x56, 0x27, 0x97, 0xE5, 0x25, 0x13, 0xFC, 0x2A, 0xE1, 0x0A, 0x53, 0x95, 0x59,
+ 0xE4, 0xA4, 0xA1, 0x63, 0xA4, 0x61, 0x30, 0x5F, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0A, 0x09, 0x92,
+ 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x03, 0x63, 0x6F, 0x6D, 0x31, 0x19, 0x30,
+ 0x17, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x09, 0x6D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x24, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F,
+ 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75,
+ 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x82, 0x10, 0x79, 0xAD, 0x16, 0xA1, 0x4A, 0xA0, 0xA5,
+ 0xAD, 0x4C, 0x73, 0x58, 0xF4, 0x07, 0x13, 0x2E, 0x65, 0x30, 0x50, 0x06, 0x03, 0x55, 0x1D, 0x1F,
+ 0x04, 0x49, 0x30, 0x47, 0x30, 0x45, 0xA0, 0x43, 0xA0, 0x41, 0x86, 0x3F, 0x68, 0x74, 0x74, 0x70,
+ 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
+ 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F,
+ 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x72,
+ 0x6F, 0x6F, 0x74, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x54, 0x06, 0x08, 0x2B,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x48, 0x30, 0x46, 0x30, 0x44, 0x06, 0x08, 0x2B,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x38, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F,
+ 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F,
+ 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x72,
+ 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x52, 0x6F, 0x6F, 0x74, 0x43, 0x65, 0x72, 0x74, 0x2E, 0x63, 0x72,
+ 0x74, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, 0x08, 0x2B, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x10, 0x97, 0x8A, 0xC3, 0x5C, 0x03,
+ 0x44, 0x36, 0xDD, 0xE9, 0xB4, 0xAD, 0x77, 0xDB, 0xCE, 0x79, 0x51, 0x4D, 0x01, 0xB1, 0x2E, 0x74,
+ 0x71, 0x5B, 0x6D, 0x0C, 0x13, 0xAB, 0xCE, 0xBE, 0x7B, 0x8F, 0xB8, 0x2E, 0xD4, 0x12, 0xA2, 0x8C,
+ 0x6D, 0x62, 0xB8, 0x57, 0x02, 0xCB, 0x4E, 0x20, 0x13, 0x50, 0x99, 0xDD, 0x7A, 0x40, 0xE2, 0x57,
+ 0xBB, 0xAF, 0x58, 0x9A, 0x1C, 0xE1, 0x1D, 0x01, 0x86, 0xAC, 0xBB, 0x78, 0xF2, 0x8B, 0xD0, 0xEC,
+ 0x3B, 0x01, 0xEE, 0xE2, 0xBE, 0x8F, 0x0A, 0x05, 0xC8, 0x8D, 0x48, 0xE2, 0xF0, 0x53, 0x15, 0xDD,
+ 0x4F, 0xAB, 0x92, 0xE4, 0xE7, 0x8D, 0x6A, 0xD5, 0x80, 0xC1, 0xE6, 0x94, 0xF2, 0x06, 0x2F, 0x85,
+ 0x03, 0xE9, 0x91, 0x2A, 0x24, 0x22, 0x70, 0xFB, 0xF6, 0xFC, 0xE4, 0x78, 0x99, 0x2E, 0x0D, 0xF7,
+ 0x07, 0xE2, 0x70, 0xBC, 0x18, 0x4E, 0x9D, 0x8E, 0x6B, 0x0A, 0x72, 0x95, 0xB8, 0xA1, 0x39, 0x9C,
+ 0x67, 0x2D, 0xC5, 0x51, 0x0E, 0xEA, 0x62, 0x5C, 0x3F, 0x16, 0x98, 0x8B, 0x20, 0x3F, 0xE2, 0x07,
+ 0x1A, 0x32, 0xF9, 0xCC, 0x31, 0x4A, 0x76, 0x31, 0x3D, 0x2B, 0x72, 0x0B, 0xC8, 0xEA, 0x70, 0x3D,
+ 0xFF, 0x85, 0x0A, 0x13, 0xDF, 0xC2, 0x0A, 0x61, 0x8E, 0xF0, 0xD7, 0xB8, 0x17, 0xEB, 0x4E, 0x8B,
+ 0x7F, 0xC5, 0x35, 0x2B, 0x5E, 0xA3, 0xBF, 0xEB, 0xBC, 0x7D, 0x0B, 0x42, 0x7B, 0xD4, 0x53, 0x72,
+ 0x21, 0xEE, 0x30, 0xCA, 0xBB, 0x78, 0x65, 0x5C, 0x5B, 0x01, 0x17, 0x0A, 0x14, 0x0E, 0xD2, 0xDA,
+ 0x14, 0x98, 0xF5, 0x3C, 0xB9, 0x66, 0x58, 0xB3, 0x2D, 0x2F, 0xE7, 0xF9, 0x85, 0x86, 0xCC, 0x51,
+ 0x56, 0xE8, 0x9D, 0x70, 0x94, 0x6C, 0xAC, 0x39, 0x4C, 0xD4, 0xF6, 0x79, 0xBF, 0xAA, 0x18, 0x7A,
+ 0x62, 0x29, 0xEF, 0xA2, 0x9B, 0x29, 0x34, 0x06, 0x77, 0x1A, 0x62, 0xC9, 0x3D, 0x1E, 0x6D, 0x1F,
+ 0x82, 0xF0, 0x0B, 0xC7, 0x2C, 0xBB, 0xCF, 0x43, 0xB3, 0xE5, 0xF9, 0xEC, 0x7D, 0xB5, 0xE3, 0xA4,
+ 0xA8, 0x74, 0x35, 0xB8, 0x4E, 0xC5, 0x71, 0x23, 0x12, 0x26, 0x76, 0x0B, 0x3C, 0x52, 0x8C, 0x71,
+ 0x5A, 0x46, 0x43, 0x14, 0xBC, 0xB3, 0xB3, 0xB0, 0x4D, 0x67, 0xC8, 0x9F, 0x42, 0xFF, 0x80, 0x79,
+ 0x21, 0x80, 0x9E, 0x15, 0x30, 0x66, 0xE8, 0x42, 0x12, 0x5E, 0x1A, 0xC8, 0x9E, 0x22, 0x21, 0xD0,
+ 0x43, 0xE9, 0x2B, 0xE9, 0xBB, 0xF4, 0x48, 0xCC, 0x2C, 0xD4, 0xD8, 0x32, 0x80, 0x4C, 0x26, 0x2A,
+ 0x48, 0x24, 0x5F, 0x5A, 0xEA, 0x56, 0xEF, 0xA6, 0xDE, 0x99, 0x9D, 0xCA, 0x3A, 0x6F, 0xBD, 0x81,
+ 0x27, 0x74, 0x06, 0x11, 0xEE, 0x76, 0x21, 0xBF, 0x9B, 0x82, 0xC1, 0x27, 0x54, 0xB6, 0xB1, 0x6A,
+ 0x3D, 0x89, 0xA1, 0x76, 0x61, 0xB4, 0x6E, 0xA1, 0x13, 0xA6, 0xBF, 0xAA, 0x47, 0xF0, 0x12, 0x6F,
+ 0xFD, 0x8A, 0x32, 0x6C, 0xB2, 0xFE, 0xDF, 0x51, 0xC8, 0x8C, 0x23, 0xC9, 0x66, 0xBD, 0x9D, 0x1D,
+ 0x87, 0x12, 0x64, 0x02, 0x3D, 0x2D, 0xAF, 0x59, 0x8F, 0xB8, 0xE4, 0x21, 0xE5, 0xB5, 0xB0, 0xCA,
+ 0x63, 0xB4, 0x78, 0x54, 0x05, 0xD4, 0x41, 0x2E, 0x50, 0xAC, 0x94, 0xB0, 0xA5, 0x78, 0xAB, 0xB3,
+ 0xA0, 0x96, 0x75, 0x1A, 0xD9, 0x92, 0x87, 0x13, 0x75, 0x22, 0x2F, 0x32, 0xA8, 0x08, 0x6E, 0xA0,
+ 0x5B, 0x8C, 0x25, 0xBF, 0xA0, 0xEF, 0x84, 0xCA, 0x21, 0xD6, 0xEB, 0x1E, 0x4F, 0xC9, 0x9A, 0xEE,
+ 0x49, 0xE0, 0xF7, 0x01, 0x65, 0x6F, 0x89, 0x0B, 0x7D, 0xC8, 0x69, 0xC8, 0xE6, 0x6E, 0xEA, 0xA7,
+ 0x97, 0xCE, 0x31, 0x29, 0xFF, 0x0E, 0xC5, 0x5B, 0x5C, 0xD8, 0x4D, 0x1B, 0xA1, 0xD8, 0xFA, 0x2F,
+ 0x9E, 0x3F, 0x2E, 0x55, 0x16, 0x6B, 0xC9, 0x13, 0xA3, 0xFD, 0x30, 0x82, 0x06, 0xA1, 0x30, 0x82,
+ 0x04, 0x89, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, 0x61, 0x07, 0x02, 0xDC, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x0B, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x5F, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2,
+ 0x2C, 0x64, 0x01, 0x19, 0x16, 0x03, 0x63, 0x6F, 0x6D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x0A, 0x09,
+ 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x09, 0x6D, 0x69, 0x63, 0x72, 0x6F,
+ 0x73, 0x6F, 0x66, 0x74, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x4D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72,
+ 0x69, 0x74, 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x30, 0x35, 0x30, 0x39, 0x31, 0x35, 0x32, 0x31, 0x35,
+ 0x35, 0x34, 0x31, 0x5A, 0x17, 0x0D, 0x31, 0x36, 0x30, 0x33, 0x31, 0x35, 0x32, 0x32, 0x30, 0x35,
+ 0x34, 0x31, 0x5A, 0x30, 0x81, 0x81, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
+ 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61,
+ 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04,
+ 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03,
+ 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43,
+ 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57,
+ 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+ 0x69, 0x6F, 0x6E, 0x20, 0x50, 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A,
+ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30,
+ 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC5, 0xAC, 0x93, 0x4E, 0xE6, 0x4A, 0x11, 0x9E,
+ 0x37, 0xD0, 0x35, 0xD2, 0xB0, 0x06, 0x5C, 0x83, 0x14, 0xA5, 0x61, 0x92, 0xFC, 0xFE, 0xB3, 0x89,
+ 0xC1, 0xE6, 0xCD, 0xC8, 0x1F, 0x31, 0x84, 0x09, 0x91, 0x34, 0x46, 0x92, 0x2C, 0xB8, 0xEE, 0x2C,
+ 0xC5, 0x20, 0x73, 0xC4, 0xE8, 0x1A, 0xD8, 0x8D, 0xCE, 0x7A, 0x68, 0xB5, 0x66, 0x78, 0x8B, 0xE5,
+ 0x60, 0x15, 0xA2, 0xF6, 0x29, 0x5A, 0x1D, 0x5E, 0x5D, 0xFC, 0x62, 0xD3, 0xC1, 0x5C, 0x29, 0x89,
+ 0xFB, 0x33, 0xF8, 0x16, 0x95, 0x36, 0xDD, 0xB1, 0x46, 0x74, 0x69, 0x72, 0x53, 0xD5, 0xAA, 0xE8,
+ 0x8A, 0x99, 0x1A, 0xD8, 0xF7, 0x67, 0x09, 0xD9, 0x09, 0x20, 0x22, 0x38, 0x7A, 0xD6, 0x03, 0x23,
+ 0xD7, 0x89, 0x9F, 0x1C, 0x01, 0xB7, 0x51, 0xDF, 0x98, 0x66, 0x2A, 0x02, 0x8B, 0x06, 0xEC, 0xE4,
+ 0x29, 0xEF, 0x5B, 0x42, 0x17, 0x15, 0x97, 0x51, 0x8D, 0x7D, 0x25, 0x0A, 0xAF, 0x25, 0xE8, 0xDE,
+ 0xDC, 0x9B, 0x67, 0x16, 0x0A, 0x56, 0x73, 0x9D, 0xB3, 0x1D, 0x85, 0x83, 0x0B, 0x7E, 0x33, 0x2B,
+ 0x62, 0x33, 0xCE, 0x1C, 0x20, 0x81, 0x4B, 0x5E, 0xD3, 0xC6, 0x49, 0xB8, 0xF6, 0x2E, 0xD3, 0x4E,
+ 0xB0, 0x71, 0x44, 0x46, 0x64, 0x3E, 0xDE, 0x43, 0x66, 0x04, 0xB9, 0xCC, 0x83, 0x48, 0x3A, 0xC5,
+ 0x36, 0x7A, 0x04, 0x48, 0x0B, 0x89, 0x02, 0x3D, 0x63, 0xA2, 0x01, 0x76, 0x29, 0x97, 0x75, 0xE9,
+ 0x01, 0xE6, 0x00, 0x97, 0x09, 0x92, 0xF8, 0xE2, 0x27, 0xF0, 0x29, 0x67, 0x43, 0x77, 0xC3, 0x50,
+ 0x96, 0x53, 0x31, 0xE1, 0xB6, 0x71, 0x8B, 0xEC, 0x77, 0xC7, 0x7C, 0x31, 0x48, 0xD5, 0xB8, 0x25,
+ 0x22, 0x8C, 0x00, 0xF7, 0x28, 0x38, 0x7A, 0xBD, 0x7C, 0xC7, 0x3F, 0xCD, 0x40, 0x26, 0x77, 0xDD,
+ 0x00, 0x00, 0x11, 0x9A, 0x95, 0xBE, 0x1F, 0xDB, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x02,
+ 0x3A, 0x30, 0x82, 0x02, 0x36, 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16,
+ 0x04, 0x14, 0x90, 0x8B, 0x11, 0xA5, 0x70, 0xED, 0xE0, 0xF9, 0xA9, 0xC0, 0xAC, 0x08, 0xC7, 0xB5,
+ 0xF4, 0x82, 0xB1, 0x3C, 0xC5, 0x4A, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, 0x04, 0x03,
+ 0x02, 0x01, 0xC6, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30,
+ 0x03, 0x01, 0x01, 0xFF, 0x30, 0x81, 0x98, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0x90, 0x30,
+ 0x81, 0x8D, 0x80, 0x14, 0x0E, 0xAC, 0x82, 0x60, 0x40, 0x56, 0x27, 0x97, 0xE5, 0x25, 0x13, 0xFC,
+ 0x2A, 0xE1, 0x0A, 0x53, 0x95, 0x59, 0xE4, 0xA4, 0xA1, 0x63, 0xA4, 0x61, 0x30, 0x5F, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x03,
+ 0x63, 0x6F, 0x6D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C,
+ 0x64, 0x01, 0x19, 0x16, 0x09, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x31, 0x2D,
+ 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63,
+ 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x82, 0x10, 0x79,
+ 0xAD, 0x16, 0xA1, 0x4A, 0xA0, 0xA5, 0xAD, 0x4C, 0x73, 0x58, 0xF4, 0x07, 0x13, 0x2E, 0x65, 0x30,
+ 0x50, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x49, 0x30, 0x47, 0x30, 0x45, 0xA0, 0x43, 0xA0, 0x41,
+ 0x86, 0x3F, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63,
+ 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63,
+ 0x72, 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x6D, 0x69, 0x63, 0x72,
+ 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x72, 0x6F, 0x6F, 0x74, 0x63, 0x65, 0x72, 0x74, 0x2E, 0x63, 0x72,
+ 0x6C, 0x30, 0x54, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x48, 0x30,
+ 0x46, 0x30, 0x44, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x38, 0x68,
+ 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73,
+ 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, 0x72, 0x74,
+ 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x52, 0x6F, 0x6F, 0x74, 0x43,
+ 0x65, 0x72, 0x74, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x81, 0x80, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04,
+ 0x79, 0x30, 0x77, 0x30, 0x75, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x2F,
+ 0x30, 0x68, 0x30, 0x66, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x5A,
+ 0x1E, 0x58, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67,
+ 0x00, 0x68, 0x00, 0x74, 0x00, 0x20, 0x00, 0xA9, 0x00, 0x20, 0x00, 0x31, 0x00, 0x39, 0x00, 0x39,
+ 0x00, 0x39, 0x00, 0x2D, 0x00, 0x32, 0x00, 0x30, 0x00, 0x30, 0x00, 0x35, 0x00, 0x20, 0x00, 0x4D,
+ 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00, 0x74,
+ 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x61,
+ 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x2E, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D,
+ 0x25, 0x04, 0x18, 0x30, 0x16, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x06,
+ 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0A, 0x03, 0x06, 0x30, 0x0D, 0x06, 0x09, 0x2A,
+ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x25,
+ 0x31, 0xA1, 0x58, 0xEA, 0x52, 0xE5, 0xE1, 0x17, 0x0C, 0xE6, 0xF1, 0x3F, 0x78, 0xA3, 0x3F, 0x72,
+ 0xAF, 0xA7, 0x57, 0x10, 0x53, 0x89, 0x10, 0x5E, 0x32, 0x9C, 0xB6, 0x70, 0xC3, 0x15, 0x2B, 0x4D,
+ 0x15, 0x30, 0x34, 0xE8, 0xC0, 0x6A, 0xE4, 0x1C, 0xD3, 0x2E, 0x20, 0x65, 0x48, 0xD7, 0x1B, 0x98,
+ 0x62, 0x21, 0xBA, 0x45, 0x9F, 0x4A, 0xEC, 0xDB, 0x2F, 0x09, 0x19, 0x51, 0xE5, 0xED, 0x32, 0x19,
+ 0x51, 0x2F, 0xE1, 0xDD, 0xFB, 0xC6, 0x52, 0xFD, 0xEB, 0xC6, 0x82, 0x25, 0x42, 0x03, 0x09, 0xA6,
+ 0x38, 0xB6, 0x36, 0x1F, 0xCC, 0xC9, 0x80, 0xBB, 0x5A, 0x69, 0x18, 0x31, 0xC3, 0xB3, 0xA0, 0xB3,
+ 0x67, 0x47, 0xBE, 0x9D, 0xC7, 0xE2, 0x3F, 0x96, 0xB3, 0x88, 0xF8, 0x19, 0xBE, 0x39, 0xB9, 0xE9,
+ 0x95, 0xCE, 0xFC, 0x7C, 0xAF, 0xA8, 0xCD, 0xD0, 0x41, 0x90, 0xE0, 0xD5, 0xB3, 0x1C, 0x2F, 0x68,
+ 0xBB, 0xDB, 0x0F, 0x6C, 0x6A, 0xDD, 0xF2, 0xAF, 0xDE, 0xF2, 0xB5, 0xDE, 0x0D, 0xB6, 0xA6, 0x5A,
+ 0xF0, 0x86, 0x0A, 0xB9, 0x6D, 0x99, 0x4B, 0x3F, 0x7B, 0x2D, 0x01, 0x84, 0x6C, 0x8F, 0x87, 0xDC,
+ 0x7F, 0x8F, 0xAB, 0x14, 0x88, 0xD0, 0x06, 0x91, 0x34, 0xBE, 0x1B, 0x82, 0x22, 0xA4, 0xBC, 0x55,
+ 0x8A, 0xAD, 0x9B, 0xFC, 0x73, 0x14, 0x10, 0xC4, 0xC9, 0x19, 0x1E, 0x07, 0x7D, 0x9B, 0x0E, 0xC0,
+ 0x95, 0x26, 0x5D, 0xC6, 0x1F, 0xAC, 0xB4, 0xF2, 0x7E, 0xBA, 0x25, 0x70, 0x4A, 0x7B, 0xD7, 0x8E,
+ 0xD1, 0x9D, 0xA0, 0x13, 0x49, 0x7A, 0xB0, 0x02, 0x52, 0x52, 0x24, 0xF4, 0xAF, 0xDD, 0x40, 0x2D,
+ 0xE5, 0x3E, 0x32, 0x58, 0xB3, 0x4A, 0x6A, 0xDD, 0x11, 0x59, 0xAA, 0x2D, 0xBC, 0xA4, 0xA0, 0x73,
+ 0x38, 0xF9, 0x40, 0x77, 0x6B, 0x34, 0x19, 0x57, 0xCD, 0x38, 0x68, 0x27, 0x82, 0xF8, 0xD1, 0x6F,
+ 0xEB, 0x23, 0xC0, 0x3F, 0x52, 0xF3, 0x4E, 0xD5, 0x02, 0x3E, 0x6A, 0x9A, 0x2B, 0xC1, 0xF5, 0x31,
+ 0x71, 0xDB, 0x41, 0x4D, 0x3B, 0xDE, 0xEF, 0xAD, 0xAF, 0x1F, 0x88, 0x65, 0x43, 0x1B, 0x51, 0xB7,
+ 0x9A, 0x75, 0xCA, 0x8E, 0x69, 0x49, 0x10, 0x8F, 0x78, 0x8A, 0x74, 0x45, 0xB9, 0x09, 0x8E, 0x73,
+ 0x77, 0x07, 0x32, 0x4A, 0x4B, 0xD7, 0x68, 0x2B, 0x98, 0xC5, 0xBA, 0x54, 0xEA, 0x3F, 0xCB, 0xA2,
+ 0x00, 0x8C, 0xBB, 0xD8, 0x10, 0x58, 0xF2, 0xDB, 0xDC, 0x9B, 0xCD, 0xD8, 0xEA, 0x48, 0x43, 0xE2,
+ 0x4A, 0x7E, 0x65, 0xB2, 0xDC, 0xF5, 0x2D, 0x4E, 0x25, 0x67, 0xA8, 0xE0, 0xB5, 0xBA, 0xA7, 0xDD,
+ 0x7E, 0x5E, 0xC1, 0x4C, 0x02, 0x74, 0xC9, 0xB3, 0x6E, 0xE3, 0xF8, 0xF0, 0x0B, 0xED, 0xFC, 0xB9,
+ 0x29, 0xC5, 0x5B, 0xC9, 0x36, 0x51, 0x90, 0xDB, 0x78, 0x7D, 0xB9, 0x32, 0x0F, 0x5E, 0x76, 0xD2,
+ 0x15, 0x5C, 0x3B, 0x37, 0x21, 0xC6, 0xDB, 0xC9, 0x19, 0x6E, 0xED, 0x74, 0x2A, 0x5C, 0x2C, 0x0B,
+ 0x51, 0x49, 0x45, 0x53, 0xB0, 0xB2, 0xB3, 0x23, 0xD4, 0xA1, 0xB0, 0x5F, 0x0D, 0x19, 0xCD, 0x14,
+ 0xA7, 0xE3, 0x3C, 0x9B, 0x97, 0x72, 0x94, 0x14, 0xDF, 0xFF, 0xC1, 0x90, 0x1B, 0xA5, 0xDF, 0xF5,
+ 0xA9, 0xF3, 0x1B, 0x17, 0xDA, 0xB5, 0xFC, 0x44, 0xE0, 0xE8, 0xE2, 0x3C, 0xA2, 0x7A, 0xBB, 0xBB,
+ 0x65, 0xE6, 0x4D, 0xB1, 0xB5, 0x15, 0xA1, 0xD9, 0x67, 0x3B, 0xB0, 0x0C, 0x7D, 0x3B, 0xE9, 0xEE,
+ 0x51, 0x2A, 0x47, 0xF5, 0x15, 0x0F, 0x8C, 0xAD, 0x5D, 0x2E, 0x35, 0xDF, 0xF4, 0xA4, 0x2E, 0xF6,
+ 0x13, 0x37, 0x5A, 0x2B, 0xE8, 0x55, 0x9A, 0x49, 0x2C, 0x97, 0xCE, 0x9D, 0x01, 0x9E, 0x97, 0x46,
+ 0x5C, 0xD9, 0x2D, 0xBC, 0x24, 0x5A, 0x95, 0x59, 0x6F, 0x4D, 0xCA, 0x9D, 0xD6, 0x57, 0x26, 0x31,
+ 0x82, 0x04, 0x96, 0x30, 0x82, 0x04, 0x92, 0x02, 0x01, 0x01, 0x30, 0x81, 0x90, 0x30, 0x81, 0x81,
+ 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30,
+ 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74,
+ 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64,
+ 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61,
+ 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D,
+ 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73,
+ 0x20, 0x56, 0x65, 0x72, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x50, 0x43,
+ 0x41, 0x02, 0x0A, 0x61, 0x01, 0xC6, 0xC1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x30, 0x09, 0x06,
+ 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0xA0, 0x81, 0xBA, 0x30, 0x19, 0x06, 0x09, 0x2A,
+ 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04,
+ 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x30, 0x1C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82,
+ 0x37, 0x02, 0x01, 0x0B, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82,
+ 0x37, 0x02, 0x01, 0x15, 0x30, 0x23, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09,
+ 0x04, 0x31, 0x16, 0x04, 0x14, 0xC5, 0xC5, 0xC1, 0xC3, 0x46, 0xC4, 0x12, 0xB9, 0x38, 0xED, 0xE5,
+ 0x7E, 0x66, 0x78, 0x4E, 0x8F, 0x55, 0x10, 0x7D, 0xAC, 0x30, 0x5A, 0x06, 0x0A, 0x2B, 0x06, 0x01,
+ 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0C, 0x31, 0x4C, 0x30, 0x4A, 0xA0, 0x24, 0x80, 0x22, 0x00,
+ 0x4D, 0x00, 0x69, 0x00, 0x63, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x73, 0x00, 0x6F, 0x00, 0x66, 0x00,
+ 0x74, 0x00, 0x20, 0x00, 0x57, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x6F, 0x00, 0x77, 0x00,
+ 0x73, 0xA1, 0x22, 0x80, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E,
+ 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x77, 0x69,
+ 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xC0, 0x53, 0x19, 0xE7, 0x27, 0xE6, 0xD6, 0xD7,
+ 0xA8, 0xAE, 0xA0, 0xE6, 0x4C, 0xEF, 0x9A, 0xBC, 0x1D, 0x19, 0xD4, 0xC5, 0x7F, 0x7C, 0x71, 0xFF,
+ 0x14, 0x7C, 0xAD, 0x7A, 0x8F, 0x2D, 0x0F, 0x40, 0x38, 0x9B, 0x83, 0x09, 0xEE, 0xF5, 0x34, 0x92,
+ 0xB4, 0x85, 0x34, 0x7C, 0xBA, 0x9B, 0x58, 0x5D, 0xA6, 0x15, 0xDE, 0x99, 0xBF, 0x25, 0x89, 0xDB,
+ 0xC0, 0x3A, 0x98, 0x21, 0x1C, 0x25, 0x09, 0xBD, 0x41, 0xAA, 0x0F, 0x90, 0x6C, 0x62, 0xE9, 0xBD,
+ 0x1D, 0xDD, 0x7C, 0xA4, 0x1F, 0x19, 0x3F, 0xC8, 0x11, 0xF5, 0x1C, 0x9E, 0xEA, 0x2E, 0x1A, 0xCE,
+ 0x5A, 0x61, 0x8A, 0x77, 0xFA, 0x65, 0x1F, 0x03, 0xB4, 0x45, 0x02, 0x0F, 0xB4, 0x0E, 0xB9, 0x44,
+ 0xF6, 0x75, 0xF6, 0x67, 0x91, 0xAD, 0xFA, 0xF9, 0xC3, 0xFA, 0x63, 0x91, 0x58, 0xFE, 0x40, 0xDF,
+ 0x92, 0x6B, 0x59, 0x42, 0x44, 0x66, 0xD2, 0x88, 0x49, 0x59, 0x29, 0x1D, 0x6A, 0xF9, 0x93, 0x9B,
+ 0xD5, 0x38, 0x84, 0x96, 0xD7, 0xAF, 0xBA, 0xEC, 0x29, 0x8D, 0x06, 0x8C, 0x8B, 0xF4, 0xA1, 0x56,
+ 0x0F, 0x78, 0x3F, 0x35, 0xCB, 0x12, 0x8A, 0x85, 0xD5, 0x7C, 0xFC, 0x63, 0xDD, 0x72, 0xA1, 0x13,
+ 0xD3, 0x25, 0x4A, 0x59, 0x21, 0xD0, 0xC6, 0x47, 0x9F, 0x22, 0xF7, 0xF8, 0x32, 0xA2, 0x05, 0x2B,
+ 0x53, 0xC5, 0x96, 0x98, 0x0D, 0x39, 0x02, 0xAD, 0x85, 0xF7, 0x18, 0x73, 0x34, 0x12, 0x7F, 0x5A,
+ 0xCB, 0xE1, 0xA2, 0xFB, 0x4E, 0x25, 0x81, 0xF0, 0x9F, 0x7A, 0x79, 0xDB, 0x4F, 0x4B, 0x66, 0x44,
+ 0x30, 0x8E, 0x0D, 0x57, 0x23, 0xD3, 0x7F, 0x60, 0x87, 0xDE, 0xD0, 0x4C, 0x90, 0x90, 0x84, 0x64,
+ 0x70, 0xE8, 0x15, 0x65, 0xCA, 0x18, 0xF8, 0x9A, 0xB6, 0x0C, 0x24, 0xF5, 0xDF, 0xC3, 0x47, 0xE2,
+ 0x7C, 0xAD, 0x91, 0x70, 0x6D, 0xF8, 0x43, 0xE9, 0xA1, 0x82, 0x02, 0x1D, 0x30, 0x82, 0x02, 0x19,
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x06, 0x31, 0x82, 0x02, 0x0A, 0x30,
+ 0x82, 0x02, 0x06, 0x02, 0x01, 0x01, 0x30, 0x81, 0x85, 0x30, 0x77, 0x31, 0x0B, 0x30, 0x09, 0x06,
+ 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04,
+ 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30,
+ 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31,
+ 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73,
+ 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31,
+ 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73,
+ 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x50,
+ 0x43, 0x41, 0x02, 0x0A, 0x61, 0x03, 0xDC, 0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x30, 0x07,
+ 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0xA0, 0x5D, 0x30, 0x18, 0x06, 0x09, 0x2A, 0x86, 0x48,
+ 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x07, 0x01, 0x30, 0x1C, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x05,
+ 0x31, 0x0F, 0x17, 0x0D, 0x30, 0x39, 0x30, 0x34, 0x32, 0x32, 0x30, 0x35, 0x35, 0x34, 0x33, 0x34,
+ 0x5A, 0x30, 0x23, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x16,
+ 0x04, 0x14, 0x74, 0xD7, 0x54, 0xA0, 0xC0, 0x9E, 0x62, 0xF0, 0xDD, 0x92, 0xDC, 0xD6, 0x96, 0x34,
+ 0xA1, 0x0B, 0xF0, 0xD5, 0xB5, 0x3A, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x01, 0x05, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x8D, 0x16, 0xB5, 0xC8, 0x3D, 0xBC, 0x8A,
+ 0xB5, 0xC3, 0x23, 0xF3, 0x33, 0xB0, 0xFA, 0x75, 0xAD, 0xAC, 0x53, 0x0D, 0x5C, 0xF4, 0xD9, 0xBE,
+ 0x63, 0xEB, 0x0D, 0x6F, 0x69, 0x63, 0x91, 0xF8, 0x8E, 0x67, 0x03, 0xE1, 0xC6, 0x2E, 0xCD, 0x9C,
+ 0xEB, 0xDD, 0x9C, 0xCA, 0x65, 0x4A, 0xBB, 0xF2, 0xF4, 0x1C, 0x85, 0x44, 0xD6, 0x58, 0x70, 0x2E,
+ 0x3B, 0xFE, 0x97, 0xD0, 0xEC, 0x72, 0x77, 0x20, 0xA8, 0x20, 0xAC, 0xF0, 0xED, 0x86, 0xC4, 0xFF,
+ 0x3A, 0x3D, 0x40, 0xD9, 0xF6, 0xD5, 0x99, 0xBE, 0xCC, 0xD2, 0xD8, 0xBA, 0x71, 0x51, 0x60, 0xAA,
+ 0x72, 0x36, 0x13, 0x8B, 0x0A, 0xA9, 0xD6, 0xF5, 0x36, 0xE0, 0x44, 0x6B, 0xC1, 0x44, 0x42, 0x43,
+ 0x56, 0x1A, 0xD6, 0xF1, 0x5A, 0x98, 0xCC, 0xBA, 0xA9, 0x4C, 0xCF, 0xC9, 0x86, 0xC3, 0x5B, 0x1C,
+ 0xDF, 0x75, 0x22, 0x54, 0x6A, 0xF0, 0x18, 0x34, 0x0B, 0x29, 0xB0, 0x26, 0x07, 0x59, 0xB6, 0x52,
+ 0x7B, 0x69, 0x74, 0x11, 0x1B, 0xB8, 0x29, 0x19, 0x36, 0x0E, 0xB7, 0x65, 0xCB, 0x87, 0x09, 0x9E,
+ 0x03, 0x28, 0x6C, 0xDB, 0xA7, 0xFB, 0xDF, 0xC7, 0xF7, 0xCE, 0x0D, 0xC2, 0xBA, 0xEA, 0x3C, 0xE8,
+ 0x43, 0x1E, 0x7F, 0xF2, 0x64, 0xDA, 0x87, 0x89, 0xC0, 0xCD, 0x67, 0xE4, 0x84, 0x9B, 0xA7, 0x77,
+ 0xFA, 0x6C, 0x69, 0x19, 0x5B, 0xD1, 0xF7, 0xD9, 0x07, 0x91, 0x50, 0xDD, 0x98, 0x26, 0x10, 0xE3,
+ 0x2E, 0x39, 0x62, 0xF0, 0x56, 0xE9, 0xD9, 0x5C, 0x85, 0x67, 0x9B, 0x2F, 0xDE, 0xD1, 0x00, 0x45,
+ 0x0E, 0x99, 0x1F, 0xDF, 0x7E, 0xC9, 0x10, 0x56, 0xC7, 0x00, 0x6D, 0x5F, 0x23, 0x57, 0x12, 0x84,
+ 0xCD, 0xAC, 0x82, 0xAE, 0x39, 0x52, 0xA5, 0x19, 0x23, 0xA3, 0x6B, 0xE7, 0x49, 0x8F, 0x86, 0x74,
+ 0x46, 0x41, 0x2A, 0x0F, 0x3D, 0x29, 0xB7, 0xAE, 0x8C, 0x00
+ };
+
+//
+// Sample Authenticode Data with SHA-256 hash algorithm.
+// This data should be retrieved from signed PE/COFF image according to SECURITY
+// directory in PE/COFF Header.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 AuthenticodeWithSha256[] = {
+ 0x30, 0x82, 0x0e, 0xd1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0,
+ 0x82, 0x0e, 0xc2, 0x30, 0x82, 0x0e, 0xbe, 0x02, 0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x5c, 0x06, 0x0a, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0xa0, 0x4e, 0x30, 0x4c, 0x30, 0x17, 0x06,
+ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0f, 0x30, 0x09, 0x03, 0x01, 0x00,
+ 0xa0, 0x04, 0xa2, 0x02, 0x80, 0x00, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01,
+ 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0x61, 0x82, 0xb7, 0xf8, 0x8c, 0xff, 0xc2,
+ 0xeb, 0x79, 0x6e, 0x9d, 0xa9, 0xdd, 0x39, 0x52, 0xdd, 0x36, 0xdd, 0xf1, 0x43, 0x27, 0x58, 0x8c,
+ 0xa7, 0xcc, 0xae, 0xde, 0xdd, 0x3c, 0x02, 0x12, 0x49, 0xa0, 0x82, 0x0c, 0x0a, 0x30, 0x82, 0x05,
+ 0xe5, 0x30, 0x82, 0x03, 0xcd, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0a, 0x61, 0x03, 0x5f, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a,
+ 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
+ 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3a, 0x30, 0x38,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x31, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65,
+ 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72,
+ 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x36,
+ 0x32, 0x31, 0x32, 0x32, 0x35, 0x35, 0x30, 0x31, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x36, 0x32,
+ 0x31, 0x32, 0x33, 0x30, 0x35, 0x30, 0x31, 0x5a, 0x30, 0x81, 0x81, 0x31, 0x13, 0x30, 0x11, 0x06,
+ 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x63, 0x6f, 0x6d,
+ 0x31, 0x19, 0x30, 0x17, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
+ 0x16, 0x09, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x31, 0x14, 0x30, 0x12, 0x06,
+ 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x04, 0x63, 0x6f, 0x72,
+ 0x70, 0x31, 0x17, 0x30, 0x15, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01,
+ 0x19, 0x16, 0x07, 0x72, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x17, 0x4d, 0x53, 0x49, 0x54, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43,
+ 0x6f, 0x64, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x33, 0x30, 0x82, 0x01, 0x22,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9b, 0x71, 0xdd,
+ 0x0d, 0x32, 0x2d, 0x08, 0xe8, 0x2d, 0x01, 0x90, 0x9c, 0xdf, 0x9f, 0x32, 0x58, 0x8b, 0x47, 0xd0,
+ 0xfe, 0x9a, 0x6b, 0x40, 0x5e, 0x76, 0xa2, 0x10, 0x00, 0x0e, 0xd2, 0x8f, 0xce, 0xa1, 0x5f, 0x42,
+ 0xa7, 0x0b, 0x5e, 0x83, 0xc2, 0xe9, 0x06, 0xa6, 0x0a, 0xb4, 0x3d, 0x30, 0x50, 0xdb, 0x35, 0x43,
+ 0x2c, 0xd3, 0xc3, 0xc6, 0x3c, 0xc9, 0xb5, 0x88, 0xfc, 0x0b, 0xe6, 0xa3, 0x71, 0x47, 0xce, 0xfd,
+ 0x88, 0x62, 0xa4, 0x25, 0xe2, 0x4e, 0x1b, 0x79, 0x3d, 0xe3, 0xbf, 0x8b, 0x84, 0x2d, 0x64, 0x25,
+ 0xa5, 0xfa, 0x8e, 0x30, 0xae, 0xe3, 0x34, 0x7d, 0x27, 0xf3, 0x5e, 0xf4, 0x05, 0x60, 0xc6, 0x0f,
+ 0x1a, 0x1b, 0x9e, 0xaf, 0x21, 0x37, 0xa9, 0xd9, 0xb6, 0xb7, 0x6a, 0x54, 0x4b, 0x5e, 0xa0, 0x75,
+ 0xb5, 0x9a, 0xc4, 0xb6, 0xbe, 0x28, 0xe3, 0x3b, 0xf7, 0x5a, 0x08, 0x77, 0xd9, 0x39, 0x4a, 0x2a,
+ 0x7a, 0xf8, 0xf4, 0xfe, 0xe8, 0x12, 0x54, 0x41, 0x11, 0x55, 0xc8, 0xc7, 0x98, 0x3e, 0x64, 0xa5,
+ 0xbb, 0xda, 0x6b, 0xa4, 0xaa, 0x29, 0x8c, 0x9f, 0x27, 0x55, 0x25, 0xe7, 0xfd, 0x31, 0x70, 0x60,
+ 0x1d, 0xd3, 0xc4, 0xf2, 0xb9, 0xef, 0x92, 0x4a, 0x9f, 0xc8, 0x4c, 0x93, 0xe7, 0x19, 0xa8, 0x4e,
+ 0xbc, 0xe3, 0x62, 0xf4, 0xe0, 0x6e, 0xec, 0x45, 0x6e, 0x61, 0x4e, 0xad, 0x58, 0xe0, 0xf0, 0xea,
+ 0xf7, 0x74, 0x2c, 0xdf, 0x1b, 0xf6, 0x43, 0x3c, 0x84, 0xc2, 0x8c, 0x0b, 0xb4, 0xbd, 0x4a, 0x57,
+ 0xa6, 0x0c, 0x4e, 0x9e, 0x73, 0x43, 0x5f, 0x2d, 0xaf, 0x22, 0xf4, 0xa6, 0xfd, 0x5a, 0x87, 0xb9,
+ 0xbe, 0x6f, 0x9e, 0x1d, 0x99, 0xc8, 0xdf, 0x95, 0xc2, 0x02, 0xad, 0x7d, 0x4a, 0xf3, 0xba, 0x5d,
+ 0xe8, 0x7b, 0x6e, 0x57, 0xe5, 0x3a, 0x02, 0xf8, 0xd3, 0x01, 0x15, 0xae, 0x4f, 0x02, 0x03, 0x01,
+ 0x00, 0x01, 0xa3, 0x82, 0x01, 0x4c, 0x30, 0x82, 0x01, 0x48, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06,
+ 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4e, 0xfe, 0x61, 0x39, 0x6f, 0xca, 0xc5, 0x64, 0xe0,
+ 0x20, 0xb6, 0xda, 0xc1, 0xb9, 0x52, 0x0e, 0xca, 0xdf, 0x8e, 0xfe, 0x30, 0x19, 0x06, 0x09, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x04, 0x0c, 0x1e, 0x0a, 0x00, 0x53, 0x00, 0x75,
+ 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
+ 0x02, 0x01, 0x86, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
+ 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
+ 0x30, 0x16, 0x80, 0x14, 0xa3, 0x01, 0x04, 0x7e, 0x30, 0x88, 0x33, 0xeb, 0xb9, 0x31, 0x9c, 0xca,
+ 0xeb, 0x85, 0x76, 0x67, 0xfc, 0x65, 0xb4, 0xd1, 0x30, 0x59, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04,
+ 0x52, 0x30, 0x50, 0x30, 0x4e, 0xa0, 0x4c, 0xa0, 0x4a, 0x86, 0x48, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x64,
+ 0x75, 0x63, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x54, 0x65, 0x73, 0x52, 0x6f, 0x6f, 0x43, 0x65,
+ 0x72, 0x41, 0x75, 0x74, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x30, 0x36, 0x2d, 0x31, 0x37, 0x2e,
+ 0x63, 0x72, 0x6c, 0x30, 0x5d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04,
+ 0x51, 0x30, 0x4f, 0x30, 0x4d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86,
+ 0x41, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x65,
+ 0x72, 0x74, 0x73, 0x2f, 0x4d, 0x69, 0x63, 0x54, 0x65, 0x73, 0x52, 0x6f, 0x6f, 0x43, 0x65, 0x72,
+ 0x41, 0x75, 0x74, 0x5f, 0x32, 0x30, 0x31, 0x30, 0x2d, 0x30, 0x36, 0x2d, 0x31, 0x37, 0x2e, 0x63,
+ 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
+ 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x91, 0x2d, 0x11, 0x36, 0xd1, 0x2c, 0x5e, 0x21, 0x77, 0x62,
+ 0x1a, 0xa1, 0xcf, 0x9a, 0x7e, 0x62, 0x2d, 0xc9, 0x90, 0xb9, 0x0e, 0x3d, 0x71, 0x0d, 0xa0, 0x4a,
+ 0x48, 0xad, 0xe1, 0xd6, 0xb0, 0x73, 0x4a, 0x51, 0x4b, 0x4c, 0xb2, 0x6b, 0x88, 0x0a, 0x5a, 0xb7,
+ 0xe9, 0x55, 0x67, 0x43, 0x8b, 0xf1, 0x9d, 0xcc, 0x52, 0x03, 0xaf, 0xac, 0x85, 0xe9, 0xd3, 0x75,
+ 0xce, 0xe5, 0x6f, 0x8b, 0x3c, 0x80, 0x81, 0xab, 0xd1, 0xd1, 0x73, 0x0d, 0x6b, 0xb0, 0x51, 0xb8,
+ 0xa2, 0x5e, 0x0c, 0x09, 0xe5, 0xa6, 0xbc, 0x54, 0x49, 0xe5, 0x54, 0x38, 0x5a, 0xb7, 0x43, 0xd2,
+ 0x75, 0x34, 0x52, 0xdd, 0x35, 0x79, 0x95, 0x98, 0xd5, 0x3c, 0xc6, 0xda, 0x46, 0xb2, 0xd8, 0xa0,
+ 0xa7, 0xcc, 0x30, 0x31, 0x0f, 0x4b, 0xeb, 0xb7, 0x02, 0xab, 0x2b, 0x38, 0xd2, 0xb7, 0x27, 0xc2,
+ 0xc7, 0x0d, 0x62, 0xa4, 0xc0, 0x48, 0xf4, 0x1a, 0x48, 0x79, 0x7d, 0xe1, 0x31, 0xa4, 0x5d, 0x19,
+ 0xd0, 0x18, 0x17, 0x00, 0xca, 0xe3, 0x5d, 0x0b, 0xc1, 0x85, 0x7f, 0xf1, 0xbe, 0xd3, 0xcb, 0x97,
+ 0xf4, 0x1b, 0x62, 0x0f, 0xd7, 0x14, 0x38, 0x8d, 0xb2, 0x2e, 0x98, 0xd4, 0x41, 0x6a, 0xb0, 0xb5,
+ 0x84, 0xee, 0xd8, 0x2c, 0x2d, 0x13, 0xfc, 0x50, 0x1d, 0x9a, 0x6f, 0x31, 0x87, 0x1c, 0xe0, 0xd0,
+ 0xd0, 0xd3, 0x24, 0x52, 0xdf, 0x12, 0x8d, 0xfb, 0xf7, 0x7f, 0x33, 0x04, 0x17, 0x7a, 0x8b, 0xe3,
+ 0xbd, 0x7c, 0x1e, 0xa2, 0x2a, 0x91, 0x76, 0xd9, 0xfc, 0x43, 0x17, 0xa7, 0x0a, 0xa1, 0xd9, 0xc6,
+ 0x3c, 0x3a, 0x42, 0xed, 0xb7, 0x12, 0xcd, 0x9e, 0xdd, 0xfe, 0x91, 0x9d, 0x98, 0xb5, 0x35, 0xe8,
+ 0x94, 0xdd, 0x9a, 0xce, 0xd4, 0xf4, 0xac, 0xca, 0xa6, 0xcd, 0x59, 0x3d, 0xde, 0x44, 0xbf, 0x0e,
+ 0x82, 0xe5, 0xdf, 0x5c, 0xe3, 0x49, 0xcb, 0x01, 0xa0, 0x7f, 0x7b, 0xe2, 0x25, 0x21, 0xab, 0x95,
+ 0x50, 0x1e, 0x9f, 0xea, 0x77, 0x56, 0x47, 0x74, 0x73, 0xf2, 0x25, 0x1b, 0x0e, 0x36, 0xb9, 0xa2,
+ 0x57, 0xbf, 0x2c, 0x57, 0xbc, 0xe4, 0xfb, 0x88, 0xb1, 0x83, 0x56, 0xd8, 0x3c, 0xe0, 0x7c, 0xfd,
+ 0x11, 0x9f, 0xde, 0xe1, 0xb7, 0xd4, 0xc6, 0x23, 0xaf, 0xae, 0xc7, 0x5e, 0x4f, 0xc5, 0x23, 0x74,
+ 0x98, 0x38, 0x74, 0x9d, 0x0d, 0x0d, 0x6d, 0xf4, 0xde, 0x28, 0x44, 0x41, 0xd8, 0x22, 0x68, 0xe7,
+ 0x57, 0xa7, 0x66, 0x74, 0xb5, 0xc3, 0x31, 0x24, 0xe2, 0x7c, 0xd5, 0x52, 0x5d, 0x8a, 0xd2, 0x4e,
+ 0x14, 0xbb, 0x08, 0xd3, 0x1a, 0x31, 0x12, 0x04, 0x58, 0x9b, 0x3a, 0x99, 0x78, 0x93, 0x51, 0x3f,
+ 0x0b, 0x85, 0xce, 0xde, 0x09, 0x58, 0xf9, 0x96, 0x1b, 0x91, 0x11, 0xa0, 0x68, 0x53, 0x33, 0xcb,
+ 0xbe, 0x08, 0x89, 0xcc, 0x95, 0x55, 0xae, 0x06, 0x78, 0x27, 0x99, 0xa2, 0x56, 0xef, 0xae, 0x95,
+ 0x0a, 0x7f, 0x0d, 0xeb, 0x43, 0x0c, 0xc6, 0x9e, 0x3f, 0x80, 0xbb, 0xc4, 0x74, 0x03, 0x9d, 0xb8,
+ 0x1a, 0xaa, 0xbc, 0xcb, 0x1e, 0x03, 0xfb, 0xd8, 0x49, 0x89, 0x9d, 0x20, 0xaa, 0x25, 0x4b, 0x47,
+ 0x67, 0xf4, 0xa7, 0x0d, 0x8d, 0x76, 0x30, 0xc6, 0x48, 0xce, 0xdd, 0x8d, 0xfa, 0xbe, 0xda, 0xb4,
+ 0xeb, 0x3d, 0xd8, 0x0c, 0x3b, 0x15, 0x9a, 0xd1, 0x83, 0x85, 0xe5, 0xe3, 0x92, 0xaa, 0x3b, 0xad,
+ 0x34, 0x0c, 0x39, 0xf1, 0x7f, 0x75, 0xae, 0xe8, 0x70, 0xb0, 0xfd, 0xf2, 0x8e, 0x29, 0xda, 0xdc,
+ 0x09, 0x4f, 0x8a, 0x7b, 0x63, 0xbe, 0x1e, 0x8a, 0xc3, 0x58, 0xd1, 0x03, 0xbe, 0x37, 0xe9, 0xed,
+ 0x32, 0x26, 0xa8, 0x0c, 0xfe, 0xed, 0x12, 0xa7, 0x63, 0x04, 0xb3, 0x92, 0x97, 0xd9, 0x46, 0xa3,
+ 0x33, 0x33, 0x9c, 0x5b, 0xbc, 0x54, 0x30, 0x82, 0x06, 0x1d, 0x30, 0x82, 0x05, 0x05, 0xa0, 0x03,
+ 0x02, 0x01, 0x02, 0x02, 0x0a, 0x4e, 0x30, 0xa5, 0xbb, 0x00, 0x00, 0x00, 0x12, 0x7b, 0xf2, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81,
+ 0x81, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01,
+ 0x19, 0x16, 0x03, 0x63, 0x6f, 0x6d, 0x31, 0x19, 0x30, 0x17, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89,
+ 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x09, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66,
+ 0x74, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01,
+ 0x19, 0x16, 0x04, 0x63, 0x6f, 0x72, 0x70, 0x31, 0x17, 0x30, 0x15, 0x06, 0x0a, 0x09, 0x92, 0x26,
+ 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x07, 0x72, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64,
+ 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x4d, 0x53, 0x49, 0x54, 0x20,
+ 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x41,
+ 0x20, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x31, 0x30, 0x34, 0x32, 0x31, 0x30, 0x33, 0x33, 0x33,
+ 0x34, 0x39, 0x5a, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x32, 0x30, 0x30, 0x33, 0x33, 0x33, 0x34,
+ 0x39, 0x5a, 0x30, 0x70, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68,
+ 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
+ 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72,
+ 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x11, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x57, 0x69, 0x6e,
+ 0x64, 0x6f, 0x77, 0x73, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a,
+ 0x02, 0x82, 0x01, 0x01, 0x00, 0xca, 0x9f, 0xcb, 0x8c, 0x5e, 0x61, 0x19, 0xb5, 0x37, 0x72, 0xd1,
+ 0xe2, 0x88, 0x1f, 0x37, 0x56, 0xce, 0xa8, 0x88, 0x05, 0x3e, 0xe8, 0xa6, 0x8d, 0xfd, 0x0b, 0x30,
+ 0x63, 0x54, 0x89, 0x1d, 0xda, 0x11, 0x70, 0x5a, 0x06, 0x00, 0x86, 0xd7, 0x7f, 0xe6, 0x21, 0x70,
+ 0x41, 0x81, 0x26, 0x4b, 0x6e, 0xc7, 0x02, 0xe2, 0xbf, 0x61, 0x45, 0x04, 0x2f, 0x45, 0xbc, 0xd2,
+ 0x0d, 0xf6, 0xac, 0xda, 0x91, 0x6d, 0xc6, 0x60, 0xad, 0xb3, 0x0b, 0x32, 0xe5, 0x13, 0x95, 0x96,
+ 0x02, 0x4e, 0x10, 0xad, 0x2e, 0x6c, 0xb0, 0xc7, 0x65, 0x6d, 0xea, 0x89, 0x91, 0x67, 0x73, 0x5d,
+ 0x05, 0x12, 0x9f, 0x95, 0x74, 0x6a, 0x6d, 0xb0, 0x6a, 0xd8, 0x94, 0x9b, 0xb0, 0x70, 0x79, 0xb0,
+ 0x85, 0x42, 0xe7, 0xd7, 0x19, 0xc4, 0x33, 0xfd, 0xac, 0xbe, 0x2b, 0xd5, 0x7e, 0x5a, 0xa9, 0xc7,
+ 0xa7, 0x68, 0x53, 0xed, 0xaa, 0x51, 0x2a, 0x6b, 0xac, 0x5a, 0xd7, 0x6e, 0xcf, 0x68, 0x60, 0x90,
+ 0xc7, 0xda, 0xd1, 0xe7, 0xf2, 0x53, 0x4a, 0x01, 0xaf, 0xe8, 0xb1, 0x29, 0x91, 0xab, 0x4c, 0x58,
+ 0x64, 0xe6, 0xb6, 0xcc, 0xdc, 0x0f, 0x43, 0xf2, 0x87, 0x15, 0xf8, 0x73, 0x06, 0xb8, 0x1f, 0xaa,
+ 0xf2, 0x66, 0x49, 0x82, 0xca, 0xf0, 0xdd, 0x4c, 0x7c, 0xd5, 0xe7, 0x59, 0xb7, 0xc6, 0xd3, 0x81,
+ 0x29, 0x5c, 0xce, 0xe4, 0xfd, 0xf7, 0xeb, 0x58, 0x6b, 0x50, 0x79, 0x72, 0x83, 0x4d, 0x59, 0xec,
+ 0xd1, 0xd2, 0xfc, 0x3a, 0x10, 0xc5, 0x7a, 0xba, 0x90, 0xea, 0xfd, 0x54, 0xc7, 0xc8, 0x58, 0x2d,
+ 0x84, 0xe5, 0x5b, 0x51, 0x98, 0x2c, 0x36, 0x7c, 0x42, 0x2b, 0xb1, 0x62, 0x4b, 0x0f, 0xf9, 0x72,
+ 0xd3, 0x3f, 0x99, 0xc8, 0xb4, 0x02, 0x17, 0x39, 0xe5, 0x0b, 0xf2, 0x5d, 0x2d, 0x7f, 0x23, 0x41,
+ 0xcd, 0x58, 0x3a, 0x25, 0x75, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x82, 0x02, 0xa5, 0x30, 0x82,
+ 0x02, 0xa1, 0x30, 0x3d, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x07, 0x04,
+ 0x30, 0x30, 0x2e, 0x06, 0x26, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x08, 0x83, 0xcf,
+ 0x89, 0x4d, 0xad, 0xf2, 0x02, 0x85, 0xa1, 0x9f, 0x0c, 0x82, 0xfa, 0xca, 0x7d, 0x81, 0xe1, 0xfb,
+ 0x74, 0x81, 0x4f, 0x84, 0x9a, 0xf1, 0x69, 0x85, 0xa1, 0xad, 0x1d, 0x02, 0x01, 0x64, 0x02, 0x01,
+ 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x29,
+ 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x0a, 0x04, 0x1c, 0x30, 0x1a, 0x30,
+ 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x06, 0x30, 0x0a, 0x06,
+ 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x25,
+ 0x04, 0x18, 0x30, 0x16, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x06,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d,
+ 0x0e, 0x04, 0x16, 0x04, 0x14, 0xc9, 0x5a, 0xb3, 0x11, 0x02, 0x66, 0x71, 0x8c, 0x5b, 0x06, 0x80,
+ 0x8a, 0x6d, 0x4f, 0x5b, 0xf2, 0xb5, 0x67, 0x45, 0xb5, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x11,
+ 0x04, 0x29, 0x30, 0x27, 0xa0, 0x25, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14,
+ 0x02, 0x03, 0xa0, 0x17, 0x0c, 0x15, 0x77, 0x69, 0x6e, 0x63, 0x62, 0x6c, 0x64, 0x40, 0x6d, 0x69,
+ 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4e, 0xfe, 0x61, 0x39, 0x6f, 0xca, 0xc5, 0x64,
+ 0xe0, 0x20, 0xb6, 0xda, 0xc1, 0xb9, 0x52, 0x0e, 0xca, 0xdf, 0x8e, 0xfe, 0x30, 0x81, 0xe8, 0x06,
+ 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x81, 0xe0, 0x30, 0x81, 0xdd, 0x30, 0x81, 0xda, 0xa0, 0x81, 0xd7,
+ 0xa0, 0x81, 0xd4, 0x86, 0x36, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6f, 0x72, 0x70,
+ 0x70, 0x6b, 0x69, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x4d, 0x53, 0x49, 0x54, 0x25, 0x32, 0x30, 0x54,
+ 0x65, 0x73, 0x74, 0x25, 0x32, 0x30, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x25, 0x32,
+ 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x86, 0x4d, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x6d, 0x73, 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73,
+ 0x6f, 0x66, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x6d, 0x73, 0x63, 0x6f,
+ 0x72, 0x70, 0x2f, 0x63, 0x72, 0x6c, 0x2f, 0x4d, 0x53, 0x49, 0x54, 0x25, 0x32, 0x30, 0x54, 0x65,
+ 0x73, 0x74, 0x25, 0x32, 0x30, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x25, 0x32, 0x30,
+ 0x43, 0x41, 0x25, 0x32, 0x30, 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x86, 0x4b, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x6d, 0x73, 0x63, 0x6f, 0x72, 0x70, 0x2f,
+ 0x63, 0x72, 0x6c, 0x2f, 0x4d, 0x53, 0x49, 0x54, 0x25, 0x32, 0x30, 0x54, 0x65, 0x73, 0x74, 0x25,
+ 0x32, 0x30, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x25, 0x32, 0x30, 0x43, 0x41, 0x25,
+ 0x32, 0x30, 0x33, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x81, 0xa9, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x01, 0x01, 0x04, 0x81, 0x9c, 0x30, 0x81, 0x99, 0x30, 0x42, 0x06, 0x08, 0x2b, 0x06,
+ 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x36, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63,
+ 0x6f, 0x72, 0x70, 0x70, 0x6b, 0x69, 0x2f, 0x61, 0x69, 0x61, 0x2f, 0x4d, 0x53, 0x49, 0x54, 0x25,
+ 0x32, 0x30, 0x54, 0x65, 0x73, 0x74, 0x25, 0x32, 0x30, 0x43, 0x6f, 0x64, 0x65, 0x53, 0x69, 0x67,
+ 0x6e, 0x25, 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x33, 0x2e, 0x63, 0x72, 0x74, 0x30, 0x53,
+ 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x47, 0x68, 0x74, 0x74, 0x70,
+ 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74,
+ 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x6b, 0x69, 0x2f, 0x6d, 0x73, 0x63, 0x6f, 0x72, 0x70, 0x2f,
+ 0x4d, 0x53, 0x49, 0x54, 0x25, 0x32, 0x30, 0x54, 0x65, 0x73, 0x74, 0x25, 0x32, 0x30, 0x43, 0x6f,
+ 0x64, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x25, 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x33, 0x2e,
+ 0x63, 0x72, 0x74, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x97, 0x6d, 0x52, 0x46, 0x65, 0x08, 0x60, 0x01, 0x12,
+ 0x7a, 0x26, 0xaa, 0xd9, 0xc3, 0x15, 0xec, 0xc6, 0xae, 0x0b, 0x75, 0xe4, 0xd5, 0xe0, 0x31, 0xf6,
+ 0xda, 0xc0, 0xb1, 0x1b, 0x7b, 0x8a, 0x07, 0xda, 0x2f, 0x82, 0x4a, 0x21, 0x89, 0xe6, 0x61, 0x97,
+ 0xe4, 0x3a, 0x38, 0xd8, 0x0a, 0x26, 0x4e, 0x83, 0x54, 0xbf, 0x32, 0xe3, 0x64, 0x36, 0x61, 0x40,
+ 0x75, 0x55, 0xf1, 0xaa, 0x34, 0xb2, 0xd3, 0x45, 0x8d, 0x79, 0x9a, 0x93, 0x0b, 0x9f, 0x5a, 0xb3,
+ 0x5b, 0xcf, 0x0d, 0x28, 0x00, 0x46, 0x68, 0xe7, 0x36, 0xc9, 0xe6, 0xd2, 0x03, 0x2d, 0x1c, 0x2b,
+ 0x24, 0x79, 0x32, 0xfb, 0xd8, 0x43, 0xb4, 0x0e, 0xd0, 0x37, 0x3b, 0x5e, 0x15, 0xbf, 0x8a, 0x00,
+ 0x56, 0x00, 0x95, 0x00, 0xd4, 0x71, 0x09, 0xe1, 0x84, 0xfa, 0x6e, 0xc5, 0x75, 0x2f, 0xe1, 0x83,
+ 0x7b, 0x66, 0xe2, 0x22, 0x75, 0x23, 0x6a, 0xf3, 0x83, 0xfc, 0x94, 0xf8, 0x51, 0x6d, 0x40, 0x6d,
+ 0x20, 0x7e, 0xb0, 0xe9, 0xac, 0xa8, 0x28, 0x04, 0xa0, 0x1a, 0x3c, 0x88, 0x7e, 0x7e, 0x3b, 0x96,
+ 0xe9, 0xd0, 0x4b, 0xfa, 0xfa, 0x34, 0x4a, 0x4f, 0xe7, 0xe8, 0x76, 0x16, 0x20, 0xc0, 0x10, 0xca,
+ 0x1f, 0x7a, 0xde, 0x54, 0xfd, 0xb7, 0xf0, 0xea, 0x8f, 0xe2, 0xcb, 0xa5, 0x1c, 0x58, 0x18, 0x57,
+ 0x6c, 0x7d, 0x06, 0xde, 0x8c, 0xbd, 0x45, 0xd7, 0x28, 0x86, 0x13, 0x42, 0xaa, 0x4a, 0x9a, 0x50,
+ 0xc5, 0x76, 0x7f, 0x63, 0x99, 0xd0, 0x90, 0x92, 0xd6, 0xc9, 0x21, 0xf2, 0xb8, 0x66, 0x9c, 0x96,
+ 0x53, 0xd2, 0xe5, 0xc4, 0xdd, 0x3a, 0x7c, 0x06, 0xae, 0xb1, 0x7a, 0xb4, 0x36, 0x04, 0x9d, 0xe6,
+ 0x2a, 0xe4, 0x6a, 0x56, 0xd0, 0x9a, 0x98, 0xa2, 0xbf, 0x6f, 0x43, 0xf2, 0xb0, 0x5b, 0xfd, 0xd9,
+ 0xfa, 0x08, 0x17, 0xc8, 0x3c, 0x61, 0xf1, 0x31, 0x82, 0x02, 0x3a, 0x30, 0x82, 0x02, 0x36, 0x02,
+ 0x01, 0x01, 0x30, 0x81, 0x90, 0x30, 0x81, 0x81, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92,
+ 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x63, 0x6f, 0x6d, 0x31, 0x19, 0x30,
+ 0x17, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x09, 0x6d,
+ 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x31, 0x14, 0x30, 0x12, 0x06, 0x0a, 0x09, 0x92,
+ 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x04, 0x63, 0x6f, 0x72, 0x70, 0x31, 0x17,
+ 0x30, 0x15, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x07,
+ 0x72, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x17, 0x4d, 0x53, 0x49, 0x54, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x6f, 0x64, 0x65,
+ 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x41, 0x20, 0x33, 0x02, 0x0a, 0x4e, 0x30, 0xa5, 0xbb, 0x00,
+ 0x00, 0x00, 0x12, 0x7b, 0xf2, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
+ 0x02, 0x01, 0x05, 0x00, 0xa0, 0x7c, 0x30, 0x10, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
+ 0x37, 0x02, 0x01, 0x0c, 0x31, 0x02, 0x30, 0x00, 0x30, 0x19, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x02, 0x01, 0x04, 0x30, 0x1c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01,
+ 0x0b, 0x31, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01,
+ 0x15, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22,
+ 0x04, 0x20, 0x25, 0x60, 0x6e, 0xc8, 0x66, 0x72, 0x73, 0xb0, 0x71, 0x7b, 0x82, 0x09, 0x8c, 0x27,
+ 0xe8, 0xb1, 0x4a, 0x36, 0x1c, 0x81, 0x36, 0xb4, 0x1b, 0x44, 0xdf, 0x09, 0x82, 0x8b, 0xf9, 0xb6,
+ 0x1c, 0x65, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x04, 0x82, 0x01, 0x00, 0x01, 0xb7, 0x8e, 0x46, 0x9b, 0xb4, 0x18, 0xcd, 0xf6, 0x39, 0x8f,
+ 0x82, 0x79, 0xbc, 0x96, 0x55, 0x7e, 0xd7, 0x84, 0x8f, 0x18, 0x37, 0x48, 0x4e, 0x8f, 0x25, 0x6f,
+ 0x1a, 0x6c, 0x60, 0xe9, 0xc1, 0x5f, 0x65, 0xec, 0xb0, 0x4b, 0x35, 0x98, 0x8a, 0x31, 0x6b, 0xfd,
+ 0xa9, 0xd2, 0x28, 0xa7, 0x00, 0xd0, 0x5c, 0x97, 0x2e, 0x3d, 0x19, 0x96, 0x75, 0xc2, 0x9a, 0xa7,
+ 0x4e, 0x2d, 0x3c, 0x6a, 0xd7, 0xd1, 0x81, 0x96, 0x2e, 0x06, 0x54, 0x82, 0xe9, 0x87, 0xa2, 0x53,
+ 0x63, 0x6a, 0xda, 0x72, 0xa3, 0x41, 0x4f, 0x14, 0xc5, 0x3d, 0x41, 0x7d, 0xbb, 0xd7, 0x29, 0x11,
+ 0x96, 0x14, 0x60, 0x5f, 0xb9, 0xd3, 0x47, 0xb6, 0x23, 0x97, 0x64, 0xf6, 0xe1, 0xac, 0x6c, 0x4d,
+ 0xa9, 0x58, 0xc2, 0x35, 0xbf, 0x02, 0xee, 0x29, 0xd4, 0x52, 0x80, 0x25, 0xa1, 0x7e, 0xbe, 0x21,
+ 0xcd, 0x04, 0x3c, 0x4d, 0x7d, 0xdb, 0x9b, 0x13, 0x71, 0x35, 0x13, 0x8d, 0x16, 0x0a, 0x40, 0x7b,
+ 0x63, 0x45, 0x00, 0x11, 0xc5, 0x3e, 0xc8, 0x21, 0x37, 0xc9, 0xbc, 0xd2, 0x0f, 0x82, 0x21, 0xf9,
+ 0x2f, 0xde, 0xb3, 0x1c, 0x9b, 0x67, 0xb6, 0x5a, 0xb8, 0x74, 0xa0, 0x30, 0xd8, 0x86, 0x1f, 0xd9,
+ 0x08, 0x45, 0xf9, 0x6b, 0xe8, 0x57, 0xda, 0xb7, 0x14, 0xf7, 0x63, 0x97, 0xfd, 0x87, 0x61, 0x1e,
+ 0x95, 0x6f, 0xba, 0x53, 0x40, 0x5e, 0x9f, 0x49, 0xf6, 0xe7, 0x3c, 0x59, 0xd9, 0x78, 0x08, 0x4c,
+ 0xa6, 0x4a, 0xa2, 0x05, 0x42, 0xa7, 0x77, 0xbc, 0x44, 0x7b, 0xed, 0xdb, 0x77, 0x63, 0x4c, 0x63,
+ 0x22, 0xb6, 0x17, 0x3f, 0x4f, 0x33, 0xed, 0xa6, 0xd9, 0x0f, 0x74, 0xfa, 0x97, 0x8d, 0x98, 0x55,
+ 0x42, 0x14, 0x76, 0xd4, 0x89, 0x07, 0xf2, 0x30, 0x5a, 0x27, 0x96, 0x1b, 0x92, 0x70, 0x5a, 0x83,
+ 0x89, 0x0f, 0xdb, 0x47, 0x7a, 0x00, 0x00, 0x00, 0x0a
+ };
+
+//
+// Sample root certificate for code signing.
+// A trusted certificate with self-signing, will be used to construct the certificate chains for
+// authority checking.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 TestRootCert1[] = {
+ 0x30, 0x82, 0x05, 0x99, 0x30, 0x82, 0x03, 0x81, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x79,
+ 0xAD, 0x16, 0xA1, 0x4A, 0xA0, 0xA5, 0xAD, 0x4C, 0x73, 0x58, 0xF4, 0x07, 0x13, 0x2E, 0x65, 0x30,
+ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x5F,
+ 0x31, 0x13, 0x30, 0x11, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19,
+ 0x16, 0x03, 0x63, 0x6F, 0x6D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93,
+ 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x09, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
+ 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x4D, 0x69, 0x63, 0x72, 0x6F,
+ 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
+ 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30,
+ 0x1E, 0x17, 0x0D, 0x30, 0x31, 0x30, 0x35, 0x30, 0x39, 0x32, 0x33, 0x31, 0x39, 0x32, 0x32, 0x5A,
+ 0x17, 0x0D, 0x32, 0x31, 0x30, 0x35, 0x30, 0x39, 0x32, 0x33, 0x32, 0x38, 0x31, 0x33, 0x5A, 0x30,
+ 0x5F, 0x31, 0x13, 0x30, 0x11, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01,
+ 0x19, 0x16, 0x03, 0x63, 0x6F, 0x6D, 0x31, 0x19, 0x30, 0x17, 0x06, 0x0A, 0x09, 0x92, 0x26, 0x89,
+ 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, 0x16, 0x09, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x31, 0x2D, 0x30, 0x2B, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x24, 0x4D, 0x69, 0x63, 0x72,
+ 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69,
+ 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79,
+ 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01,
+ 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0F, 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, 0x01,
+ 0x00, 0xF3, 0x5D, 0xFA, 0x80, 0x67, 0xD4, 0x5A, 0xA7, 0xA9, 0x0C, 0x2C, 0x90, 0x20, 0xD0, 0x35,
+ 0x08, 0x3C, 0x75, 0x84, 0xCD, 0xB7, 0x07, 0x89, 0x9C, 0x89, 0xDA, 0xDE, 0xCE, 0xC3, 0x60, 0xFA,
+ 0x91, 0x68, 0x5A, 0x9E, 0x94, 0x71, 0x29, 0x18, 0x76, 0x7C, 0xC2, 0xE0, 0xC8, 0x25, 0x76, 0x94,
+ 0x0E, 0x58, 0xFA, 0x04, 0x34, 0x36, 0xE6, 0xDF, 0xAF, 0xF7, 0x80, 0xBA, 0xE9, 0x58, 0x0B, 0x2B,
+ 0x93, 0xE5, 0x9D, 0x05, 0xE3, 0x77, 0x22, 0x91, 0xF7, 0x34, 0x64, 0x3C, 0x22, 0x91, 0x1D, 0x5E,
+ 0xE1, 0x09, 0x90, 0xBC, 0x14, 0xFE, 0xFC, 0x75, 0x58, 0x19, 0xE1, 0x79, 0xB7, 0x07, 0x92, 0xA3,
+ 0xAE, 0x88, 0x59, 0x08, 0xD8, 0x9F, 0x07, 0xCA, 0x03, 0x58, 0xFC, 0x68, 0x29, 0x6D, 0x32, 0xD7,
+ 0xD2, 0xA8, 0xCB, 0x4B, 0xFC, 0xE1, 0x0B, 0x48, 0x32, 0x4F, 0xE6, 0xEB, 0xB8, 0xAD, 0x4F, 0xE4,
+ 0x5C, 0x6F, 0x13, 0x94, 0x99, 0xDB, 0x95, 0xD5, 0x75, 0xDB, 0xA8, 0x1A, 0xB7, 0x94, 0x91, 0xB4,
+ 0x77, 0x5B, 0xF5, 0x48, 0x0C, 0x8F, 0x6A, 0x79, 0x7D, 0x14, 0x70, 0x04, 0x7D, 0x6D, 0xAF, 0x90,
+ 0xF5, 0xDA, 0x70, 0xD8, 0x47, 0xB7, 0xBF, 0x9B, 0x2F, 0x6C, 0xE7, 0x05, 0xB7, 0xE1, 0x11, 0x60,
+ 0xAC, 0x79, 0x91, 0x14, 0x7C, 0xC5, 0xD6, 0xA6, 0xE4, 0xE1, 0x7E, 0xD5, 0xC3, 0x7E, 0xE5, 0x92,
+ 0xD2, 0x3C, 0x00, 0xB5, 0x36, 0x82, 0xDE, 0x79, 0xE1, 0x6D, 0xF3, 0xB5, 0x6E, 0xF8, 0x9F, 0x33,
+ 0xC9, 0xCB, 0x52, 0x7D, 0x73, 0x98, 0x36, 0xDB, 0x8B, 0xA1, 0x6B, 0xA2, 0x95, 0x97, 0x9B, 0xA3,
+ 0xDE, 0xC2, 0x4D, 0x26, 0xFF, 0x06, 0x96, 0x67, 0x25, 0x06, 0xC8, 0xE7, 0xAC, 0xE4, 0xEE, 0x12,
+ 0x33, 0x95, 0x31, 0x99, 0xC8, 0x35, 0x08, 0x4E, 0x34, 0xCA, 0x79, 0x53, 0xD5, 0xB5, 0xBE, 0x63,
+ 0x32, 0x59, 0x40, 0x36, 0xC0, 0xA5, 0x4E, 0x04, 0x4D, 0x3D, 0xDB, 0x5B, 0x07, 0x33, 0xE4, 0x58,
+ 0xBF, 0xEF, 0x3F, 0x53, 0x64, 0xD8, 0x42, 0x59, 0x35, 0x57, 0xFD, 0x0F, 0x45, 0x7C, 0x24, 0x04,
+ 0x4D, 0x9E, 0xD6, 0x38, 0x74, 0x11, 0x97, 0x22, 0x90, 0xCE, 0x68, 0x44, 0x74, 0x92, 0x6F, 0xD5,
+ 0x4B, 0x6F, 0xB0, 0x86, 0xE3, 0xC7, 0x36, 0x42, 0xA0, 0xD0, 0xFC, 0xC1, 0xC0, 0x5A, 0xF9, 0xA3,
+ 0x61, 0xB9, 0x30, 0x47, 0x71, 0x96, 0x0A, 0x16, 0xB0, 0x91, 0xC0, 0x42, 0x95, 0xEF, 0x10, 0x7F,
+ 0x28, 0x6A, 0xE3, 0x2A, 0x1F, 0xB1, 0xE4, 0xCD, 0x03, 0x3F, 0x77, 0x71, 0x04, 0xC7, 0x20, 0xFC,
+ 0x49, 0x0F, 0x1D, 0x45, 0x88, 0xA4, 0xD7, 0xCB, 0x7E, 0x88, 0xAD, 0x8E, 0x2D, 0xEC, 0x45, 0xDB,
+ 0xC4, 0x51, 0x04, 0xC9, 0x2A, 0xFC, 0xEC, 0x86, 0x9E, 0x9A, 0x11, 0x97, 0x5B, 0xDE, 0xCE, 0x53,
+ 0x88, 0xE6, 0xE2, 0xB7, 0xFD, 0xAC, 0x95, 0xC2, 0x28, 0x40, 0xDB, 0xEF, 0x04, 0x90, 0xDF, 0x81,
+ 0x33, 0x39, 0xD9, 0xB2, 0x45, 0xA5, 0x23, 0x87, 0x06, 0xA5, 0x55, 0x89, 0x31, 0xBB, 0x06, 0x2D,
+ 0x60, 0x0E, 0x41, 0x18, 0x7D, 0x1F, 0x2E, 0xB5, 0x97, 0xCB, 0x11, 0xEB, 0x15, 0xD5, 0x24, 0xA5,
+ 0x94, 0xEF, 0x15, 0x14, 0x89, 0xFD, 0x4B, 0x73, 0xFA, 0x32, 0x5B, 0xFC, 0xD1, 0x33, 0x00, 0xF9,
+ 0x59, 0x62, 0x70, 0x07, 0x32, 0xEA, 0x2E, 0xAB, 0x40, 0x2D, 0x7B, 0xCA, 0xDD, 0x21, 0x67, 0x1B,
+ 0x30, 0x99, 0x8F, 0x16, 0xAA, 0x23, 0xA8, 0x41, 0xD1, 0xB0, 0x6E, 0x11, 0x9B, 0x36, 0xC4, 0xDE,
+ 0x40, 0x74, 0x9C, 0xE1, 0x58, 0x65, 0xC1, 0x60, 0x1E, 0x7A, 0x5B, 0x38, 0xC8, 0x8F, 0xBB, 0x04,
+ 0x26, 0x7C, 0xD4, 0x16, 0x40, 0xE5, 0xB6, 0x6B, 0x6C, 0xAA, 0x86, 0xFD, 0x00, 0xBF, 0xCE, 0xC1,
+ 0x35, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x51, 0x30, 0x4F, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D,
+ 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
+ 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04,
+ 0x16, 0x04, 0x14, 0x0E, 0xAC, 0x82, 0x60, 0x40, 0x56, 0x27, 0x97, 0xE5, 0x25, 0x13, 0xFC, 0x2A,
+ 0xE1, 0x0A, 0x53, 0x95, 0x59, 0xE4, 0xA4, 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01,
+ 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48,
+ 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xC5, 0x11, 0x4D,
+ 0x03, 0x3A, 0x60, 0xDD, 0x5D, 0x52, 0x11, 0x77, 0x8F, 0xB2, 0xBB, 0x36, 0xC8, 0xB2, 0x05, 0xBF,
+ 0xB4, 0xB7, 0xA8, 0xD8, 0x20, 0x9D, 0x5C, 0x13, 0x03, 0xB6, 0x1C, 0x22, 0xFA, 0x06, 0x13, 0x35,
+ 0xB6, 0xC8, 0x63, 0xD4, 0x9A, 0x47, 0x6F, 0x26, 0x57, 0xD2, 0x55, 0xF1, 0x04, 0xB1, 0x26, 0x5F,
+ 0xD6, 0xA9, 0x50, 0x68, 0xA0, 0xBC, 0xD2, 0xB8, 0x6E, 0xCC, 0xC3, 0xE9, 0xAC, 0xDF, 0x19, 0xCD,
+ 0x78, 0xAC, 0x59, 0x74, 0xAC, 0x66, 0x34, 0x36, 0xC4, 0x1B, 0x3E, 0x6C, 0x38, 0x4C, 0x33, 0x0E,
+ 0x30, 0x12, 0x0D, 0xA3, 0x26, 0xFE, 0x51, 0x53, 0x00, 0xFF, 0xAF, 0x5A, 0x4E, 0x84, 0x0D, 0x0F,
+ 0x1F, 0xE4, 0x6D, 0x05, 0x2E, 0x4E, 0x85, 0x4B, 0x8D, 0x6C, 0x33, 0x6F, 0x54, 0xD2, 0x64, 0xAB,
+ 0xBF, 0x50, 0xAF, 0x7D, 0x7A, 0x39, 0xA0, 0x37, 0xED, 0x63, 0x03, 0x0F, 0xFC, 0x13, 0x06, 0xCE,
+ 0x16, 0x36, 0xD4, 0x54, 0x3B, 0x95, 0x1B, 0x51, 0x62, 0x3A, 0xE5, 0x4D, 0x17, 0xD4, 0x05, 0x39,
+ 0x92, 0x9A, 0x27, 0xA8, 0x5B, 0xAA, 0xBD, 0xEC, 0xBB, 0xBE, 0xE3, 0x20, 0x89, 0x60, 0x71, 0x6C,
+ 0x56, 0xB3, 0xA5, 0x13, 0xD0, 0x6D, 0x0E, 0x23, 0x7E, 0x95, 0x03, 0xED, 0x68, 0x3D, 0xF2, 0xD8,
+ 0x63, 0xB8, 0x6B, 0x4D, 0xB6, 0xE8, 0x30, 0xB5, 0xE1, 0xCA, 0x94, 0x4B, 0xF7, 0xA2, 0xAA, 0x5D,
+ 0x99, 0x30, 0xB2, 0x3D, 0xA7, 0xC2, 0x51, 0x6C, 0x28, 0x20, 0x01, 0x24, 0x27, 0x2B, 0x4B, 0x00,
+ 0xB7, 0x9D, 0x11, 0x6B, 0x70, 0xBE, 0xB2, 0x10, 0x82, 0xBC, 0x0C, 0x9B, 0x68, 0xD0, 0x8D, 0x3B,
+ 0x24, 0x87, 0xAA, 0x99, 0x28, 0x72, 0x9D, 0x33, 0x5F, 0x59, 0x90, 0xBD, 0xF5, 0xDE, 0x93, 0x9E,
+ 0x3A, 0x62, 0x5A, 0x34, 0x39, 0xE2, 0x88, 0x55, 0x1D, 0xB9, 0x06, 0xB0, 0xC1, 0x89, 0x6B, 0x2D,
+ 0xD7, 0x69, 0xC3, 0x19, 0x12, 0x36, 0x84, 0xD0, 0xC9, 0xA0, 0xDA, 0xFF, 0x2F, 0x69, 0x78, 0xB2,
+ 0xE5, 0x7A, 0xDA, 0xEB, 0xD7, 0x0C, 0xC0, 0xF7, 0xBD, 0x63, 0x17, 0xB8, 0x39, 0x13, 0x38, 0xA2,
+ 0x36, 0x5B, 0x7B, 0xF2, 0x85, 0x56, 0x6A, 0x1D, 0x64, 0x62, 0xC1, 0x38, 0xE2, 0xAA, 0xBF, 0x51,
+ 0x66, 0xA2, 0x94, 0xF5, 0x12, 0x9C, 0x66, 0x22, 0x10, 0x6B, 0xF2, 0xB7, 0x30, 0x92, 0x2D, 0xF2,
+ 0x29, 0xF0, 0x3D, 0x3B, 0x14, 0x43, 0x68, 0xA2, 0xF1, 0x9C, 0x29, 0x37, 0xCB, 0xCE, 0x38, 0x20,
+ 0x25, 0x6D, 0x7C, 0x67, 0xF3, 0x7E, 0x24, 0x12, 0x24, 0x03, 0x08, 0x81, 0x47, 0xEC, 0xA5, 0x9E,
+ 0x97, 0xF5, 0x18, 0xD7, 0xCF, 0xBB, 0xD5, 0xEF, 0x76, 0x96, 0xEF, 0xFD, 0xCE, 0xDB, 0x56, 0x9D,
+ 0x95, 0xA0, 0x42, 0xF9, 0x97, 0x58, 0xE1, 0xD7, 0x31, 0x22, 0xD3, 0x5F, 0x59, 0xE6, 0x3E, 0x6E,
+ 0x22, 0x00, 0xEA, 0x43, 0x84, 0xB6, 0x25, 0xDB, 0xD9, 0xF3, 0x08, 0x56, 0x68, 0xC0, 0x64, 0x6B,
+ 0x1D, 0x7C, 0xEC, 0xB6, 0x93, 0xA2, 0x62, 0x57, 0x6E, 0x2E, 0xD8, 0xE7, 0x58, 0x8F, 0xC4, 0x31,
+ 0x49, 0x26, 0xDD, 0xDE, 0x29, 0x35, 0x87, 0xF5, 0x30, 0x71, 0x70, 0x5B, 0x14, 0x3C, 0x69, 0xBD,
+ 0x89, 0x12, 0x7D, 0xEB, 0x2E, 0xA3, 0xFE, 0xD8, 0x7F, 0x9E, 0x82, 0x5A, 0x52, 0x0A, 0x2B, 0xC1,
+ 0x43, 0x2B, 0xD9, 0x30, 0x88, 0x9F, 0xC8, 0x10, 0xFB, 0x89, 0x8D, 0xE6, 0xA1, 0x85, 0x75, 0x33,
+ 0x7E, 0x6C, 0x9E, 0xDB, 0x73, 0x13, 0x64, 0x62, 0x69, 0xA5, 0x2F, 0x7D, 0xCA, 0x96, 0x6D, 0x9F,
+ 0xF8, 0x04, 0x4D, 0x30, 0x92, 0x3D, 0x6E, 0x21, 0x14, 0x21, 0xC9, 0x3D, 0xE0, 0xC3, 0xFD, 0x8A,
+ 0x6B, 0x9D, 0x4A, 0xFD, 0xD1, 0xA1, 0x9D, 0x99, 0x43, 0x77, 0x3F, 0xB0, 0xDA
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 TestRootCert2[] = {
+ 0x30, 0x82, 0x05, 0xfd, 0x30, 0x82, 0x03, 0xe5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x74,
+ 0x45, 0xc8, 0x78, 0x4e, 0x0c, 0xc9, 0x96, 0x4a, 0xb4, 0x2f, 0xbc, 0xda, 0x29, 0xe1, 0xbc, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x81,
+ 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67,
+ 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65,
+ 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15,
+ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72,
+ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x31,
+ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x54, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
+ 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31,
+ 0x30, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x36, 0x31, 0x37, 0x32, 0x30, 0x35, 0x38, 0x30,
+ 0x32, 0x5a, 0x17, 0x0d, 0x33, 0x35, 0x30, 0x36, 0x31, 0x37, 0x32, 0x31, 0x30, 0x34, 0x31, 0x31,
+ 0x5a, 0x30, 0x81, 0x90, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0a, 0x57, 0x61, 0x73, 0x68,
+ 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
+ 0x07, 0x52, 0x65, 0x64, 0x6d, 0x6f, 0x6e, 0x64, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72,
+ 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x3a, 0x30, 0x38, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x13, 0x31, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x54, 0x65, 0x73,
+ 0x74, 0x69, 0x6e, 0x67, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66,
+ 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20,
+ 0x32, 0x30, 0x31, 0x30, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a,
+ 0x02, 0x82, 0x02, 0x01, 0x00, 0x95, 0xe3, 0xa8, 0xc1, 0xb9, 0x9c, 0x26, 0x54, 0xb0, 0x99, 0xef,
+ 0x26, 0x1f, 0xac, 0x1e, 0xc7, 0x30, 0x80, 0xbb, 0xf5, 0x3f, 0xf2, 0xe4, 0xbb, 0xf8, 0xfe, 0x06,
+ 0x6a, 0x0a, 0xa6, 0x88, 0xbc, 0xb4, 0x8c, 0x45, 0xe0, 0x70, 0x55, 0x19, 0x88, 0xb4, 0x05, 0xcb,
+ 0xb5, 0xc1, 0xa1, 0xfa, 0xd4, 0x7c, 0xc2, 0x42, 0x53, 0x07, 0x9c, 0x54, 0x56, 0xa8, 0x97, 0xe0,
+ 0x94, 0x69, 0xbe, 0x13, 0x24, 0xef, 0xe5, 0x8a, 0x29, 0x9c, 0xa6, 0xd0, 0x2b, 0x2f, 0x8a, 0xa6,
+ 0xe8, 0x79, 0x44, 0x2e, 0x8b, 0xea, 0xc9, 0xbe, 0xb8, 0x54, 0x86, 0x53, 0xbe, 0x07, 0x24, 0x34,
+ 0x54, 0x15, 0x22, 0x20, 0x01, 0x7b, 0x8a, 0x46, 0xfb, 0xd2, 0x91, 0x07, 0x95, 0x09, 0xb0, 0x56,
+ 0x11, 0xcc, 0x76, 0xb2, 0xd0, 0x1f, 0x44, 0x79, 0x52, 0x34, 0x28, 0xec, 0x4f, 0x49, 0xc2, 0xcb,
+ 0x61, 0xd3, 0x86, 0xdc, 0xe4, 0xa3, 0x7e, 0x55, 0x9e, 0x9f, 0xee, 0x10, 0x6f, 0xcf, 0xe1, 0x3d,
+ 0xf8, 0xb7, 0x84, 0x79, 0xa2, 0x3b, 0x8d, 0x1c, 0xb0, 0x81, 0x7c, 0xe4, 0x44, 0x07, 0xe4, 0xce,
+ 0x46, 0xb0, 0x98, 0x83, 0x8d, 0x87, 0x8f, 0xe5, 0xf5, 0xae, 0x40, 0x7a, 0xf1, 0xed, 0x3d, 0x9b,
+ 0x9a, 0x7c, 0x4a, 0xd1, 0xb9, 0xc3, 0x94, 0x05, 0x7b, 0xdc, 0xda, 0xb8, 0xce, 0xdc, 0x1e, 0x6c,
+ 0xcf, 0xd9, 0x9e, 0x37, 0xef, 0xc3, 0x5a, 0x36, 0x7b, 0x90, 0x86, 0x45, 0xdc, 0xf6, 0x2e, 0xca,
+ 0xdd, 0xee, 0xde, 0x27, 0xd9, 0x74, 0x9a, 0x69, 0xf5, 0xd9, 0x5d, 0x09, 0x2d, 0x45, 0x41, 0xcc,
+ 0xb7, 0xc2, 0x82, 0xd4, 0x2a, 0x8c, 0x16, 0x25, 0x92, 0x97, 0x3d, 0x94, 0x4e, 0x89, 0x33, 0x7e,
+ 0x5b, 0x03, 0x54, 0xcd, 0xb0, 0x83, 0xa0, 0x8e, 0x41, 0xb7, 0x87, 0x8d, 0xd9, 0x05, 0x63, 0x52,
+ 0xf6, 0xee, 0xe6, 0x4e, 0x13, 0x9d, 0x54, 0xcd, 0x49, 0xfe, 0xe3, 0x8b, 0x3b, 0x50, 0x9b, 0x48,
+ 0xbb, 0xb2, 0xe5, 0x92, 0xd4, 0xab, 0xa0, 0xc5, 0x10, 0xaf, 0x3e, 0xb1, 0x45, 0x21, 0x34, 0x90,
+ 0xdc, 0xad, 0xb9, 0xf7, 0xfe, 0x21, 0xae, 0xee, 0x50, 0x58, 0x7a, 0x3a, 0xe5, 0xaa, 0xd8, 0xe3,
+ 0x82, 0xd6, 0xcf, 0x6d, 0x4d, 0xc9, 0x15, 0xac, 0x9c, 0x31, 0x17, 0xa5, 0x16, 0xa7, 0x42, 0xf6,
+ 0xda, 0x12, 0x78, 0xa7, 0x66, 0x90, 0xec, 0xfc, 0xcd, 0x01, 0x63, 0xff, 0xf0, 0x0e, 0xba, 0xe1,
+ 0xcd, 0xf0, 0xdb, 0x6b, 0x9a, 0x0f, 0xf6, 0x0f, 0x04, 0x01, 0x09, 0xbc, 0x9f, 0xce, 0xb7, 0x6c,
+ 0x51, 0x70, 0x57, 0x08, 0x1b, 0xff, 0x79, 0x9a, 0x52, 0x5d, 0xba, 0xac, 0x14, 0xe5, 0x3b, 0x67,
+ 0xcf, 0x2c, 0x52, 0xde, 0x27, 0x9a, 0x34, 0x03, 0x6e, 0x25, 0x48, 0xb0, 0x19, 0x74, 0xfc, 0x4d,
+ 0x98, 0xc2, 0x4b, 0x8c, 0x92, 0xe1, 0x88, 0xae, 0x48, 0x2a, 0xab, 0xab, 0xcd, 0x14, 0x4d, 0xb6,
+ 0x61, 0x0e, 0xa1, 0x09, 0x8f, 0x2c, 0xdb, 0x45, 0xaf, 0x7d, 0x3b, 0x81, 0x56, 0x08, 0xc9, 0x3b,
+ 0x41, 0xb7, 0x64, 0x9f, 0x5d, 0x2e, 0x12, 0x7f, 0xb9, 0x69, 0x29, 0x1f, 0x52, 0x45, 0x4a, 0x23,
+ 0xc6, 0xaf, 0xb6, 0xb2, 0x38, 0x72, 0x9d, 0x08, 0x33, 0xff, 0xd0, 0xcf, 0x89, 0xb6, 0xea, 0x6e,
+ 0x85, 0x44, 0x94, 0x3e, 0x91, 0x59, 0xeb, 0xef, 0x9e, 0xbd, 0x9b, 0x9c, 0x1a, 0x47, 0x03, 0x4e,
+ 0xa2, 0x17, 0x96, 0xfa, 0x62, 0x0b, 0xe8, 0x53, 0xb6, 0x4e, 0xe3, 0xe8, 0x2a, 0x73, 0x59, 0xe2,
+ 0x13, 0xb8, 0xf8, 0x5a, 0x7e, 0xc6, 0xe2, 0x0a, 0xdd, 0x4a, 0x43, 0xcc, 0xc3, 0x77, 0x3b, 0x7a,
+ 0x31, 0x04, 0x0a, 0xc1, 0x84, 0x96, 0x3a, 0x63, 0x6e, 0x1a, 0x3e, 0x0a, 0x0c, 0x25, 0xb8, 0x7e,
+ 0xb5, 0x52, 0x0c, 0xb9, 0xab, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x51, 0x30, 0x4f, 0x30, 0x0b,
+ 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xa3, 0x01, 0x04, 0x7e, 0x30, 0x88, 0x33, 0xeb, 0xb9,
+ 0x31, 0x9c, 0xca, 0xeb, 0x85, 0x76, 0x67, 0xfc, 0x65, 0xb4, 0xd1, 0x30, 0x10, 0x06, 0x09, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01,
+ 0x00, 0x49, 0x8b, 0xc1, 0xfc, 0x4f, 0xe8, 0xe4, 0x2d, 0x67, 0x92, 0x9a, 0x76, 0x05, 0xba, 0xd1,
+ 0xbc, 0x98, 0xe4, 0x2b, 0xba, 0x1f, 0x66, 0x5f, 0x66, 0x23, 0xcf, 0x1c, 0x27, 0xeb, 0xb4, 0xaa,
+ 0xdd, 0xa0, 0x17, 0x20, 0x55, 0x72, 0x33, 0xb1, 0x76, 0xde, 0xc9, 0x6d, 0x0d, 0x3c, 0x2d, 0x0a,
+ 0x08, 0x24, 0x2d, 0xec, 0x38, 0x96, 0x7a, 0x83, 0xf1, 0x27, 0x50, 0x3c, 0x86, 0x09, 0xdd, 0x0d,
+ 0x41, 0xce, 0xaa, 0x5e, 0xf3, 0x8f, 0x7a, 0x3e, 0x3e, 0xf1, 0xf0, 0xba, 0x8b, 0x72, 0xdd, 0x36,
+ 0xa1, 0x69, 0x05, 0x5b, 0x7c, 0xec, 0xe7, 0x70, 0x63, 0x8d, 0x1d, 0x6e, 0xc0, 0xfd, 0x3a, 0x03,
+ 0xf1, 0x10, 0x3e, 0x90, 0xd7, 0x7b, 0x7a, 0xdc, 0xea, 0x60, 0xec, 0x2f, 0x53, 0xfd, 0x19, 0x1d,
+ 0x3a, 0xa1, 0x74, 0x08, 0xc2, 0x7b, 0x3c, 0xe0, 0x50, 0xac, 0x21, 0xd7, 0xb6, 0xdd, 0xdd, 0x3c,
+ 0x44, 0x1b, 0xf7, 0xf3, 0x44, 0x3e, 0x6c, 0x96, 0xe0, 0xc0, 0x9f, 0xe6, 0xef, 0xdd, 0xdd, 0xb1,
+ 0xa6, 0x68, 0x61, 0x6c, 0x5e, 0x9e, 0xf9, 0xff, 0x9a, 0x06, 0xa4, 0x6a, 0xcd, 0x9e, 0x75, 0x43,
+ 0x89, 0x9b, 0xcb, 0x85, 0xf6, 0xdc, 0x0c, 0x46, 0x4a, 0x8c, 0x9b, 0xac, 0x11, 0xa6, 0x63, 0x45,
+ 0xfb, 0xfc, 0xde, 0x20, 0xee, 0xce, 0x67, 0x9f, 0x3d, 0xd0, 0x93, 0xdb, 0x39, 0xfb, 0xea, 0x5e,
+ 0x4b, 0xfc, 0xd6, 0x20, 0xf1, 0x95, 0x36, 0x08, 0x8c, 0xb2, 0xb3, 0xa1, 0x97, 0x1b, 0x41, 0x19,
+ 0xb0, 0xac, 0xfe, 0xe2, 0xd5, 0xab, 0x7d, 0xd9, 0x26, 0xd4, 0xdc, 0xbd, 0x1f, 0x38, 0xc0, 0xe3,
+ 0x86, 0xdf, 0x24, 0xe7, 0xf5, 0x3e, 0x09, 0xca, 0x4d, 0xa1, 0xba, 0x16, 0xc3, 0x4a, 0xb1, 0xfc,
+ 0x72, 0x98, 0xcf, 0x0e, 0x92, 0xfa, 0x57, 0x45, 0xe9, 0x48, 0x4d, 0xc6, 0xa2, 0x7c, 0x3b, 0x72,
+ 0x63, 0xac, 0x4e, 0xf4, 0x74, 0xe9, 0x2b, 0x57, 0xac, 0xab, 0x32, 0x88, 0x0b, 0xa9, 0x10, 0x67,
+ 0x53, 0x7e, 0xd2, 0x62, 0xd2, 0xfa, 0x68, 0xe8, 0x9d, 0x5b, 0xae, 0xcd, 0xe0, 0xe5, 0xe2, 0x06,
+ 0x96, 0x0c, 0x34, 0x32, 0xf6, 0xbc, 0x25, 0xad, 0x98, 0xf3, 0x32, 0x60, 0xbe, 0x14, 0xd3, 0x78,
+ 0xd1, 0x10, 0x6f, 0xff, 0x32, 0xe3, 0x9e, 0x3d, 0x88, 0xda, 0xb3, 0x32, 0x0a, 0xcf, 0x20, 0x65,
+ 0x47, 0x78, 0xaa, 0xa5, 0x4b, 0x87, 0x6a, 0x83, 0xdc, 0x1a, 0x5a, 0x2a, 0xdf, 0x70, 0x61, 0xaf,
+ 0x35, 0x32, 0xe0, 0x59, 0xa1, 0x9f, 0x0b, 0x14, 0x7a, 0xaa, 0xab, 0x42, 0x0b, 0x6b, 0xff, 0xfb,
+ 0x34, 0xcb, 0x9d, 0x96, 0xd7, 0x26, 0x2a, 0x13, 0x3b, 0xe3, 0xdf, 0x11, 0xe6, 0x86, 0x7d, 0x0d,
+ 0x09, 0x11, 0x93, 0x4b, 0xa4, 0xf6, 0xd2, 0x07, 0xc2, 0xcd, 0xc8, 0xbe, 0xf5, 0x67, 0xf7, 0xae,
+ 0x05, 0xce, 0x16, 0xfe, 0x90, 0xc9, 0x4a, 0x98, 0x1b, 0x24, 0x69, 0x78, 0x90, 0xf9, 0x34, 0x8e,
+ 0x37, 0xe8, 0x6e, 0x1d, 0xdc, 0xcf, 0x4f, 0xe7, 0xd2, 0x64, 0x40, 0x1d, 0xc4, 0x30, 0xba, 0xd5,
+ 0x08, 0x88, 0x67, 0x4b, 0x0f, 0xb8, 0xe5, 0x59, 0xe9, 0x18, 0xd8, 0x0c, 0x60, 0x68, 0xae, 0x7f,
+ 0xea, 0x91, 0x55, 0xbe, 0xeb, 0xf1, 0xa7, 0x8e, 0xd8, 0x5d, 0x50, 0x3e, 0xbf, 0xd5, 0x69, 0x57,
+ 0x95, 0x8f, 0xa7, 0xff, 0xe4, 0x09, 0x3f, 0x08, 0x80, 0x97, 0x32, 0x42, 0xb8, 0x82, 0x43, 0x82,
+ 0x6f, 0x8b, 0x0b, 0x93, 0xda, 0x19, 0xbf, 0x63, 0x4e, 0x5f, 0x9f, 0xed, 0x2c, 0x22, 0xb6, 0x20,
+ 0x5f, 0x70, 0x44, 0xfa, 0x89, 0x59, 0x93, 0xb0, 0x7b, 0x12, 0x0f, 0x5e, 0x62, 0x62, 0x51, 0x11,
+ 0xbd, 0xba, 0x5a, 0xd0, 0xce, 0xa1, 0xb6, 0xef, 0x80, 0x20, 0xe6, 0x73, 0x4b, 0x11, 0x06, 0x56,
+ 0xe2, 0x0a
+ };
+
+//
+// OID ASN.1 Value for Hash Algorithms
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 HashOidValue[] = {
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512
+ };
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyAuthenticodeVerify (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+
+ //
+ // Sample Code: Demonstrate how to check the Hash algorithm in PE/COFF Authenticode.
+ // According to PKCS#7 Definition:
+ // SignedData ::= SEQUENCE {
+ // version Version,
+ // digestAlgorithms DigestAlgorithmIdentifiers,
+ // contentInfo ContentInfo,
+ // .... }
+ // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing
+ // This field has the fixed offset (+32) in final Authenticode ASN.1 data.
+ //
+ if (CompareMem (AuthenticodeWithSha1 + 32, &HashOidValue[8], 5) == 0) {
+ //
+ // Verify Authenticode signature.
+ // The PeHash value should be calculated following MSFT's Authenticode Specification.
+ //
+ Status = AuthenticodeVerify (
+ AuthenticodeWithSha1,
+ sizeof (AuthenticodeWithSha1),
+ TestRootCert1,
+ sizeof (TestRootCert1),
+ PeSha1Hash,
+ SHA1_DIGEST_SIZE
+ );
+ UT_ASSERT_TRUE (Status);
+ }
+
+ if (CompareMem (AuthenticodeWithSha256 + 32, &HashOidValue[22], 9) == 0) {
+ Status = AuthenticodeVerify (
+ AuthenticodeWithSha256,
+ sizeof (AuthenticodeWithSha256),
+ TestRootCert2,
+ sizeof (TestRootCert2),
+ PeSha256Hash,
+ SHA256_DIGEST_SIZE
+ );
+ UT_ASSERT_TRUE (Status);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mAuthenticodeTest[] = {
+ //
+ // -----Description--------------------------------------Class----------------------Function-----------------Pre---Post--Context
+ //
+ {"TestVerifyAuthenticodeVerify()", "CryptoPkg.BaseCryptLib.Authenticode", TestVerifyAuthenticodeVerify, NULL, NULL, NULL},
+};
+
+UINTN mAuthenticodeTestNum = ARRAY_SIZE(mAuthenticodeTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
new file mode 100644
index 00000000000..ffb46160d82
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c
@@ -0,0 +1,67 @@
+/** @file
+ This is defines the tests that will run on BaseCryptLib
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "TestBaseCryptLib.h"
+
+SUITE_DESC mSuiteDesc[] = {
+ //
+ // Title--------------------------Package-------------------Sup--Tdn----TestNum------------TestDesc
+ //
+ {"EKU verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mPkcs7EkuTestNum, mPkcs7EkuTest},
+ {"HASH verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mHashTestNum, mHashTest},
+ {"HMAC verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mHmacTestNum, mHmacTest},
+ {"BlockCipher verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mBlockCipherTestNum, mBlockCipherTest},
+ {"RSA verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mRsaTestNum, mRsaTest},
+ {"RSA PSS verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mRsaPssTestNum, mRsaPssTest},
+ {"RSACert verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mRsaCertTestNum, mRsaCertTest},
+ {"PKCS7 verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mPkcs7TestNum, mPkcs7Test},
+ {"PKCS5 verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mPkcs5TestNum, mPkcs5Test},
+ {"Authenticode verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mAuthenticodeTestNum, mAuthenticodeTest},
+ {"ImageTimestamp verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mImageTimestampTestNum, mImageTimestampTest},
+ {"DH verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mDhTestNum, mDhTest},
+ {"PRNG verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mPrngTestNum, mPrngTest},
+ {"OAEP encrypt verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, &mOaepTestNum, mOaepTest},
+};
+
+EFI_STATUS
+EFIAPI
+CreateUnitTest (
+ IN CHAR8* UnitTestName,
+ IN CHAR8* UnitTestVersion,
+ IN OUT UNIT_TEST_FRAMEWORK_HANDLE* Framework
+) {
+ EFI_STATUS Status;
+ UINTN SuiteIndex;
+ UINTN TestIndex;
+
+ if ( Framework == NULL || UnitTestVersion == NULL || UnitTestName == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = EFI_SUCCESS;
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (Framework, UnitTestName, gEfiCallerBaseName, UnitTestVersion);
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ for (SuiteIndex = 0; SuiteIndex < ARRAY_SIZE(mSuiteDesc); SuiteIndex++) {
+ UNIT_TEST_SUITE_HANDLE Suite = NULL;
+ Status = CreateUnitTestSuite (&Suite, *Framework, mSuiteDesc[SuiteIndex].Title, mSuiteDesc[SuiteIndex].Package, mSuiteDesc[SuiteIndex].Sup, mSuiteDesc[SuiteIndex].Tdn);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+ for (TestIndex = 0; TestIndex < *mSuiteDesc[SuiteIndex].TestNum; TestIndex++) {
+ AddTestCase (Suite, (mSuiteDesc[SuiteIndex].TestDesc + TestIndex)->Description, (mSuiteDesc[SuiteIndex].TestDesc + TestIndex)->ClassName, (mSuiteDesc[SuiteIndex].TestDesc + TestIndex)->Func, (mSuiteDesc[SuiteIndex].TestDesc + TestIndex)->PreReq, (mSuiteDesc[SuiteIndex].TestDesc + TestIndex)->CleanUp, (mSuiteDesc[SuiteIndex].TestDesc + TestIndex)->Context);
+ }
+ }
+ EXIT:
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BlockCipherTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BlockCipherTests.c
new file mode 100644
index 00000000000..441218daa86
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BlockCipherTests.c
@@ -0,0 +1,293 @@
+/** @file
+ Application for Block Cipher Primitives Validation.
+
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// TDES test vectors are extracted from OpenSSL 0.9.8l, crypto\des\destest.c
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesEcbData[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesEcbKey[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesEcbCipher[] = {
+ 0x8C, 0xA6, 0x4D, 0xE9, 0xC1, 0xB1, 0x23, 0xA7,
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesEcb2Cipher[] = {
+ 0x92, 0x95, 0xB5, 0x9B, 0xB3, 0x84, 0x73, 0x6E,
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesCbcData[] = {
+ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x20,
+ 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74,
+ 0x68, 0x65, 0x20, 0x74, 0x69, 0x6D, 0x65, 0x20
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesCbcKey[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
+ 0xf1, 0xe0, 0xd3, 0xc2, 0xb5, 0xa4, 0x97, 0x86,
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 TdesCbcIvec[] = {
+ 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TdesCbc3Cipher[] = {
+ 0x3F, 0xE3, 0x01, 0xC9, 0x62, 0xAC, 0x01, 0xD0,
+ 0x22, 0x13, 0x76, 0x3C, 0x1C, 0xBD, 0x4C, 0xDC,
+ 0x79, 0x96, 0x57, 0xC0, 0x64, 0xEC, 0xF5, 0xD4
+ };
+
+//
+// AES test vectors are from NIST KAT of AES
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128EcbData[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128EcbKey[] = {
+ 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128EcbCipher[] = {
+ 0x6d, 0x25, 0x1e, 0x69, 0x44, 0xb0, 0x51, 0xe0, 0x4e, 0xaa, 0x6f, 0xb4, 0xdb, 0xf7, 0x84, 0x65
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes192EcbData[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes192EcbKey[] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes192EcbCipher[] = {
+ 0xdd, 0x8a, 0x49, 0x35, 0x14, 0x23, 0x1c, 0xbf, 0x56, 0xec, 0xce, 0xe4, 0xc4, 0x08, 0x89, 0xfb
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes256EcbData[] = {
+ 0x01, 0x47, 0x30, 0xf8, 0x0a, 0xc6, 0x25, 0xfe, 0x84, 0xf0, 0x26, 0xc6, 0x0b, 0xfd, 0x54, 0x7d
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes256EcbKey[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes256EcbCipher[] = {
+ 0x5c, 0x9d, 0x84, 0x4e, 0xd4, 0x6f, 0x98, 0x85, 0x08, 0x5e, 0x5d, 0x6a, 0x4f, 0x94, 0xc7, 0xd7
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128CbcData[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128CbcKey[] = {
+ 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128CbcIvec[] = {
+ 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Aes128CbcCipher[] = {
+ 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a,
+ 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1
+ };
+
+//
+// ARC4 Test Vector defined in "Appendix A.1 Test Vectors from [CRYPTLIB]" of
+// IETF Draft draft-kaukonen-cipher-arcfour-03 ("A Stream Cipher Encryption Algorithm 'Arcfour'").
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Arc4Data[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Arc4Key[] = {
+ 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Arc4Cipher[] = {
+ 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79
+ };
+
+
+typedef
+UINTN
+(EFIAPI *EFI_BLOCK_CIPHER_GET_CONTEXT_SIZE) (
+ VOID
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_BLOCK_CIPHER_INIT) (
+ OUT VOID *BlockCipherContext,
+ IN CONST UINT8 *Key,
+ IN UINTN KeyLength
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_BLOCK_CIPHER_ECB_ENCRYPT_DECRYPT) (
+ IN VOID *BlockCipherContext,
+ IN CONST UINT8 *Input,
+ IN UINTN InputSize,
+ OUT UINT8 *Output
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_BLOCK_CIPHER_CBC_ENCRYPT_DECRYPT) (
+ IN VOID *BlockCipherContext,
+ IN CONST UINT8 *Input,
+ IN UINTN InputSize,
+ IN CONST UINT8 *Ivec,
+ OUT UINT8 *Output
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_BLOCK_CIPHER_RESET) (
+ IN OUT VOID *BlockCipherContext
+ );
+
+typedef struct {
+ EFI_BLOCK_CIPHER_GET_CONTEXT_SIZE GetContextSize;
+ EFI_BLOCK_CIPHER_INIT Init;
+ EFI_BLOCK_CIPHER_ECB_ENCRYPT_DECRYPT EcbEncrypt;
+ EFI_BLOCK_CIPHER_ECB_ENCRYPT_DECRYPT EcbDecrypt;
+ EFI_BLOCK_CIPHER_CBC_ENCRYPT_DECRYPT CbcEncrypt;
+ EFI_BLOCK_CIPHER_CBC_ENCRYPT_DECRYPT CbcDecrypt;
+ EFI_BLOCK_CIPHER_RESET Reset;
+ CONST UINT8 *Key;
+ UINTN KeySize;
+ CONST UINT8 *Ivec;
+ CONST UINT8 *Data;
+ UINTN DataSize;
+ CONST UINT8 *Cipher;
+ UINTN CipherSize;
+ VOID *Ctx;
+} BLOCK_CIPHER_TEST_CONTEXT;
+
+// These are commented out as they are deprecated, but are left in should they be used again
+//BLOCK_CIPHER_TEST_CONTEXT mTdesEcbTestCtx = {TdesGetContextSize, TdesInit, TdesEcbEncrypt, TdesEcbDecrypt, NULL, NULL, NULL, TdesEcbKey, 64, NULL, TdesEcbData, 8, TdesEcbCipher, 8};
+//BLOCK_CIPHER_TEST_CONTEXT mTdesCbcTestCtx = {TdesGetContextSize, TdesInit, NULL, NULL, TdesCbcEncrypt, TdesCbcDecrypt, NULL, TdesCbcKey, 192, TdesCbcIvec, TdesCbcData, sizeof(TdesCbcData), TdesCbc3Cipher, sizeof(TdesCbc3Cipher)};
+//BLOCK_CIPHER_TEST_CONTEXT mAes128EcbTestCtx = {AesGetContextSize, AesInit, AesEcbEncrypt, AesEcbDecrypt, NULL, NULL, NULL, Aes128EcbKey, 128, NULL, Aes128EcbData, sizeof(Aes128EcbData), Aes128EcbCipher, sizeof(Aes128EcbCipher)};
+//BLOCK_CIPHER_TEST_CONTEXT mAes192EcbTestCtx = {AesGetContextSize, AesInit, AesEcbEncrypt, AesEcbDecrypt, NULL, NULL, NULL, Aes192EcbKey, 192, NULL, Aes192EcbData, sizeof(Aes192EcbData), Aes192EcbCipher, sizeof(Aes192EcbCipher)};
+//BLOCK_CIPHER_TEST_CONTEXT mAes256EcbTestCtx = {AesGetContextSize, AesInit, AesEcbEncrypt, AesEcbDecrypt, NULL, NULL, NULL, Aes256EcbKey, 256, NULL, Aes256EcbData, sizeof(Aes256EcbData), Aes256EcbCipher, sizeof(Aes256EcbCipher)};
+//BLOCK_CIPHER_TEST_CONTEXT mArc4TestCtx = {Arc4GetContextSize, Arc4Init, Arc4Encrypt, (EFI_BLOCK_CIPHER_ECB_ENCRYPT_DECRYPT), Arc4Decrypt, NULL, NULL, Arc4Reset, Arc4Key, sizeof(Arc4Key), NULL, Arc4Data, sizeof(Arc4Data), Arc4Cipher, sizeof(Arc4Cipher)};
+BLOCK_CIPHER_TEST_CONTEXT mAes128CbcTestCtx = {AesGetContextSize, AesInit, NULL, NULL, AesCbcEncrypt, AesCbcDecrypt, NULL, Aes128CbcKey, 128, Aes128CbcIvec, Aes128CbcData, sizeof(Aes128CbcData), Aes128CbcCipher, sizeof(Aes128CbcCipher)};
+
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyBLockCiperPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ BLOCK_CIPHER_TEST_CONTEXT *TestContext;
+ UINTN CtxSize;
+
+ TestContext = Context;
+ CtxSize = TestContext->GetContextSize ();
+ TestContext->Ctx = AllocatePool (CtxSize);
+ if (TestContext->Ctx == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyBLockCiperCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ BLOCK_CIPHER_TEST_CONTEXT *TestContext;
+
+ TestContext = Context;
+ if (TestContext->Ctx != NULL) {
+ FreePool (TestContext->Ctx);
+ }
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyBLockCiper (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 Encrypt[256];
+ UINT8 Decrypt[256];
+ BOOLEAN Status;
+ BLOCK_CIPHER_TEST_CONTEXT *TestContext;
+
+ TestContext = Context;
+
+ ZeroMem (Encrypt, sizeof (Encrypt));
+ ZeroMem (Decrypt, sizeof (Decrypt));
+
+ Status = TestContext->Init (TestContext->Ctx, TestContext->Key, TestContext->KeySize);
+ UT_ASSERT_TRUE (Status);
+
+ if (TestContext->Ivec == NULL) {
+ Status = TestContext->EcbEncrypt (TestContext->Ctx, TestContext->Data, TestContext->DataSize, Encrypt);
+ UT_ASSERT_TRUE (Status);
+
+ if (TestContext->Reset != NULL) {
+ Status = TestContext->Reset (TestContext->Ctx);
+ UT_ASSERT_TRUE (Status);
+ }
+
+ Status = TestContext->EcbDecrypt (TestContext->Ctx, Encrypt, TestContext->DataSize, Decrypt);
+ UT_ASSERT_TRUE (Status);
+
+ } else {
+ Status = TestContext->CbcEncrypt (TestContext->Ctx, TestContext->Data, TestContext->DataSize, TestContext->Ivec, Encrypt);
+ UT_ASSERT_TRUE (Status);
+
+ if (TestContext->Reset != NULL) {
+ Status = TestContext->Reset (TestContext->Ctx);
+ UT_ASSERT_TRUE (Status);
+ }
+
+ Status = TestContext->CbcDecrypt (TestContext->Ctx, Encrypt, TestContext->DataSize, TestContext->Ivec, Decrypt);
+ UT_ASSERT_TRUE (Status);
+ }
+
+ UT_ASSERT_MEM_EQUAL (Encrypt, TestContext->Cipher, TestContext->CipherSize);
+ UT_ASSERT_MEM_EQUAL (Decrypt, TestContext->Data, TestContext->DataSize);
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mBlockCipherTest[] = {
+ //
+ // -----Description-------------------------Class-------------------------Function---------------Pre---------------------------Post------------------Context
+ //
+ {"TestVerifyAes128Cbc()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mAes128CbcTestCtx},
+ // These are commented out as these functions have been deprecated, but they have been left in for future reference
+ //{"TestVerifyTdesEcb()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mTdesEcbTestCtx},
+ //{"TestVerifyTdesCbc()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mTdesCbcTestCtx},
+ //{"TestVerifyAes128Ecb()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mAes128EcbTestCtx},
+ //{"TestVerifyAes192Ecb()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mAes192EcbTestCtx},
+ //{"TestVerifyAes256Ecb()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mAes256EcbTestCtx},
+ //{"TestVerifyArc4()", "CryptoPkg.BaseCryptLib.BlockCipher", TestVerifyBLockCiper, TestVerifyBLockCiperPreReq, TestVerifyBLockCiperCleanUp, &mArc4TestCtx},
+};
+
+UINTN mBlockCipherTestNum = ARRAY_SIZE(mBlockCipherTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/DhTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/DhTests.c
new file mode 100644
index 00000000000..7f3ec1a3f6d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/DhTests.c
@@ -0,0 +1,106 @@
+/** @file
+ Application for Diffie-Hellman Primitives Validation.
+
+Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+VOID *mDh1;
+VOID *mDh2;
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyDhPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ mDh1 = DhNew ();
+ if (mDh1 == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ mDh2 = DhNew ();
+ if (mDh2 == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyDhCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ if (mDh1 != NULL) {
+ DhFree (mDh1);
+ mDh1 = NULL;
+ }
+ if (mDh2 != NULL) {
+ DhFree (mDh2);
+ mDh2 = NULL;
+ }
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyDhGenerateKey (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 Prime[64];
+ UINT8 PublicKey1[64];
+ UINTN PublicKey1Length;
+ UINT8 PublicKey2[64];
+ UINTN PublicKey2Length;
+ UINT8 Key1[64];
+ UINTN Key1Length;
+ UINT8 Key2[64];
+ UINTN Key2Length;
+ BOOLEAN Status;
+
+ //
+ // Initialize Key Length
+ //
+ PublicKey1Length = sizeof (PublicKey1);
+ PublicKey2Length = sizeof (PublicKey2);
+ Key1Length = sizeof (Key1);
+ Key2Length = sizeof (Key2);
+
+ Status = DhGenerateParameter (mDh1, 2, 64, Prime);
+ UT_ASSERT_TRUE (Status);
+
+ Status = DhSetParameter (mDh2, 2, 64, Prime);
+ UT_ASSERT_TRUE (Status);
+
+ Status = DhGenerateKey (mDh1, PublicKey1, &PublicKey1Length);
+ UT_ASSERT_TRUE (Status);
+
+ Status = DhGenerateKey (mDh2, PublicKey2, &PublicKey2Length);
+ UT_ASSERT_TRUE (Status);
+
+ Status = DhComputeKey (mDh1, PublicKey2, PublicKey2Length, Key1, &Key1Length);
+ UT_ASSERT_TRUE (Status);
+
+ Status = DhComputeKey (mDh2, PublicKey1, PublicKey1Length, Key2, &Key2Length);
+ UT_ASSERT_TRUE (Status);
+
+ UT_ASSERT_EQUAL (Key1Length, Key2Length);
+
+ UT_ASSERT_MEM_EQUAL (Key1, Key2, Key1Length);
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mDhTest[] = {
+ //
+ // -----Description--------------------------------Class---------------------Function----------------Pre-----------------Post------------Context
+ //
+ {"TestVerifyDhGenerateKey()", "CryptoPkg.BaseCryptLib.Dh", TestVerifyDhGenerateKey, TestVerifyDhPreReq, TestVerifyDhCleanUp, NULL},
+};
+
+UINTN mDhTestNum = ARRAY_SIZE(mDhTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HashTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HashTests.c
new file mode 100644
index 00000000000..1b71f2bf2ee
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HashTests.c
@@ -0,0 +1,202 @@
+/** @file
+ Application for Hash Primitives Validation.
+
+Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// Max Known Digest Size is SHA512 Output (64 bytes) by far
+//
+#define MAX_DIGEST_SIZE 64
+
+//
+// Message string for digest validation
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *HashData = "abc";
+
+//
+// Result for MD5("abc"). (From "A.5 Test suite" of IETF RFC1321)
+//
+#ifdef ENABLE_MD5_DEPRECATED_INTERFACES
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Md5Digest[MD5_DIGEST_SIZE] = {
+ 0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d, 0x28, 0xe1, 0x7f, 0x72
+ };
+#endif
+
+//
+// Result for SHA-1("abc"). (From "A.1 SHA-1 Example" of NIST FIPS 180-2)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Sha1Digest[SHA1_DIGEST_SIZE] = {
+ 0xa9, 0x99, 0x3e, 0x36, 0x47, 0x06, 0x81, 0x6a, 0xba, 0x3e, 0x25, 0x71, 0x78, 0x50, 0xc2, 0x6c,
+ 0x9c, 0xd0, 0xd8, 0x9d
+ };
+
+//
+// Result for SHA-256("abc"). (From "B.1 SHA-256 Example" of NIST FIPS 180-2)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Sha256Digest[SHA256_DIGEST_SIZE] = {
+ 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
+ 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
+ };
+
+//
+// Result for SHA-384("abc"). (From "D.1 SHA-384 Example" of NIST FIPS 180-2)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Sha384Digest[SHA384_DIGEST_SIZE] = {
+ 0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b, 0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
+ 0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63, 0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
+ 0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23, 0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
+ };
+
+//
+// Result for SHA-512("abc"). (From "C.1 SHA-512 Example" of NIST FIPS 180-2)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 Sha512Digest[SHA512_DIGEST_SIZE] = {
+ 0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
+ 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
+ 0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
+ 0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
+ };
+
+typedef
+UINTN
+(EFIAPI *EFI_HASH_GET_CONTEXT_SIZE) (
+ VOID
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_INIT) (
+ OUT VOID *HashContext
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_UPDATE) (
+ IN OUT VOID *HashContext,
+ IN CONST VOID *Data,
+ IN UINTN DataSize
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_FINAL) (
+ IN OUT VOID *HashContext,
+ OUT UINT8 *HashValue
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HASH_ALL) (
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT8 *HashValue
+ );
+
+typedef struct {
+ UINT32 DigestSize;
+ EFI_HASH_GET_CONTEXT_SIZE GetContextSize;
+ EFI_HASH_INIT HashInit;
+ EFI_HASH_UPDATE HashUpdate;
+ EFI_HASH_FINAL HashFinal;
+ EFI_HASH_ALL HashAll;
+ CONST UINT8 *Digest;
+ VOID *HashCtx;
+} HASH_TEST_CONTEXT;
+
+#ifdef ENABLE_MD5_DEPRECATED_INTERFACES
+HASH_TEST_CONTEXT mMd5TestCtx = {MD5_DIGEST_SIZE, Md5GetContextSize, Md5Init, Md5Update, Md5Final, Md5HashAll, Md5Digest};
+#endif
+HASH_TEST_CONTEXT mSha1TestCtx = {SHA1_DIGEST_SIZE, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final, Sha1HashAll, Sha1Digest};
+HASH_TEST_CONTEXT mSha256TestCtx = {SHA256_DIGEST_SIZE, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final, Sha256HashAll, Sha256Digest};
+HASH_TEST_CONTEXT mSha384TestCtx = {SHA384_DIGEST_SIZE, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final, Sha384HashAll, Sha384Digest};
+HASH_TEST_CONTEXT mSha512TestCtx = {SHA512_DIGEST_SIZE, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final, Sha512HashAll, Sha512Digest};
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyHashPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ HASH_TEST_CONTEXT *HashTestContext;
+ UINTN CtxSize;
+
+ HashTestContext = Context;
+ CtxSize = HashTestContext->GetContextSize ();
+ HashTestContext->HashCtx = AllocatePool (CtxSize);
+ if (HashTestContext->HashCtx == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyHashCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ HASH_TEST_CONTEXT *HashTestContext;
+
+ HashTestContext = Context;
+ if (HashTestContext->HashCtx != NULL) {
+ FreePool (HashTestContext->HashCtx);
+ }
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyHash (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINTN DataSize;
+ UINT8 Digest[MAX_DIGEST_SIZE];
+ BOOLEAN Status;
+ HASH_TEST_CONTEXT *HashTestContext;
+
+ HashTestContext = Context;
+
+ DataSize = AsciiStrLen (HashData);
+
+ ZeroMem (Digest, MAX_DIGEST_SIZE);
+
+ Status = HashTestContext->HashInit (HashTestContext->HashCtx);
+ UT_ASSERT_TRUE (Status);
+
+ Status = HashTestContext->HashUpdate (HashTestContext->HashCtx, HashData, DataSize);
+ UT_ASSERT_TRUE (Status);
+
+ Status = HashTestContext->HashFinal (HashTestContext->HashCtx, Digest);
+ UT_ASSERT_TRUE (Status);
+
+ UT_ASSERT_MEM_EQUAL (Digest, HashTestContext->Digest, HashTestContext->DigestSize);
+
+ ZeroMem (Digest, MAX_DIGEST_SIZE);
+ Status = HashTestContext->HashAll (HashData, DataSize, Digest);
+ UT_ASSERT_TRUE (Status);
+
+ UT_ASSERT_MEM_EQUAL (Digest, HashTestContext->Digest, HashTestContext->DigestSize);
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mHashTest[] = {
+ //
+ // -----Description----------------Class---------------------Function---------------Pre------------------Post------------Context
+ //
+#ifdef ENABLE_MD5_DEPRECATED_INTERFACES
+ {"TestVerifyMd5()", "CryptoPkg.BaseCryptLib.Hash", TestVerifyHash, TestVerifyHashPreReq, TestVerifyHashCleanUp, &mMd5TestCtx},
+#endif
+ {"TestVerifySha1()", "CryptoPkg.BaseCryptLib.Hash", TestVerifyHash, TestVerifyHashPreReq, TestVerifyHashCleanUp, &mSha1TestCtx},
+ {"TestVerifySha256()", "CryptoPkg.BaseCryptLib.Hash", TestVerifyHash, TestVerifyHashPreReq, TestVerifyHashCleanUp, &mSha256TestCtx},
+ {"TestVerifySha384()", "CryptoPkg.BaseCryptLib.Hash", TestVerifyHash, TestVerifyHashPreReq, TestVerifyHashCleanUp, &mSha384TestCtx},
+ {"TestVerifySha512()", "CryptoPkg.BaseCryptLib.Hash", TestVerifyHash, TestVerifyHashPreReq, TestVerifyHashCleanUp, &mSha512TestCtx},
+};
+
+UINTN mHashTestNum = ARRAY_SIZE(mHashTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HmacTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HmacTests.c
new file mode 100644
index 00000000000..777a6945486
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/HmacTests.c
@@ -0,0 +1,184 @@
+/** @file
+ Application for HMAC Primitives Validation.
+
+Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// Max Known Digest Size is SHA512 Output (64 bytes) by far
+//
+#define MAX_DIGEST_SIZE 64
+
+//
+// Data string for HMAC validation
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *HmacData = "Hi There";
+
+//
+// Key value for HMAC-MD5 validation. (From "2. Test Cases for HMAC-MD5" of IETF RFC2202)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 HmacMd5Key[16] = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b
+ };
+
+//
+// Result for HMAC-MD5("Hi There"). (From "2. Test Cases for HMAC-MD5" of IETF RFC2202)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 HmacMd5Digest[] = {
+ 0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d
+ };
+
+//
+// Key value for HMAC-SHA-1 validation. (From "3. Test Cases for HMAC-SHA-1" of IETF RFC2202)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 HmacSha1Key[20] = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b
+ };
+
+//
+// Result for HMAC-SHA-1 ("Hi There"). (From "3. Test Cases for HMAC-SHA-1" of IETF RFC2202)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 HmacSha1Digest[] = {
+ 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6, 0xfb, 0x37, 0x8c, 0x8e,
+ 0xf1, 0x46, 0xbe, 0x00
+ };
+
+//
+// Key value for HMAC-SHA-256 validation. (From "4. Test Vectors" of IETF RFC4231)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 HmacSha256Key[20] = {
+ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+ 0x0b, 0x0b, 0x0b, 0x0b
+ };
+
+//
+// Result for HMAC-SHA-256 ("Hi There"). (From "4. Test Vectors" of IETF RFC4231)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 HmacSha256Digest[] = {
+ 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b,
+ 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7
+ };
+
+typedef
+VOID*
+(EFIAPI *EFI_HMAC_NEW) (
+ VOID
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HMAC_INIT) (
+ IN OUT VOID *HashContext,
+ IN CONST UINT8 *Key,
+ IN UINTN KeySize
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HMAC_UPDATE) (
+ IN OUT VOID *HashContext,
+ IN CONST VOID *Data,
+ IN UINTN DataSize
+ );
+
+typedef
+BOOLEAN
+(EFIAPI *EFI_HMAC_FINAL) (
+ IN OUT VOID *HashContext,
+ OUT UINT8 *HashValue
+ );
+
+typedef struct {
+ UINT32 DigestSize;
+ EFI_HMAC_NEW HmacNew;
+ EFI_HMAC_INIT HmacInit;
+ EFI_HMAC_UPDATE HmacUpdate;
+ EFI_HMAC_FINAL HmacFinal;
+ CONST UINT8 *Key;
+ UINTN KeySize;
+ CONST UINT8 *Digest;
+ VOID *HmacCtx;
+} HMAC_TEST_CONTEXT;
+
+// These functions have been deprecated but they've been left commented out for future reference
+//HMAC_TEST_CONTEXT mHmacMd5TestCtx = {MD5_DIGEST_SIZE, HmacMd5New, HmacMd5SetKey, HmacMd5Update, HmacMd5Final, HmacMd5Key, sizeof(HmacMd5Key), HmacMd5Digest};
+//HMAC_TEST_CONTEXT mHmacSha1TestCtx = {SHA1_DIGEST_SIZE, HmacSha1New, HmacSha1SetKey, HmacSha1Update, HmacSha1Final, HmacSha1Key, sizeof(HmacSha1Key), HmacSha1Digest};
+HMAC_TEST_CONTEXT mHmacSha256TestCtx = {SHA256_DIGEST_SIZE, HmacSha256New, HmacSha256SetKey, HmacSha256Update, HmacSha256Final, HmacSha256Key, sizeof(HmacSha256Key), HmacSha256Digest};
+
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyHmacPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ HMAC_TEST_CONTEXT *HmacTestContext;
+
+ HmacTestContext = Context;
+ HmacTestContext->HmacCtx = HmacTestContext->HmacNew();
+ if (HmacTestContext->HmacCtx == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyHmacCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ HMAC_TEST_CONTEXT *HmacTestContext;
+
+ HmacTestContext = Context;
+ if (HmacTestContext->HmacCtx != NULL) {
+ FreePool (HmacTestContext->HmacCtx);
+ }
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyHmac (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 Digest[MAX_DIGEST_SIZE];
+ BOOLEAN Status;
+ HMAC_TEST_CONTEXT *HmacTestContext;
+
+ HmacTestContext = Context;
+
+ ZeroMem (Digest, MAX_DIGEST_SIZE);
+
+ Status = HmacTestContext->HmacInit (HmacTestContext->HmacCtx, HmacTestContext->Key, HmacTestContext->KeySize);
+ UT_ASSERT_TRUE (Status);
+
+ Status = HmacTestContext->HmacUpdate (HmacTestContext->HmacCtx, HmacData, 8);
+ UT_ASSERT_TRUE (Status);
+
+ Status = HmacTestContext->HmacFinal (HmacTestContext->HmacCtx, Digest);
+ UT_ASSERT_TRUE (Status);
+
+ UT_ASSERT_MEM_EQUAL (Digest, HmacTestContext->Digest, HmacTestContext->DigestSize);
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mHmacTest[] = {
+ //
+ // -----Description---------------------Class---------------------Function---------------Pre------------------Post------------Context
+ //
+ {"TestVerifyHmacSha256()", "CryptoPkg.BaseCryptLib.Hmac", TestVerifyHmac, TestVerifyHmacPreReq, TestVerifyHmacCleanUp, &mHmacSha256TestCtx},
+ // These functions have been deprecated but they've been left commented out for future reference
+ //{"TestVerifyHmacMd5()", "CryptoPkg.BaseCryptLib.Hmac", TestVerifyHmac, TestVerifyHmacPreReq, TestVerifyHmacCleanUp, &mHmacMd5TestCtx},
+ //{"TestVerifyHmacSha1()", "CryptoPkg.BaseCryptLib.Hmac", TestVerifyHmac, TestVerifyHmacPreReq, TestVerifyHmacCleanUp, &mHmacSha1TestCtx},
+
+};
+
+UINTN mHmacTestNum = ARRAY_SIZE(mHmacTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/OaepEncryptTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/OaepEncryptTests.c
new file mode 100644
index 00000000000..d67c4895418
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/OaepEncryptTests.c
@@ -0,0 +1,308 @@
+/** @file
+ This is a unit test for RSA OAEP encrypt.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "TestBaseCryptLib.h"
+
+CONST UINT8 RandSeed[] = "This is the random seed for PRNG verification.";
+
+//
+// Self signed X509 certificate
+// CN = ca.self
+// O = Intel
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 SelfTestCert[] = {
+ 0x30, 0x82, 0x03, 0x90, 0x30, 0x82, 0x02, 0x78, 0x02, 0x09, 0x00, 0xE4, 0xDF, 0x47, 0x80, 0xEF,
+ 0x4B, 0x3C, 0x6D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B,
+ 0x05, 0x00, 0x30, 0x81, 0x89, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x43, 0x4E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x08, 0x53, 0x68, 0x61,
+ 0x6E, 0x67, 0x48, 0x61, 0x69, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x08,
+ 0x53, 0x68, 0x61, 0x6E, 0x67, 0x48, 0x61, 0x69, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04,
+ 0x0A, 0x0C, 0x05, 0x49, 0x6E, 0x74, 0x65, 0x6C, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04,
+ 0x0B, 0x0C, 0x03, 0x46, 0x49, 0x45, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x07, 0x63, 0x61, 0x2E, 0x73, 0x65, 0x6C, 0x66, 0x31, 0x24, 0x30, 0x22, 0x06, 0x09, 0x2A, 0x86,
+ 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x15, 0x7A, 0x68, 0x69, 0x63, 0x68, 0x61, 0x6F,
+ 0x2E, 0x67, 0x61, 0x6F, 0x40, 0x69, 0x6E, 0x74, 0x65, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E,
+ 0x17, 0x0D, 0x31, 0x39, 0x30, 0x33, 0x32, 0x37, 0x30, 0x35, 0x35, 0x37, 0x30, 0x39, 0x5A, 0x17,
+ 0x0D, 0x32, 0x30, 0x30, 0x33, 0x32, 0x36, 0x30, 0x35, 0x35, 0x37, 0x30, 0x39, 0x5A, 0x30, 0x81,
+ 0x89, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x4E, 0x31, 0x11,
+ 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x08, 0x53, 0x68, 0x61, 0x6E, 0x67, 0x48, 0x61,
+ 0x69, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x08, 0x53, 0x68, 0x61, 0x6E,
+ 0x67, 0x48, 0x61, 0x69, 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x05, 0x49,
+ 0x6E, 0x74, 0x65, 0x6C, 0x31, 0x0C, 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03, 0x46,
+ 0x49, 0x45, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x07, 0x63, 0x61, 0x2E,
+ 0x73, 0x65, 0x6C, 0x66, 0x31, 0x24, 0x30, 0x22, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x09, 0x01, 0x16, 0x15, 0x7A, 0x68, 0x69, 0x63, 0x68, 0x61, 0x6F, 0x2E, 0x67, 0x61, 0x6F,
+ 0x40, 0x69, 0x6E, 0x74, 0x65, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D,
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBC, 0xE4, 0x67, 0xDC, 0xC7,
+ 0xEA, 0x6F, 0x8A, 0xA7, 0xCC, 0xB2, 0x54, 0x47, 0x48, 0x6A, 0xE2, 0x39, 0xFF, 0xC2, 0x48, 0x58,
+ 0x34, 0x07, 0x03, 0x6D, 0x39, 0xB3, 0x67, 0x46, 0x4C, 0xBC, 0xA0, 0xFA, 0x4E, 0x64, 0x23, 0x56,
+ 0x47, 0x7B, 0xC9, 0x1A, 0x2A, 0x55, 0x42, 0x54, 0x10, 0x18, 0x30, 0x92, 0x60, 0x30, 0x5B, 0x9E,
+ 0xC0, 0x65, 0xD2, 0xD4, 0x05, 0x4A, 0xA6, 0x10, 0x66, 0x04, 0xA9, 0x54, 0x4E, 0xEE, 0x49, 0x39,
+ 0x43, 0x65, 0x1E, 0x2E, 0x28, 0xDE, 0x79, 0x24, 0xA9, 0x7E, 0xD8, 0x5B, 0xBC, 0x2F, 0x46, 0x6A,
+ 0xB7, 0xB6, 0x0D, 0x17, 0x88, 0x37, 0x52, 0x5C, 0xFE, 0x93, 0xC0, 0xE2, 0xFD, 0x6A, 0x08, 0x1B,
+ 0xFB, 0xD1, 0x87, 0xBD, 0xBD, 0x58, 0x57, 0x2C, 0x06, 0x5D, 0xD2, 0x7D, 0x52, 0xE2, 0x49, 0x8E,
+ 0xDC, 0xE5, 0x26, 0xBD, 0x92, 0x60, 0xB0, 0x3F, 0x58, 0x5E, 0x52, 0xD7, 0x91, 0xDA, 0x93, 0x62,
+ 0x8D, 0x71, 0x80, 0x53, 0xBA, 0x15, 0xC4, 0x1F, 0xF3, 0xBD, 0xE0, 0xC5, 0xA4, 0xB8, 0xD3, 0x64,
+ 0x12, 0x14, 0x1B, 0x11, 0x6B, 0x7B, 0xC2, 0x92, 0xC7, 0xE2, 0x94, 0x0B, 0xB8, 0x67, 0x38, 0x48,
+ 0x63, 0x11, 0x74, 0x25, 0x7C, 0x37, 0xC3, 0xB2, 0xAE, 0xD9, 0xA7, 0x17, 0x9C, 0x4B, 0x9D, 0x6C,
+ 0x27, 0xB0, 0x87, 0x16, 0x6B, 0xF2, 0x96, 0xE5, 0x1D, 0x37, 0x27, 0xDE, 0xF2, 0x98, 0xB7, 0x81,
+ 0x08, 0xD9, 0x7A, 0xBA, 0x84, 0x14, 0x61, 0x60, 0x48, 0xCE, 0xCE, 0x51, 0x73, 0xF4, 0xDB, 0xF1,
+ 0x5F, 0x7A, 0x17, 0x71, 0x4F, 0xC1, 0x0B, 0xCE, 0xC7, 0x31, 0xC1, 0x4E, 0xA3, 0xEE, 0x6F, 0x72,
+ 0x97, 0x90, 0xFB, 0x8B, 0x54, 0x9F, 0x82, 0x5B, 0x48, 0x5A, 0xF1, 0xAD, 0x8B, 0x3A, 0xCD, 0xCA,
+ 0xB2, 0x8B, 0x7A, 0x53, 0xD4, 0xF7, 0x71, 0x16, 0x75, 0xA7, 0x35, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03,
+ 0x82, 0x01, 0x01, 0x00, 0x78, 0x64, 0xCD, 0x6F, 0xC0, 0xF9, 0xE7, 0xAB, 0x19, 0x0B, 0xA4, 0x92,
+ 0x88, 0xD7, 0xE3, 0xC4, 0x9C, 0xCF, 0xF2, 0x49, 0xFC, 0xCE, 0x8C, 0xEC, 0x33, 0x3F, 0x24, 0x6F,
+ 0xF7, 0xBC, 0x7C, 0x28, 0xEF, 0xAE, 0xAB, 0x7B, 0xAF, 0x84, 0xE3, 0x4E, 0x38, 0xAB, 0x66, 0x20,
+ 0x7C, 0xB9, 0xE0, 0x37, 0xFD, 0x84, 0x28, 0x3C, 0xEE, 0x35, 0xC4, 0x75, 0x04, 0x43, 0xCA, 0x4F,
+ 0x36, 0x60, 0xC4, 0x06, 0x16, 0x54, 0x3C, 0xF9, 0x47, 0x78, 0xBD, 0xE9, 0x7F, 0xF1, 0xE3, 0x0B,
+ 0xC7, 0x7E, 0x30, 0xA4, 0xCB, 0x3A, 0xC7, 0xCD, 0x50, 0x9A, 0x6C, 0xC1, 0xE3, 0xF8, 0xF8, 0x16,
+ 0xAA, 0x67, 0x7F, 0x92, 0xEE, 0x1D, 0x47, 0xF2, 0x96, 0xDF, 0xD7, 0x43, 0x64, 0x78, 0xA7, 0xD9,
+ 0xF6, 0xA1, 0xD9, 0xEB, 0x5B, 0x2E, 0xC6, 0x9E, 0xEA, 0xD5, 0x04, 0x52, 0xA4, 0x73, 0x97, 0xC8,
+ 0xB3, 0xFD, 0xE1, 0x7E, 0xB1, 0xA4, 0x3F, 0xF4, 0x56, 0x66, 0x8E, 0x6B, 0xBC, 0xD8, 0xF0, 0x7C,
+ 0xBF, 0x58, 0xA4, 0xE0, 0x45, 0xDC, 0x2B, 0x0B, 0x2C, 0x40, 0x52, 0x4D, 0x4B, 0xA9, 0x8A, 0x77,
+ 0x87, 0x31, 0xF8, 0x45, 0xD9, 0x60, 0xBB, 0xAD, 0x28, 0x29, 0x14, 0x0D, 0x0D, 0x8F, 0x0F, 0x34,
+ 0x76, 0x88, 0xF3, 0x5A, 0x65, 0x00, 0x54, 0x22, 0x35, 0xBF, 0x3A, 0x2B, 0xE9, 0xB0, 0x24, 0xE5,
+ 0xBE, 0xDF, 0x08, 0xA0, 0x02, 0xB2, 0x81, 0x01, 0xE8, 0x14, 0xBE, 0x6E, 0x7E, 0xBD, 0x60, 0x0C,
+ 0x4A, 0xD8, 0x57, 0xA4, 0x50, 0xD3, 0xD0, 0x59, 0xCE, 0x57, 0x27, 0xE9, 0xA6, 0x16, 0x15, 0x5F,
+ 0xF2, 0x6C, 0xCC, 0x57, 0x36, 0x20, 0x06, 0xE6, 0xA7, 0x24, 0x22, 0xB0, 0xB1, 0xC4, 0xBC, 0x2C,
+ 0x5C, 0xCE, 0x92, 0x11, 0xFF, 0x6F, 0x8C, 0x14, 0x7E, 0xC4, 0x10, 0x02, 0xF6, 0x69, 0x86, 0x6D,
+ 0x5B, 0x64, 0x81, 0x13,
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 PrivateKey[] = {
+ 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBC, 0xE4, 0x67, 0xDC,
+ 0xC7, 0xEA, 0x6F, 0x8A, 0xA7, 0xCC, 0xB2, 0x54, 0x47, 0x48, 0x6A, 0xE2, 0x39, 0xFF, 0xC2, 0x48,
+ 0x58, 0x34, 0x07, 0x03, 0x6D, 0x39, 0xB3, 0x67, 0x46, 0x4C, 0xBC, 0xA0, 0xFA, 0x4E, 0x64, 0x23,
+ 0x56, 0x47, 0x7B, 0xC9, 0x1A, 0x2A, 0x55, 0x42, 0x54, 0x10, 0x18, 0x30, 0x92, 0x60, 0x30, 0x5B,
+ 0x9E, 0xC0, 0x65, 0xD2, 0xD4, 0x05, 0x4A, 0xA6, 0x10, 0x66, 0x04, 0xA9, 0x54, 0x4E, 0xEE, 0x49,
+ 0x39, 0x43, 0x65, 0x1E, 0x2E, 0x28, 0xDE, 0x79, 0x24, 0xA9, 0x7E, 0xD8, 0x5B, 0xBC, 0x2F, 0x46,
+ 0x6A, 0xB7, 0xB6, 0x0D, 0x17, 0x88, 0x37, 0x52, 0x5C, 0xFE, 0x93, 0xC0, 0xE2, 0xFD, 0x6A, 0x08,
+ 0x1B, 0xFB, 0xD1, 0x87, 0xBD, 0xBD, 0x58, 0x57, 0x2C, 0x06, 0x5D, 0xD2, 0x7D, 0x52, 0xE2, 0x49,
+ 0x8E, 0xDC, 0xE5, 0x26, 0xBD, 0x92, 0x60, 0xB0, 0x3F, 0x58, 0x5E, 0x52, 0xD7, 0x91, 0xDA, 0x93,
+ 0x62, 0x8D, 0x71, 0x80, 0x53, 0xBA, 0x15, 0xC4, 0x1F, 0xF3, 0xBD, 0xE0, 0xC5, 0xA4, 0xB8, 0xD3,
+ 0x64, 0x12, 0x14, 0x1B, 0x11, 0x6B, 0x7B, 0xC2, 0x92, 0xC7, 0xE2, 0x94, 0x0B, 0xB8, 0x67, 0x38,
+ 0x48, 0x63, 0x11, 0x74, 0x25, 0x7C, 0x37, 0xC3, 0xB2, 0xAE, 0xD9, 0xA7, 0x17, 0x9C, 0x4B, 0x9D,
+ 0x6C, 0x27, 0xB0, 0x87, 0x16, 0x6B, 0xF2, 0x96, 0xE5, 0x1D, 0x37, 0x27, 0xDE, 0xF2, 0x98, 0xB7,
+ 0x81, 0x08, 0xD9, 0x7A, 0xBA, 0x84, 0x14, 0x61, 0x60, 0x48, 0xCE, 0xCE, 0x51, 0x73, 0xF4, 0xDB,
+ 0xF1, 0x5F, 0x7A, 0x17, 0x71, 0x4F, 0xC1, 0x0B, 0xCE, 0xC7, 0x31, 0xC1, 0x4E, 0xA3, 0xEE, 0x6F,
+ 0x72, 0x97, 0x90, 0xFB, 0x8B, 0x54, 0x9F, 0x82, 0x5B, 0x48, 0x5A, 0xF1, 0xAD, 0x8B, 0x3A, 0xCD,
+ 0xCA, 0xB2, 0x8B, 0x7A, 0x53, 0xD4, 0xF7, 0x71, 0x16, 0x75, 0xA7, 0x35, 0x02, 0x03, 0x01, 0x00,
+ 0x01, 0x02, 0x82, 0x01, 0x00, 0x13, 0xF7, 0xD1, 0x42, 0xF5, 0x9F, 0x42, 0xCB, 0x55, 0x91, 0xBE,
+ 0x08, 0x4A, 0xC0, 0xCD, 0x0B, 0xBD, 0x35, 0xDC, 0x43, 0xE9, 0x8F, 0x16, 0x6E, 0xB6, 0x4D, 0x33,
+ 0x39, 0xE7, 0xA4, 0x95, 0x0C, 0x2F, 0x69, 0xBA, 0x0C, 0x42, 0x42, 0xAC, 0x43, 0x46, 0x10, 0xD3,
+ 0x92, 0x7F, 0x70, 0x74, 0x1E, 0x2E, 0x5B, 0x1C, 0xC1, 0x92, 0xB6, 0xA4, 0x0C, 0xF5, 0x7C, 0xD9,
+ 0xB7, 0x54, 0x64, 0x74, 0x79, 0xB1, 0xFF, 0xE6, 0x10, 0xB7, 0x8C, 0xF8, 0x53, 0x88, 0x6D, 0xA9,
+ 0x97, 0x04, 0xD9, 0x26, 0x1F, 0x99, 0x12, 0xFB, 0xAC, 0x65, 0xFB, 0xA5, 0xB3, 0x1C, 0x99, 0xB9,
+ 0xBF, 0x6B, 0x35, 0x3E, 0x49, 0x55, 0xB5, 0x94, 0x4F, 0xE7, 0x25, 0x67, 0xB1, 0x01, 0xCD, 0xD2,
+ 0x58, 0xE4, 0xBE, 0x87, 0x8C, 0x88, 0xD3, 0x0A, 0x38, 0xDC, 0x71, 0x5D, 0x88, 0x0A, 0xE2, 0x3E,
+ 0x76, 0x63, 0x3B, 0xE4, 0x3C, 0x8F, 0x2F, 0x29, 0x1D, 0xD1, 0x66, 0x8D, 0xC0, 0x4A, 0x68, 0x15,
+ 0x90, 0x4C, 0x95, 0x61, 0xF4, 0xFD, 0xE8, 0xFA, 0x9C, 0x6C, 0x00, 0x22, 0x23, 0xD5, 0x17, 0x6E,
+ 0xEE, 0xA8, 0xD8, 0x70, 0xC5, 0x74, 0xEA, 0x09, 0x13, 0x7F, 0x0C, 0x37, 0x4D, 0x50, 0xCD, 0xE9,
+ 0x16, 0xC2, 0xD5, 0xDE, 0x5E, 0xC3, 0xFC, 0x46, 0x08, 0xF1, 0x99, 0xC0, 0xB4, 0x28, 0xFD, 0x2B,
+ 0x29, 0xEF, 0x76, 0xD7, 0x04, 0x4F, 0x02, 0x54, 0x16, 0x54, 0x55, 0x20, 0xEC, 0xBC, 0xBF, 0x85,
+ 0x5F, 0x12, 0xCC, 0xFC, 0x0D, 0xF2, 0xEF, 0xFC, 0x4D, 0x3E, 0xA2, 0x5E, 0x97, 0xFE, 0x35, 0x10,
+ 0x0F, 0x53, 0x1F, 0x80, 0xD5, 0xC0, 0xB4, 0xE9, 0xE9, 0x31, 0x4C, 0x89, 0x14, 0x72, 0x39, 0x65,
+ 0x89, 0xEF, 0x7A, 0x51, 0x4A, 0xB9, 0xA9, 0xCC, 0x1B, 0x52, 0xB0, 0x02, 0x52, 0x65, 0x2F, 0x0B,
+ 0x89, 0x41, 0x70, 0x1E, 0x01, 0x02, 0x81, 0x81, 0x00, 0xDB, 0xE8, 0x21, 0x9E, 0xDB, 0x58, 0x42,
+ 0x0B, 0x02, 0x35, 0x87, 0xDF, 0x35, 0xF4, 0xC1, 0xEE, 0xD5, 0x72, 0x2C, 0xDC, 0x4D, 0xC7, 0xDA,
+ 0x6D, 0x18, 0x0F, 0x68, 0x6F, 0xE7, 0xB0, 0x6C, 0xA0, 0xB2, 0x9E, 0xB8, 0x5E, 0x4A, 0x86, 0x81,
+ 0x97, 0xBD, 0x78, 0xFC, 0x06, 0xD5, 0xBE, 0x98, 0x42, 0x38, 0x78, 0x78, 0x16, 0xAE, 0x39, 0x56,
+ 0xFB, 0x67, 0x6B, 0xED, 0x7F, 0xB3, 0xC3, 0x7D, 0x95, 0x86, 0x05, 0x0C, 0xF1, 0x4C, 0xC2, 0x67,
+ 0x94, 0x93, 0x1B, 0xB7, 0x91, 0x0A, 0x80, 0xE2, 0x85, 0xA7, 0x75, 0x20, 0x61, 0xCD, 0x40, 0x5B,
+ 0x39, 0x13, 0x32, 0xF7, 0xB8, 0xD7, 0x0C, 0x39, 0x4C, 0x82, 0x4B, 0xA3, 0x9F, 0x5E, 0xB1, 0xB0,
+ 0x38, 0x81, 0x8B, 0x1E, 0xBD, 0x2B, 0xC2, 0x9F, 0x3A, 0x68, 0x72, 0xC2, 0x90, 0xCB, 0xA2, 0xE2,
+ 0xAC, 0x86, 0xFF, 0xC8, 0xD7, 0xB8, 0x97, 0x0E, 0x69, 0x02, 0x81, 0x81, 0x00, 0xDB, 0xE5, 0x21,
+ 0x1F, 0x4C, 0x83, 0xD9, 0x7A, 0x56, 0x87, 0x82, 0xF1, 0x40, 0x1A, 0xD3, 0x5B, 0xC5, 0xB4, 0x4D,
+ 0x18, 0x8A, 0xE3, 0x6B, 0xC9, 0x7E, 0x8F, 0x5D, 0x00, 0x33, 0x66, 0xEB, 0xAE, 0x8E, 0x54, 0x49,
+ 0xD7, 0xEA, 0xF3, 0xF9, 0xED, 0xD7, 0xEE, 0x2C, 0xC8, 0xD6, 0x8F, 0x40, 0x0A, 0x53, 0xCB, 0x5D,
+ 0x16, 0xB7, 0xEB, 0x4E, 0xFB, 0x11, 0x18, 0x1B, 0x4B, 0x6B, 0x43, 0x04, 0xD6, 0x1D, 0x8F, 0x6D,
+ 0x4D, 0x48, 0x8B, 0x6C, 0x82, 0x52, 0xB4, 0x8D, 0x58, 0x9B, 0x19, 0x8D, 0xE0, 0x0D, 0xFD, 0x15,
+ 0x9D, 0x35, 0xDF, 0x5E, 0xED, 0xDB, 0x8F, 0x8C, 0x44, 0x11, 0xC9, 0x9A, 0xD9, 0x3F, 0xD4, 0xA5,
+ 0xEE, 0x68, 0x3B, 0x38, 0xD1, 0x66, 0xB0, 0x62, 0x7E, 0xA5, 0x04, 0xD1, 0x67, 0xA4, 0x1D, 0x93,
+ 0xD6, 0x2A, 0xFB, 0xF6, 0xC1, 0xB2, 0xC4, 0x02, 0x8A, 0xB2, 0xA8, 0xD0, 0xED, 0x02, 0x81, 0x81,
+ 0x00, 0xD1, 0x1D, 0x98, 0x43, 0x09, 0x10, 0x8F, 0x95, 0x0A, 0x5F, 0xBF, 0x3A, 0x1A, 0x84, 0x0A,
+ 0x9B, 0x44, 0x6C, 0x53, 0x8E, 0x97, 0x84, 0x72, 0x08, 0x85, 0xF5, 0xB8, 0xF9, 0x99, 0x58, 0x22,
+ 0xA4, 0x59, 0xD7, 0x27, 0x39, 0xBB, 0x22, 0xD7, 0x3F, 0x65, 0x95, 0x14, 0x0C, 0xA7, 0xDB, 0x9B,
+ 0xCC, 0x75, 0x08, 0xD2, 0x21, 0xB7, 0x41, 0x9D, 0x9E, 0x6A, 0x85, 0xAE, 0x8E, 0x5E, 0x72, 0x8B,
+ 0x0C, 0xD2, 0x2A, 0x21, 0x59, 0xA1, 0x05, 0xC9, 0x1B, 0xF7, 0x1C, 0x47, 0x5E, 0x6C, 0x9F, 0x8D,
+ 0x49, 0x4D, 0xA9, 0xCA, 0xC6, 0x56, 0x39, 0x59, 0xC6, 0x17, 0xA4, 0xC2, 0xFF, 0x09, 0xB8, 0x7D,
+ 0x10, 0x6D, 0x62, 0xE2, 0x50, 0x9D, 0xEA, 0xD8, 0xC9, 0x93, 0x1E, 0xA9, 0x77, 0x78, 0x92, 0x95,
+ 0x7A, 0x24, 0x72, 0xE4, 0xE4, 0x6E, 0x51, 0x11, 0xBE, 0xC0, 0x8D, 0xA1, 0xFE, 0xC9, 0x71, 0x13,
+ 0xE9, 0x02, 0x81, 0x80, 0x38, 0xE5, 0x3F, 0x3D, 0xB6, 0xF1, 0x82, 0x8A, 0xD9, 0xEA, 0xB4, 0x21,
+ 0xB1, 0xE1, 0x7F, 0x00, 0x86, 0xD6, 0x11, 0x00, 0xA1, 0xA7, 0x18, 0x53, 0x89, 0x50, 0x94, 0xD2,
+ 0xA1, 0x7A, 0x26, 0xCF, 0x02, 0x7A, 0xA2, 0xA4, 0xA0, 0x61, 0x42, 0x30, 0x9D, 0x27, 0x3E, 0x25,
+ 0x35, 0x06, 0xD9, 0x9E, 0x12, 0x72, 0x53, 0x02, 0xB6, 0xD1, 0xC6, 0x9C, 0xC5, 0x9E, 0x84, 0x29,
+ 0x6E, 0x76, 0x67, 0xC0, 0xF2, 0xE3, 0x12, 0x77, 0xE5, 0xA6, 0x55, 0x8C, 0x1E, 0xD4, 0x22, 0xA2,
+ 0x63, 0x77, 0x28, 0x33, 0x69, 0xCB, 0x2B, 0x15, 0x83, 0x43, 0xE9, 0x6F, 0x07, 0xD9, 0x4B, 0x84,
+ 0xAD, 0x49, 0x89, 0xAC, 0x5E, 0x8C, 0xA9, 0xE6, 0x56, 0xC7, 0xC3, 0xFA, 0xC2, 0x64, 0x2F, 0x07,
+ 0xEF, 0xB0, 0xA0, 0x71, 0xFD, 0x8F, 0xBD, 0x99, 0xB3, 0x83, 0x80, 0x24, 0x3C, 0x19, 0xE5, 0x42,
+ 0x77, 0xD9, 0xA0, 0x3D, 0x02, 0x81, 0x81, 0x00, 0xB7, 0x35, 0xE9, 0x66, 0x4A, 0xCD, 0x5F, 0x5C,
+ 0x44, 0x9A, 0x7F, 0x23, 0xAE, 0xC2, 0x7F, 0xF0, 0x8D, 0xE4, 0xDB, 0xCD, 0x1A, 0x8A, 0x40, 0xD7,
+ 0x0A, 0xC4, 0x3E, 0xC5, 0x03, 0xFB, 0x47, 0xAB, 0x72, 0xDF, 0xD7, 0x68, 0x27, 0x6E, 0x86, 0x94,
+ 0x2A, 0x2A, 0xDA, 0x25, 0x9E, 0xF6, 0x5E, 0xE0, 0x6D, 0x7C, 0x7D, 0xFE, 0x72, 0xDD, 0xC7, 0xBC,
+ 0x74, 0xC7, 0xAD, 0xEA, 0x44, 0xBE, 0x5C, 0x8A, 0x03, 0xCD, 0x35, 0x74, 0x6F, 0x4E, 0x92, 0x31,
+ 0xBE, 0x57, 0x9A, 0x02, 0x0C, 0xFC, 0xD1, 0xD5, 0xE7, 0x3E, 0x53, 0x0C, 0x47, 0x12, 0x39, 0x45,
+ 0x6E, 0x35, 0x24, 0xA6, 0xDA, 0x42, 0x63, 0xC6, 0xBF, 0xCA, 0xE8, 0x32, 0xFD, 0x61, 0xC0, 0x80,
+ 0x39, 0xD2, 0xB7, 0x0D, 0xF3, 0xA2, 0xF3, 0xE4, 0x49, 0x26, 0x89, 0xD0, 0xA0, 0x24, 0xC8, 0x27,
+ 0x86, 0x10, 0x09, 0x88, 0x6C, 0x35, 0x60, 0xF2,
+ };
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyOaepEncrypt (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ UINT8 File[4];
+ UINT8 *OutBuffer;
+ UINTN OutBufferSize;
+ UINT8 *OutBuffer2;
+ UINTN OutBuffer2Size;
+
+ // Create a file and add content '123' in it
+ File[0] = '1';
+ File[1] = '2';
+ File[2] = '3';
+ File[3] = 0;
+
+ OutBuffer = NULL;
+ OutBufferSize = 0;
+ OutBuffer2 = NULL;
+ OutBuffer2Size = 0;
+
+ Status = Pkcs1v2Encrypt (
+ SelfTestCert,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)sizeof (File),
+ NULL,
+ 0,
+ &OutBuffer,
+ (UINTN *)&OutBufferSize
+ );
+ UT_ASSERT_TRUE (Status);
+
+ Status = Pkcs1v2Encrypt (
+ SelfTestCert,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)4,
+ NULL,
+ 0,
+ &OutBuffer2,
+ (UINTN *)&OutBuffer2Size
+ );
+ UT_ASSERT_TRUE (Status);
+
+ // TRUE - the two OutBuffers are indentical. That means the Oaep encrypt result is incorrect.
+ Status = (CompareMem (OutBuffer, OutBuffer2, OutBufferSize >= OutBuffer2Size ? OutBufferSize : OutBuffer2Size) == 0);
+ UT_ASSERT_FALSE (Status);
+
+ if (OutBuffer) {
+ FreePool (OutBuffer);
+ OutBuffer = NULL;
+ OutBufferSize = 0;
+ }
+
+ if (OutBuffer2) {
+ FreePool (OutBuffer2);
+ OutBuffer2 = NULL;
+ OutBuffer2Size = 0;
+ }
+
+ Status = Pkcs1v2Encrypt (
+ SelfTestCert,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)4,
+ RandSeed,
+ (UINTN)sizeof (RandSeed),
+ &OutBuffer,
+ (UINTN *)&OutBufferSize
+ );
+ UT_ASSERT_TRUE (Status);
+
+ Status = Pkcs1v2Encrypt (
+ SelfTestCert,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)4,
+ RandSeed,
+ (UINTN)sizeof (RandSeed),
+ &OutBuffer2,
+ (UINTN *)&OutBuffer2Size
+ );
+ UT_ASSERT_TRUE (Status);
+
+ // TRUE - the two OutBuffers are indentical. That means the Oaep encrypt result is incorrect.
+ Status = (CompareMem (OutBuffer, OutBuffer2, OutBufferSize >= OutBuffer2Size ? OutBufferSize : OutBuffer2Size) == 0);
+ UT_ASSERT_FALSE (Status);
+
+ if (OutBuffer) {
+ FreePool (OutBuffer);
+ OutBuffer = NULL;
+ OutBufferSize = 0;
+ }
+
+ if (OutBuffer2) {
+ FreePool (OutBuffer2);
+ OutBuffer2 = NULL;
+ OutBuffer2Size = 0;
+ }
+
+ Status = Pkcs1v2Encrypt (
+ NULL,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)4,
+ NULL,
+ 0,
+ &OutBuffer,
+ (UINTN *)&OutBufferSize
+ );
+ UT_ASSERT_FALSE (Status);
+
+ Status = Pkcs1v2Encrypt (
+ SelfTestCert,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)4,
+ NULL,
+ 0,
+ (UINT8 **)NULL,
+ (UINTN *)&OutBufferSize
+ );
+ UT_ASSERT_FALSE (Status);
+
+ Status = Pkcs1v2Encrypt (
+ SelfTestCert,
+ (UINTN)sizeof (SelfTestCert),
+ File,
+ (UINTN)4,
+ NULL,
+ 0,
+ &OutBuffer,
+ (UINTN *)NULL
+ );
+ UT_ASSERT_FALSE (Status);
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mOaepTest[] = {
+ //
+ // -----Description--------------------------------------Class----------------------Function-----------------Pre---Post--Context
+ //
+ {"TestVerifyOaepEncrypt()", "CryptoPkg.BaseCryptLib.Pkcs1v2Encrypt", TestVerifyOaepEncrypt, NULL, NULL, NULL},
+};
+
+UINTN mOaepTestNum = ARRAY_SIZE(mOaepTest);
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs5Pbkdf2Tests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs5Pbkdf2Tests.c
new file mode 100644
index 00000000000..b2f4cc4f18c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs5Pbkdf2Tests.c
@@ -0,0 +1,71 @@
+/** @file
+ Application for PKCS#5 PBKDF2 Function Validation.
+
+Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// PBKDF2 HMAC-SHA1 Test Vector from RFC6070
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *Password = "password"; // Input Password
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN PassLen = 8; // Length of Input Password
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *Salt = "salt"; // Input Salt
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN SaltLen = 4; // Length of Input Salt
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN Count = 2; // InterationCount
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN KeyLen = 20; // Length of derived key
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DerivedKey[] = { // Expected output key
+ 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0,
+ 0xd8, 0xde, 0x89, 0x57
+ };
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyPkcs5Pbkdf2 (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ UINT8 *OutKey;
+
+ OutKey = AllocatePool (KeyLen);
+
+ //
+ // Verify PKCS#5 PBKDF2 Key Derivation Function
+ //
+ Status = Pkcs5HashPassword (
+ PassLen,
+ Password,
+ SaltLen,
+ (CONST UINT8 *)Salt,
+ Count,
+ SHA1_DIGEST_SIZE,
+ KeyLen,
+ OutKey
+ );
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Check the output key with the expected key result
+ //
+ UT_ASSERT_MEM_EQUAL (OutKey, DerivedKey, KeyLen);
+
+ //
+ // Release Resources
+ //
+ FreePool (OutKey);
+
+ return EFI_SUCCESS;
+}
+
+TEST_DESC mPkcs5Test[] = {
+ //
+ // -----Description------------------------------Class----------------------Function-----------------Pre---Post--Context
+ //
+ {"TestVerifyPkcs5Pbkdf2()", "CryptoPkg.BaseCryptLib.Pkcs5", TestVerifyPkcs5Pbkdf2, NULL, NULL, NULL},
+};
+
+UINTN mPkcs5TestNum = ARRAY_SIZE(mPkcs5Test);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTestSignatures.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTestSignatures.h
new file mode 100644
index 00000000000..6a0c3f27d45
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTestSignatures.h
@@ -0,0 +1,789 @@
+/*++
+
+Copyright (C) Microsoft Corporation. All Rights Reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+ AllTestSignatures.h
+
+Abstract:
+ This file has test signatures in byte array format for Unit-Testing the
+ Enhanced Key Usage (EKU) parsing function.
+
+ EFI_STATUS
+ EFIAPI
+ VerifyEKUsInPkcs7Signature (
+ IN CONST UINT8 *Pkcs7Signature,
+ IN CONST UINT32 SignatureSize,
+ IN CONST CHAR8 *RequiredEKUs[],
+ IN CONST UINT32 RequiredEKUsSize,
+ IN BOOLEAN RequireAllPresent
+ );
+
+ Note: These byte arrays were created by running BinToH.exe on the P7B
+ signature files.
+--*/
+
+
+//
+// This is the ProductionECCSignature.p7b in byte array format. It has one
+// EKU in it. (Firmware signing)
+// "1.3.6.1.4.1.311.76.9.21.1"
+//
+CONST UINT8 ProductionECCSignature[] =
+{
+ 0x30, 0x82, 0x04, 0xC0, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x80, 0x30, 0x82, 0x03, 0x7C, 0x30, 0x82, 0x03,
+ 0x22, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x03, 0x7E, 0x2E, 0x8F,
+ 0xBD, 0xA5, 0xC9, 0x2C, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x0A, 0x06, 0x08, 0x2A,
+ 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E,
+ 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x39,
+ 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x30, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x41,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x6F, 0x72, 0x79, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72,
+ 0x65, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x38, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30,
+ 0x37, 0x31, 0x32, 0x31, 0x38, 0x33, 0x37, 0x30, 0x37, 0x5A, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x37,
+ 0x31, 0x32, 0x31, 0x38, 0x33, 0x37, 0x30, 0x37, 0x5A, 0x30, 0x3A, 0x31, 0x38, 0x30, 0x36, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20,
+ 0x45, 0x43, 0x43, 0x20, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x41, 0x63, 0x63, 0x65,
+ 0x73, 0x73, 0x6F, 0x72, 0x79, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x20, 0x53,
+ 0x69, 0x67, 0x6E, 0x65, 0x72, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
+ 0x7D, 0xDF, 0xDE, 0xFA, 0xEE, 0xA5, 0x66, 0x33, 0xAA, 0xCC, 0xA4, 0x18, 0x65, 0x9E, 0x3A, 0xC6,
+ 0x4B, 0xCB, 0xD5, 0x78, 0x94, 0x14, 0xEE, 0xAA, 0xF3, 0x9D, 0xCB, 0x38, 0x6C, 0x5D, 0xFE, 0x3F,
+ 0x8A, 0xA9, 0x8D, 0x04, 0xD2, 0xFE, 0xAA, 0x38, 0xF3, 0xD6, 0x4A, 0x7E, 0xCF, 0x12, 0x95, 0xCF,
+ 0xAD, 0x92, 0x33, 0xF7, 0x38, 0x83, 0xC5, 0xFD, 0xCF, 0xD0, 0x96, 0x08, 0xCA, 0x62, 0x7D, 0x22,
+ 0xA3, 0x82, 0x01, 0xAF, 0x30, 0x82, 0x01, 0xAB, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01,
+ 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04,
+ 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x09, 0x15, 0x01,
+ 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1D,
+ 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xE7, 0xD1, 0xD4, 0x74, 0x71, 0xF4, 0xC9,
+ 0x35, 0x04, 0xA7, 0x9A, 0x1E, 0x0C, 0xDD, 0xF4, 0x8D, 0x5C, 0x1E, 0xF2, 0x29, 0x30, 0x37, 0x06,
+ 0x03, 0x55, 0x1D, 0x11, 0x04, 0x30, 0x30, 0x2E, 0xA4, 0x2C, 0x30, 0x2A, 0x31, 0x10, 0x30, 0x0E,
+ 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x07, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x31, 0x16,
+ 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x0D, 0x34, 0x34, 0x30, 0x38, 0x31, 0x31, 0x2B,
+ 0x34, 0x34, 0x30, 0x38, 0x36, 0x32, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x6F, 0x3A, 0xCC, 0x1B, 0x2F, 0x17, 0x5C, 0xED, 0xEB, 0xC8, 0xBF, 0x93, 0xA7,
+ 0xB5, 0x93, 0xD1, 0x4D, 0x40, 0xAA, 0x03, 0x30, 0x75, 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x6E,
+ 0x30, 0x6C, 0x30, 0x6A, 0xA0, 0x68, 0xA0, 0x66, 0x86, 0x64, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F,
+ 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63,
+ 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x4D, 0x69,
+ 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, 0x45, 0x43, 0x43, 0x25, 0x32, 0x30,
+ 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x25, 0x32, 0x30, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73,
+ 0x6F, 0x72, 0x79, 0x25, 0x32, 0x30, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x25, 0x32,
+ 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x38, 0x2E, 0x63, 0x72, 0x6C, 0x30, 0x81,
+ 0x82, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x76, 0x30, 0x74, 0x30,
+ 0x72, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x66, 0x68, 0x74, 0x74,
+ 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x65, 0x72,
+ 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, 0x45,
+ 0x43, 0x43, 0x25, 0x32, 0x30, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x25, 0x32, 0x30, 0x41,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x6F, 0x72, 0x79, 0x25, 0x32, 0x30, 0x46, 0x69, 0x72, 0x6D, 0x77,
+ 0x61, 0x72, 0x65, 0x25, 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x38, 0x2E,
+ 0x63, 0x72, 0x74, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03,
+ 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x3D, 0xCF, 0xEF, 0xB8, 0xF0, 0x87, 0xEE, 0x7E, 0x80, 0x71,
+ 0x04, 0x77, 0x68, 0xDC, 0x66, 0x2F, 0x09, 0xA7, 0xF0, 0x76, 0x57, 0x7C, 0x12, 0x5A, 0xE4, 0x80,
+ 0x5A, 0xA0, 0xF2, 0x2C, 0x45, 0x1B, 0x02, 0x21, 0x00, 0xEB, 0x5F, 0x89, 0xD5, 0xEB, 0x03, 0x46,
+ 0x9E, 0x08, 0x95, 0x2A, 0x39, 0x30, 0x5D, 0x49, 0xB6, 0x24, 0xCE, 0x78, 0x1B, 0xB8, 0x1D, 0x0F,
+ 0xD1, 0x24, 0xD0, 0xA9, 0x18, 0x0F, 0x45, 0x4F, 0xF6, 0x31, 0x82, 0x01, 0x17, 0x30, 0x82, 0x01,
+ 0x13, 0x02, 0x01, 0x01, 0x30, 0x81, 0xA7, 0x30, 0x81, 0x8F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
+ 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E,
+ 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x39,
+ 0x30, 0x37, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x30, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
+ 0x66, 0x74, 0x20, 0x45, 0x43, 0x43, 0x20, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x41,
+ 0x63, 0x63, 0x65, 0x73, 0x73, 0x6F, 0x72, 0x79, 0x20, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72,
+ 0x65, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x38, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x03,
+ 0x7E, 0x2E, 0x8F, 0xBD, 0xA5, 0xC9, 0x2C, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x0D,
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06,
+ 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x05, 0x00, 0x04, 0x48, 0x30, 0x46, 0x02, 0x21,
+ 0x00, 0x85, 0xC7, 0x25, 0x5C, 0xF8, 0x5A, 0x13, 0xB7, 0xB6, 0x3A, 0xF1, 0x04, 0x72, 0xAC, 0xB3,
+ 0xF8, 0xC3, 0xE0, 0xE3, 0xD7, 0x98, 0x1B, 0xCF, 0x04, 0xA8, 0x0C, 0x7B, 0xBB, 0x7D, 0x40, 0xC2,
+ 0x99, 0x02, 0x21, 0x00, 0xA3, 0x83, 0x12, 0xE4, 0xB6, 0x3C, 0xC9, 0x3F, 0x05, 0xCF, 0x70, 0x57,
+ 0x54, 0x74, 0x0E, 0xEC, 0x14, 0xAD, 0x2C, 0x66, 0x9D, 0x72, 0x73, 0x62, 0x41, 0xA6, 0xC7, 0x90,
+ 0x05, 0x35, 0xF5, 0x80,
+};
+
+//
+// This is the TestSignedWithMultipleCerts.bin.Signature.p7b in byte array
+// format. It has two certs in it, and the leaf has an EKU of
+// "1.3.6.1.4.1.311.76.9.21.1"
+//
+CONST UINT8 TestSignedMultipleCerts[] =
+{
+ 0x30, 0x82, 0x04, 0x90, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0xC2, 0x30, 0x82, 0x01, 0xC5, 0x30, 0x82, 0x01,
+ 0x6A, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x16, 0x2F, 0xD8, 0x2B, 0x8A, 0x98, 0x6A, 0x8A,
+ 0x43, 0xC2, 0x22, 0xA5, 0x47, 0xA1, 0x18, 0xDD, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D,
+ 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D,
+ 0x31, 0x38, 0x30, 0x37, 0x31, 0x38, 0x32, 0x33, 0x31, 0x36, 0x31, 0x32, 0x5A, 0x17, 0x0D, 0x33,
+ 0x38, 0x30, 0x37, 0x31, 0x38, 0x32, 0x33, 0x32, 0x36, 0x31, 0x32, 0x5A, 0x30, 0x28, 0x31, 0x26,
+ 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1D, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65,
+ 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E,
+ 0x65, 0x72, 0x4C, 0x65, 0x61, 0x66, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
+ 0x04, 0x2E, 0x4C, 0x85, 0xFD, 0x86, 0x85, 0x4C, 0x55, 0x96, 0x17, 0xE3, 0x0C, 0xC1, 0xCB, 0xD9,
+ 0x95, 0xCF, 0xC7, 0xEA, 0x57, 0x02, 0x5C, 0x4F, 0x92, 0x7C, 0x35, 0xBF, 0x2B, 0x3D, 0xBA, 0x14,
+ 0xE5, 0x39, 0x9D, 0x9B, 0x64, 0x4A, 0x25, 0x29, 0xD5, 0x61, 0xDA, 0xFD, 0x51, 0x24, 0xB3, 0xE2,
+ 0x4E, 0x00, 0x59, 0xDF, 0xB4, 0x96, 0x42, 0x59, 0xA4, 0xBC, 0xA7, 0x64, 0x8F, 0x3A, 0x17, 0x33,
+ 0x55, 0xA3, 0x78, 0x30, 0x76, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04,
+ 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0F, 0x30, 0x0D,
+ 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x09, 0x15, 0x01, 0x30, 0x0C, 0x06,
+ 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55,
+ 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x63, 0x69, 0x95, 0xE3, 0xDD, 0xF4, 0xF8, 0x42,
+ 0xEA, 0x55, 0x95, 0x54, 0x07, 0xC4, 0xC5, 0x2A, 0xD2, 0xA9, 0x2D, 0x2F, 0x30, 0x1D, 0x06, 0x03,
+ 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xD6, 0x4A, 0xF8, 0x77, 0x21, 0x34, 0xEC, 0xC0, 0xAE,
+ 0x4D, 0x8F, 0x17, 0x86, 0xFF, 0xEA, 0xE3, 0x83, 0x42, 0x32, 0x83, 0x30, 0x0A, 0x06, 0x08, 0x2A,
+ 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x9A,
+ 0xAB, 0xE3, 0x6F, 0xD7, 0xB3, 0x0F, 0x83, 0x8A, 0xA1, 0x64, 0x70, 0xC1, 0xAC, 0x54, 0xE2, 0x59,
+ 0x7C, 0x8B, 0x11, 0x8F, 0x76, 0xB1, 0x9C, 0x5F, 0xDA, 0x7D, 0x04, 0x3C, 0x73, 0xB5, 0xCF, 0x02,
+ 0x21, 0x00, 0xB3, 0x31, 0xC1, 0x48, 0x3C, 0xEE, 0xA1, 0x6D, 0xA9, 0xF7, 0xF5, 0x9F, 0xD3, 0x6F,
+ 0x7D, 0x6F, 0xAB, 0x76, 0x12, 0xEE, 0x01, 0x4D, 0xFC, 0xE6, 0x87, 0xEA, 0xAB, 0x09, 0x98, 0xD8,
+ 0x97, 0x6F, 0x30, 0x82, 0x01, 0xF5, 0x30, 0x82, 0x01, 0x58, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x10, 0x4D, 0x88, 0xBF, 0x04, 0xDF, 0x10, 0x57, 0xBA, 0x43, 0x53, 0x6C, 0xFD, 0xA5, 0x90, 0xA7,
+ 0x6F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x28, 0x31,
+ 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1D, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63,
+ 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67,
+ 0x6E, 0x65, 0x72, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x31,
+ 0x36, 0x32, 0x33, 0x32, 0x31, 0x31, 0x33, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x31, 0x31, 0x36,
+ 0x32, 0x33, 0x33, 0x31, 0x31, 0x33, 0x5A, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46,
+ 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x30,
+ 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x0E, 0x58, 0xA3, 0xDB, 0xD3, 0x9C,
+ 0x21, 0xFC, 0x63, 0x6F, 0xBD, 0xB9, 0xA7, 0x8A, 0xB3, 0xBF, 0x40, 0x87, 0x43, 0x06, 0x53, 0x91,
+ 0x54, 0x31, 0x11, 0x0D, 0x3B, 0x50, 0x32, 0xEA, 0x11, 0xA3, 0x3D, 0x77, 0x08, 0x9E, 0xBC, 0x06,
+ 0x5C, 0x21, 0x48, 0x9D, 0x9B, 0x7C, 0x45, 0xFD, 0x4B, 0xD7, 0x0C, 0x04, 0xD4, 0xE0, 0x0C, 0xB7,
+ 0x6C, 0xBF, 0x22, 0xE1, 0x00, 0x99, 0x75, 0x39, 0x27, 0x59, 0xA3, 0x66, 0x30, 0x64, 0x30, 0x0E,
+ 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x12,
+ 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02,
+ 0x01, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6D,
+ 0x8B, 0x24, 0xBF, 0x20, 0x9D, 0x54, 0xAF, 0x04, 0x5B, 0x84, 0x91, 0x96, 0xAE, 0x99, 0xC1, 0x23,
+ 0x1C, 0x0E, 0xAC, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x63, 0x69,
+ 0x95, 0xE3, 0xDD, 0xF4, 0xF8, 0x42, 0xEA, 0x55, 0x95, 0x54, 0x07, 0xC4, 0xC5, 0x2A, 0xD2, 0xA9,
+ 0x2D, 0x2F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x81,
+ 0x8A, 0x00, 0x30, 0x81, 0x86, 0x02, 0x41, 0x2A, 0xD4, 0xFC, 0x35, 0x28, 0x73, 0x9F, 0xB3, 0x8A,
+ 0xE3, 0x13, 0x7F, 0xCA, 0x36, 0x88, 0x1E, 0xD0, 0x95, 0xDC, 0xE9, 0x8A, 0x9D, 0xC0, 0x27, 0x8C,
+ 0xD8, 0x57, 0x57, 0x5F, 0xDC, 0x13, 0x53, 0x68, 0xED, 0x2F, 0x4D, 0x6A, 0x77, 0xA2, 0x55, 0x48,
+ 0xCB, 0x24, 0x55, 0x3A, 0x30, 0x32, 0xE5, 0x5C, 0xDF, 0x96, 0xF1, 0x15, 0xD4, 0xE7, 0xCD, 0x6A,
+ 0x26, 0xBD, 0x7B, 0x92, 0x50, 0x74, 0xE4, 0x56, 0x02, 0x41, 0x46, 0x33, 0x61, 0x30, 0xFF, 0xA8,
+ 0x53, 0x31, 0x38, 0xCA, 0x6B, 0x77, 0x88, 0x36, 0x9A, 0x0B, 0x57, 0xC3, 0xD1, 0xB2, 0xA7, 0x40,
+ 0x53, 0x6A, 0xD1, 0x6C, 0x8A, 0x8B, 0x3C, 0x29, 0xC1, 0x2B, 0x82, 0x61, 0x2F, 0x1A, 0x9F, 0x2C,
+ 0x9A, 0x81, 0xD0, 0x2B, 0x3E, 0x0D, 0x99, 0xB7, 0xD4, 0x7E, 0xA7, 0xEA, 0x0C, 0x8E, 0x13, 0x0E,
+ 0x53, 0x65, 0x48, 0x17, 0xE5, 0xFA, 0x91, 0x79, 0x98, 0xC7, 0xA1, 0x31, 0x81, 0xA6, 0x30, 0x81,
+ 0xA3, 0x02, 0x01, 0x01, 0x30, 0x3A, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69,
+ 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x02, 0x10,
+ 0x16, 0x2F, 0xD8, 0x2B, 0x8A, 0x98, 0x6A, 0x8A, 0x43, 0xC2, 0x22, 0xA5, 0x47, 0xA1, 0x18, 0xDD,
+ 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30,
+ 0x0B, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x05, 0x00, 0x04, 0x46, 0x30, 0x44,
+ 0x02, 0x20, 0x40, 0xD4, 0xD4, 0xAF, 0x89, 0xFA, 0x83, 0x44, 0x7B, 0x59, 0xB4, 0x2B, 0x99, 0xF0,
+ 0xD4, 0xB0, 0x75, 0x2E, 0x56, 0xAA, 0x0A, 0xDA, 0xCC, 0x82, 0xD5, 0xBC, 0x8D, 0xC4, 0x00, 0xF6,
+ 0x46, 0xA4, 0x02, 0x20, 0x6F, 0xA7, 0xE1, 0x32, 0xB2, 0xF2, 0x5A, 0x69, 0xC5, 0x45, 0xB6, 0x35,
+ 0x04, 0x05, 0x9B, 0xAC, 0x44, 0xB4, 0xA0, 0xE1, 0x25, 0x92, 0xE8, 0x3E, 0x8F, 0x85, 0xA3, 0xBE,
+ 0x34, 0xFE, 0x78, 0x31,
+};
+
+//
+// This is the TestSignedWithMultipleEKUsInCert.bin.Signature.p7b signature in
+// byte array format. It has two EKU's in it:
+// "1.3.6.1.4.1.311.76.9.21.1"
+// "1.3.6.1.4.1.311.76.9.21.2"
+//
+CONST UINT8 TestSignedWithMultipleEKUsInCert[] =
+{
+ 0x30, 0x82, 0x06, 0x2C, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x04, 0x9E, 0x30, 0x82, 0x01, 0xF5, 0x30, 0x82, 0x01,
+ 0x58, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4D, 0x88, 0xBF, 0x04, 0xDF, 0x10, 0x57, 0xBA,
+ 0x43, 0x53, 0x6C, 0xFD, 0xA5, 0x90, 0xA7, 0x6F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x28, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x1D, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D,
+ 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E,
+ 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x31, 0x36, 0x32, 0x33, 0x32, 0x31, 0x31, 0x33, 0x5A, 0x17,
+ 0x0D, 0x33, 0x38, 0x30, 0x31, 0x31, 0x36, 0x32, 0x33, 0x33, 0x31, 0x31, 0x33, 0x5A, 0x30, 0x26,
+ 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69,
+ 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
+ 0x04, 0x0E, 0x58, 0xA3, 0xDB, 0xD3, 0x9C, 0x21, 0xFC, 0x63, 0x6F, 0xBD, 0xB9, 0xA7, 0x8A, 0xB3,
+ 0xBF, 0x40, 0x87, 0x43, 0x06, 0x53, 0x91, 0x54, 0x31, 0x11, 0x0D, 0x3B, 0x50, 0x32, 0xEA, 0x11,
+ 0xA3, 0x3D, 0x77, 0x08, 0x9E, 0xBC, 0x06, 0x5C, 0x21, 0x48, 0x9D, 0x9B, 0x7C, 0x45, 0xFD, 0x4B,
+ 0xD7, 0x0C, 0x04, 0xD4, 0xE0, 0x0C, 0xB7, 0x6C, 0xBF, 0x22, 0xE1, 0x00, 0x99, 0x75, 0x39, 0x27,
+ 0x59, 0xA3, 0x66, 0x30, 0x64, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04,
+ 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04,
+ 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6D, 0x8B, 0x24, 0xBF, 0x20, 0x9D, 0x54, 0xAF, 0x04, 0x5B,
+ 0x84, 0x91, 0x96, 0xAE, 0x99, 0xC1, 0x23, 0x1C, 0x0E, 0xAC, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D,
+ 0x0E, 0x04, 0x16, 0x04, 0x14, 0x63, 0x69, 0x95, 0xE3, 0xDD, 0xF4, 0xF8, 0x42, 0xEA, 0x55, 0x95,
+ 0x54, 0x07, 0xC4, 0xC5, 0x2A, 0xD2, 0xA9, 0x2D, 0x2F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x81, 0x8A, 0x00, 0x30, 0x81, 0x86, 0x02, 0x41, 0x2A, 0xD4,
+ 0xFC, 0x35, 0x28, 0x73, 0x9F, 0xB3, 0x8A, 0xE3, 0x13, 0x7F, 0xCA, 0x36, 0x88, 0x1E, 0xD0, 0x95,
+ 0xDC, 0xE9, 0x8A, 0x9D, 0xC0, 0x27, 0x8C, 0xD8, 0x57, 0x57, 0x5F, 0xDC, 0x13, 0x53, 0x68, 0xED,
+ 0x2F, 0x4D, 0x6A, 0x77, 0xA2, 0x55, 0x48, 0xCB, 0x24, 0x55, 0x3A, 0x30, 0x32, 0xE5, 0x5C, 0xDF,
+ 0x96, 0xF1, 0x15, 0xD4, 0xE7, 0xCD, 0x6A, 0x26, 0xBD, 0x7B, 0x92, 0x50, 0x74, 0xE4, 0x56, 0x02,
+ 0x41, 0x46, 0x33, 0x61, 0x30, 0xFF, 0xA8, 0x53, 0x31, 0x38, 0xCA, 0x6B, 0x77, 0x88, 0x36, 0x9A,
+ 0x0B, 0x57, 0xC3, 0xD1, 0xB2, 0xA7, 0x40, 0x53, 0x6A, 0xD1, 0x6C, 0x8A, 0x8B, 0x3C, 0x29, 0xC1,
+ 0x2B, 0x82, 0x61, 0x2F, 0x1A, 0x9F, 0x2C, 0x9A, 0x81, 0xD0, 0x2B, 0x3E, 0x0D, 0x99, 0xB7, 0xD4,
+ 0x7E, 0xA7, 0xEA, 0x0C, 0x8E, 0x13, 0x0E, 0x53, 0x65, 0x48, 0x17, 0xE5, 0xFA, 0x91, 0x79, 0x98,
+ 0xC7, 0xA1, 0x30, 0x82, 0x02, 0xA1, 0x30, 0x82, 0x02, 0x47, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x10, 0x29, 0xBB, 0x52, 0x25, 0xED, 0x34, 0xB7, 0xBA, 0x40, 0xF8, 0xC3, 0x14, 0xB5, 0xC8, 0x86,
+ 0x9E, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x26, 0x31,
+ 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63,
+ 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67,
+ 0x6E, 0x65, 0x72, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x37, 0x32, 0x37, 0x32,
+ 0x30, 0x33, 0x34, 0x31, 0x31, 0x5A, 0x17, 0x0D, 0x32, 0x33, 0x30, 0x37, 0x32, 0x37, 0x32, 0x30,
+ 0x34, 0x34, 0x31, 0x31, 0x5A, 0x30, 0x3A, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0C, 0x2F, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x46, 0x69, 0x72,
+ 0x6D, 0x77, 0x61, 0x72, 0x65, 0x4C, 0x65, 0x61, 0x66, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x4D,
+ 0x75, 0x6C, 0x74, 0x69, 0x70, 0x6C, 0x65, 0x45, 0x4B, 0x55, 0x73, 0x49, 0x6E, 0x43, 0x65, 0x72,
+ 0x74, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01,
+ 0x01, 0x00, 0xD0, 0x61, 0xA5, 0xCD, 0x49, 0x4B, 0x5C, 0x88, 0x89, 0x09, 0xCA, 0xE7, 0xEB, 0x58,
+ 0x91, 0x8F, 0x59, 0xBE, 0xE8, 0x16, 0xC0, 0xEF, 0x75, 0xE5, 0x18, 0x88, 0xE8, 0xCE, 0xFA, 0xD2,
+ 0xB0, 0x77, 0xC1, 0xD2, 0xF2, 0x9E, 0x65, 0xE8, 0xDB, 0x6B, 0x8C, 0x93, 0xE5, 0x39, 0x1D, 0xF9,
+ 0x37, 0x2A, 0x52, 0x7F, 0xC3, 0x93, 0xD7, 0x9F, 0x03, 0x83, 0xBC, 0x6E, 0xC6, 0x83, 0x64, 0x15,
+ 0x1A, 0x5C, 0x74, 0x41, 0x40, 0x21, 0xC9, 0x25, 0xF0, 0x14, 0xA3, 0x29, 0x97, 0x29, 0x8C, 0x5D,
+ 0xED, 0xE9, 0x8D, 0x66, 0xCC, 0xD1, 0xD1, 0xE0, 0x08, 0x52, 0xA5, 0x93, 0x07, 0xCB, 0xF8, 0x95,
+ 0x2C, 0x8D, 0x29, 0x84, 0x10, 0x5F, 0x57, 0x52, 0x10, 0x75, 0x35, 0x8A, 0x84, 0xE3, 0xAE, 0x10,
+ 0x57, 0x29, 0xE9, 0xEB, 0x6E, 0xD2, 0xC7, 0x6D, 0x35, 0x43, 0x67, 0x82, 0xE3, 0x98, 0x29, 0x9C,
+ 0x59, 0x77, 0xA0, 0x00, 0x27, 0xB2, 0x5D, 0xB9, 0x84, 0x31, 0x89, 0x2F, 0x77, 0xC5, 0xB9, 0x23,
+ 0xE0, 0x14, 0x94, 0x6F, 0x33, 0xD5, 0x3B, 0x58, 0xFB, 0xD6, 0xB6, 0xE5, 0xD4, 0x09, 0x3D, 0xB2,
+ 0xE7, 0x87, 0xC6, 0xEA, 0x73, 0x61, 0x6D, 0xDA, 0xFA, 0x95, 0x2B, 0x2B, 0x8A, 0xEC, 0x7E, 0x68,
+ 0x0F, 0x98, 0x16, 0x08, 0xFF, 0xB2, 0xC1, 0xBF, 0xAB, 0x3D, 0xB0, 0xC2, 0xD5, 0x16, 0xAE, 0x71,
+ 0x54, 0x48, 0xD1, 0x52, 0x72, 0xFD, 0x42, 0x09, 0x66, 0xAF, 0x50, 0xDE, 0x4C, 0x3C, 0x6A, 0xBC,
+ 0x1F, 0xC5, 0x0A, 0xA0, 0xC5, 0x9A, 0xF1, 0xB2, 0xB2, 0x3F, 0x14, 0xE1, 0x93, 0x07, 0xF0, 0x00,
+ 0x04, 0xEF, 0x16, 0x76, 0x18, 0x10, 0x65, 0x63, 0x42, 0x42, 0x12, 0xD0, 0x65, 0xF5, 0xA2, 0xCF,
+ 0x90, 0xBE, 0x65, 0x57, 0x25, 0x8C, 0xAC, 0x5E, 0x05, 0x31, 0x91, 0x9E, 0x4D, 0x18, 0xBC, 0x15,
+ 0x30, 0x7B, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x78, 0x30, 0x76, 0x30, 0x0E, 0x06, 0x03, 0x55,
+ 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x24, 0x06, 0x03, 0x55,
+ 0x1D, 0x25, 0x04, 0x1D, 0x30, 0x1B, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C,
+ 0x09, 0x15, 0x01, 0x06, 0x0C, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x09, 0x15, 0x01,
+ 0x02, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x63, 0x69,
+ 0x95, 0xE3, 0xDD, 0xF4, 0xF8, 0x42, 0xEA, 0x55, 0x95, 0x54, 0x07, 0xC4, 0xC5, 0x2A, 0xD2, 0xA9,
+ 0x2D, 0x2F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0xC0, 0xDC, 0xCB,
+ 0x76, 0x52, 0x84, 0x91, 0xF5, 0x37, 0x0D, 0x85, 0xB6, 0x45, 0x23, 0xFA, 0xA0, 0xAD, 0xC1, 0x1D,
+ 0x92, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00,
+ 0x30, 0x45, 0x02, 0x21, 0x00, 0xF4, 0xB0, 0x8A, 0x91, 0x96, 0x61, 0xDF, 0xC3, 0x54, 0xA5, 0xB3,
+ 0x1A, 0x3C, 0x28, 0x06, 0xC0, 0xA1, 0xF5, 0x72, 0xD1, 0x02, 0x5C, 0x69, 0xB6, 0x6C, 0xA8, 0xDC,
+ 0x6B, 0x78, 0xD9, 0x0C, 0x9A, 0x02, 0x20, 0x37, 0x2C, 0x61, 0x9E, 0x6E, 0x5F, 0xC6, 0xFA, 0x92,
+ 0x52, 0xB0, 0x4E, 0x52, 0xC7, 0xF1, 0xE9, 0x0F, 0xB6, 0xD5, 0x08, 0x10, 0x41, 0x3A, 0x61, 0xFD,
+ 0xC5, 0x70, 0x87, 0xBB, 0x49, 0x82, 0xEA, 0x31, 0x82, 0x01, 0x65, 0x30, 0x82, 0x01, 0x61, 0x02,
+ 0x01, 0x01, 0x30, 0x3A, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D,
+ 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x02, 0x10, 0x29, 0xBB,
+ 0x52, 0x25, 0xED, 0x34, 0xB7, 0xBA, 0x40, 0xF8, 0xC3, 0x14, 0xB5, 0xC8, 0x86, 0x9E, 0x30, 0x0D,
+ 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0D, 0x06,
+ 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00,
+ 0xBB, 0x51, 0xDD, 0x8F, 0xB4, 0x99, 0x37, 0x13, 0x94, 0x6F, 0x09, 0x05, 0xBA, 0x5B, 0x8D, 0x86,
+ 0x9A, 0xB0, 0x51, 0xEB, 0x6B, 0x10, 0xD7, 0xD1, 0x95, 0x4A, 0x4D, 0x23, 0xA3, 0x37, 0x82, 0xDF,
+ 0x1F, 0x24, 0xE4, 0x62, 0x4F, 0xD4, 0x52, 0x73, 0xF8, 0x39, 0x2B, 0x46, 0xF4, 0x61, 0xCE, 0xF1,
+ 0x64, 0xD7, 0x60, 0xC9, 0xCC, 0xCA, 0x8D, 0x94, 0xA5, 0x67, 0x68, 0x2B, 0xE4, 0xB0, 0xD7, 0x64,
+ 0xC8, 0xF3, 0x9C, 0x98, 0x2C, 0x0A, 0x69, 0x56, 0xD6, 0x59, 0xDF, 0x4D, 0x38, 0xE7, 0xD4, 0x63,
+ 0x2B, 0x74, 0xA1, 0xA3, 0xF9, 0xE1, 0x1A, 0x12, 0x2B, 0x04, 0x46, 0x11, 0xA8, 0x26, 0x00, 0x15,
+ 0x4F, 0x14, 0x7F, 0xB1, 0xB4, 0x25, 0x0C, 0x87, 0xB0, 0x56, 0x8C, 0xBE, 0x0D, 0xFA, 0x66, 0x6F,
+ 0x8A, 0xCB, 0x0A, 0x88, 0x3B, 0xF6, 0x52, 0xCD, 0xBB, 0xA2, 0xA9, 0xAD, 0xAD, 0x09, 0x0D, 0xDA,
+ 0x79, 0x8A, 0xAE, 0xE5, 0x9D, 0xCE, 0x5C, 0x60, 0x99, 0x67, 0x26, 0xC4, 0xAF, 0xD4, 0x01, 0xB1,
+ 0x6D, 0xD1, 0x8C, 0x4D, 0x1D, 0xBD, 0xAB, 0x42, 0x2C, 0xF2, 0xD8, 0x07, 0x3F, 0xDC, 0x5E, 0x68,
+ 0x4C, 0xD9, 0xDB, 0xC0, 0x93, 0xBB, 0x8E, 0xA0, 0xA2, 0x09, 0x5F, 0x03, 0x58, 0x48, 0x54, 0xF6,
+ 0xF0, 0xDA, 0x7A, 0x7F, 0xC4, 0xD2, 0x9F, 0x64, 0xF5, 0x85, 0x86, 0x48, 0xDF, 0x7F, 0x86, 0x14,
+ 0x7C, 0x62, 0x77, 0x1D, 0x22, 0xE5, 0x34, 0x42, 0xE4, 0x49, 0x38, 0xB4, 0xE4, 0x22, 0xFB, 0x5F,
+ 0xB5, 0xEA, 0xBA, 0x90, 0x51, 0xC0, 0xC6, 0x94, 0x09, 0xE4, 0xB7, 0x15, 0x3F, 0x07, 0x23, 0xE8,
+ 0x46, 0x93, 0xA5, 0x7B, 0x7A, 0x91, 0xDA, 0x8E, 0x7C, 0xAF, 0xBD, 0x41, 0xB9, 0xDE, 0x85, 0x04,
+ 0xBC, 0x08, 0x6C, 0x08, 0x56, 0x16, 0xDB, 0xB5, 0xEE, 0x65, 0x76, 0xE9, 0x78, 0xD3, 0xDD, 0xD8,
+
+};
+
+//
+// This is the TestSignedWithProductId10001.bin.p7b in byte array format.
+// It has two EKU's in it: (Product ID is 10001)
+// "1.3.6.1.4.1.311.76.9.21.1"
+// "1.3.6.1.4.1.311.76.9.21.1.10001"
+//
+CONST UINT8 TestSignedWithProductId10001[] =
+{
+ 0x30, 0x82, 0x06, 0x1E, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x04, 0x90, 0x30, 0x82, 0x01, 0xF5, 0x30, 0x82, 0x01,
+ 0x58, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4D, 0x88, 0xBF, 0x04, 0xDF, 0x10, 0x57, 0xBA,
+ 0x43, 0x53, 0x6C, 0xFD, 0xA5, 0x90, 0xA7, 0x6F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x28, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x1D, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D,
+ 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E,
+ 0x17, 0x0D, 0x31, 0x38, 0x30, 0x31, 0x31, 0x36, 0x32, 0x33, 0x32, 0x31, 0x31, 0x33, 0x5A, 0x17,
+ 0x0D, 0x33, 0x38, 0x30, 0x31, 0x31, 0x36, 0x32, 0x33, 0x33, 0x31, 0x31, 0x33, 0x5A, 0x30, 0x26,
+ 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61,
+ 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69,
+ 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
+ 0x04, 0x0E, 0x58, 0xA3, 0xDB, 0xD3, 0x9C, 0x21, 0xFC, 0x63, 0x6F, 0xBD, 0xB9, 0xA7, 0x8A, 0xB3,
+ 0xBF, 0x40, 0x87, 0x43, 0x06, 0x53, 0x91, 0x54, 0x31, 0x11, 0x0D, 0x3B, 0x50, 0x32, 0xEA, 0x11,
+ 0xA3, 0x3D, 0x77, 0x08, 0x9E, 0xBC, 0x06, 0x5C, 0x21, 0x48, 0x9D, 0x9B, 0x7C, 0x45, 0xFD, 0x4B,
+ 0xD7, 0x0C, 0x04, 0xD4, 0xE0, 0x0C, 0xB7, 0x6C, 0xBF, 0x22, 0xE1, 0x00, 0x99, 0x75, 0x39, 0x27,
+ 0x59, 0xA3, 0x66, 0x30, 0x64, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04,
+ 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04,
+ 0x08, 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x6D, 0x8B, 0x24, 0xBF, 0x20, 0x9D, 0x54, 0xAF, 0x04, 0x5B,
+ 0x84, 0x91, 0x96, 0xAE, 0x99, 0xC1, 0x23, 0x1C, 0x0E, 0xAC, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D,
+ 0x0E, 0x04, 0x16, 0x04, 0x14, 0x63, 0x69, 0x95, 0xE3, 0xDD, 0xF4, 0xF8, 0x42, 0xEA, 0x55, 0x95,
+ 0x54, 0x07, 0xC4, 0xC5, 0x2A, 0xD2, 0xA9, 0x2D, 0x2F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x81, 0x8A, 0x00, 0x30, 0x81, 0x86, 0x02, 0x41, 0x2A, 0xD4,
+ 0xFC, 0x35, 0x28, 0x73, 0x9F, 0xB3, 0x8A, 0xE3, 0x13, 0x7F, 0xCA, 0x36, 0x88, 0x1E, 0xD0, 0x95,
+ 0xDC, 0xE9, 0x8A, 0x9D, 0xC0, 0x27, 0x8C, 0xD8, 0x57, 0x57, 0x5F, 0xDC, 0x13, 0x53, 0x68, 0xED,
+ 0x2F, 0x4D, 0x6A, 0x77, 0xA2, 0x55, 0x48, 0xCB, 0x24, 0x55, 0x3A, 0x30, 0x32, 0xE5, 0x5C, 0xDF,
+ 0x96, 0xF1, 0x15, 0xD4, 0xE7, 0xCD, 0x6A, 0x26, 0xBD, 0x7B, 0x92, 0x50, 0x74, 0xE4, 0x56, 0x02,
+ 0x41, 0x46, 0x33, 0x61, 0x30, 0xFF, 0xA8, 0x53, 0x31, 0x38, 0xCA, 0x6B, 0x77, 0x88, 0x36, 0x9A,
+ 0x0B, 0x57, 0xC3, 0xD1, 0xB2, 0xA7, 0x40, 0x53, 0x6A, 0xD1, 0x6C, 0x8A, 0x8B, 0x3C, 0x29, 0xC1,
+ 0x2B, 0x82, 0x61, 0x2F, 0x1A, 0x9F, 0x2C, 0x9A, 0x81, 0xD0, 0x2B, 0x3E, 0x0D, 0x99, 0xB7, 0xD4,
+ 0x7E, 0xA7, 0xEA, 0x0C, 0x8E, 0x13, 0x0E, 0x53, 0x65, 0x48, 0x17, 0xE5, 0xFA, 0x91, 0x79, 0x98,
+ 0xC7, 0xA1, 0x30, 0x82, 0x02, 0x93, 0x30, 0x82, 0x02, 0x39, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x10, 0x1F, 0x65, 0xF1, 0x29, 0x3B, 0x89, 0x6A, 0xBF, 0x43, 0xAF, 0xC7, 0x30, 0x36, 0xD1, 0x0D,
+ 0x2B, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x26, 0x31,
+ 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63,
+ 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67,
+ 0x6E, 0x65, 0x72, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38, 0x30, 0x32, 0x31,
+ 0x36, 0x34, 0x32, 0x32, 0x33, 0x5A, 0x17, 0x0D, 0x32, 0x33, 0x30, 0x38, 0x30, 0x32, 0x31, 0x36,
+ 0x35, 0x32, 0x32, 0x33, 0x5A, 0x30, 0x2B, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x0C, 0x20, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69,
+ 0x67, 0x6E, 0x65, 0x72, 0x50, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x49, 0x44, 0x31, 0x30, 0x30,
+ 0x30, 0x31, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
+ 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82,
+ 0x01, 0x01, 0x00, 0x8C, 0x26, 0x35, 0xBC, 0x18, 0x06, 0x44, 0x65, 0xF6, 0x55, 0x29, 0x78, 0x26,
+ 0xCA, 0x57, 0xD0, 0x4C, 0x31, 0x84, 0x5B, 0x64, 0xDE, 0x8E, 0x34, 0x84, 0x45, 0x12, 0xE8, 0x5A,
+ 0x86, 0x4B, 0x5A, 0x61, 0x4C, 0xD8, 0xE2, 0x7D, 0x3B, 0xBD, 0x25, 0x58, 0x30, 0x1D, 0x5E, 0x65,
+ 0x50, 0xC3, 0x07, 0xF2, 0x50, 0xE1, 0x48, 0x2A, 0xD9, 0x70, 0x5F, 0xF3, 0x2B, 0xF1, 0x1F, 0x21,
+ 0x06, 0x62, 0x81, 0xE9, 0x8E, 0xDA, 0xDC, 0x69, 0xA3, 0x6E, 0x2F, 0xD2, 0x3A, 0x79, 0x01, 0xAF,
+ 0xA1, 0x2A, 0x28, 0xDD, 0x32, 0x4E, 0xCE, 0x40, 0xB8, 0x41, 0xA4, 0x7D, 0x3D, 0x70, 0x3F, 0xC4,
+ 0xDA, 0x61, 0x18, 0xBF, 0xFC, 0xAB, 0x16, 0xE3, 0x65, 0x3F, 0x6D, 0x76, 0x37, 0xAD, 0x1F, 0x11,
+ 0x05, 0x0F, 0xC2, 0x56, 0xD1, 0x45, 0xBD, 0x25, 0xCC, 0x19, 0xC4, 0x2A, 0x03, 0xED, 0x3B, 0x05,
+ 0xA7, 0x87, 0x30, 0xE6, 0x84, 0x11, 0x88, 0xD0, 0x91, 0x4E, 0x52, 0xB5, 0x97, 0xDF, 0x57, 0xEF,
+ 0x5E, 0x72, 0x68, 0x49, 0x85, 0xC8, 0x7F, 0xA7, 0x5F, 0x7B, 0xE7, 0xCE, 0xA1, 0x53, 0xBA, 0xF8,
+ 0xA9, 0xDF, 0x8C, 0x8C, 0x72, 0xD2, 0xA9, 0x7A, 0xF5, 0x07, 0x4A, 0x75, 0x1A, 0x0F, 0x50, 0x9E,
+ 0xEA, 0x4C, 0xFC, 0xC7, 0x74, 0xE2, 0x4D, 0xD1, 0x01, 0xC4, 0xB6, 0xCA, 0xA5, 0xCC, 0x23, 0xFA,
+ 0xDE, 0xF2, 0x9C, 0x8B, 0xA6, 0x32, 0x8D, 0xED, 0x97, 0xCC, 0x50, 0xB0, 0xB6, 0x1C, 0x89, 0x64,
+ 0xFC, 0xD7, 0xD0, 0x19, 0x01, 0x50, 0xD9, 0xBC, 0x78, 0xB1, 0x76, 0x6D, 0x01, 0xF8, 0xEC, 0x68,
+ 0x97, 0x20, 0x32, 0xD0, 0x57, 0x76, 0x93, 0x73, 0xC9, 0x2B, 0x68, 0x9D, 0x5E, 0xE1, 0x70, 0xDD,
+ 0x6F, 0x3A, 0x09, 0x20, 0x63, 0xE9, 0xD9, 0x30, 0x05, 0x14, 0x4A, 0x76, 0xA7, 0x3E, 0x61, 0xCD,
+ 0x2F, 0x6D, 0xE3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x79, 0x30, 0x77, 0x30, 0x0E, 0x06, 0x03,
+ 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x25, 0x06, 0x03,
+ 0x55, 0x1D, 0x25, 0x04, 0x1E, 0x30, 0x1C, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x4C, 0x09, 0x15, 0x01, 0x06, 0x0D, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x09, 0x15,
+ 0x01, 0xCE, 0x11, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0x63, 0x69, 0x95, 0xE3, 0xDD, 0xF4, 0xF8, 0x42, 0xEA, 0x55, 0x95, 0x54, 0x07, 0xC4, 0xC5, 0x2A,
+ 0xD2, 0xA9, 0x2D, 0x2F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x09,
+ 0x10, 0xEE, 0x7B, 0xB0, 0x56, 0xB0, 0xCE, 0x42, 0x83, 0x84, 0x90, 0x70, 0xAF, 0x8D, 0x58, 0x1B,
+ 0x77, 0x43, 0x0E, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03,
+ 0x48, 0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xEE, 0x2A, 0x00, 0x7E, 0xC6, 0x4E, 0x6F, 0x22, 0xCC,
+ 0x16, 0xEA, 0xAC, 0x90, 0x3D, 0xD7, 0x6E, 0xAA, 0xBF, 0x7E, 0xC7, 0x45, 0x3F, 0x36, 0x22, 0x81,
+ 0xC6, 0x38, 0xD3, 0x1E, 0xDF, 0x5F, 0x2C, 0x02, 0x20, 0x21, 0xEC, 0xCF, 0x78, 0x1D, 0xDB, 0x4F,
+ 0x50, 0xE8, 0xD6, 0x07, 0xB0, 0x6A, 0xE9, 0x1E, 0xBF, 0x9C, 0xE8, 0xB9, 0xF7, 0xC6, 0xEA, 0x04,
+ 0x7B, 0x5E, 0xD8, 0x67, 0xAB, 0xD2, 0xDE, 0x77, 0xB9, 0x31, 0x82, 0x01, 0x65, 0x30, 0x82, 0x01,
+ 0x61, 0x02, 0x01, 0x01, 0x30, 0x3A, 0x30, 0x26, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0C, 0x1B, 0x53, 0x75, 0x72, 0x66, 0x61, 0x63, 0x65, 0x54, 0x65, 0x73, 0x74, 0x46, 0x69,
+ 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x43, 0x41, 0x02, 0x10,
+ 0x1F, 0x65, 0xF1, 0x29, 0x3B, 0x89, 0x6A, 0xBF, 0x43, 0xAF, 0xC7, 0x30, 0x36, 0xD1, 0x0D, 0x2B,
+ 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30,
+ 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
+ 0x01, 0x00, 0x1F, 0x7F, 0x30, 0xDC, 0xD4, 0x12, 0x9D, 0x0B, 0x71, 0x30, 0x69, 0x91, 0xCC, 0x8A,
+ 0xFB, 0xF6, 0x54, 0x14, 0x4C, 0x0B, 0x78, 0xCE, 0xD3, 0xC6, 0xCE, 0x3E, 0xAC, 0xCC, 0x0F, 0xCE,
+ 0x3A, 0xFC, 0x63, 0x96, 0xD2, 0x7B, 0xDB, 0xF7, 0xE7, 0x6D, 0x64, 0x52, 0x5C, 0x5D, 0x19, 0xBF,
+ 0xE3, 0x04, 0x71, 0x8A, 0xD1, 0x2A, 0xB6, 0x5A, 0x8C, 0xFC, 0xE2, 0x51, 0x27, 0x64, 0x9B, 0xA8,
+ 0x84, 0x69, 0x60, 0x4E, 0x56, 0x83, 0x91, 0x4F, 0xEB, 0x5A, 0xB7, 0x73, 0xE1, 0xAC, 0x24, 0xD2,
+ 0x60, 0xD8, 0x58, 0x21, 0x51, 0x7B, 0x87, 0x93, 0x5B, 0x5F, 0x91, 0x4B, 0x8C, 0xFE, 0xA5, 0x16,
+ 0x2E, 0x33, 0x4D, 0xBB, 0x0C, 0x95, 0x5C, 0xC3, 0x9C, 0x3D, 0xBB, 0x58, 0x17, 0x39, 0x1E, 0x10,
+ 0x47, 0xCD, 0xEE, 0xD3, 0xE7, 0x73, 0x44, 0x7D, 0x35, 0xD9, 0x9F, 0xC3, 0xAC, 0x11, 0x2E, 0x29,
+ 0x54, 0x80, 0x8F, 0x19, 0xDC, 0xC3, 0x11, 0x3D, 0x75, 0xF0, 0x3B, 0x34, 0x63, 0xB1, 0x59, 0x1D,
+ 0x4B, 0x66, 0xBE, 0xB8, 0xAC, 0x36, 0x71, 0x63, 0xD4, 0x41, 0xCF, 0x24, 0x2A, 0x3F, 0xC5, 0x25,
+ 0xD2, 0x45, 0x9B, 0xD3, 0x77, 0xD8, 0xD8, 0x1A, 0xC6, 0xAE, 0xE3, 0xF5, 0xC5, 0xEB, 0xF3, 0x92,
+ 0x27, 0x3C, 0x3F, 0x48, 0x96, 0xF2, 0xB4, 0x66, 0x0A, 0xFB, 0xBF, 0x76, 0xDC, 0x1E, 0xC5, 0xC6,
+ 0x4D, 0xA1, 0x5C, 0x13, 0x22, 0xF8, 0x89, 0xE2, 0x15, 0x43, 0x84, 0xEF, 0xC8, 0x30, 0xE5, 0xF0,
+ 0xBA, 0x51, 0x96, 0x3E, 0xF9, 0xCB, 0x41, 0xE6, 0x36, 0xD4, 0xE3, 0xDA, 0x71, 0xC8, 0x5E, 0x43,
+ 0x7A, 0xBE, 0x8E, 0xC0, 0xA5, 0xEF, 0x66, 0xFD, 0x63, 0xD3, 0xF1, 0xBF, 0x66, 0x4F, 0x35, 0x24,
+ 0x66, 0xC9, 0xCD, 0x1E, 0x3D, 0x71, 0x19, 0x84, 0x1A, 0x9D, 0xA5, 0x56, 0xF4, 0xF9, 0xE0, 0x88,
+ 0x7C, 0x52,
+};
+
+//
+// This is TestSignEKUsWith1CertInSignature.bin.p7b in byte array format.
+// It has one EKU in it:
+// "1.3.6.1.4.1.311.76.9.21.1"
+//
+CONST UINT8 TestSignEKUsWith1CertInSignature[] =
+{
+ 0x30, 0x82, 0x02, 0x7D, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x01, 0xB2, 0x30, 0x82, 0x01, 0xAE, 0x30, 0x82, 0x01,
+ 0x53, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3E, 0xEE, 0x4B, 0xFB, 0x00, 0x35, 0xC8, 0x96,
+ 0x41, 0xF4, 0xF6, 0x57, 0x16, 0xAD, 0x20, 0xCB, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x49,
+ 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38,
+ 0x31, 0x35, 0x31, 0x37, 0x33, 0x35, 0x35, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38, 0x31,
+ 0x35, 0x31, 0x37, 0x34, 0x35, 0x35, 0x30, 0x5A, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0C, 0x18, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73,
+ 0x69, 0x6E, 0x67, 0x4C, 0x65, 0x61, 0x66, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x30, 0x59, 0x30,
+ 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF6, 0xEA, 0x5E, 0x14, 0x20, 0x6D, 0x11, 0xC0,
+ 0xFD, 0xF9, 0xB9, 0xB5, 0x8F, 0xBB, 0x3E, 0x8B, 0xE8, 0x21, 0x21, 0x3A, 0xC2, 0xBA, 0x37, 0x24,
+ 0x61, 0x14, 0x7E, 0xA8, 0x86, 0x0A, 0x5C, 0xD3, 0x5F, 0xA8, 0xDC, 0x3A, 0x06, 0x30, 0x53, 0xFC,
+ 0x85, 0xBC, 0x60, 0x5C, 0x28, 0x07, 0xCA, 0x12, 0x40, 0xE8, 0x97, 0x6A, 0x63, 0x30, 0xF7, 0x37,
+ 0x25, 0x76, 0x4D, 0xA9, 0x1A, 0x8C, 0x36, 0xAA, 0xA3, 0x6A, 0x30, 0x68, 0x30, 0x0E, 0x06, 0x03,
+ 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x1D, 0x25, 0x04, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x4C, 0x09, 0x15, 0x01, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40, 0x3C, 0x3E, 0x9C,
+ 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14,
+ 0xE8, 0x47, 0x05, 0xA2, 0x59, 0xE9, 0x89, 0x81, 0xF4, 0xC8, 0x0D, 0x4C, 0x0A, 0xD3, 0xD4, 0xDE,
+ 0x9F, 0xA6, 0xC7, 0x79, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02,
+ 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x8C, 0x39, 0xC6, 0x6C, 0xD6, 0x8F, 0x20, 0xA5,
+ 0x85, 0x97, 0x27, 0xF9, 0xB5, 0x26, 0xA2, 0xAB, 0xEC, 0x2E, 0x1B, 0x6F, 0x6F, 0x79, 0x9F, 0x8D,
+ 0xCE, 0x9D, 0x12, 0x23, 0x5F, 0x04, 0xFA, 0xBE, 0x02, 0x21, 0x00, 0xC5, 0xD8, 0x49, 0xD1, 0x40,
+ 0xE3, 0x2C, 0xDF, 0xC3, 0xD4, 0x11, 0xF9, 0x5E, 0x10, 0x8A, 0x3C, 0x4E, 0xA0, 0xD6, 0x6B, 0x8C,
+ 0x0E, 0x7B, 0xF1, 0x2B, 0x20, 0x9C, 0x68, 0x53, 0x43, 0x4B, 0x35, 0x31, 0x81, 0xA3, 0x30, 0x81,
+ 0xA0, 0x02, 0x01, 0x01, 0x30, 0x36, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E,
+ 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x02, 0x10, 0x3E, 0xEE, 0x4B, 0xFB,
+ 0x00, 0x35, 0xC8, 0x96, 0x41, 0xF4, 0xF6, 0x57, 0x16, 0xAD, 0x20, 0xCB, 0x30, 0x0D, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x07, 0x2A,
+ 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x05, 0x00, 0x04, 0x47, 0x30, 0x45, 0x02, 0x21, 0x00, 0xB8,
+ 0xCC, 0x0F, 0xD2, 0x50, 0x47, 0x3A, 0x11, 0x8D, 0xAE, 0x6C, 0xE9, 0x03, 0x64, 0xA7, 0x44, 0xE6,
+ 0x0F, 0xF8, 0x6F, 0x7E, 0xE7, 0x61, 0x25, 0x8C, 0x67, 0xE8, 0xC2, 0xD6, 0x33, 0x91, 0x62, 0x02,
+ 0x20, 0x78, 0xF8, 0x94, 0x0F, 0x46, 0xD2, 0xE2, 0x2B, 0x33, 0xAF, 0xBD, 0x38, 0xA4, 0x43, 0xA6,
+ 0x6F, 0x8A, 0xBE, 0x26, 0xDC, 0xD0, 0x82, 0x01, 0x3D, 0x00, 0xF3, 0xC2, 0x07, 0x8A, 0xE8, 0xFD,
+ 0x18,
+};
+
+//
+// This is TestSignEKUsWith2CertsInSignature.bin.p7b in byte array format.
+// It has one EKU in it:
+// "1.3.6.1.4.1.311.76.9.21.1"
+//
+CONST UINT8 TestSignEKUsWith2CertsInSignature[] =
+{
+ 0x30, 0x82, 0x04, 0x61, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x03, 0x96, 0x30, 0x82, 0x01, 0xAE, 0x30, 0x82, 0x01,
+ 0x53, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3E, 0xEE, 0x4B, 0xFB, 0x00, 0x35, 0xC8, 0x96,
+ 0x41, 0xF4, 0xF6, 0x57, 0x16, 0xAD, 0x20, 0xCB, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x49,
+ 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38,
+ 0x31, 0x35, 0x31, 0x37, 0x33, 0x35, 0x35, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38, 0x31,
+ 0x35, 0x31, 0x37, 0x34, 0x35, 0x35, 0x30, 0x5A, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0C, 0x18, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73,
+ 0x69, 0x6E, 0x67, 0x4C, 0x65, 0x61, 0x66, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x30, 0x59, 0x30,
+ 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF6, 0xEA, 0x5E, 0x14, 0x20, 0x6D, 0x11, 0xC0,
+ 0xFD, 0xF9, 0xB9, 0xB5, 0x8F, 0xBB, 0x3E, 0x8B, 0xE8, 0x21, 0x21, 0x3A, 0xC2, 0xBA, 0x37, 0x24,
+ 0x61, 0x14, 0x7E, 0xA8, 0x86, 0x0A, 0x5C, 0xD3, 0x5F, 0xA8, 0xDC, 0x3A, 0x06, 0x30, 0x53, 0xFC,
+ 0x85, 0xBC, 0x60, 0x5C, 0x28, 0x07, 0xCA, 0x12, 0x40, 0xE8, 0x97, 0x6A, 0x63, 0x30, 0xF7, 0x37,
+ 0x25, 0x76, 0x4D, 0xA9, 0x1A, 0x8C, 0x36, 0xAA, 0xA3, 0x6A, 0x30, 0x68, 0x30, 0x0E, 0x06, 0x03,
+ 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x1D, 0x25, 0x04, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x4C, 0x09, 0x15, 0x01, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40, 0x3C, 0x3E, 0x9C,
+ 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14,
+ 0xE8, 0x47, 0x05, 0xA2, 0x59, 0xE9, 0x89, 0x81, 0xF4, 0xC8, 0x0D, 0x4C, 0x0A, 0xD3, 0xD4, 0xDE,
+ 0x9F, 0xA6, 0xC7, 0x79, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02,
+ 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x8C, 0x39, 0xC6, 0x6C, 0xD6, 0x8F, 0x20, 0xA5,
+ 0x85, 0x97, 0x27, 0xF9, 0xB5, 0x26, 0xA2, 0xAB, 0xEC, 0x2E, 0x1B, 0x6F, 0x6F, 0x79, 0x9F, 0x8D,
+ 0xCE, 0x9D, 0x12, 0x23, 0x5F, 0x04, 0xFA, 0xBE, 0x02, 0x21, 0x00, 0xC5, 0xD8, 0x49, 0xD1, 0x40,
+ 0xE3, 0x2C, 0xDF, 0xC3, 0xD4, 0x11, 0xF9, 0x5E, 0x10, 0x8A, 0x3C, 0x4E, 0xA0, 0xD6, 0x6B, 0x8C,
+ 0x0E, 0x7B, 0xF1, 0x2B, 0x20, 0x9C, 0x68, 0x53, 0x43, 0x4B, 0x35, 0x30, 0x82, 0x01, 0xE0, 0x30,
+ 0x82, 0x01, 0x65, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x79, 0x28, 0x1A, 0xE8, 0x7F, 0x21,
+ 0x4F, 0xBB, 0x47, 0x2F, 0x74, 0x75, 0xE6, 0x98, 0x60, 0xD6, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x21, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0C, 0x16, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E,
+ 0x67, 0x50, 0x6F, 0x6C, 0x69, 0x63, 0x79, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30,
+ 0x38, 0x31, 0x35, 0x31, 0x37, 0x33, 0x32, 0x35, 0x34, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38,
+ 0x31, 0x35, 0x31, 0x37, 0x34, 0x32, 0x35, 0x34, 0x5A, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72,
+ 0x73, 0x69, 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x30, 0x59, 0x30,
+ 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x66, 0x41, 0xE6, 0x86, 0x7D, 0x5B, 0x96, 0x6C,
+ 0x99, 0x2A, 0x82, 0x53, 0x58, 0xA3, 0x6F, 0x59, 0xFC, 0x1C, 0x9F, 0xEB, 0xBE, 0x9D, 0x53, 0xBA,
+ 0x50, 0x0F, 0x66, 0xBC, 0xE5, 0x90, 0x7E, 0xAA, 0xA2, 0x6C, 0xC2, 0xC9, 0xAA, 0x99, 0x0B, 0x04,
+ 0xA0, 0x6A, 0xB4, 0xC1, 0xF7, 0x55, 0x60, 0x58, 0xE3, 0xDE, 0x22, 0x57, 0xB1, 0x8A, 0x5C, 0xBC,
+ 0xDF, 0x22, 0x8A, 0x2B, 0x04, 0x7D, 0x7A, 0x6C, 0xA3, 0x7E, 0x30, 0x7C, 0x30, 0x0E, 0x06, 0x03,
+ 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x1D, 0x25, 0x04, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x4C, 0x09, 0x15, 0x01, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08,
+ 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04,
+ 0x18, 0x30, 0x16, 0x80, 0x14, 0x0B, 0x8A, 0xC7, 0xA8, 0x53, 0x07, 0x40, 0x74, 0x75, 0x0F, 0x85,
+ 0xCE, 0x5D, 0x5C, 0xC2, 0x23, 0x32, 0xC0, 0xFC, 0xC9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
+ 0x04, 0x16, 0x04, 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40,
+ 0x3C, 0x3E, 0x9C, 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xEE, 0x78, 0xDB, 0x74,
+ 0x56, 0xA3, 0xC2, 0x44, 0x25, 0x0F, 0xA1, 0x89, 0xC0, 0x76, 0xD1, 0xE4, 0xFE, 0xAA, 0xA4, 0xC3,
+ 0x7D, 0x40, 0xE3, 0x28, 0x1B, 0x0D, 0xAB, 0x32, 0x6B, 0x9A, 0x60, 0x37, 0x2F, 0xB6, 0xF4, 0xCB,
+ 0xEA, 0xC8, 0x65, 0xB6, 0xDC, 0x24, 0x90, 0x10, 0xFB, 0xD2, 0x42, 0x05, 0x02, 0x31, 0x00, 0x9E,
+ 0x91, 0xF9, 0x96, 0x8A, 0x41, 0x2C, 0x5E, 0x6B, 0xBC, 0x36, 0x05, 0x3B, 0x50, 0x11, 0x91, 0x9A,
+ 0xFA, 0x6B, 0x7F, 0x01, 0xF4, 0x6A, 0x7E, 0xCD, 0x98, 0x7E, 0x7D, 0xFD, 0xA8, 0xE3, 0xB2, 0x4F,
+ 0x71, 0x91, 0xF5, 0xE0, 0x82, 0xA5, 0xE7, 0x5A, 0xE8, 0x19, 0x09, 0xF6, 0x22, 0xBE, 0xC4, 0x31,
+ 0x81, 0xA3, 0x30, 0x81, 0xA0, 0x02, 0x01, 0x01, 0x30, 0x36, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61,
+ 0x72, 0x73, 0x69, 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x02, 0x10,
+ 0x3E, 0xEE, 0x4B, 0xFB, 0x00, 0x35, 0xC8, 0x96, 0x41, 0xF4, 0xF6, 0x57, 0x16, 0xAD, 0x20, 0xCB,
+ 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30,
+ 0x0B, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x05, 0x00, 0x04, 0x47, 0x30, 0x45,
+ 0x02, 0x20, 0x4A, 0xFD, 0xAE, 0xDD, 0x5D, 0xC5, 0x86, 0x48, 0xDC, 0xC1, 0xC3, 0xA7, 0xE6, 0x4E,
+ 0x7F, 0x8B, 0x7B, 0xAB, 0x2C, 0x60, 0xDD, 0x79, 0x4C, 0xF2, 0x45, 0xED, 0x7A, 0xA5, 0x24, 0xE6,
+ 0x0E, 0x60, 0x02, 0x21, 0x00, 0xAD, 0xCA, 0x3C, 0x29, 0x2F, 0xF9, 0xB1, 0x8E, 0x58, 0x29, 0x3F,
+ 0x97, 0x20, 0x03, 0x6A, 0x14, 0xDA, 0x83, 0x4A, 0x8F, 0x3E, 0x95, 0x37, 0xC3, 0xF0, 0x12, 0x2A,
+ 0x7B, 0x24, 0x59, 0x69, 0x27,
+};
+
+//
+// This is TestSignEKUsWith3CertsInSignature.bin.p7b
+// It has one EKU in it:
+// "1.3.6.1.4.1.311.76.9.21.1"
+//
+const UINT8 TestSignEKUsWith3CertsInSignature[] =
+{
+ 0x30, 0x82, 0x06, 0x65, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x05, 0x9B, 0x30, 0x82, 0x01, 0xAE, 0x30, 0x82, 0x01,
+ 0x53, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x3E, 0xEE, 0x4B, 0xFB, 0x00, 0x35, 0xC8, 0x96,
+ 0x41, 0xF4, 0xF6, 0x57, 0x16, 0xAD, 0x20, 0xCB, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x49,
+ 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38,
+ 0x31, 0x35, 0x31, 0x37, 0x33, 0x35, 0x35, 0x30, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38, 0x31,
+ 0x35, 0x31, 0x37, 0x34, 0x35, 0x35, 0x30, 0x5A, 0x30, 0x23, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0C, 0x18, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73,
+ 0x69, 0x6E, 0x67, 0x4C, 0x65, 0x61, 0x66, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x30, 0x59, 0x30,
+ 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xF6, 0xEA, 0x5E, 0x14, 0x20, 0x6D, 0x11, 0xC0,
+ 0xFD, 0xF9, 0xB9, 0xB5, 0x8F, 0xBB, 0x3E, 0x8B, 0xE8, 0x21, 0x21, 0x3A, 0xC2, 0xBA, 0x37, 0x24,
+ 0x61, 0x14, 0x7E, 0xA8, 0x86, 0x0A, 0x5C, 0xD3, 0x5F, 0xA8, 0xDC, 0x3A, 0x06, 0x30, 0x53, 0xFC,
+ 0x85, 0xBC, 0x60, 0x5C, 0x28, 0x07, 0xCA, 0x12, 0x40, 0xE8, 0x97, 0x6A, 0x63, 0x30, 0xF7, 0x37,
+ 0x25, 0x76, 0x4D, 0xA9, 0x1A, 0x8C, 0x36, 0xAA, 0xA3, 0x6A, 0x30, 0x68, 0x30, 0x0E, 0x06, 0x03,
+ 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x1D, 0x25, 0x04, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x4C, 0x09, 0x15, 0x01, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40, 0x3C, 0x3E, 0x9C,
+ 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14,
+ 0xE8, 0x47, 0x05, 0xA2, 0x59, 0xE9, 0x89, 0x81, 0xF4, 0xC8, 0x0D, 0x4C, 0x0A, 0xD3, 0xD4, 0xDE,
+ 0x9F, 0xA6, 0xC7, 0x79, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02,
+ 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0x8C, 0x39, 0xC6, 0x6C, 0xD6, 0x8F, 0x20, 0xA5,
+ 0x85, 0x97, 0x27, 0xF9, 0xB5, 0x26, 0xA2, 0xAB, 0xEC, 0x2E, 0x1B, 0x6F, 0x6F, 0x79, 0x9F, 0x8D,
+ 0xCE, 0x9D, 0x12, 0x23, 0x5F, 0x04, 0xFA, 0xBE, 0x02, 0x21, 0x00, 0xC5, 0xD8, 0x49, 0xD1, 0x40,
+ 0xE3, 0x2C, 0xDF, 0xC3, 0xD4, 0x11, 0xF9, 0x5E, 0x10, 0x8A, 0x3C, 0x4E, 0xA0, 0xD6, 0x6B, 0x8C,
+ 0x0E, 0x7B, 0xF1, 0x2B, 0x20, 0x9C, 0x68, 0x53, 0x43, 0x4B, 0x35, 0x30, 0x82, 0x01, 0xE0, 0x30,
+ 0x82, 0x01, 0x65, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x79, 0x28, 0x1A, 0xE8, 0x7F, 0x21,
+ 0x4F, 0xBB, 0x47, 0x2F, 0x74, 0x75, 0xE6, 0x98, 0x60, 0xD6, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86,
+ 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x21, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04,
+ 0x03, 0x0C, 0x16, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E,
+ 0x67, 0x50, 0x6F, 0x6C, 0x69, 0x63, 0x79, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30,
+ 0x38, 0x31, 0x35, 0x31, 0x37, 0x33, 0x32, 0x35, 0x34, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38,
+ 0x31, 0x35, 0x31, 0x37, 0x34, 0x32, 0x35, 0x34, 0x5A, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72,
+ 0x73, 0x69, 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x30, 0x59, 0x30,
+ 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x66, 0x41, 0xE6, 0x86, 0x7D, 0x5B, 0x96, 0x6C,
+ 0x99, 0x2A, 0x82, 0x53, 0x58, 0xA3, 0x6F, 0x59, 0xFC, 0x1C, 0x9F, 0xEB, 0xBE, 0x9D, 0x53, 0xBA,
+ 0x50, 0x0F, 0x66, 0xBC, 0xE5, 0x90, 0x7E, 0xAA, 0xA2, 0x6C, 0xC2, 0xC9, 0xAA, 0x99, 0x0B, 0x04,
+ 0xA0, 0x6A, 0xB4, 0xC1, 0xF7, 0x55, 0x60, 0x58, 0xE3, 0xDE, 0x22, 0x57, 0xB1, 0x8A, 0x5C, 0xBC,
+ 0xDF, 0x22, 0x8A, 0x2B, 0x04, 0x7D, 0x7A, 0x6C, 0xA3, 0x7E, 0x30, 0x7C, 0x30, 0x0E, 0x06, 0x03,
+ 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x16, 0x06, 0x03,
+ 0x55, 0x1D, 0x25, 0x04, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37,
+ 0x4C, 0x09, 0x15, 0x01, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08,
+ 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04,
+ 0x18, 0x30, 0x16, 0x80, 0x14, 0x0B, 0x8A, 0xC7, 0xA8, 0x53, 0x07, 0x40, 0x74, 0x75, 0x0F, 0x85,
+ 0xCE, 0x5D, 0x5C, 0xC2, 0x23, 0x32, 0xC0, 0xFC, 0xC9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E,
+ 0x04, 0x16, 0x04, 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40,
+ 0x3C, 0x3E, 0x9C, 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xEE, 0x78, 0xDB, 0x74,
+ 0x56, 0xA3, 0xC2, 0x44, 0x25, 0x0F, 0xA1, 0x89, 0xC0, 0x76, 0xD1, 0xE4, 0xFE, 0xAA, 0xA4, 0xC3,
+ 0x7D, 0x40, 0xE3, 0x28, 0x1B, 0x0D, 0xAB, 0x32, 0x6B, 0x9A, 0x60, 0x37, 0x2F, 0xB6, 0xF4, 0xCB,
+ 0xEA, 0xC8, 0x65, 0xB6, 0xDC, 0x24, 0x90, 0x10, 0xFB, 0xD2, 0x42, 0x05, 0x02, 0x31, 0x00, 0x9E,
+ 0x91, 0xF9, 0x96, 0x8A, 0x41, 0x2C, 0x5E, 0x6B, 0xBC, 0x36, 0x05, 0x3B, 0x50, 0x11, 0x91, 0x9A,
+ 0xFA, 0x6B, 0x7F, 0x01, 0xF4, 0x6A, 0x7E, 0xCD, 0x98, 0x7E, 0x7D, 0xFD, 0xA8, 0xE3, 0xB2, 0x4F,
+ 0x71, 0x91, 0xF5, 0xE0, 0x82, 0xA5, 0xE7, 0x5A, 0xE8, 0x19, 0x09, 0xF6, 0x22, 0xBE, 0xC4, 0x30,
+ 0x82, 0x02, 0x01, 0x30, 0x82, 0x01, 0x62, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x41, 0x02,
+ 0xBA, 0xF9, 0x87, 0x65, 0x6C, 0xB8, 0x4C, 0xD9, 0xA1, 0x04, 0x1C, 0x46, 0x4F, 0xE4, 0x30, 0x0A,
+ 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1D, 0x31, 0x1B, 0x30, 0x19,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x12, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61,
+ 0x72, 0x73, 0x69, 0x6E, 0x67, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30,
+ 0x38, 0x31, 0x35, 0x31, 0x37, 0x32, 0x39, 0x32, 0x39, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38,
+ 0x31, 0x35, 0x31, 0x37, 0x33, 0x39, 0x32, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x1F, 0x30, 0x1D, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0C, 0x16, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72,
+ 0x73, 0x69, 0x6E, 0x67, 0x50, 0x6F, 0x6C, 0x69, 0x63, 0x79, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10,
+ 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22,
+ 0x03, 0x62, 0x00, 0x04, 0xF9, 0xDC, 0xB9, 0x3F, 0xA8, 0xB5, 0x2B, 0x2E, 0xA7, 0xFC, 0x88, 0xC6,
+ 0xEF, 0x9C, 0x36, 0x61, 0x3E, 0xFF, 0x8A, 0x5A, 0x52, 0xFF, 0x5A, 0xD0, 0x2C, 0x08, 0xD6, 0x73,
+ 0x12, 0xF9, 0x62, 0x1E, 0x73, 0x76, 0x83, 0x49, 0xC8, 0xDE, 0xEB, 0x29, 0xA4, 0x78, 0x2A, 0xC1,
+ 0x30, 0x11, 0x0B, 0x2F, 0x38, 0x00, 0xB7, 0x6B, 0x6B, 0x8E, 0x8C, 0x4B, 0x33, 0x09, 0xF1, 0xEA,
+ 0xA4, 0x9E, 0x10, 0x4F, 0xC3, 0xBC, 0x30, 0x16, 0x1A, 0x8B, 0xD7, 0x9C, 0x14, 0x11, 0x4E, 0x56,
+ 0x64, 0x7E, 0x51, 0xE7, 0xDA, 0x26, 0x40, 0xB0, 0xD0, 0xF8, 0xF2, 0xB2, 0x5D, 0x8C, 0x8B, 0x49,
+ 0x0C, 0x4E, 0x58, 0xB0, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01,
+ 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01,
+ 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23,
+ 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x04, 0xA6, 0xCD, 0x4D, 0xAE, 0x9C, 0x17, 0xDB, 0xC8, 0x13,
+ 0x57, 0x2D, 0x72, 0x48, 0xAC, 0xBB, 0x6B, 0x1F, 0xFF, 0x61, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D,
+ 0x0E, 0x04, 0x16, 0x04, 0x14, 0x0B, 0x8A, 0xC7, 0xA8, 0x53, 0x07, 0x40, 0x74, 0x75, 0x0F, 0x85,
+ 0xCE, 0x5D, 0x5C, 0xC2, 0x23, 0x32, 0xC0, 0xFC, 0xC9, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48,
+ 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x81, 0x8C, 0x00, 0x30, 0x81, 0x88, 0x02, 0x42, 0x01, 0xB4,
+ 0x75, 0x0B, 0x2F, 0x2A, 0xAA, 0x77, 0x03, 0x08, 0xD9, 0x95, 0x13, 0x2C, 0xE8, 0x47, 0x69, 0x97,
+ 0xD1, 0x6B, 0xE0, 0x23, 0x94, 0xD5, 0x34, 0x8F, 0x80, 0x20, 0xE3, 0x72, 0x07, 0x7C, 0x6A, 0x52,
+ 0xE6, 0xF2, 0xC7, 0x85, 0xBD, 0xB6, 0x65, 0x8F, 0x61, 0x73, 0xF9, 0xE7, 0x3A, 0x31, 0x46, 0xC6,
+ 0xF2, 0xCE, 0xA7, 0x9E, 0xD0, 0xE2, 0xEF, 0x07, 0x59, 0xD0, 0xF1, 0xC4, 0xF6, 0x58, 0x9A, 0x16,
+ 0x02, 0x42, 0x00, 0x86, 0xE0, 0x25, 0xC1, 0x48, 0xD0, 0x33, 0x30, 0x55, 0xA8, 0x60, 0x44, 0xCA,
+ 0x47, 0x04, 0x93, 0x46, 0x81, 0xE9, 0x13, 0xE9, 0x67, 0x26, 0x23, 0x2A, 0xBD, 0xEF, 0xC4, 0xCC,
+ 0x12, 0x99, 0xB3, 0x9E, 0x3D, 0x78, 0xC8, 0x42, 0x06, 0x40, 0x48, 0xCA, 0x3D, 0xCC, 0xD7, 0xA2,
+ 0x35, 0x37, 0x76, 0x12, 0xDB, 0x9C, 0x90, 0xA4, 0xE4, 0x16, 0xAC, 0x5E, 0xD8, 0x04, 0xF1, 0x59,
+ 0x66, 0x85, 0xE2, 0x68, 0x31, 0x81, 0xA2, 0x30, 0x81, 0x9F, 0x02, 0x01, 0x01, 0x30, 0x36, 0x30,
+ 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74,
+ 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E,
+ 0x67, 0x43, 0x41, 0x02, 0x10, 0x3E, 0xEE, 0x4B, 0xFB, 0x00, 0x35, 0xC8, 0x96, 0x41, 0xF4, 0xF6,
+ 0x57, 0x16, 0xAD, 0x20, 0xCB, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
+ 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x05,
+ 0x00, 0x04, 0x46, 0x30, 0x44, 0x02, 0x20, 0x52, 0x90, 0x02, 0x9E, 0xE8, 0xBF, 0xE8, 0x7E, 0x05,
+ 0x3B, 0xA3, 0x93, 0xDD, 0x6C, 0x35, 0x31, 0xA3, 0x29, 0x4F, 0x9A, 0x78, 0xEF, 0xD1, 0xAD, 0x07,
+ 0x37, 0x2D, 0x9A, 0x81, 0xFD, 0x7D, 0xFC, 0x02, 0x20, 0x4C, 0x8A, 0xA4, 0xBD, 0x63, 0x7B, 0x8A,
+ 0x2C, 0x9E, 0xFC, 0x2A, 0x0F, 0x91, 0xF4, 0x97, 0xB5, 0x3B, 0xC9, 0xD1, 0xCA, 0xEB, 0x02, 0x6A,
+ 0xB6, 0xFF, 0xE1, 0x15, 0xF5, 0xA2, 0x11, 0xF4, 0xD9,
+};
+
+//
+// This signature was signed with a leaf that has no EKU's present in the certificate.
+//
+CONST UINT8 TestSignatureWithNoEKUsPresent[] =
+{
+ 0x30, 0x82, 0x07, 0xDB, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
+ 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0B, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
+ 0xF7, 0x0D, 0x01, 0x07, 0x01, 0xA0, 0x82, 0x06, 0x51, 0x30, 0x82, 0x01, 0xE0, 0x30, 0x82, 0x01,
+ 0x65, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x79, 0x28, 0x1A, 0xE8, 0x7F, 0x21, 0x4F, 0xBB,
+ 0x47, 0x2F, 0x74, 0x75, 0xE6, 0x98, 0x60, 0xD6, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE,
+ 0x3D, 0x04, 0x03, 0x02, 0x30, 0x21, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C,
+ 0x16, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x50,
+ 0x6F, 0x6C, 0x69, 0x63, 0x79, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38, 0x31,
+ 0x35, 0x31, 0x37, 0x33, 0x32, 0x35, 0x34, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38, 0x31, 0x35,
+ 0x31, 0x37, 0x34, 0x32, 0x35, 0x34, 0x5A, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69,
+ 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x30, 0x59, 0x30, 0x13, 0x06,
+ 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03,
+ 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x66, 0x41, 0xE6, 0x86, 0x7D, 0x5B, 0x96, 0x6C, 0x99, 0x2A,
+ 0x82, 0x53, 0x58, 0xA3, 0x6F, 0x59, 0xFC, 0x1C, 0x9F, 0xEB, 0xBE, 0x9D, 0x53, 0xBA, 0x50, 0x0F,
+ 0x66, 0xBC, 0xE5, 0x90, 0x7E, 0xAA, 0xA2, 0x6C, 0xC2, 0xC9, 0xAA, 0x99, 0x0B, 0x04, 0xA0, 0x6A,
+ 0xB4, 0xC1, 0xF7, 0x55, 0x60, 0x58, 0xE3, 0xDE, 0x22, 0x57, 0xB1, 0x8A, 0x5C, 0xBC, 0xDF, 0x22,
+ 0x8A, 0x2B, 0x04, 0x7D, 0x7A, 0x6C, 0xA3, 0x7E, 0x30, 0x7C, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D,
+ 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1D,
+ 0x25, 0x04, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x4C, 0x09,
+ 0x15, 0x01, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x08, 0x30, 0x06,
+ 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0x0B, 0x8A, 0xC7, 0xA8, 0x53, 0x07, 0x40, 0x74, 0x75, 0x0F, 0x85, 0xCE, 0x5D,
+ 0x5C, 0xC2, 0x23, 0x32, 0xC0, 0xFC, 0xC9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16,
+ 0x04, 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40, 0x3C, 0x3E,
+ 0x9C, 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04,
+ 0x03, 0x02, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xEE, 0x78, 0xDB, 0x74, 0x56, 0xA3,
+ 0xC2, 0x44, 0x25, 0x0F, 0xA1, 0x89, 0xC0, 0x76, 0xD1, 0xE4, 0xFE, 0xAA, 0xA4, 0xC3, 0x7D, 0x40,
+ 0xE3, 0x28, 0x1B, 0x0D, 0xAB, 0x32, 0x6B, 0x9A, 0x60, 0x37, 0x2F, 0xB6, 0xF4, 0xCB, 0xEA, 0xC8,
+ 0x65, 0xB6, 0xDC, 0x24, 0x90, 0x10, 0xFB, 0xD2, 0x42, 0x05, 0x02, 0x31, 0x00, 0x9E, 0x91, 0xF9,
+ 0x96, 0x8A, 0x41, 0x2C, 0x5E, 0x6B, 0xBC, 0x36, 0x05, 0x3B, 0x50, 0x11, 0x91, 0x9A, 0xFA, 0x6B,
+ 0x7F, 0x01, 0xF4, 0x6A, 0x7E, 0xCD, 0x98, 0x7E, 0x7D, 0xFD, 0xA8, 0xE3, 0xB2, 0x4F, 0x71, 0x91,
+ 0xF5, 0xE0, 0x82, 0xA5, 0xE7, 0x5A, 0xE8, 0x19, 0x09, 0xF6, 0x22, 0xBE, 0xC4, 0x30, 0x82, 0x02,
+ 0x01, 0x30, 0x82, 0x01, 0x62, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x41, 0x02, 0xBA, 0xF9,
+ 0x87, 0x65, 0x6C, 0xB8, 0x4C, 0xD9, 0xA1, 0x04, 0x1C, 0x46, 0x4F, 0xE4, 0x30, 0x0A, 0x06, 0x08,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x1D, 0x31, 0x1B, 0x30, 0x19, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x0C, 0x12, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73,
+ 0x69, 0x6E, 0x67, 0x52, 0x6F, 0x6F, 0x74, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38, 0x31,
+ 0x35, 0x31, 0x37, 0x32, 0x39, 0x32, 0x39, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38, 0x31, 0x35,
+ 0x31, 0x37, 0x33, 0x39, 0x32, 0x39, 0x5A, 0x30, 0x21, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0C, 0x16, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69,
+ 0x6E, 0x67, 0x50, 0x6F, 0x6C, 0x69, 0x63, 0x79, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
+ 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62,
+ 0x00, 0x04, 0xF9, 0xDC, 0xB9, 0x3F, 0xA8, 0xB5, 0x2B, 0x2E, 0xA7, 0xFC, 0x88, 0xC6, 0xEF, 0x9C,
+ 0x36, 0x61, 0x3E, 0xFF, 0x8A, 0x5A, 0x52, 0xFF, 0x5A, 0xD0, 0x2C, 0x08, 0xD6, 0x73, 0x12, 0xF9,
+ 0x62, 0x1E, 0x73, 0x76, 0x83, 0x49, 0xC8, 0xDE, 0xEB, 0x29, 0xA4, 0x78, 0x2A, 0xC1, 0x30, 0x11,
+ 0x0B, 0x2F, 0x38, 0x00, 0xB7, 0x6B, 0x6B, 0x8E, 0x8C, 0x4B, 0x33, 0x09, 0xF1, 0xEA, 0xA4, 0x9E,
+ 0x10, 0x4F, 0xC3, 0xBC, 0x30, 0x16, 0x1A, 0x8B, 0xD7, 0x9C, 0x14, 0x11, 0x4E, 0x56, 0x64, 0x7E,
+ 0x51, 0xE7, 0xDA, 0x26, 0x40, 0xB0, 0xD0, 0xF8, 0xF2, 0xB2, 0x5D, 0x8C, 0x8B, 0x49, 0x0C, 0x4E,
+ 0x58, 0xB0, 0xA3, 0x63, 0x30, 0x61, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF,
+ 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF,
+ 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18,
+ 0x30, 0x16, 0x80, 0x14, 0x04, 0xA6, 0xCD, 0x4D, 0xAE, 0x9C, 0x17, 0xDB, 0xC8, 0x13, 0x57, 0x2D,
+ 0x72, 0x48, 0xAC, 0xBB, 0x6B, 0x1F, 0xFF, 0x61, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04,
+ 0x16, 0x04, 0x14, 0x0B, 0x8A, 0xC7, 0xA8, 0x53, 0x07, 0x40, 0x74, 0x75, 0x0F, 0x85, 0xCE, 0x5D,
+ 0x5C, 0xC2, 0x23, 0x32, 0xC0, 0xFC, 0xC9, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
+ 0x04, 0x03, 0x02, 0x03, 0x81, 0x8C, 0x00, 0x30, 0x81, 0x88, 0x02, 0x42, 0x01, 0xB4, 0x75, 0x0B,
+ 0x2F, 0x2A, 0xAA, 0x77, 0x03, 0x08, 0xD9, 0x95, 0x13, 0x2C, 0xE8, 0x47, 0x69, 0x97, 0xD1, 0x6B,
+ 0xE0, 0x23, 0x94, 0xD5, 0x34, 0x8F, 0x80, 0x20, 0xE3, 0x72, 0x07, 0x7C, 0x6A, 0x52, 0xE6, 0xF2,
+ 0xC7, 0x85, 0xBD, 0xB6, 0x65, 0x8F, 0x61, 0x73, 0xF9, 0xE7, 0x3A, 0x31, 0x46, 0xC6, 0xF2, 0xCE,
+ 0xA7, 0x9E, 0xD0, 0xE2, 0xEF, 0x07, 0x59, 0xD0, 0xF1, 0xC4, 0xF6, 0x58, 0x9A, 0x16, 0x02, 0x42,
+ 0x00, 0x86, 0xE0, 0x25, 0xC1, 0x48, 0xD0, 0x33, 0x30, 0x55, 0xA8, 0x60, 0x44, 0xCA, 0x47, 0x04,
+ 0x93, 0x46, 0x81, 0xE9, 0x13, 0xE9, 0x67, 0x26, 0x23, 0x2A, 0xBD, 0xEF, 0xC4, 0xCC, 0x12, 0x99,
+ 0xB3, 0x9E, 0x3D, 0x78, 0xC8, 0x42, 0x06, 0x40, 0x48, 0xCA, 0x3D, 0xCC, 0xD7, 0xA2, 0x35, 0x37,
+ 0x76, 0x12, 0xDB, 0x9C, 0x90, 0xA4, 0xE4, 0x16, 0xAC, 0x5E, 0xD8, 0x04, 0xF1, 0x59, 0x66, 0x85,
+ 0xE2, 0x68, 0x30, 0x82, 0x02, 0x64, 0x30, 0x82, 0x02, 0x0A, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02,
+ 0x10, 0x2B, 0x7B, 0xDA, 0xCD, 0x87, 0xA0, 0xFD, 0x81, 0x49, 0x5E, 0x0E, 0xDD, 0x4F, 0x81, 0x48,
+ 0x2D, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31,
+ 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B,
+ 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43,
+ 0x41, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x38, 0x32, 0x33, 0x31, 0x39, 0x33, 0x30, 0x30,
+ 0x32, 0x5A, 0x17, 0x0D, 0x33, 0x38, 0x30, 0x38, 0x32, 0x33, 0x31, 0x39, 0x34, 0x30, 0x30, 0x32,
+ 0x5A, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x1C, 0x54, 0x65,
+ 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69, 0x6E, 0x67, 0x4E, 0x6F, 0x45, 0x4B,
+ 0x55, 0x73, 0x49, 0x6E, 0x53, 0x69, 0x67, 0x6E, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D,
+ 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA5, 0x9B, 0x95, 0xF0, 0x63,
+ 0x88, 0xC3, 0x74, 0x26, 0x08, 0x68, 0x25, 0xAA, 0x16, 0xBB, 0x2A, 0x15, 0xC1, 0xA2, 0xAF, 0x72,
+ 0x06, 0x51, 0x37, 0xE1, 0x4F, 0x6D, 0x6A, 0xFC, 0x17, 0xCE, 0x82, 0x7B, 0x79, 0xFF, 0x2A, 0x84,
+ 0x0F, 0xCB, 0xA9, 0x65, 0x70, 0xC9, 0xF9, 0xE7, 0x61, 0x90, 0x28, 0x03, 0x6E, 0x41, 0x25, 0xFF,
+ 0xC2, 0x3A, 0x60, 0x1A, 0x42, 0x37, 0x80, 0x9F, 0x6B, 0x99, 0x11, 0x5A, 0x1F, 0xAE, 0x7B, 0x3F,
+ 0xF3, 0x2B, 0x45, 0xDD, 0xDA, 0xC4, 0x32, 0xD7, 0xD8, 0xB5, 0x3D, 0x46, 0x0C, 0x8A, 0x11, 0xEE,
+ 0x94, 0x8C, 0xB5, 0x69, 0xD3, 0x91, 0x4F, 0x4E, 0xE5, 0xBB, 0x93, 0xDD, 0x1E, 0xA7, 0x20, 0x03,
+ 0xFD, 0xD6, 0x8F, 0x76, 0x91, 0x9A, 0x2B, 0x41, 0x91, 0xD8, 0x35, 0x7A, 0x0D, 0x80, 0xB9, 0xD4,
+ 0xD2, 0x56, 0xF1, 0xF9, 0xC5, 0xE6, 0xF2, 0xAE, 0x10, 0x7E, 0xD7, 0x6C, 0x40, 0x86, 0x37, 0x99,
+ 0x85, 0xF4, 0xCA, 0x1D, 0x6D, 0x90, 0x63, 0xF7, 0x63, 0xC6, 0x00, 0xA1, 0xA9, 0x79, 0x7D, 0x88,
+ 0x05, 0xA2, 0x92, 0x64, 0xA7, 0x8E, 0xA8, 0x9E, 0xC3, 0x1F, 0x63, 0xEE, 0x6C, 0xE3, 0x9B, 0xA6,
+ 0xD7, 0x9D, 0x9C, 0x9F, 0x0D, 0x7A, 0xF7, 0x00, 0x92, 0x16, 0xE8, 0x64, 0x36, 0x07, 0x66, 0x8E,
+ 0x6E, 0x51, 0x09, 0x3F, 0x2A, 0xD6, 0x6D, 0x4E, 0xCC, 0x49, 0xE1, 0xC3, 0x59, 0x63, 0xDC, 0x51,
+ 0xAA, 0xD1, 0xE7, 0x42, 0x2F, 0x72, 0x25, 0x46, 0x83, 0x7D, 0x23, 0xCE, 0xF7, 0x96, 0x2F, 0x04,
+ 0xE8, 0xAE, 0xF6, 0x19, 0x6D, 0x2D, 0xB2, 0x64, 0xDB, 0x69, 0x33, 0x96, 0x58, 0xA0, 0x6C, 0x77,
+ 0xF0, 0xD0, 0x5E, 0x36, 0xB1, 0x28, 0x89, 0x83, 0xB6, 0xA5, 0x13, 0x0E, 0x6B, 0x6E, 0x73, 0x2C,
+ 0x6F, 0xDA, 0xF9, 0x6C, 0x11, 0x4F, 0xCC, 0xF7, 0x89, 0x77, 0x83, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xA3, 0x52, 0x30, 0x50, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04,
+ 0x03, 0x02, 0x01, 0x86, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xA4, 0x21, 0xA5, 0x99, 0x40, 0x41, 0xF7, 0x1B, 0xFF, 0x35, 0xD0, 0x40, 0x3C, 0x3E, 0x9C,
+ 0x7C, 0xD1, 0xCC, 0xD1, 0xD1, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14,
+ 0xB6, 0xAF, 0x0D, 0xC1, 0xBE, 0xD1, 0xE4, 0x21, 0x37, 0xFF, 0xAC, 0x7D, 0x2D, 0xD4, 0x51, 0x8A,
+ 0x61, 0x95, 0x50, 0x7F, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02,
+ 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x74, 0x7D, 0xF5, 0xAF, 0xC3, 0xA7, 0x06, 0x99, 0x1F,
+ 0x2C, 0xAF, 0x69, 0xAA, 0x40, 0x97, 0xE9, 0xF8, 0x4C, 0xD2, 0x71, 0x17, 0x25, 0x85, 0xB7, 0xA6,
+ 0x97, 0x61, 0x89, 0x82, 0xED, 0xF0, 0xF6, 0x02, 0x21, 0x00, 0xA6, 0xF4, 0x59, 0x85, 0x53, 0x31,
+ 0xEF, 0x6F, 0x37, 0xB6, 0x8E, 0xA2, 0xDE, 0xC3, 0xFD, 0xD6, 0xFB, 0x50, 0x63, 0x4E, 0xB4, 0xBB,
+ 0xC1, 0xB1, 0x07, 0x82, 0x80, 0x14, 0x28, 0x6A, 0x94, 0x94, 0x31, 0x82, 0x01, 0x61, 0x30, 0x82,
+ 0x01, 0x5D, 0x02, 0x01, 0x01, 0x30, 0x36, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1E, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x0C, 0x17, 0x54, 0x65, 0x73, 0x74, 0x45, 0x4B, 0x55, 0x50, 0x61, 0x72, 0x73, 0x69,
+ 0x6E, 0x67, 0x49, 0x73, 0x73, 0x75, 0x69, 0x6E, 0x67, 0x43, 0x41, 0x02, 0x10, 0x2B, 0x7B, 0xDA,
+ 0xCD, 0x87, 0xA0, 0xFD, 0x81, 0x49, 0x5E, 0x0E, 0xDD, 0x4F, 0x81, 0x48, 0x2D, 0x30, 0x0D, 0x06,
+ 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x0D, 0x06, 0x09,
+ 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0x39,
+ 0xEC, 0xA8, 0x00, 0x4F, 0x7E, 0x2C, 0x3C, 0x48, 0xDF, 0x6F, 0x6A, 0x37, 0x69, 0xA4, 0xB1, 0xEB,
+ 0x7D, 0xD2, 0x3B, 0xC5, 0xEE, 0x57, 0x1F, 0x8F, 0xCA, 0x60, 0x80, 0x88, 0x24, 0x29, 0xB5, 0x00,
+ 0x28, 0xFF, 0x8F, 0x0A, 0x1E, 0xB0, 0x9E, 0x90, 0x09, 0xF1, 0x46, 0xC1, 0x53, 0xE8, 0x27, 0x29,
+ 0xFA, 0xFE, 0xA3, 0x84, 0x79, 0xB2, 0x27, 0x46, 0x9B, 0xD8, 0x33, 0xBD, 0x8F, 0x41, 0x06, 0xEE,
+ 0xD6, 0xE7, 0x49, 0xAF, 0x48, 0xD0, 0xD4, 0xF1, 0x06, 0xCC, 0xD3, 0x26, 0x47, 0xAE, 0x03, 0x7A,
+ 0xA5, 0xAF, 0xDE, 0x7F, 0x57, 0x32, 0x51, 0x49, 0x8C, 0x18, 0xD2, 0x4D, 0x50, 0x27, 0xAC, 0x7C,
+ 0x33, 0xB8, 0xB8, 0x1C, 0xF8, 0x0C, 0x49, 0xEB, 0xF5, 0xD7, 0xA0, 0x35, 0x77, 0x61, 0xC0, 0x60,
+ 0xAF, 0x23, 0x8C, 0xCC, 0xB0, 0x58, 0xB3, 0x08, 0x89, 0x2B, 0xC0, 0x61, 0x0C, 0xA6, 0x40, 0x7A,
+ 0x37, 0x6D, 0x6D, 0x44, 0xFF, 0xF1, 0xCE, 0xDE, 0x7A, 0x0C, 0xC4, 0x51, 0x61, 0xE6, 0x72, 0x6B,
+ 0xA9, 0x6A, 0x7B, 0xCF, 0xAA, 0x9A, 0x28, 0x74, 0x87, 0x30, 0xBA, 0xED, 0x40, 0xF0, 0x75, 0x2B,
+ 0xD7, 0xE6, 0x9F, 0xDD, 0x6B, 0xB7, 0xEA, 0x08, 0x0D, 0x9F, 0xA3, 0x25, 0x27, 0xB7, 0xBF, 0x41,
+ 0xC2, 0x64, 0xB5, 0x6F, 0x8F, 0xB1, 0x5F, 0xE5, 0xDF, 0xCA, 0x16, 0x04, 0x61, 0xFF, 0x74, 0x25,
+ 0xEE, 0xF6, 0x69, 0xF1, 0x7F, 0xE5, 0x97, 0x72, 0x58, 0xD8, 0x9F, 0xA5, 0x19, 0x32, 0x46, 0x95,
+ 0x67, 0x63, 0x23, 0x54, 0x46, 0x05, 0x15, 0xC3, 0x3E, 0x04, 0x7E, 0x88, 0xD0, 0xB5, 0x52, 0xF0,
+ 0x38, 0x3C, 0x8B, 0xD4, 0x3D, 0x9A, 0x55, 0x1B, 0x14, 0xE5, 0x37, 0x8D, 0xB7, 0x6C, 0x39, 0x91,
+ 0x23, 0x31, 0x63, 0x89, 0x7C, 0x75, 0x02, 0x79, 0xCC, 0x95, 0x58, 0x99, 0x3A, 0xDB, 0xF5,
+};
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c
new file mode 100644
index 00000000000..4e09c993cc1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/Pkcs7EkuTests.c
@@ -0,0 +1,524 @@
+/** @file -- Pkcs7EkuVerify.c
+ * Copyright (c) Microsoft Corporation.
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ This is an test code which verifies specified
+ Enhanced Key Usages (EKU)'s are present in the leaf signer
+ of a PKCS7 formatted signature.
+
+
+ A typical signing certificate chain looks like this: (Could be RSA or ECC).
+
+ ------------------------------------------
+ | | // Root of trust. ECDSA P521 curve
+ | TestEKUParsingRoot | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+ ------------------------------------------
+ ^
+ |
+ ------------------------------------------
+ | | // Policy CA. Issues subordinate CAs. ECC P384 curve.
+ | TestEKUParsingPolicyCA | // SHA 256 Key Usage:
+ | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+ ------------------------------------------
+ ^
+ |
+ ------------------------------------------
+ | | // Issues end-entity (leaf) signers. ECC P256 curve.
+ | TestEKUParsingIssuingCA | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ | | // Enhanced Key Usage:
+ ------------------------------------------ // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+ ^
+ |
+ --------------------------------------
+ / TestEKUParsingLeafSigner && / // Leaf signer, ECC P256 curve.
+ / TestEKUParsingLeafSignerPid12345 / // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ / / // Enhanced Key usages:
+ -------------------------------------- // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+ // 1.3.6.1.4.1.311.76.9.21.1.N, N == Product ID.
+
+
+
+
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+#include "Pkcs7EkuTestSignatures.h"
+
+EFI_STATUS
+EFIAPI
+VerifyEKUsInPkcs7Signature (
+ IN CONST UINT8 *Pkcs7Signature,
+ IN CONST UINT32 SignatureSize,
+ IN CONST CHAR8 *RequiredEKUs[],
+ IN CONST UINT32 RequiredEKUsSize,
+ IN BOOLEAN RequireAllPresent
+ );
+
+///================================================================================================
+///================================================================================================
+///
+/// TEST CASES
+///
+///================================================================================================
+///================================================================================================
+
+CONST CHAR8 FIRMWARE_SIGNER_EKU[] = "1.3.6.1.4.1.311.76.9.21.1";
+
+
+/**
+ TestVerifyEKUsInSignature()
+
+ Verify that "1.3.6.1.4.1.311.76.9.21.1" (Firmware signature) is in the
+ leaf signer certificate.
+
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(ProductionECCSignature,
+ ARRAY_SIZE(ProductionECCSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsInSignature()
+
+
+/**
+ TestVerifyEKUsWith3CertsInSignature()
+
+ This PKCS7 signature has 3 certificates in it. (Policy CA, Issuing CA
+ and leaf signer). It has one firmware signing EKU in it.
+ "1.3.6.1.4.1.311.76.9.21.1"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWith3CertsInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignEKUsWith3CertsInSignature,
+ ARRAY_SIZE(TestSignEKUsWith3CertsInSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWith3CertsInSignature()
+
+/**
+ TestVerifyEKUsWith2CertsInSignature()
+
+ This PKCS7 signature has 2 certificates in it. (Issuing CA and leaf signer).
+ It has one firmware signing EKU in it. "1.3.6.1.4.1.311.76.9.21.1"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWith2CertsInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignEKUsWith2CertsInSignature,
+ ARRAY_SIZE(TestSignEKUsWith2CertsInSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWith2CertsInSignature()
+
+
+/**
+ TestVerifyEKUsWith1CertInSignature()
+
+ This PKCS7 signature only has the leaf signer in it.
+ It has one firmware signing EKU in it. "1.3.6.1.4.1.311.76.9.21.1"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWith1CertInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { FIRMWARE_SIGNER_EKU };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignEKUsWith1CertInSignature,
+ ARRAY_SIZE(TestSignEKUsWith1CertInSignature),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWith1CertInSignature()
+
+
+/**
+ TestVerifyEKUsWithMultipleEKUsInCert()
+
+
+ This signature has two EKU's in it:
+ "1.3.6.1.4.1.311.76.9.21.1"
+ "1.3.6.1.4.1.311.76.9.21.2"
+ We verify that both EKU's were present in the leaf signer.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyEKUsWithMultipleEKUsInCert (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1",
+ "1.3.6.1.4.1.311.76.9.21.1.2" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithMultipleEKUsInCert,
+ ARRAY_SIZE(TestSignedWithMultipleEKUsInCert),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestVerifyEKUsWithMultipleEKUsInCert()
+
+
+/**
+ TestEkusNotPresentInSignature()
+
+ This test verifies that if we send an EKU that is not in the signature,
+ that we get back an error.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestEkusNotPresentInSignature (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This EKU is not in the signature.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.3" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithMultipleEKUsInCert,
+ ARRAY_SIZE(TestSignedWithMultipleEKUsInCert),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestEkusNotPresentInSignature()
+
+/**
+ TestEkusNotPresentInSignature()
+
+ This test signature has two EKU's in it: (Product ID is 10001)
+ "1.3.6.1.4.1.311.76.9.21.1"
+ "1.3.6.1.4.1.311.76.9.21.1.10001"
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestProductId10001PresentInSignature(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // These EKU's are present in the leaf signer certificate.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1",
+ "1.3.6.1.4.1.311.76.9.21.1.10001" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestProductId10001PresentInSignature()
+
+
+/**
+ TestOnlyOneEkuInListRequired()
+
+ This test will check the BOOLEAN RequireAllPresent parameter in the
+ call to VerifyEKUsInPkcs7Signature() behaves properly. The signature
+ has two EKU's in it:
+
+ "1.3.6.1.4.1.311.76.9.21.1"
+ "1.3.6.1.4.1.311.76.9.21.1.10001"
+
+ but we only pass in one of them, and set RequireAllPresent to FALSE.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestOnlyOneEkuInListRequired(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This will test the flag that specifies it is OK to succeed if
+ // any one of the EKU's passed in is found.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1.10001" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ FALSE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestOnlyOneEkuInListRequired()
+
+/**
+ TestNoEKUsInSignature()
+
+ This test uses a signature that was signed with a certificate that does
+ not contain any EKUs.
+
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestNoEKUsInSignature(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This EKU is not in the certificate, so it should fail.
+ //
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignatureWithNoEKUsPresent,
+ ARRAY_SIZE(TestSignatureWithNoEKUsPresent),
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestNoEKUsInSignature()
+
+
+/**
+ TestInvalidParameters()
+
+ Passes the API invalid parameters, and ensures that it does not succeed.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestInvalidParameters(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ CONST CHAR8* RequiredEKUs[] = { "1.3.6.1.4.1.311.76.9.21.1" };
+
+ //
+ // Check bad signature.
+ //
+ Status = VerifyEKUsInPkcs7Signature(NULL,
+ 0,
+ (CONST CHAR8**)RequiredEKUs,
+ ARRAY_SIZE(RequiredEKUs),
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ //
+ // Check invalid EKU's
+ //
+ Status = VerifyEKUsInPkcs7Signature(TestSignatureWithNoEKUsPresent,
+ ARRAY_SIZE(TestSignatureWithNoEKUsPresent),
+ (CONST CHAR8**)NULL,
+ 0,
+ TRUE);
+ UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER);
+
+ return UNIT_TEST_PASSED;
+}// TestInvalidParameters()
+
+
+/**
+ TestEKUSubStringFails()
+
+ Pass the API a sub set and super set of an EKU and ensure that they
+ don't pass.
+
+ @param[in] Framework - Unit-test framework handle.
+ @param[in] Context - Optional context pointer for this test.
+
+ @retval UNIT_TEST_PASSED - The required EKUs were found in the signature.
+ @retval UNIT_TEST_ERROR_TEST_FAILED - Something failed, check the debug output.
+**/
+static
+UNIT_TEST_STATUS
+EFIAPI
+TestEKUSubsetSupersetFails(
+ IN UNIT_TEST_CONTEXT Context
+)
+{
+ EFI_STATUS Status = EFI_SUCCESS;
+
+ //
+ // This signature has an EKU of:
+ // "1.3.6.1.4.1.311.76.9.21.1.10001"
+ // so ensure that
+ // "1.3.6.1.4.1.311.76.9.21"
+ // does not pass.
+ //
+ CONST CHAR8* RequiredEKUs1[] = { "1.3.6.1.4.1.311.76.9.21" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs1,
+ ARRAY_SIZE(RequiredEKUs1),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ //
+ // This signature has an EKU of:
+ // "1.3.6.1.4.1.311.76.9.21.1.10001"
+ // so ensure that a super set
+ // "1.3.6.1.4.1.311.76.9.21.1.10001.1"
+ // does not pass.
+ //
+ CONST CHAR8* RequiredEKUs2[] = { "1.3.6.1.4.1.311.76.9.21.1.10001.1" };
+
+ Status = VerifyEKUsInPkcs7Signature(TestSignedWithProductId10001,
+ ARRAY_SIZE(TestSignedWithProductId10001),
+ (CONST CHAR8**)RequiredEKUs2,
+ ARRAY_SIZE(RequiredEKUs2),
+ TRUE);
+ UT_ASSERT_NOT_EQUAL (Status, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}// TestEKUSubsetSupersetFails()
+
+TEST_DESC mPkcs7EkuTest[] = {
+ //
+ // -----Description--------------------------------Class----------------------------Function------------------------------Pre---Post--Context
+ //
+ {"TestVerifyEKUsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWith3CertsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWith3CertsInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWith2CertsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWith2CertsInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWith1CertInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWith1CertInSignature, NULL, NULL, NULL},
+ {"TestVerifyEKUsWithMultipleEKUsInCert()", "CryptoPkg.BaseCryptLib.Eku", TestVerifyEKUsWithMultipleEKUsInCert, NULL, NULL, NULL},
+ {"TestEkusNotPresentInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestEkusNotPresentInSignature, NULL, NULL, NULL},
+ {"TestProductId10001PresentInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestProductId10001PresentInSignature, NULL, NULL, NULL},
+ {"TestOnlyOneEkuInListRequired()", "CryptoPkg.BaseCryptLib.Eku", TestOnlyOneEkuInListRequired, NULL, NULL, NULL},
+ {"TestNoEKUsInSignature()", "CryptoPkg.BaseCryptLib.Eku", TestNoEKUsInSignature, NULL, NULL, NULL},
+ {"TestInvalidParameters()", "CryptoPkg.BaseCryptLib.Eku", TestInvalidParameters, NULL, NULL, NULL},
+ {"TestEKUSubsetSupersetFails()", "CryptoPkg.BaseCryptLib.Eku", TestEKUSubsetSupersetFails, NULL, NULL, NULL},
+};
+
+UINTN mPkcs7EkuTestNum = ARRAY_SIZE(mPkcs7EkuTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RandTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RandTests.c
new file mode 100644
index 00000000000..053436124ee
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RandTests.c
@@ -0,0 +1,51 @@
+/** @file
+ Application for Pseudorandom Number Generator Validation.
+
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+#define RANDOM_NUMBER_SIZE 256
+
+CONST UINT8 SeedString[] = "This is the random seed for PRNG verification.";
+
+UINT8 PreviousRandomBuffer[RANDOM_NUMBER_SIZE] = { 0x0 };
+
+UINT8 RandomBuffer[RANDOM_NUMBER_SIZE] = { 0x0 };
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyPrngGeneration (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ UINTN Index;
+ BOOLEAN Status;
+
+ Status = RandomSeed (SeedString, sizeof (SeedString));
+ UT_ASSERT_TRUE (Status);
+
+ for (Index = 0; Index < 10; Index ++) {
+ Status = RandomBytes (RandomBuffer, RANDOM_NUMBER_SIZE);
+ UT_ASSERT_TRUE (Status);
+
+ Status = (CompareMem (PreviousRandomBuffer, RandomBuffer, RANDOM_NUMBER_SIZE) == 0);
+ UT_ASSERT_FALSE (Status);
+
+ CopyMem (PreviousRandomBuffer, RandomBuffer, RANDOM_NUMBER_SIZE);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mPrngTest[] = {
+ //
+ // -----Description--------------------------------Class--------------------Function----------------Pre---Post--Context
+ //
+ {"TestVerifyPrngGeneration()", "CryptoPkg.BaseCryptLib.Prng", TestVerifyPrngGeneration, NULL, NULL, NULL},
+};
+
+UINTN mPrngTestNum = ARRAY_SIZE(mPrngTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPkcs7Tests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPkcs7Tests.c
new file mode 100644
index 00000000000..fc3bbfa4daf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPkcs7Tests.c
@@ -0,0 +1,415 @@
+/** @file
+ Application for RSA Key Retrieving (from PEM and X509) & Signature Validation.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+
+//
+// Password-protected PEM Key data for RSA Private Key Retrieving (encryption key is "client").
+// (Generated by OpenSSL utility).
+// $ openssl genrsa -aes256 -out TestKeyPem -passout pass:client 1024
+// password should match PemPass in this file
+// $ xxd --include TestKeyPem
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TestKeyPem[] = {
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x42, 0x45, 0x47, 0x49, 0x4e, 0x20, 0x52,
+ 0x53, 0x41, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b,
+ 0x45, 0x59, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a, 0x50, 0x72, 0x6f, 0x63,
+ 0x2d, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x34, 0x2c, 0x45, 0x4e, 0x43,
+ 0x52, 0x59, 0x50, 0x54, 0x45, 0x44, 0x0a, 0x44, 0x45, 0x4b, 0x2d, 0x49,
+ 0x6e, 0x66, 0x6f, 0x3a, 0x20, 0x41, 0x45, 0x53, 0x2d, 0x32, 0x35, 0x36,
+ 0x2d, 0x43, 0x42, 0x43, 0x2c, 0x34, 0x42, 0x44, 0x31, 0x30, 0x45, 0x39,
+ 0x35, 0x42, 0x38, 0x33, 0x39, 0x42, 0x30, 0x44, 0x33, 0x35, 0x36, 0x31,
+ 0x38, 0x41, 0x44, 0x36, 0x45, 0x46, 0x44, 0x36, 0x34, 0x32, 0x34, 0x44,
+ 0x36, 0x0a, 0x0a, 0x42, 0x50, 0x39, 0x49, 0x32, 0x42, 0x30, 0x6c, 0x50,
+ 0x7a, 0x4c, 0x50, 0x50, 0x38, 0x2f, 0x4b, 0x71, 0x35, 0x34, 0x2f, 0x56,
+ 0x68, 0x75, 0x4b, 0x35, 0x5a, 0x63, 0x72, 0x32, 0x55, 0x6c, 0x32, 0x75,
+ 0x43, 0x57, 0x4a, 0x62, 0x59, 0x33, 0x50, 0x77, 0x39, 0x6e, 0x4c, 0x6d,
+ 0x45, 0x41, 0x6a, 0x47, 0x74, 0x4a, 0x68, 0x57, 0x46, 0x66, 0x50, 0x47,
+ 0x38, 0x62, 0x6d, 0x41, 0x6f, 0x73, 0x56, 0x0a, 0x47, 0x76, 0x42, 0x30,
+ 0x6d, 0x2b, 0x7a, 0x5a, 0x43, 0x2b, 0x30, 0x6c, 0x57, 0x6c, 0x72, 0x59,
+ 0x7a, 0x51, 0x4b, 0x6a, 0x57, 0x79, 0x44, 0x6e, 0x4d, 0x58, 0x72, 0x33,
+ 0x51, 0x39, 0x69, 0x57, 0x32, 0x4b, 0x33, 0x68, 0x4d, 0x6b, 0x71, 0x51,
+ 0x4c, 0x31, 0x68, 0x65, 0x71, 0x52, 0x66, 0x66, 0x74, 0x47, 0x57, 0x51,
+ 0x5a, 0x36, 0x78, 0x4e, 0x6a, 0x72, 0x30, 0x7a, 0x6f, 0x51, 0x59, 0x73,
+ 0x0a, 0x34, 0x76, 0x69, 0x55, 0x46, 0x72, 0x7a, 0x2b, 0x52, 0x76, 0x4b,
+ 0x43, 0x2f, 0x33, 0x69, 0x71, 0x57, 0x59, 0x78, 0x55, 0x35, 0x4c, 0x6a,
+ 0x45, 0x74, 0x63, 0x5a, 0x4f, 0x2b, 0x53, 0x6d, 0x39, 0x42, 0x4c, 0x62,
+ 0x66, 0x58, 0x49, 0x71, 0x56, 0x72, 0x53, 0x6a, 0x54, 0x79, 0x58, 0x49,
+ 0x39, 0x70, 0x76, 0x78, 0x6f, 0x67, 0x50, 0x39, 0x38, 0x6b, 0x2b, 0x6c,
+ 0x41, 0x66, 0x37, 0x47, 0x36, 0x0a, 0x75, 0x39, 0x2b, 0x30, 0x31, 0x4d,
+ 0x47, 0x5a, 0x69, 0x36, 0x6b, 0x53, 0x73, 0x67, 0x48, 0x57, 0x7a, 0x43,
+ 0x41, 0x49, 0x51, 0x75, 0x38, 0x72, 0x6a, 0x4d, 0x34, 0x65, 0x74, 0x64,
+ 0x50, 0x62, 0x4a, 0x49, 0x77, 0x34, 0x65, 0x47, 0x6f, 0x32, 0x45, 0x49,
+ 0x44, 0x45, 0x54, 0x61, 0x52, 0x70, 0x73, 0x76, 0x47, 0x6a, 0x54, 0x6f,
+ 0x30, 0x51, 0x56, 0x69, 0x79, 0x79, 0x4a, 0x4f, 0x48, 0x32, 0x0a, 0x61,
+ 0x32, 0x71, 0x69, 0x2f, 0x47, 0x7a, 0x2f, 0x64, 0x48, 0x61, 0x62, 0x68,
+ 0x4d, 0x4e, 0x35, 0x4e, 0x53, 0x58, 0x56, 0x4d, 0x31, 0x54, 0x2f, 0x6d,
+ 0x69, 0x6f, 0x74, 0x68, 0x78, 0x59, 0x72, 0x2f, 0x4a, 0x69, 0x37, 0x6d,
+ 0x4e, 0x45, 0x75, 0x4a, 0x57, 0x38, 0x74, 0x6d, 0x75, 0x55, 0x4b, 0x58,
+ 0x33, 0x66, 0x63, 0x39, 0x42, 0x39, 0x32, 0x51, 0x6e, 0x54, 0x68, 0x43,
+ 0x69, 0x49, 0x2f, 0x0a, 0x79, 0x4f, 0x31, 0x32, 0x4c, 0x46, 0x58, 0x38,
+ 0x74, 0x4b, 0x4a, 0x37, 0x4b, 0x7a, 0x6f, 0x6b, 0x36, 0x44, 0x74, 0x6d,
+ 0x35, 0x73, 0x41, 0x74, 0x2b, 0x65, 0x4b, 0x76, 0x6f, 0x61, 0x47, 0x62,
+ 0x75, 0x4a, 0x78, 0x62, 0x52, 0x63, 0x36, 0x63, 0x4d, 0x58, 0x57, 0x46,
+ 0x36, 0x4d, 0x72, 0x4d, 0x30, 0x53, 0x78, 0x65, 0x4e, 0x6b, 0x5a, 0x77,
+ 0x5a, 0x36, 0x6c, 0x62, 0x4d, 0x39, 0x63, 0x55, 0x0a, 0x6c, 0x75, 0x34,
+ 0x4c, 0x56, 0x64, 0x34, 0x73, 0x56, 0x4c, 0x61, 0x76, 0x68, 0x75, 0x32,
+ 0x58, 0x48, 0x48, 0x53, 0x56, 0x30, 0x32, 0x32, 0x6d, 0x51, 0x72, 0x73,
+ 0x32, 0x69, 0x68, 0x74, 0x58, 0x44, 0x2b, 0x6c, 0x4d, 0x63, 0x2f, 0x35,
+ 0x62, 0x54, 0x41, 0x55, 0x6b, 0x4b, 0x4f, 0x42, 0x73, 0x43, 0x69, 0x4f,
+ 0x4b, 0x42, 0x56, 0x2b, 0x66, 0x70, 0x49, 0x62, 0x2b, 0x6d, 0x44, 0x33,
+ 0x58, 0x0a, 0x39, 0x37, 0x66, 0x36, 0x54, 0x66, 0x68, 0x37, 0x4f, 0x4f,
+ 0x6a, 0x74, 0x44, 0x79, 0x31, 0x6f, 0x52, 0x36, 0x70, 0x68, 0x48, 0x47,
+ 0x6e, 0x73, 0x43, 0x78, 0x72, 0x53, 0x72, 0x64, 0x48, 0x73, 0x2f, 0x34,
+ 0x33, 0x72, 0x61, 0x65, 0x42, 0x78, 0x59, 0x45, 0x41, 0x42, 0x4e, 0x59,
+ 0x68, 0x54, 0x47, 0x57, 0x49, 0x4d, 0x4a, 0x6b, 0x50, 0x63, 0x54, 0x53,
+ 0x73, 0x76, 0x77, 0x46, 0x37, 0x6d, 0x0a, 0x33, 0x6c, 0x38, 0x6b, 0x44,
+ 0x50, 0x48, 0x43, 0x4e, 0x68, 0x6e, 0x6e, 0x42, 0x69, 0x7a, 0x36, 0x2f,
+ 0x43, 0x38, 0x56, 0x31, 0x37, 0x78, 0x57, 0x34, 0x50, 0x2b, 0x79, 0x71,
+ 0x4a, 0x78, 0x58, 0x63, 0x49, 0x53, 0x72, 0x7a, 0x57, 0x53, 0x55, 0x72,
+ 0x34, 0x74, 0x71, 0x6b, 0x55, 0x58, 0x43, 0x57, 0x4c, 0x43, 0x66, 0x76,
+ 0x57, 0x7a, 0x4e, 0x65, 0x5a, 0x34, 0x4f, 0x34, 0x34, 0x54, 0x65, 0x0a,
+ 0x74, 0x31, 0x59, 0x65, 0x36, 0x77, 0x2b, 0x71, 0x4f, 0x55, 0x38, 0x50,
+ 0x42, 0x68, 0x72, 0x65, 0x4d, 0x38, 0x75, 0x32, 0x32, 0x42, 0x4f, 0x31,
+ 0x65, 0x2b, 0x44, 0x7a, 0x63, 0x74, 0x6c, 0x67, 0x43, 0x43, 0x6c, 0x38,
+ 0x79, 0x69, 0x37, 0x6f, 0x43, 0x56, 0x74, 0x66, 0x75, 0x59, 0x2f, 0x4c,
+ 0x72, 0x42, 0x61, 0x31, 0x74, 0x69, 0x43, 0x41, 0x37, 0x6c, 0x34, 0x75,
+ 0x58, 0x6b, 0x73, 0x4c, 0x0a, 0x2b, 0x31, 0x51, 0x79, 0x69, 0x4b, 0x31,
+ 0x6e, 0x43, 0x4f, 0x76, 0x74, 0x30, 0x46, 0x7a, 0x71, 0x62, 0x71, 0x78,
+ 0x54, 0x37, 0x53, 0x35, 0x4c, 0x56, 0x33, 0x5a, 0x33, 0x74, 0x34, 0x4a,
+ 0x46, 0x4f, 0x50, 0x62, 0x67, 0x63, 0x7a, 0x4e, 0x6b, 0x58, 0x55, 0x2b,
+ 0x4f, 0x74, 0x50, 0x6b, 0x6e, 0x45, 0x45, 0x76, 0x67, 0x57, 0x64, 0x76,
+ 0x31, 0x4f, 0x30, 0x6d, 0x52, 0x4a, 0x50, 0x31, 0x4e, 0x0a, 0x71, 0x43,
+ 0x32, 0x33, 0x4a, 0x6a, 0x36, 0x38, 0x4c, 0x30, 0x46, 0x63, 0x46, 0x4c,
+ 0x56, 0x56, 0x59, 0x76, 0x61, 0x44, 0x53, 0x76, 0x54, 0x45, 0x64, 0x50,
+ 0x54, 0x34, 0x62, 0x2f, 0x7a, 0x66, 0x64, 0x36, 0x51, 0x52, 0x6b, 0x38,
+ 0x70, 0x4d, 0x36, 0x77, 0x66, 0x61, 0x32, 0x50, 0x63, 0x75, 0x57, 0x65,
+ 0x79, 0x38, 0x48, 0x38, 0x76, 0x4e, 0x4b, 0x67, 0x2f, 0x65, 0x76, 0x34,
+ 0x77, 0x37, 0x0a, 0x6b, 0x6f, 0x6f, 0x4e, 0x59, 0x64, 0x77, 0x59, 0x69,
+ 0x6c, 0x37, 0x41, 0x50, 0x76, 0x42, 0x50, 0x4d, 0x63, 0x6c, 0x51, 0x76,
+ 0x63, 0x64, 0x71, 0x7a, 0x52, 0x7a, 0x4a, 0x6e, 0x4a, 0x74, 0x37, 0x70,
+ 0x35, 0x7a, 0x69, 0x2b, 0x2b, 0x4c, 0x43, 0x59, 0x55, 0x4d, 0x3d, 0x0a,
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x45, 0x4e, 0x44, 0x20, 0x52, 0x53, 0x41,
+ 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4b, 0x45, 0x59,
+ 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x0a
+ };
+
+//
+// Password for private key retrieving from encrypted PEM ("TestKeyPem").
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *PemPass = "client";
+
+//
+// Test CA X509 Certificate for X509 Verification Routine (Generated by OpenSSL utility).
+// $ openssl req -x509 -days 10000 -key TestKeyPem -out TestCACert -outform DER -subj "/C=US/ST=WA/L=Seattle/O=Tianocore/OU=EDK2/CN=UEFI"
+// use password from PemPass variable in this file
+// $ xxd --include TestCACert
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TestCACert[] = {
+ 0x30, 0x82, 0x02, 0x98, 0x30, 0x82, 0x02, 0x01, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x14, 0x39, 0xde, 0x9e, 0xce, 0x3a, 0x36, 0x11, 0x38, 0x6f,
+ 0x64, 0xb4, 0x69, 0xa7, 0x93, 0xdd, 0xff, 0xbd, 0x3e, 0x75, 0x6a, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+ 0x05, 0x00, 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65,
+ 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x54,
+ 0x69, 0x61, 0x6e, 0x6f, 0x63, 0x6f, 0x72, 0x65, 0x31, 0x0d, 0x30, 0x0b,
+ 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x45, 0x44, 0x4b, 0x32, 0x31,
+ 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04, 0x55, 0x45,
+ 0x46, 0x49, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x36, 0x32, 0x39,
+ 0x32, 0x32, 0x34, 0x37, 0x33, 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x37, 0x31,
+ 0x31, 0x31, 0x35, 0x32, 0x32, 0x34, 0x37, 0x33, 0x36, 0x5a, 0x30, 0x5e,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x02,
+ 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c,
+ 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x12, 0x30, 0x10,
+ 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x54, 0x69, 0x61, 0x6e, 0x6f,
+ 0x63, 0x6f, 0x72, 0x65, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x0c, 0x04, 0x45, 0x44, 0x4b, 0x32, 0x31, 0x0d, 0x30, 0x0b, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04, 0x55, 0x45, 0x46, 0x49, 0x30, 0x81,
+ 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02,
+ 0x81, 0x81, 0x00, 0x9f, 0xef, 0x1b, 0x46, 0x45, 0x55, 0x33, 0x4b, 0xee,
+ 0x95, 0x14, 0xd3, 0x5a, 0x3e, 0xd9, 0x29, 0xfb, 0xd9, 0x29, 0x4e, 0x8b,
+ 0xf1, 0xf5, 0x68, 0x7c, 0x58, 0x86, 0x0c, 0xda, 0xd7, 0xe0, 0xd2, 0x9a,
+ 0xe8, 0x37, 0x16, 0x4d, 0x54, 0x92, 0x18, 0x20, 0x4c, 0x09, 0xa1, 0xcf,
+ 0xe1, 0xaa, 0x7a, 0x5a, 0x64, 0x7e, 0x5c, 0xeb, 0x4e, 0x15, 0x8e, 0x40,
+ 0xd1, 0xcb, 0x7d, 0x01, 0x71, 0x15, 0x11, 0xd2, 0xc7, 0xdb, 0x6b, 0x00,
+ 0xdc, 0x02, 0xcb, 0x5a, 0x6d, 0x2b, 0x2a, 0x75, 0xb6, 0x3f, 0xec, 0xc1,
+ 0x9d, 0xbf, 0xda, 0xe5, 0x3a, 0x77, 0x4b, 0x21, 0x1c, 0x99, 0x42, 0x84,
+ 0x5e, 0x27, 0x53, 0x9b, 0xe6, 0xc1, 0xa1, 0x95, 0x58, 0xba, 0xbe, 0x62,
+ 0x58, 0xd5, 0x09, 0xa8, 0xe6, 0xb6, 0x1b, 0xb1, 0x18, 0x28, 0x13, 0xc7,
+ 0x89, 0x1c, 0x68, 0xce, 0x15, 0xaf, 0x2e, 0x68, 0xac, 0x1c, 0xf7, 0x02,
+ 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x50, 0xe5, 0x05, 0xa3, 0x6e,
+ 0x8f, 0x00, 0xf7, 0x93, 0x30, 0xe5, 0x25, 0x20, 0xdc, 0x8a, 0xc3, 0xad,
+ 0x14, 0x6d, 0x90, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
+ 0x30, 0x16, 0x80, 0x14, 0x50, 0xe5, 0x05, 0xa3, 0x6e, 0x8f, 0x00, 0xf7,
+ 0x93, 0x30, 0xe5, 0x25, 0x20, 0xdc, 0x8a, 0xc3, 0xad, 0x14, 0x6d, 0x90,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
+ 0x8e, 0xe4, 0x27, 0x42, 0x16, 0x6e, 0xbd, 0x28, 0x47, 0x09, 0x99, 0xc1,
+ 0x55, 0x02, 0x82, 0x1a, 0xe1, 0xd0, 0xf3, 0xef, 0x4d, 0xaf, 0x30, 0x9a,
+ 0x29, 0x4b, 0x74, 0x03, 0x6a, 0x95, 0x28, 0xf1, 0xbe, 0x62, 0x68, 0x9f,
+ 0x82, 0x59, 0x7a, 0x49, 0x91, 0xb6, 0xaf, 0x6b, 0x23, 0x30, 0xb4, 0xf4,
+ 0xdd, 0xfa, 0x30, 0x3f, 0xb6, 0xed, 0x74, 0x3f, 0x91, 0xe8, 0xd7, 0x84,
+ 0x1a, 0xf3, 0xc6, 0x3d, 0xd8, 0x59, 0x8d, 0x68, 0x6e, 0xb3, 0x66, 0x9e,
+ 0xe8, 0xeb, 0x1a, 0x8b, 0x1e, 0x92, 0x71, 0x73, 0x8c, 0x4f, 0x63, 0xce,
+ 0x71, 0x7b, 0x97, 0x3b, 0x59, 0xd2, 0x9b, 0xe4, 0xd0, 0xef, 0x31, 0x9f,
+ 0x0d, 0x61, 0x27, 0x97, 0x9d, 0xe8, 0xe0, 0xcd, 0x8d, 0xc1, 0x4d, 0xad,
+ 0xf7, 0x3a, 0x8d, 0xb8, 0x86, 0x8c, 0x23, 0x1d, 0x4c, 0x02, 0x5c, 0x53,
+ 0x46, 0x84, 0xb2, 0x97, 0x0c, 0xd3, 0x35, 0x6b
+};
+
+//
+// X509 Cert Data for RSA Public Key Retrieving and X509 Verification (Generated by OpenSSL utility).
+// $ openssl req -new -key TestKeyPem -out TestCertCsr -subj "/C=US/ST=WA/L=Seattle/O=Tianocore/OU=EDK2CHILD/CN=UEFI"
+// $ openssl x509 -days 10000 -CA TestCACert.pem -CAkey TestKeyPem -req -out TestCert -set_serial 3432 --outform DER -in TestCertCsr
+// password should be in the PemPass variable
+// $ xxd --include TestCert
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 TestCert[] = {
+ 0x30, 0x82, 0x02, 0x31, 0x30, 0x82, 0x01, 0x9a, 0x02, 0x02, 0x0d, 0x68,
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+ 0x0b, 0x05, 0x00, 0x30, 0x5e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x08, 0x0c, 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c,
+ 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09,
+ 0x54, 0x69, 0x61, 0x6e, 0x6f, 0x63, 0x6f, 0x72, 0x65, 0x31, 0x0d, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x04, 0x45, 0x44, 0x4b, 0x32,
+ 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04, 0x55,
+ 0x45, 0x46, 0x49, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x36, 0x32,
+ 0x39, 0x32, 0x33, 0x31, 0x35, 0x33, 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x37,
+ 0x31, 0x31, 0x31, 0x35, 0x32, 0x33, 0x31, 0x35, 0x33, 0x36, 0x5a, 0x30,
+ 0x63, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c,
+ 0x02, 0x57, 0x41, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07,
+ 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x12, 0x30,
+ 0x10, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x09, 0x54, 0x69, 0x61, 0x6e,
+ 0x6f, 0x63, 0x6f, 0x72, 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55,
+ 0x04, 0x0b, 0x0c, 0x09, 0x45, 0x44, 0x4b, 0x32, 0x43, 0x48, 0x49, 0x4c,
+ 0x44, 0x31, 0x0d, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x04,
+ 0x55, 0x45, 0x46, 0x49, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
+ 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0x9f, 0xef, 0x1b,
+ 0x46, 0x45, 0x55, 0x33, 0x4b, 0xee, 0x95, 0x14, 0xd3, 0x5a, 0x3e, 0xd9,
+ 0x29, 0xfb, 0xd9, 0x29, 0x4e, 0x8b, 0xf1, 0xf5, 0x68, 0x7c, 0x58, 0x86,
+ 0x0c, 0xda, 0xd7, 0xe0, 0xd2, 0x9a, 0xe8, 0x37, 0x16, 0x4d, 0x54, 0x92,
+ 0x18, 0x20, 0x4c, 0x09, 0xa1, 0xcf, 0xe1, 0xaa, 0x7a, 0x5a, 0x64, 0x7e,
+ 0x5c, 0xeb, 0x4e, 0x15, 0x8e, 0x40, 0xd1, 0xcb, 0x7d, 0x01, 0x71, 0x15,
+ 0x11, 0xd2, 0xc7, 0xdb, 0x6b, 0x00, 0xdc, 0x02, 0xcb, 0x5a, 0x6d, 0x2b,
+ 0x2a, 0x75, 0xb6, 0x3f, 0xec, 0xc1, 0x9d, 0xbf, 0xda, 0xe5, 0x3a, 0x77,
+ 0x4b, 0x21, 0x1c, 0x99, 0x42, 0x84, 0x5e, 0x27, 0x53, 0x9b, 0xe6, 0xc1,
+ 0xa1, 0x95, 0x58, 0xba, 0xbe, 0x62, 0x58, 0xd5, 0x09, 0xa8, 0xe6, 0xb6,
+ 0x1b, 0xb1, 0x18, 0x28, 0x13, 0xc7, 0x89, 0x1c, 0x68, 0xce, 0x15, 0xaf,
+ 0x2e, 0x68, 0xac, 0x1c, 0xf7, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05,
+ 0x00, 0x03, 0x81, 0x81, 0x00, 0x0d, 0xa4, 0x18, 0xa2, 0xb6, 0x09, 0xe1,
+ 0x77, 0x22, 0x97, 0x46, 0x29, 0x1b, 0xd8, 0x67, 0x0a, 0xc0, 0x91, 0x36,
+ 0x53, 0xe1, 0x4c, 0x73, 0x1b, 0xc1, 0x90, 0x6d, 0x98, 0x46, 0x7e, 0x65,
+ 0x71, 0x1c, 0xf0, 0x62, 0x9f, 0x9e, 0x62, 0x0b, 0x8b, 0x73, 0x35, 0x4c,
+ 0x2d, 0xc3, 0x5d, 0x38, 0x22, 0xfe, 0x43, 0x0f, 0xf2, 0x57, 0x17, 0x75,
+ 0xa8, 0x76, 0x79, 0xab, 0x4e, 0x33, 0xa5, 0x91, 0xbd, 0x55, 0x5b, 0xc0,
+ 0x7e, 0xfb, 0x1d, 0xc9, 0xf3, 0x5f, 0x12, 0x6f, 0x7c, 0xdc, 0x24, 0x5a,
+ 0x84, 0x16, 0x28, 0x5b, 0xf9, 0xcc, 0x8b, 0xfe, 0x11, 0xe6, 0x29, 0xcf,
+ 0xac, 0x90, 0x66, 0xc0, 0x70, 0x25, 0xf8, 0x71, 0xdb, 0x29, 0xcb, 0x6b,
+ 0x10, 0xa7, 0xbe, 0x3e, 0x9d, 0x61, 0xd8, 0x04, 0xe0, 0x71, 0x63, 0x83,
+ 0xa3, 0xca, 0x26, 0x6d, 0x7f, 0xf3, 0xaa, 0x8e, 0xb2, 0x66, 0x98, 0x41,
+ 0xd6
+};
+
+//
+// Message Hash for Signing & Verification Validation.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 MsgHash[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09
+ };
+
+//
+// Payload for PKCS#7 Signing & Verification Validation.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *Payload = "Payload Data for PKCS#7 Signing";
+
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaCertPkcs1SignVerify (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ VOID *RsaPrivKey;
+ VOID *RsaPubKey;
+ UINT8 *Signature;
+ UINTN SigSize;
+ UINT8 *Subject;
+ UINTN SubjectSize;
+ RETURN_STATUS ReturnStatus;
+ CHAR8 CommonName[64];
+ UINTN CommonNameSize;
+ CHAR8 OrgName[64];
+ UINTN OrgNameSize;
+
+ //
+ // Retrieve RSA private key from encrypted PEM data.
+ //
+ Status = RsaGetPrivateKeyFromPem (TestKeyPem, sizeof (TestKeyPem), PemPass, &RsaPrivKey);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Retrieve RSA public key from X509 Certificate.
+ //
+ RsaPubKey = NULL;
+ Status = RsaGetPublicKeyFromX509 (TestCert, sizeof (TestCert), &RsaPubKey);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Generate RSA PKCS#1 Signature.
+ //
+ SigSize = 0;
+ Status = RsaPkcs1Sign (RsaPrivKey, MsgHash, SHA1_DIGEST_SIZE, NULL, &SigSize);
+ UT_ASSERT_FALSE (Status);
+ UT_ASSERT_NOT_EQUAL (SigSize, 0);
+
+ Signature = AllocatePool (SigSize);
+ Status = RsaPkcs1Sign (RsaPrivKey, MsgHash, SHA1_DIGEST_SIZE, Signature, &SigSize);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Verify RSA PKCS#1-encoded Signature.
+ //
+ Status = RsaPkcs1Verify (RsaPubKey, MsgHash, SHA1_DIGEST_SIZE, Signature, SigSize);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // X509 Certificate Subject Retrieving.
+ //
+ SubjectSize = 0;
+ Status = X509GetSubjectName (TestCert, sizeof (TestCert), NULL, &SubjectSize);
+ Subject = (UINT8 *)AllocatePool (SubjectSize);
+ Status = X509GetSubjectName (TestCert, sizeof (TestCert), Subject, &SubjectSize);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Get CommonName from X509 Certificate Subject
+ //
+ CommonNameSize = 64;
+ ZeroMem (CommonName, CommonNameSize);
+ ReturnStatus = X509GetCommonName (TestCert, sizeof (TestCert), CommonName, &CommonNameSize);
+ UT_ASSERT_NOT_EFI_ERROR (ReturnStatus);
+
+ UT_ASSERT_EQUAL (CommonNameSize, 5);
+ UT_ASSERT_MEM_EQUAL (CommonName, "UEFI", 5);
+
+ OrgNameSize = 64;
+ ZeroMem (OrgName, OrgNameSize);
+ ReturnStatus = X509GetOrganizationName (TestCert, sizeof (TestCert), OrgName, &OrgNameSize);
+ UT_ASSERT_NOT_EFI_ERROR (ReturnStatus);
+
+ UT_ASSERT_EQUAL (OrgNameSize, 10);
+ UT_ASSERT_MEM_EQUAL (OrgName, "Tianocore", 10);
+
+ //
+ // X509 Certificate Verification.
+ //
+ Status = X509VerifyCert (TestCert, sizeof (TestCert), TestCACert, sizeof (TestCACert));
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Release Resources.
+ //
+ RsaFree (RsaPubKey);
+ RsaFree (RsaPrivKey);
+ FreePool (Signature);
+ FreePool (Subject);
+
+ return UNIT_TEST_PASSED;
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyPkcs7SignVerify (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ UINT8 *P7SignedData;
+ UINTN P7SignedDataSize;
+ UINT8 *SignCert;
+
+ P7SignedData = NULL;
+ SignCert = NULL;
+
+ //
+ // Construct Signer Certificate from RAW data.
+ //
+ Status = X509ConstructCertificate (TestCert, sizeof (TestCert), (UINT8 **) &SignCert);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_NOT_NULL (SignCert);
+
+ //
+ // Create PKCS#7 signedData on Payload.
+ // Note: Caller should release P7SignedData manually.
+ //
+ Status = Pkcs7Sign (
+ TestKeyPem,
+ sizeof (TestKeyPem),
+ (CONST UINT8 *) PemPass,
+ (UINT8 *) Payload,
+ AsciiStrLen (Payload),
+ SignCert,
+ NULL,
+ &P7SignedData,
+ &P7SignedDataSize
+ );
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_NOT_EQUAL (P7SignedDataSize, 0);
+
+ Status = Pkcs7Verify (
+ P7SignedData,
+ P7SignedDataSize,
+ TestCACert,
+ sizeof (TestCACert),
+ (UINT8 *) Payload,
+ AsciiStrLen (Payload)
+ );
+ UT_ASSERT_TRUE (Status);
+
+ if (P7SignedData != NULL) {
+ FreePool (P7SignedData);
+ }
+ if (SignCert != NULL) {
+ X509Free (SignCert);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mRsaCertTest[] = {
+ //
+ // -----Description--------------------------------------Class----------------------Function-----------------Pre---Post--Context
+ //
+ {"TestVerifyRsaCertPkcs1SignVerify()", "CryptoPkg.BaseCryptLib.RsaCert", TestVerifyRsaCertPkcs1SignVerify, NULL, NULL, NULL},
+};
+
+UINTN mRsaCertTestNum = ARRAY_SIZE(mRsaCertTest);
+
+TEST_DESC mPkcs7Test[] = {
+ //
+ // -----Description--------------------------------------Class----------------------Function-----------------Pre---Post--Context
+ //
+ {"TestVerifyPkcs7SignVerify()", "CryptoPkg.BaseCryptLib.Pkcs7", TestVerifyPkcs7SignVerify, NULL, NULL, NULL},
+};
+
+UINTN mPkcs7TestNum = ARRAY_SIZE(mPkcs7Test);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c
new file mode 100644
index 00000000000..c2f1512289c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c
@@ -0,0 +1,191 @@
+/** @file
+ Application for RSA PSS Primitives Validation.
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// RSA PSS test vectors from NIST FIPS 186-3 RSA files
+//
+
+//
+// Public Modulus of RSA Key
+//
+UINT8 RsaPssN[]={
+ 0xa4, 0x7d, 0x04, 0xe7, 0xca, 0xcd, 0xba, 0x4e, 0xa2, 0x6e, 0xca, 0x8a, 0x4c, 0x6e, 0x14, 0x56,
+ 0x3c, 0x2c, 0xe0, 0x3b, 0x62, 0x3b, 0x76, 0x8c, 0x0d, 0x49, 0x86, 0x8a, 0x57, 0x12, 0x13, 0x01,
+ 0xdb, 0xf7, 0x83, 0xd8, 0x2f, 0x4c, 0x05, 0x5e, 0x73, 0x96, 0x0e, 0x70, 0x55, 0x01, 0x87, 0xd0,
+ 0xaf, 0x62, 0xac, 0x34, 0x96, 0xf0, 0xa3, 0xd9, 0x10, 0x3c, 0x2e, 0xb7, 0x91, 0x9a, 0x72, 0x75,
+ 0x2f, 0xa7, 0xce, 0x8c, 0x68, 0x8d, 0x81, 0xe3, 0xae, 0xe9, 0x94, 0x68, 0x88, 0x7a, 0x15, 0x28,
+ 0x8a, 0xfb, 0xb7, 0xac, 0xb8, 0x45, 0xb7, 0xc5, 0x22, 0xb5, 0xc6, 0x4e, 0x67, 0x8f, 0xcd, 0x3d,
+ 0x22, 0xfe, 0xb8, 0x4b, 0x44, 0x27, 0x27, 0x00, 0xbe, 0x52, 0x7d, 0x2b, 0x20, 0x25, 0xa3, 0xf8,
+ 0x3c, 0x23, 0x83, 0xbf, 0x6a, 0x39, 0xcf, 0x5b, 0x4e, 0x48, 0xb3, 0xcf, 0x2f, 0x56, 0xee, 0xf0,
+ 0xdf, 0xff, 0x18, 0x55, 0x5e, 0x31, 0x03, 0x7b, 0x91, 0x52, 0x48, 0x69, 0x48, 0x76, 0xf3, 0x04,
+ 0x78, 0x14, 0x41, 0x51, 0x64, 0xf2, 0xc6, 0x60, 0x88, 0x1e, 0x69, 0x4b, 0x58, 0xc2, 0x80, 0x38,
+ 0xa0, 0x32, 0xad, 0x25, 0x63, 0x4a, 0xad, 0x7b, 0x39, 0x17, 0x1d, 0xee, 0x36, 0x8e, 0x3d, 0x59,
+ 0xbf, 0xb7, 0x29, 0x9e, 0x46, 0x01, 0xd4, 0x58, 0x7e, 0x68, 0xca, 0xaf, 0x8d, 0xb4, 0x57, 0xb7,
+ 0x5a, 0xf4, 0x2f, 0xc0, 0xcf, 0x1a, 0xe7, 0xca, 0xce, 0xd2, 0x86, 0xd7, 0x7f, 0xac, 0x6c, 0xed,
+ 0xb0, 0x3a, 0xd9, 0x4f, 0x14, 0x33, 0xd2, 0xc9, 0x4d, 0x08, 0xe6, 0x0b, 0xc1, 0xfd, 0xef, 0x05,
+ 0x43, 0xcd, 0x29, 0x51, 0xe7, 0x65, 0xb3, 0x82, 0x30, 0xfd, 0xd1, 0x8d, 0xe5, 0xd2, 0xca, 0x62,
+ 0x7d, 0xdc, 0x03, 0x2f, 0xe0, 0x5b, 0xbd, 0x2f, 0xf2, 0x1e, 0x2d, 0xb1, 0xc2, 0xf9, 0x4d, 0x8b,
+ };
+
+//
+// Public Exponent of RSA Key
+//
+UINT8 RsaPssE[]={ 0x10, 0xe4, 0x3f };
+
+//
+// Private Exponent of RSA Key
+//
+UINT8 RsaPssD[]={
+ 0x11, 0xa0, 0xdd, 0x28, 0x5f, 0x66, 0x47, 0x1a, 0x8d, 0xa3, 0x0b, 0xcb, 0x8c, 0x24, 0xa1, 0xd5,
+ 0xc8, 0xdb, 0x94, 0x2f, 0xc9, 0x92, 0x07, 0x97, 0xca, 0x44, 0x24, 0x60, 0xa8, 0x00, 0xb7, 0x5b,
+ 0xbc, 0x73, 0x8b, 0xeb, 0x8e, 0xe0, 0xe8, 0x74, 0xb0, 0x53, 0xe6, 0x47, 0x07, 0xdf, 0x4c, 0xfc,
+ 0x78, 0x37, 0xc4, 0x0e, 0x5b, 0xe6, 0x8b, 0x8a, 0x8e, 0x1d, 0x01, 0x45, 0x16, 0x9c, 0xa6, 0x27,
+ 0x1d, 0x81, 0x88, 0x7e, 0x19, 0xa1, 0xcd, 0x95, 0xb2, 0xfd, 0x0d, 0xe0, 0xdb, 0xa3, 0x47, 0xfe,
+ 0x63, 0x7b, 0xcc, 0x6c, 0xdc, 0x24, 0xee, 0xbe, 0x03, 0xc2, 0x4d, 0x4c, 0xf3, 0xa5, 0xc6, 0x15,
+ 0x4d, 0x78, 0xf1, 0x41, 0xfe, 0x34, 0x16, 0x99, 0x24, 0xd0, 0xf8, 0x95, 0x33, 0x65, 0x8e, 0xac,
+ 0xfd, 0xea, 0xe9, 0x9c, 0xe1, 0xa8, 0x80, 0x27, 0xc1, 0x8f, 0xf9, 0x26, 0x53, 0xa8, 0x35, 0xaa,
+ 0x38, 0x91, 0xbf, 0xff, 0xcd, 0x38, 0x8f, 0xfc, 0x23, 0x88, 0xce, 0x2b, 0x10, 0x56, 0x85, 0x43,
+ 0x75, 0x05, 0x02, 0xcc, 0xbc, 0x69, 0xc0, 0x08, 0x8f, 0x1d, 0x69, 0x0e, 0x97, 0xa5, 0xf5, 0xbd,
+ 0xd1, 0x88, 0x8c, 0xd2, 0xfa, 0xa4, 0x3c, 0x04, 0xae, 0x24, 0x53, 0x95, 0x22, 0xdd, 0xe2, 0xd9,
+ 0xc2, 0x02, 0xf6, 0x55, 0xfc, 0x55, 0x75, 0x44, 0x40, 0xb5, 0x3a, 0x15, 0x32, 0xaa, 0xb4, 0x78,
+ 0x51, 0xf6, 0x0b, 0x7a, 0x06, 0x7e, 0x24, 0x0b, 0x73, 0x8e, 0x1b, 0x1d, 0xaa, 0xe6, 0xca, 0x0d,
+ 0x59, 0xee, 0xae, 0x27, 0x68, 0x6c, 0xd8, 0x88, 0x57, 0xe9, 0xad, 0xad, 0xc2, 0xd4, 0xb8, 0x2b,
+ 0x07, 0xa6, 0x1a, 0x35, 0x84, 0x56, 0xaa, 0xf8, 0x07, 0x66, 0x96, 0x93, 0xff, 0xb1, 0x3c, 0x99,
+ 0x64, 0xa6, 0x36, 0x54, 0xca, 0xdc, 0x81, 0xee, 0x59, 0xdf, 0x51, 0x1c, 0xa3, 0xa4, 0xbd, 0x67,
+ };
+
+//
+// Binary message to be signed and verified
+//
+UINT8 PssMessage[]={
+ 0xe0, 0x02, 0x37, 0x7a, 0xff, 0xb0, 0x4f, 0x0f, 0xe4, 0x59, 0x8d, 0xe9, 0xd9, 0x2d, 0x31, 0xd6,
+ 0xc7, 0x86, 0x04, 0x0d, 0x57, 0x76, 0x97, 0x65, 0x56, 0xa2, 0xcf, 0xc5, 0x5e, 0x54, 0xa1, 0xdc,
+ 0xb3, 0xcb, 0x1b, 0x12, 0x6b, 0xd6, 0xa4, 0xbe, 0xd2, 0xa1, 0x84, 0x99, 0x0c, 0xce, 0xa7, 0x73,
+ 0xfc, 0xc7, 0x9d, 0x24, 0x65, 0x53, 0xe6, 0xc6, 0x4f, 0x68, 0x6d, 0x21, 0xad, 0x41, 0x52, 0x67,
+ 0x3c, 0xaf, 0xec, 0x22, 0xae, 0xb4, 0x0f, 0x6a, 0x08, 0x4e, 0x8a, 0x5b, 0x49, 0x91, 0xf4, 0xc6,
+ 0x4c, 0xf8, 0xa9, 0x27, 0xef, 0xfd, 0x0f, 0xd7, 0x75, 0xe7, 0x1e, 0x83, 0x29, 0xe4, 0x1f, 0xdd,
+ 0x44, 0x57, 0xb3, 0x91, 0x11, 0x73, 0x18, 0x7b, 0x4f, 0x09, 0xa8, 0x17, 0xd7, 0x9e, 0xa2, 0x39,
+ 0x7f, 0xc1, 0x2d, 0xfe, 0x3d, 0x9c, 0x9a, 0x02, 0x90, 0xc8, 0xea, 0xd3, 0x1b, 0x66, 0x90, 0xa6,
+ };
+
+//
+// Binary message to be signed and verified
+//
+UINT8 PssSalt[]={
+ 0xd6, 0x6f, 0x72, 0xf1, 0x0b, 0x69, 0x00, 0x1a, 0x5b, 0x59, 0xcf, 0x10, 0x92, 0xad, 0x27, 0x4d,
+ 0x50, 0x56, 0xc4, 0xe9, 0x5c, 0xcc, 0xcf, 0xbe, 0x3b, 0x53, 0x0d, 0xcb, 0x02, 0x7e, 0x57, 0xd6
+ };
+
+//
+// RSASSA-PSS Signature over above message using above keys, salt and SHA256 digest(and MGF1) algo.
+//
+UINT8 TestVectorSignature[]={
+ 0x4f, 0x9b, 0x42, 0x5c, 0x20, 0x58, 0x46, 0x0e, 0x4a, 0xb2, 0xf5, 0xc9, 0x63, 0x84, 0xda, 0x23,
+ 0x27, 0xfd, 0x29, 0x15, 0x0f, 0x01, 0x95, 0x5a, 0x76, 0xb4, 0xef, 0xe9, 0x56, 0xaf, 0x06, 0xdc,
+ 0x08, 0x77, 0x9a, 0x37, 0x4e, 0xe4, 0x60, 0x7e, 0xab, 0x61, 0xa9, 0x3a, 0xdc, 0x56, 0x08, 0xf4,
+ 0xec, 0x36, 0xe4, 0x7f, 0x2a, 0x0f, 0x75, 0x4e, 0x8f, 0xf8, 0x39, 0xa8, 0xa1, 0x9b, 0x1d, 0xb1,
+ 0xe8, 0x84, 0xea, 0x4c, 0xf3, 0x48, 0xcd, 0x45, 0x50, 0x69, 0xeb, 0x87, 0xaf, 0xd5, 0x36, 0x45,
+ 0xb4, 0x4e, 0x28, 0xa0, 0xa5, 0x68, 0x08, 0xf5, 0x03, 0x1d, 0xa5, 0xba, 0x91, 0x12, 0x76, 0x8d,
+ 0xfb, 0xfc, 0xa4, 0x4e, 0xbe, 0x63, 0xa0, 0xc0, 0x57, 0x2b, 0x73, 0x1d, 0x66, 0x12, 0x2f, 0xb7,
+ 0x16, 0x09, 0xbe, 0x14, 0x80, 0xfa, 0xa4, 0xe4, 0xf7, 0x5e, 0x43, 0x95, 0x51, 0x59, 0xd7, 0x0f,
+ 0x08, 0x1e, 0x2a, 0x32, 0xfb, 0xb1, 0x9a, 0x48, 0xb9, 0xf1, 0x62, 0xcf, 0x6b, 0x2f, 0xb4, 0x45,
+ 0xd2, 0xd6, 0x99, 0x4b, 0xc5, 0x89, 0x10, 0xa2, 0x6b, 0x59, 0x43, 0x47, 0x78, 0x03, 0xcd, 0xaa,
+ 0xa1, 0xbd, 0x74, 0xb0, 0xda, 0x0a, 0x5d, 0x05, 0x3d, 0x8b, 0x1d, 0xc5, 0x93, 0x09, 0x1d, 0xb5,
+ 0x38, 0x83, 0x83, 0xc2, 0x60, 0x79, 0xf3, 0x44, 0xe2, 0xae, 0xa6, 0x00, 0xd0, 0xe3, 0x24, 0x16,
+ 0x4b, 0x45, 0x0f, 0x7b, 0x9b, 0x46, 0x51, 0x11, 0xb7, 0x26, 0x5f, 0x3b, 0x1b, 0x06, 0x30, 0x89,
+ 0xae, 0x7e, 0x26, 0x23, 0xfc, 0x0f, 0xda, 0x80, 0x52, 0xcf, 0x4b, 0xf3, 0x37, 0x91, 0x02, 0xfb,
+ 0xf7, 0x1d, 0x7c, 0x98, 0xe8, 0x25, 0x86, 0x64, 0xce, 0xed, 0x63, 0x7d, 0x20, 0xf9, 0x5f, 0xf0,
+ 0x11, 0x18, 0x81, 0xe6, 0x50, 0xce, 0x61, 0xf2, 0x51, 0xd9, 0xc3, 0xa6, 0x29, 0xef, 0x22, 0x2d,
+ };
+
+
+STATIC VOID *mRsa;
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaPssPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ mRsa = RsaNew ();
+
+ if (mRsa == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyRsaPssCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ if (mRsa != NULL) {
+ RsaFree (mRsa);
+ mRsa = NULL;
+ }
+}
+
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaPssSignVerify (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 *Signature;
+ UINTN SigSize;
+ BOOLEAN Status;
+
+ Status = RsaSetKey (mRsa, RsaKeyN, RsaPssN, sizeof (RsaPssN));
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaSetKey (mRsa, RsaKeyE, RsaPssE, sizeof (RsaPssE));
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaSetKey (mRsa, RsaKeyD, RsaPssD, sizeof (RsaPssD));
+ UT_ASSERT_TRUE (Status);
+
+ SigSize = 0;
+ Status = RsaPssSign (mRsa, PssMessage, sizeof(PssMessage), SHA256_DIGEST_SIZE, SHA256_DIGEST_SIZE, NULL, &SigSize);
+ UT_ASSERT_FALSE (Status);
+ UT_ASSERT_NOT_EQUAL (SigSize, 0);
+
+ Signature = AllocatePool (SigSize);
+ Status = RsaPssSign (mRsa, PssMessage, sizeof(PssMessage), SHA256_DIGEST_SIZE, SHA256_DIGEST_SIZE, Signature, &SigSize);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Verify RSA PSS encoded Signature generated in above step
+ //
+ Status = RsaPssVerify (mRsa, PssMessage, sizeof(PssMessage), Signature, SigSize, SHA256_DIGEST_SIZE, SHA256_DIGEST_SIZE);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Verify NIST FIPS 186-3 RSA test vector signature
+ //
+ Status = RsaPssVerify (mRsa, PssMessage, sizeof(PssMessage), TestVectorSignature, sizeof(TestVectorSignature), SHA256_DIGEST_SIZE, SHA256_DIGEST_SIZE);
+ UT_ASSERT_TRUE (Status);
+
+ FreePool(Signature);
+ return UNIT_TEST_PASSED;
+}
+
+
+TEST_DESC mRsaPssTest[] = {
+ //
+ // -----Description--------------------------------------Class----------------------Function---------------------------------Pre---------------------Post---------Context
+ //
+ {"TestVerifyRsaPssSignVerify()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaPssSignVerify, TestVerifyRsaPssPreReq, TestVerifyRsaPssCleanUp, NULL},
+};
+
+UINTN mRsaPssTestNum = ARRAY_SIZE(mRsaPssTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c
new file mode 100644
index 00000000000..4186c706c40
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c
@@ -0,0 +1,312 @@
+/** @file
+ Application for RSA Primitives Validation.
+
+Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+#define RSA_MODULUS_LENGTH 512
+
+//
+// RSA PKCS#1 Validation Data from OpenSSL "Fips_rsa_selftest.c"
+//
+
+//
+// Public Modulus of RSA Key
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 RsaN[] = {
+ 0xBB, 0xF8, 0x2F, 0x09, 0x06, 0x82, 0xCE, 0x9C, 0x23, 0x38, 0xAC, 0x2B, 0x9D, 0xA8, 0x71, 0xF7,
+ 0x36, 0x8D, 0x07, 0xEE, 0xD4, 0x10, 0x43, 0xA4, 0x40, 0xD6, 0xB6, 0xF0, 0x74, 0x54, 0xF5, 0x1F,
+ 0xB8, 0xDF, 0xBA, 0xAF, 0x03, 0x5C, 0x02, 0xAB, 0x61, 0xEA, 0x48, 0xCE, 0xEB, 0x6F, 0xCD, 0x48,
+ 0x76, 0xED, 0x52, 0x0D, 0x60, 0xE1, 0xEC, 0x46, 0x19, 0x71, 0x9D, 0x8A, 0x5B, 0x8B, 0x80, 0x7F,
+ 0xAF, 0xB8, 0xE0, 0xA3, 0xDF, 0xC7, 0x37, 0x72, 0x3E, 0xE6, 0xB4, 0xB7, 0xD9, 0x3A, 0x25, 0x84,
+ 0xEE, 0x6A, 0x64, 0x9D, 0x06, 0x09, 0x53, 0x74, 0x88, 0x34, 0xB2, 0x45, 0x45, 0x98, 0x39, 0x4E,
+ 0xE0, 0xAA, 0xB1, 0x2D, 0x7B, 0x61, 0xA5, 0x1F, 0x52, 0x7A, 0x9A, 0x41, 0xF6, 0xC1, 0x68, 0x7F,
+ 0xE2, 0x53, 0x72, 0x98, 0xCA, 0x2A, 0x8F, 0x59, 0x46, 0xF8, 0xE5, 0xFD, 0x09, 0x1D, 0xBD, 0xCB
+ };
+
+//
+// Public Exponent of RSA Key
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 RsaE[] = { 0x11 };
+
+//
+// Private Exponent of RSA Key
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 RsaD[] = {
+ 0xA5, 0xDA, 0xFC, 0x53, 0x41, 0xFA, 0xF2, 0x89, 0xC4, 0xB9, 0x88, 0xDB, 0x30, 0xC1, 0xCD, 0xF8,
+ 0x3F, 0x31, 0x25, 0x1E, 0x06, 0x68, 0xB4, 0x27, 0x84, 0x81, 0x38, 0x01, 0x57, 0x96, 0x41, 0xB2,
+ 0x94, 0x10, 0xB3, 0xC7, 0x99, 0x8D, 0x6B, 0xC4, 0x65, 0x74, 0x5E, 0x5C, 0x39, 0x26, 0x69, 0xD6,
+ 0x87, 0x0D, 0xA2, 0xC0, 0x82, 0xA9, 0x39, 0xE3, 0x7F, 0xDC, 0xB8, 0x2E, 0xC9, 0x3E, 0xDA, 0xC9,
+ 0x7F, 0xF3, 0xAD, 0x59, 0x50, 0xAC, 0xCF, 0xBC, 0x11, 0x1C, 0x76, 0xF1, 0xA9, 0x52, 0x94, 0x44,
+ 0xE5, 0x6A, 0xAF, 0x68, 0xC5, 0x6C, 0x09, 0x2C, 0xD3, 0x8D, 0xC3, 0xBE, 0xF5, 0xD2, 0x0A, 0x93,
+ 0x99, 0x26, 0xED, 0x4F, 0x74, 0xA1, 0x3E, 0xDD, 0xFB, 0xE1, 0xA1, 0xCE, 0xCC, 0x48, 0x94, 0xAF,
+ 0x94, 0x28, 0xC2, 0xB7, 0xB8, 0x88, 0x3F, 0xE4, 0x46, 0x3A, 0x4B, 0xC8, 0x5B, 0x1C, 0xB3, 0xC1
+ };
+
+//
+// Known Answer Test (KAT) Data for RSA PKCS#1 Signing
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 RsaSignData[] = "OpenSSL FIPS 140-2 Public Key RSA KAT";
+
+//
+// Known Signature for the above message, under SHA-1 Digest
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 RsaPkcs1Signature[] = {
+ 0x71, 0xEE, 0x1A, 0xC0, 0xFE, 0x01, 0x93, 0x54, 0x79, 0x5C, 0xF2, 0x4C, 0x4A, 0xFD, 0x1A, 0x05,
+ 0x8F, 0x64, 0xB1, 0x6D, 0x61, 0x33, 0x8D, 0x9B, 0xE7, 0xFD, 0x60, 0xA3, 0x83, 0xB5, 0xA3, 0x51,
+ 0x55, 0x77, 0x90, 0xCF, 0xDC, 0x22, 0x37, 0x8E, 0xD0, 0xE1, 0xAE, 0x09, 0xE3, 0x3D, 0x1E, 0xF8,
+ 0x80, 0xD1, 0x8B, 0xC2, 0xEC, 0x0A, 0xD7, 0x6B, 0x88, 0x8B, 0x8B, 0xA1, 0x20, 0x22, 0xBE, 0x59,
+ 0x5B, 0xE0, 0x23, 0x24, 0xA1, 0x49, 0x30, 0xBA, 0xA9, 0x9E, 0xE8, 0xB1, 0x8A, 0x62, 0x16, 0xBF,
+ 0x4E, 0xCA, 0x2E, 0x4E, 0xBC, 0x29, 0xA8, 0x67, 0x13, 0xB7, 0x9F, 0x1D, 0x04, 0x44, 0xE5, 0x5F,
+ 0x35, 0x07, 0x11, 0xBC, 0xED, 0x19, 0x37, 0x21, 0xCF, 0x23, 0x48, 0x1F, 0x72, 0x05, 0xDE, 0xE6,
+ 0xE8, 0x7F, 0x33, 0x8A, 0x76, 0x4B, 0x2F, 0x95, 0xDF, 0xF1, 0x5F, 0x84, 0x80, 0xD9, 0x46, 0xB4
+ };
+
+//
+// Default public key 0x10001 = 65537
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 DefaultPublicKey[] = {
+ 0x01, 0x00, 0x01
+};
+
+VOID *mRsa;
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaPreReq (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ mRsa = RsaNew ();
+
+ if (mRsa == NULL) {
+ return UNIT_TEST_ERROR_TEST_FAILED;
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+VOID
+EFIAPI
+TestVerifyRsaCleanUp (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ if (mRsa != NULL) {
+ RsaFree (mRsa);
+ mRsa = NULL;
+ }
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaSetGetKeyComponents (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ UINTN KeySize;
+ UINT8 *KeyBuffer;
+
+ //
+ // Set/Get RSA Key Components
+ //
+
+ //
+ // Set/Get RSA Key N
+ //
+ Status = RsaSetKey (mRsa, RsaKeyN, RsaN, sizeof (RsaN));
+ UT_ASSERT_TRUE (Status);
+
+ KeySize = 0;
+ Status = RsaGetKey (mRsa, RsaKeyN, NULL, &KeySize);
+ UT_ASSERT_FALSE (Status);
+ UT_ASSERT_EQUAL (KeySize, sizeof (RsaN));
+
+ KeyBuffer = AllocatePool (KeySize);
+ Status = RsaGetKey (mRsa, RsaKeyN, KeyBuffer, &KeySize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (KeySize, sizeof (RsaN));
+
+ UT_ASSERT_MEM_EQUAL (KeyBuffer, RsaN, KeySize);
+
+ FreePool (KeyBuffer);
+
+ //
+ // Set/Get RSA Key E
+ //
+ Status = RsaSetKey (mRsa, RsaKeyE, RsaE, sizeof (RsaE));
+ UT_ASSERT_TRUE (Status);
+
+ KeySize = 0;
+ Status = RsaGetKey (mRsa, RsaKeyE, NULL, &KeySize);
+ UT_ASSERT_FALSE (Status);
+ UT_ASSERT_EQUAL (KeySize, sizeof (RsaE));
+
+ KeyBuffer = AllocatePool (KeySize);
+ Status = RsaGetKey (mRsa, RsaKeyE, KeyBuffer, &KeySize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (KeySize, sizeof (RsaE));
+
+ UT_ASSERT_MEM_EQUAL (KeyBuffer, RsaE, KeySize);
+
+ FreePool (KeyBuffer);
+
+ //
+ // Clear/Get RSA Key Components
+ //
+
+ //
+ // Clear/Get RSA Key N
+ //
+ Status = RsaSetKey (mRsa, RsaKeyN, NULL, 0);
+ UT_ASSERT_TRUE (Status);
+
+ KeySize = 1;
+ Status = RsaGetKey (mRsa, RsaKeyN, NULL, &KeySize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (KeySize, 0);
+
+ //
+ // Clear/Get RSA Key E
+ //
+ Status = RsaSetKey (mRsa, RsaKeyE, NULL, 0);
+ UT_ASSERT_TRUE (Status);
+
+ KeySize = 1;
+ Status = RsaGetKey (mRsa, RsaKeyE, NULL, &KeySize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (KeySize, 0);
+
+ return UNIT_TEST_PASSED;
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaGenerateKeyComponents (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ UINTN KeySize;
+ UINT8 *KeyBuffer;
+
+ //
+ // Generate RSA Key Components
+ //
+
+ Status = RsaGenerateKey (mRsa, RSA_MODULUS_LENGTH, NULL, 0);
+ UT_ASSERT_TRUE (Status);
+
+ KeySize = RSA_MODULUS_LENGTH / 8;
+ KeyBuffer = AllocatePool (KeySize);
+ Status = RsaGetKey (mRsa, RsaKeyE, KeyBuffer, &KeySize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (KeySize, 3);
+ UT_ASSERT_MEM_EQUAL (KeyBuffer, DefaultPublicKey, 3);
+
+ KeySize = RSA_MODULUS_LENGTH / 8;
+ Status = RsaGetKey (mRsa, RsaKeyN, KeyBuffer, &KeySize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (KeySize, RSA_MODULUS_LENGTH / 8);
+
+ Status = RsaCheckKey (mRsa);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Check invalid RSA key components
+ //
+ Status = RsaSetKey (mRsa, RsaKeyN, RsaN, sizeof (RsaN));
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaCheckKey (mRsa);
+ UT_ASSERT_FALSE (Status);
+
+ Status = RsaSetKey (mRsa, RsaKeyN, KeyBuffer, KeySize);
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaCheckKey (mRsa);
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaSetKey (mRsa, RsaKeyE, RsaE, sizeof (RsaE));
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaCheckKey (mRsa);
+ UT_ASSERT_FALSE (Status);
+
+ FreePool (KeyBuffer);
+
+ return UNIT_TEST_PASSED;
+}
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyRsaPkcs1SignVerify (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT8 HashValue[SHA1_DIGEST_SIZE];
+ UINTN HashSize;
+ UINT8 *Signature;
+ UINTN SigSize;
+ BOOLEAN Status;
+
+ //
+ // SHA-1 Digest Message for PKCS#1 Signature
+ //
+ HashSize = SHA1_DIGEST_SIZE;
+ ZeroMem (HashValue, HashSize);
+
+ Status = Sha1HashAll (RsaSignData, AsciiStrLen (RsaSignData), HashValue);
+ UT_ASSERT_TRUE (Status);
+
+ //
+ // Sign RSA PKCS#1-encoded Signature
+ //
+
+ Status = RsaSetKey (mRsa, RsaKeyN, RsaN, sizeof (RsaN));
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaSetKey (mRsa, RsaKeyE, RsaE, sizeof (RsaE));
+ UT_ASSERT_TRUE (Status);
+
+ Status = RsaSetKey (mRsa, RsaKeyD, RsaD, sizeof (RsaD));
+ UT_ASSERT_TRUE (Status);
+
+ SigSize = 0;
+ Status = RsaPkcs1Sign (mRsa, HashValue, HashSize, NULL, &SigSize);
+ UT_ASSERT_FALSE (Status);
+ UT_ASSERT_NOT_EQUAL (SigSize, 0);
+
+ Signature = AllocatePool (SigSize);
+ Status = RsaPkcs1Sign (mRsa, HashValue, HashSize, Signature, &SigSize);
+ UT_ASSERT_TRUE (Status);
+ UT_ASSERT_EQUAL (SigSize, sizeof (RsaPkcs1Signature));
+
+ UT_ASSERT_MEM_EQUAL (Signature, RsaPkcs1Signature, SigSize);
+
+ //
+ // Verify RSA PKCS#1-encoded Signature
+ //
+ Status = RsaPkcs1Verify (mRsa, HashValue, HashSize, Signature, SigSize);
+ UT_ASSERT_TRUE (Status);
+
+ FreePool(Signature);
+
+ return UNIT_TEST_PASSED;
+}
+
+TEST_DESC mRsaTest[] = {
+ //
+ // -----Description--------------------------------------Class----------------------Function---------------------------------Pre---------------------Post---------Context
+ //
+ {"TestVerifyRsaSetGetKeyComponents()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaSetGetKeyComponents, TestVerifyRsaPreReq, TestVerifyRsaCleanUp, NULL},
+ {"TestVerifyRsaGenerateKeyComponents()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaGenerateKeyComponents, TestVerifyRsaPreReq, TestVerifyRsaCleanUp, NULL},
+ {"TestVerifyRsaPkcs1SignVerify()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaPkcs1SignVerify, TestVerifyRsaPreReq, TestVerifyRsaCleanUp, NULL},
+};
+
+UINTN mRsaTestNum = ARRAY_SIZE(mRsaTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TSTests.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TSTests.c
new file mode 100644
index 00000000000..c326ce18262
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TSTests.c
@@ -0,0 +1,335 @@
+/** @file
+ Sample Implementation for RFC3161 Time Stamping Verification.
+
+Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// Sample Authenticode Data with RFC3161 time stamping signature.
+// The data retrieved from one signed sample UEFI image, which is generated by MSFT's signtool
+// utility in conjunction with RFC3161 timestamping, as the following command:
+// signtool sign /ac <xxx.cer> / f <xxx.pfx> /p <pass> /fd <digestAlg>
+// /tr http://timestamp.comodoca.com/rfc3161 sample.efi
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 AuthenticodeWithTS[] = {
+ 0x30, 0x82, 0x0c, 0x00, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0,
+ 0x82, 0x0b, 0xf1, 0x30, 0x82, 0x0b, 0xed, 0x02, 0x01, 0x01, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x78, 0x06, 0x0a, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0xa0, 0x6a, 0x30, 0x68, 0x30, 0x33, 0x06,
+ 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0f, 0x30, 0x25, 0x03, 0x01, 0x00,
+ 0xa0, 0x20, 0xa2, 0x1e, 0x80, 0x1c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x4f, 0x00, 0x62,
+ 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x3e, 0x00, 0x3e,
+ 0x00, 0x3e, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
+ 0x01, 0x05, 0x00, 0x04, 0x20, 0x1e, 0x9e, 0x74, 0x31, 0xe1, 0x3e, 0x51, 0x46, 0xab, 0xce, 0x10,
+ 0x0d, 0x7c, 0x38, 0x66, 0x34, 0xd4, 0xdd, 0x04, 0xa5, 0xe7, 0x75, 0x40, 0xdd, 0x99, 0x73, 0xf3,
+ 0x2a, 0x54, 0x3e, 0xa8, 0x18, 0xa0, 0x82, 0x01, 0xee, 0x30, 0x82, 0x01, 0xea, 0x30, 0x82, 0x01,
+ 0x57, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x2c, 0x65, 0xcf, 0xcf, 0xdd, 0x61, 0x7b, 0xa4,
+ 0x41, 0xad, 0x26, 0x1b, 0x63, 0xce, 0x91, 0x0f, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
+ 0x1d, 0x05, 0x00, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08,
+ 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37,
+ 0x32, 0x38, 0x30, 0x37, 0x33, 0x38, 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x33, 0x39, 0x31, 0x32, 0x33,
+ 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x07, 0x54, 0x65, 0x73, 0x74, 0x53, 0x75, 0x62, 0x30, 0x81, 0x9f, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81,
+ 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0x94, 0xa6, 0x02, 0x15, 0x87, 0xd6, 0xbf,
+ 0x71, 0xe8, 0xc6, 0x68, 0xf6, 0x9f, 0x66, 0x09, 0x6c, 0xe7, 0x39, 0x52, 0xf4, 0x4e, 0xaf, 0xf5,
+ 0xe0, 0xba, 0x0f, 0xfd, 0xe6, 0x77, 0xa9, 0x71, 0x5b, 0x5c, 0x92, 0x50, 0x1d, 0xfd, 0x9b, 0x6e,
+ 0x52, 0x92, 0x9e, 0x3a, 0x75, 0x86, 0x41, 0x2a, 0x41, 0x30, 0x1b, 0x67, 0x66, 0x91, 0xde, 0x71,
+ 0x84, 0xe0, 0x90, 0xc3, 0x50, 0x36, 0x78, 0xb5, 0xa0, 0x1e, 0x72, 0xde, 0xe7, 0x66, 0x42, 0x4f,
+ 0x59, 0x5e, 0x3d, 0xf3, 0x85, 0x82, 0x0b, 0xa8, 0x26, 0x2d, 0xd9, 0xe3, 0x14, 0xda, 0x9d, 0x2e,
+ 0x3f, 0x53, 0x4d, 0x8d, 0x10, 0xbf, 0xa4, 0x7c, 0xe5, 0xaf, 0x3a, 0xa6, 0xaf, 0x49, 0x64, 0xb0,
+ 0x60, 0x17, 0x87, 0x71, 0x77, 0x59, 0x52, 0xe5, 0x5a, 0xed, 0x96, 0x7d, 0x7e, 0x5d, 0xc1, 0xef,
+ 0x6b, 0xfb, 0x80, 0xc5, 0x2b, 0x10, 0xfe, 0xe7, 0xd3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x48,
+ 0x30, 0x46, 0x30, 0x44, 0x06, 0x03, 0x55, 0x1d, 0x01, 0x04, 0x3d, 0x30, 0x3b, 0x80, 0x10, 0x19,
+ 0x8d, 0x48, 0xa1, 0xb9, 0xf3, 0x5e, 0x3c, 0x13, 0xb4, 0x08, 0xb6, 0xd9, 0xf3, 0x4f, 0x0a, 0xa1,
+ 0x15, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x08, 0x54, 0x65,
+ 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x82, 0x10, 0x27, 0xcb, 0x16, 0x33, 0x8b, 0xed, 0x4d, 0xa8,
+ 0x47, 0xf0, 0x86, 0x47, 0x10, 0xef, 0x15, 0xd9, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
+ 0x1d, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x51, 0x94, 0xed, 0x7a, 0x5c, 0x0b, 0x34, 0x16, 0x9c,
+ 0xf4, 0x5f, 0x88, 0x16, 0xa8, 0x4b, 0x13, 0xfc, 0xa4, 0x0a, 0xc7, 0xd9, 0x20, 0xb1, 0x93, 0xc5,
+ 0x81, 0x4f, 0x35, 0x3a, 0x89, 0x10, 0x04, 0xc4, 0xcc, 0x10, 0x34, 0xc3, 0x15, 0x57, 0x06, 0x97,
+ 0xee, 0x06, 0x2f, 0xf3, 0x24, 0xa1, 0xe6, 0x3a, 0x89, 0x4d, 0xb4, 0x7b, 0x12, 0x87, 0x90, 0x8c,
+ 0xfc, 0x5b, 0xb0, 0xf0, 0xdd, 0xaa, 0x3a, 0x24, 0x6d, 0x55, 0x47, 0x8a, 0xf2, 0x61, 0x08, 0x7a,
+ 0x59, 0x5f, 0x6e, 0x7b, 0xcb, 0x34, 0xbe, 0xb6, 0x5d, 0xcb, 0x60, 0xae, 0xc4, 0xda, 0x62, 0xbb,
+ 0x7f, 0x17, 0x1e, 0x73, 0xd1, 0x4e, 0x9f, 0x6e, 0xd3, 0xc8, 0x35, 0x58, 0x30, 0xd2, 0x89, 0xe5,
+ 0x22, 0x5e, 0x86, 0xac, 0x7a, 0x56, 0xd6, 0x70, 0xdb, 0x54, 0x10, 0x6c, 0xd3, 0xd5, 0x38, 0xfb,
+ 0x69, 0xcb, 0x4f, 0x36, 0x83, 0xc2, 0xe8, 0x31, 0x82, 0x09, 0x69, 0x30, 0x82, 0x09, 0x65, 0x02,
+ 0x01, 0x01, 0x30, 0x27, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
+ 0x08, 0x54, 0x65, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x02, 0x10, 0x2c, 0x65, 0xcf, 0xcf, 0xdd,
+ 0x61, 0x7b, 0xa4, 0x41, 0xad, 0x26, 0x1b, 0x63, 0xce, 0x91, 0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60,
+ 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa0, 0x5e, 0x30, 0x10, 0x06, 0x0a,
+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0c, 0x31, 0x02, 0x30, 0x00, 0x30, 0x19,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, 0x0c, 0x06, 0x0a, 0x2b,
+ 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x30, 0x2f, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0x97, 0x6e, 0x29, 0x47, 0xc4, 0x03,
+ 0x68, 0x70, 0x1c, 0x99, 0x2c, 0x61, 0xb0, 0xbc, 0xde, 0x77, 0xe1, 0xa1, 0xeb, 0x4c, 0x1c, 0xac,
+ 0x4c, 0x64, 0xf6, 0x43, 0x96, 0x94, 0x0b, 0xc0, 0xbb, 0x03, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x81, 0x80, 0x85, 0x93, 0xad, 0x93,
+ 0x92, 0x9e, 0xa4, 0x94, 0x30, 0x02, 0xe1, 0xc8, 0xcd, 0x37, 0xb2, 0xe1, 0xcb, 0xb2, 0x0f, 0x1c,
+ 0x67, 0xd1, 0xc9, 0xeb, 0x4d, 0x68, 0x85, 0x97, 0x5a, 0xa6, 0x0c, 0x03, 0xc7, 0x86, 0xae, 0xb3,
+ 0x35, 0xb4, 0x1d, 0x0e, 0x95, 0x5f, 0xed, 0x37, 0x13, 0x6b, 0x1e, 0x94, 0x80, 0xf1, 0xac, 0x55,
+ 0x73, 0xd1, 0x31, 0xf9, 0xad, 0x13, 0x7b, 0x26, 0xbf, 0xe7, 0x55, 0x7b, 0xb2, 0xf9, 0x21, 0x42,
+ 0x23, 0x64, 0xe6, 0x45, 0x03, 0x67, 0xcb, 0x42, 0xd3, 0x71, 0x3f, 0xd5, 0x29, 0x17, 0x4b, 0x49,
+ 0x45, 0x0e, 0x8b, 0xba, 0x1f, 0x15, 0x5a, 0x7f, 0x7b, 0x5e, 0x9b, 0x22, 0x46, 0xa7, 0x9c, 0x0d,
+ 0x25, 0x9c, 0x76, 0x25, 0x02, 0xc8, 0x15, 0x00, 0x51, 0xe6, 0x73, 0x39, 0xac, 0x8d, 0x41, 0x7b,
+ 0xc8, 0x42, 0xc9, 0xdb, 0x1b, 0x16, 0x13, 0xf6, 0x44, 0x32, 0xef, 0x17, 0xa1, 0x82, 0x08, 0x34,
+ 0x30, 0x82, 0x08, 0x30, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01,
+ 0x31, 0x82, 0x08, 0x20,
+ 0x30, 0x82, 0x08, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, 0xa0,
+ 0x82, 0x08, 0x0d, 0x30, 0x82, 0x08, 0x09, 0x02, 0x01, 0x03, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x05,
+ 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x30, 0x81, 0xf6, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x04, 0xa0, 0x81, 0xe6, 0x04, 0x81, 0xe3, 0x30, 0x81, 0xe0,
+ 0x02, 0x01, 0x01, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xb2, 0x31, 0x02, 0x01, 0x01, 0x30,
+ 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, 0xcd, 0x06,
+ 0xf0, 0xbd, 0x8b, 0xcd, 0x5c, 0x2e, 0x5a, 0x7c, 0x42, 0x56, 0x2c, 0x20, 0x4a, 0x15, 0xcb, 0x1d,
+ 0x8b, 0x0e, 0x02, 0x15, 0x00, 0xb6, 0xff, 0x47, 0x05, 0xb6, 0x2d, 0x15, 0xac, 0x3f, 0x5d, 0xd9,
+ 0xcf, 0x9d, 0x54, 0x35, 0x56, 0x7c, 0xc1, 0x6e, 0x8b, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x34, 0x30,
+ 0x37, 0x32, 0x38, 0x30, 0x38, 0x35, 0x30, 0x30, 0x33, 0x5a, 0xa0, 0x81, 0x83, 0xa4, 0x81, 0x80,
+ 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31,
+ 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65,
+ 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e,
+ 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a,
+ 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20,
+ 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03,
+ 0x55, 0x04, 0x03, 0x13, 0x1b, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x54, 0x69, 0x6d, 0x65,
+ 0x20, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72,
+ 0xa0, 0x82, 0x04, 0x97, 0x30, 0x82, 0x04, 0x93, 0x30, 0x82, 0x03, 0x7b, 0xa0, 0x03, 0x02, 0x01,
+ 0x02, 0x02, 0x10, 0x47, 0x8a, 0x8e, 0xfb, 0x59, 0xe1, 0xd8, 0x3f, 0x0c, 0xe1, 0x42, 0xd2, 0xa2,
+ 0x87, 0x07, 0xbe, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x81, 0x95, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31,
+ 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c,
+ 0x61, 0x6b, 0x65, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54,
+ 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
+ 0x0b, 0x13, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73,
+ 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x1d, 0x30, 0x1b, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69,
+ 0x72, 0x73, 0x74, 0x2d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30,
+ 0x30, 0x35, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30,
+ 0x35, 0x31, 0x30, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x12, 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63,
+ 0x68, 0x65, 0x73, 0x74, 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
+ 0x07, 0x53, 0x61, 0x6c, 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x11, 0x43, 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d,
+ 0x69, 0x74, 0x65, 0x64, 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x43,
+ 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6d, 0x70,
+ 0x69, 0x6e, 0x67, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbc, 0x35, 0xa0, 0x36, 0x70,
+ 0x22, 0x81, 0x11, 0xc3, 0xb2, 0x83, 0xb9, 0xd3, 0x28, 0xc6, 0x36, 0xcd, 0x25, 0x6b, 0xa9, 0x7b,
+ 0xb2, 0x1c, 0xf6, 0x9b, 0x51, 0x9c, 0xef, 0x35, 0xf4, 0xed, 0x08, 0x8e, 0x5e, 0x38, 0x08, 0xf8,
+ 0x77, 0x3c, 0x0a, 0x42, 0xe0, 0xf3, 0x70, 0xdc, 0xa3, 0xd7, 0xca, 0xf5, 0x4c, 0x0b, 0xcf, 0xff,
+ 0x22, 0x9c, 0x0a, 0x7e, 0x68, 0xd6, 0x09, 0xa2, 0x2a, 0x84, 0x7b, 0xa6, 0x9d, 0xb4, 0xa9, 0xc1,
+ 0x33, 0xe2, 0xef, 0x1f, 0x17, 0x48, 0xca, 0x3a, 0xcd, 0x46, 0xe6, 0xc5, 0xaa, 0x77, 0xbd, 0xe3,
+ 0x77, 0x9a, 0xfa, 0x47, 0x53, 0x40, 0x28, 0x59, 0x43, 0x93, 0xf1, 0xa4, 0x81, 0xea, 0xef, 0x80,
+ 0xb5, 0x4f, 0xa7, 0x08, 0xce, 0xba, 0x6e, 0xbc, 0xca, 0x76, 0x0c, 0x97, 0x64, 0x59, 0x86, 0x24,
+ 0xbb, 0x3d, 0x82, 0x90, 0xa8, 0x55, 0xb1, 0x92, 0xd3, 0xa0, 0xa7, 0x05, 0xac, 0x9f, 0x53, 0x25,
+ 0x08, 0x10, 0x47, 0x99, 0xcd, 0x98, 0xde, 0x68, 0xe5, 0xb4, 0x50, 0x78, 0xa3, 0xaf, 0x01, 0xcc,
+ 0x59, 0x43, 0x58, 0xe4, 0x76, 0x6e, 0x7e, 0xac, 0xc7, 0xe2, 0x9e, 0x1f, 0x4f, 0xb0, 0x47, 0x2d,
+ 0xc8, 0x0c, 0xa3, 0x49, 0x27, 0x80, 0x75, 0x8c, 0xbb, 0x06, 0x91, 0x65, 0x0f, 0x90, 0x9b, 0xf4,
+ 0xba, 0xd1, 0x81, 0xc8, 0x5c, 0x6a, 0xec, 0x14, 0xe9, 0x25, 0x09, 0xbf, 0x23, 0x16, 0xf4, 0x95,
+ 0x46, 0x40, 0x40, 0x21, 0xbb, 0x83, 0x96, 0xfd, 0x86, 0x1f, 0x7a, 0xc8, 0x0d, 0x10, 0x8e, 0xa2,
+ 0xf8, 0x19, 0x07, 0x58, 0x7f, 0x9f, 0xbd, 0x37, 0x02, 0x60, 0xf2, 0xa4, 0xe9, 0x9d, 0x44, 0x3f,
+ 0x30, 0x05, 0xe4, 0xa7, 0x70, 0x99, 0x51, 0x9a, 0xe8, 0x17, 0xf1, 0x55, 0xca, 0xb2, 0x61, 0x89,
+ 0x65, 0x46, 0xa7, 0x6a, 0xf2, 0x58, 0x46, 0x7e, 0xaa, 0xa0, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01,
+ 0xa3, 0x81, 0xf4, 0x30, 0x81, 0xf1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+ 0x16, 0x80, 0x14, 0xda, 0xed, 0x64, 0x74, 0x14, 0x9c, 0x14, 0x3c, 0xab, 0xdd, 0x99, 0xa9, 0xbd,
+ 0x5b, 0x28, 0x4d, 0x8b, 0x3c, 0xc9, 0xd8, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+ 0x04, 0x14, 0x2e, 0x2d, 0xb0, 0x0a, 0x44, 0x4a, 0xd3, 0x87, 0xc0, 0x02, 0x07, 0xce, 0x97, 0x7d,
+ 0x50, 0x62, 0x20, 0xfd, 0x0f, 0x83, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff,
+ 0x04, 0x04, 0x03, 0x02, 0x06, 0xc0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
+ 0x04, 0x02, 0x30, 0x00, 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c,
+ 0x30, 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x42, 0x06, 0x03,
+ 0x55, 0x1d, 0x1f, 0x04, 0x3b, 0x30, 0x39, 0x30, 0x37, 0xa0, 0x35, 0xa0, 0x33, 0x86, 0x31, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72,
+ 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52,
+ 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x72, 0x6c,
+ 0x30, 0x35, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x29, 0x30, 0x27,
+ 0x30, 0x25, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x19, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72,
+ 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xc8, 0xfb, 0x63, 0xf8, 0x0b,
+ 0x75, 0x75, 0x2c, 0x3a, 0xf1, 0xf2, 0x13, 0xa7, 0x2d, 0xb6, 0xa3, 0x1a, 0x9c, 0xad, 0x01, 0x07,
+ 0xd3, 0x34, 0x8e, 0x77, 0xe0, 0xc2, 0x6e, 0xae, 0x02, 0x5d, 0x48, 0x4f, 0xa4, 0xd2, 0x21, 0xb6,
+ 0x36, 0xfd, 0x2a, 0x35, 0x43, 0x7c, 0x6b, 0xdf, 0x80, 0x87, 0x0b, 0x15, 0xf0, 0x76, 0x32, 0x00,
+ 0xb4, 0xce, 0xb5, 0x67, 0xa4, 0x2f, 0x2f, 0x20, 0x1b, 0x9c, 0x54, 0x9e, 0x83, 0x3f, 0x1f, 0x5f,
+ 0x14, 0x95, 0x62, 0x82, 0x0f, 0x22, 0x41, 0x22, 0x1f, 0x70, 0xb3, 0xf3, 0xf7, 0x42, 0xde, 0x6c,
+ 0x51, 0xcd, 0x4b, 0xf8, 0x21, 0xac, 0x9b, 0x3b, 0x8c, 0xb1, 0xe5, 0xe6, 0x28, 0x8f, 0xce, 0x2a,
+ 0x8a, 0xf9, 0xaa, 0x52, 0x4d, 0x8c, 0x5b, 0x77, 0xba, 0x4d, 0x5a, 0x58, 0xdb, 0xbb, 0x6a, 0x04,
+ 0xcc, 0x52, 0x1e, 0x9d, 0xe2, 0x28, 0x37, 0x0e, 0xbb, 0xe7, 0x0e, 0x91, 0xc7, 0xf8, 0xdb, 0xf1,
+ 0x81, 0x98, 0xeb, 0xcd, 0x37, 0xb3, 0x0e, 0xab, 0x65, 0xd3, 0x62, 0xec, 0x3a, 0xa5, 0x76, 0xeb,
+ 0x13, 0xa8, 0x35, 0x93, 0xc9, 0x2e, 0x0a, 0x01, 0xec, 0xc0, 0xe8, 0xcc, 0x3d, 0x7e, 0xb6, 0xeb,
+ 0xe2, 0xc1, 0xec, 0xd3, 0x14, 0x92, 0x82, 0x66, 0x87, 0x50, 0xdc, 0xfd, 0x50, 0x97, 0xac, 0xb3,
+ 0x4a, 0x76, 0x73, 0x06, 0xc4, 0x86, 0x11, 0x3a, 0xb3, 0x5f, 0x43, 0x04, 0x52, 0x6f, 0xea, 0xb3,
+ 0xd0, 0x74, 0x36, 0x4c, 0xca, 0xf1, 0x1b, 0x79, 0x84, 0x37, 0x70, 0x63, 0xad, 0x74, 0xb9, 0xaa,
+ 0x0e, 0xf3, 0x98, 0xb0, 0x86, 0x08, 0xeb, 0xdb, 0xe0, 0x1f, 0x8c, 0x10, 0xf2, 0x39, 0x64, 0x9b,
+ 0xae, 0x4f, 0x0a, 0x2c, 0x92, 0x8a, 0x4f, 0x18, 0xb5, 0x91, 0xe5, 0x8d, 0x1a, 0x93, 0x5f, 0x1f,
+ 0xae, 0xf1, 0xa6, 0xf0, 0x2e, 0x97, 0xd0, 0xd2, 0xf6, 0x2b, 0x3c, 0x31, 0x82, 0x02, 0x61, 0x30,
+ 0x82, 0x02, 0x5d, 0x02, 0x01, 0x01, 0x30, 0x81, 0xaa, 0x30, 0x81, 0x95, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
+ 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13,
+ 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20, 0x43, 0x69, 0x74, 0x79, 0x31,
+ 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54, 0x68, 0x65, 0x20, 0x55, 0x53,
+ 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x31,
+ 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63,
+ 0x6f, 0x6d, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x55, 0x54, 0x4e,
+ 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d, 0x4f, 0x62, 0x6a, 0x65, 0x63,
+ 0x74, 0x02, 0x10, 0x47, 0x8a, 0x8e, 0xfb, 0x59, 0xe1, 0xd8, 0x3f, 0x0c, 0xe1, 0x42, 0xd2, 0xa2,
+ 0x87, 0x07, 0xbe, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0xa0, 0x81,
+ 0x8c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03, 0x31, 0x0d,
+ 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x04, 0x30, 0x1c, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05, 0x31, 0x0f, 0x17, 0x0d, 0x31, 0x34,
+ 0x30, 0x37, 0x32, 0x38, 0x30, 0x38, 0x35, 0x30, 0x30, 0x33, 0x5a, 0x30, 0x23, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04, 0x31, 0x16, 0x04, 0x14, 0x7a, 0xad, 0x35, 0xdc,
+ 0x5b, 0xd6, 0x00, 0xd7, 0x44, 0xac, 0x80, 0x8f, 0x4f, 0xb6, 0xb4, 0x03, 0x62, 0x34, 0x53, 0xdc,
+ 0x30, 0x2b, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0c, 0x31,
+ 0x1c, 0x30, 0x1a, 0x30, 0x18, 0x30, 0x16, 0x04, 0x14, 0x3d, 0xbb, 0x6d, 0xb5, 0x08, 0x5c, 0x6d,
+ 0xd5, 0xa1, 0xca, 0x7f, 0x9c, 0xf8, 0x4e, 0xcb, 0x1a, 0x39, 0x10, 0xca, 0xc8, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, 0x01, 0x00,
+ 0x73, 0x64, 0xb9, 0xa3, 0x54, 0x6f, 0x50, 0x97, 0x01, 0xa7, 0xf6, 0x0d, 0xb8, 0xce, 0x4b, 0xaa,
+ 0x43, 0xa2, 0x8f, 0xa3, 0xea, 0x93, 0xf2, 0xa3, 0xd0, 0x46, 0xde, 0xdd, 0x45, 0xe5, 0x94, 0x5a,
+ 0x45, 0xc2, 0x13, 0x1b, 0x90, 0x9b, 0xcf, 0x73, 0xcd, 0x28, 0x70, 0xf0, 0xf4, 0x54, 0xb5, 0x2d,
+ 0x31, 0xf9, 0xf3, 0x2d, 0x38, 0x78, 0xfe, 0x68, 0xea, 0x3c, 0xc0, 0xbe, 0x0b, 0x5a, 0x91, 0x49,
+ 0x63, 0xeb, 0x26, 0x32, 0x5b, 0x86, 0xcf, 0xe5, 0x8a, 0xa5, 0x9d, 0xe6, 0x4b, 0x57, 0x91, 0x8f,
+ 0x3c, 0xdc, 0xa6, 0x53, 0xd8, 0xdb, 0x8a, 0xfd, 0x3e, 0x7e, 0x19, 0x6f, 0x27, 0x72, 0x95, 0xc2,
+ 0x79, 0x73, 0xdf, 0xfb, 0x08, 0x5c, 0x5b, 0xc8, 0xb7, 0x94, 0x75, 0x88, 0x7a, 0x9a, 0x85, 0x9f,
+ 0x1b, 0xa3, 0x98, 0x30, 0x91, 0xee, 0xc0, 0x52, 0xd2, 0x75, 0x9c, 0xcb, 0x45, 0x0d, 0x94, 0x43,
+ 0x67, 0x7a, 0x49, 0x1c, 0xb1, 0x89, 0x9d, 0x6e, 0xfa, 0x87, 0xd2, 0x4d, 0x6e, 0x74, 0x90, 0xf5,
+ 0x80, 0x8c, 0x92, 0xda, 0xd9, 0xa1, 0x48, 0x20, 0x31, 0x02, 0x79, 0xde, 0xe3, 0xbd, 0x09, 0x04,
+ 0xa8, 0xd4, 0x99, 0xd7, 0x3b, 0xea, 0xf8, 0xdf, 0xb3, 0xb9, 0xd7, 0xa3, 0x36, 0xa1, 0xdb, 0xd3,
+ 0xec, 0x65, 0x8c, 0xb8, 0x8f, 0xfb, 0xd6, 0xef, 0x9c, 0x32, 0x3e, 0xab, 0x20, 0x74, 0xb9, 0x65,
+ 0x4c, 0xc6, 0x15, 0x2f, 0x31, 0x2a, 0x34, 0x3e, 0x84, 0x09, 0xb4, 0x75, 0xbc, 0xbe, 0xaf, 0xb3,
+ 0x9e, 0x85, 0xf1, 0xbb, 0x99, 0x1a, 0x07, 0xbd, 0x20, 0xa6, 0xed, 0xcf, 0xd1, 0xa6, 0x9a, 0x22,
+ 0xb2, 0x6d, 0x75, 0xf4, 0x23, 0x58, 0x13, 0x78, 0x73, 0x1a, 0xb2, 0x84, 0xde, 0xad, 0xe8, 0x6d,
+ 0xe6, 0xe7, 0x5c, 0xb6, 0xe6, 0x5b, 0x10, 0x37, 0x1f, 0xe3, 0x6e, 0xbd, 0x83, 0xd7, 0x51, 0xb1,
+ 0x00, 0x00, 0x00, 0x00, 0x0a
+ };
+
+//
+// The Comodo Time Stamping Signer Certificate Used for the verification of TimeStamp signature.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 TSTrustedCert[] = {
+ 0x30, 0x82, 0x04, 0x93, 0x30, 0x82, 0x03, 0x7b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x47,
+ 0x8a, 0x8e, 0xfb, 0x59, 0xe1, 0xd8, 0x3f, 0x0c, 0xe1, 0x42, 0xd2, 0xa2, 0x87, 0x07, 0xbe, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x81,
+ 0x95, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x02, 0x55, 0x54, 0x31, 0x17, 0x30, 0x15, 0x06,
+ 0x03, 0x55, 0x04, 0x07, 0x13, 0x0e, 0x53, 0x61, 0x6c, 0x74, 0x20, 0x4c, 0x61, 0x6b, 0x65, 0x20,
+ 0x43, 0x69, 0x74, 0x79, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x54,
+ 0x68, 0x65, 0x20, 0x55, 0x53, 0x45, 0x52, 0x54, 0x52, 0x55, 0x53, 0x54, 0x20, 0x4e, 0x65, 0x74,
+ 0x77, 0x6f, 0x72, 0x6b, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x18, 0x68,
+ 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72,
+ 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03,
+ 0x13, 0x14, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73, 0x74, 0x2d,
+ 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x30, 0x30, 0x35, 0x31, 0x30,
+ 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x35, 0x31, 0x30, 0x32,
+ 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x7e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x47, 0x42, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x12,
+ 0x47, 0x72, 0x65, 0x61, 0x74, 0x65, 0x72, 0x20, 0x4d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x74,
+ 0x65, 0x72, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x53, 0x61, 0x6c,
+ 0x66, 0x6f, 0x72, 0x64, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x11, 0x43,
+ 0x4f, 0x4d, 0x4f, 0x44, 0x4f, 0x20, 0x43, 0x41, 0x20, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x64,
+ 0x31, 0x24, 0x30, 0x22, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1b, 0x43, 0x4f, 0x4d, 0x4f, 0x44,
+ 0x4f, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6d, 0x70, 0x69, 0x6e, 0x67, 0x20,
+ 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
+ 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xbc, 0x35, 0xa0, 0x36, 0x70, 0x22, 0x81, 0x11, 0xc3,
+ 0xb2, 0x83, 0xb9, 0xd3, 0x28, 0xc6, 0x36, 0xcd, 0x25, 0x6b, 0xa9, 0x7b, 0xb2, 0x1c, 0xf6, 0x9b,
+ 0x51, 0x9c, 0xef, 0x35, 0xf4, 0xed, 0x08, 0x8e, 0x5e, 0x38, 0x08, 0xf8, 0x77, 0x3c, 0x0a, 0x42,
+ 0xe0, 0xf3, 0x70, 0xdc, 0xa3, 0xd7, 0xca, 0xf5, 0x4c, 0x0b, 0xcf, 0xff, 0x22, 0x9c, 0x0a, 0x7e,
+ 0x68, 0xd6, 0x09, 0xa2, 0x2a, 0x84, 0x7b, 0xa6, 0x9d, 0xb4, 0xa9, 0xc1, 0x33, 0xe2, 0xef, 0x1f,
+ 0x17, 0x48, 0xca, 0x3a, 0xcd, 0x46, 0xe6, 0xc5, 0xaa, 0x77, 0xbd, 0xe3, 0x77, 0x9a, 0xfa, 0x47,
+ 0x53, 0x40, 0x28, 0x59, 0x43, 0x93, 0xf1, 0xa4, 0x81, 0xea, 0xef, 0x80, 0xb5, 0x4f, 0xa7, 0x08,
+ 0xce, 0xba, 0x6e, 0xbc, 0xca, 0x76, 0x0c, 0x97, 0x64, 0x59, 0x86, 0x24, 0xbb, 0x3d, 0x82, 0x90,
+ 0xa8, 0x55, 0xb1, 0x92, 0xd3, 0xa0, 0xa7, 0x05, 0xac, 0x9f, 0x53, 0x25, 0x08, 0x10, 0x47, 0x99,
+ 0xcd, 0x98, 0xde, 0x68, 0xe5, 0xb4, 0x50, 0x78, 0xa3, 0xaf, 0x01, 0xcc, 0x59, 0x43, 0x58, 0xe4,
+ 0x76, 0x6e, 0x7e, 0xac, 0xc7, 0xe2, 0x9e, 0x1f, 0x4f, 0xb0, 0x47, 0x2d, 0xc8, 0x0c, 0xa3, 0x49,
+ 0x27, 0x80, 0x75, 0x8c, 0xbb, 0x06, 0x91, 0x65, 0x0f, 0x90, 0x9b, 0xf4, 0xba, 0xd1, 0x81, 0xc8,
+ 0x5c, 0x6a, 0xec, 0x14, 0xe9, 0x25, 0x09, 0xbf, 0x23, 0x16, 0xf4, 0x95, 0x46, 0x40, 0x40, 0x21,
+ 0xbb, 0x83, 0x96, 0xfd, 0x86, 0x1f, 0x7a, 0xc8, 0x0d, 0x10, 0x8e, 0xa2, 0xf8, 0x19, 0x07, 0x58,
+ 0x7f, 0x9f, 0xbd, 0x37, 0x02, 0x60, 0xf2, 0xa4, 0xe9, 0x9d, 0x44, 0x3f, 0x30, 0x05, 0xe4, 0xa7,
+ 0x70, 0x99, 0x51, 0x9a, 0xe8, 0x17, 0xf1, 0x55, 0xca, 0xb2, 0x61, 0x89, 0x65, 0x46, 0xa7, 0x6a,
+ 0xf2, 0x58, 0x46, 0x7e, 0xaa, 0xa0, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xf4, 0x30,
+ 0x81, 0xf1, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xda,
+ 0xed, 0x64, 0x74, 0x14, 0x9c, 0x14, 0x3c, 0xab, 0xdd, 0x99, 0xa9, 0xbd, 0x5b, 0x28, 0x4d, 0x8b,
+ 0x3c, 0xc9, 0xd8, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2e, 0x2d,
+ 0xb0, 0x0a, 0x44, 0x4a, 0xd3, 0x87, 0xc0, 0x02, 0x07, 0xce, 0x97, 0x7d, 0x50, 0x62, 0x20, 0xfd,
+ 0x0f, 0x83, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
+ 0x06, 0xc0, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
+ 0x30, 0x16, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x01, 0x01, 0xff, 0x04, 0x0c, 0x30, 0x0a, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x42, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04,
+ 0x3b, 0x30, 0x39, 0x30, 0x37, 0xa0, 0x35, 0xa0, 0x33, 0x86, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3a,
+ 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x55, 0x54, 0x4e, 0x2d, 0x55, 0x53, 0x45, 0x52, 0x46, 0x69, 0x72, 0x73,
+ 0x74, 0x2d, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x35, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0x06, 0x08,
+ 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x19, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xc8, 0xfb, 0x63, 0xf8, 0x0b, 0x75, 0x75, 0x2c, 0x3a,
+ 0xf1, 0xf2, 0x13, 0xa7, 0x2d, 0xb6, 0xa3, 0x1a, 0x9c, 0xad, 0x01, 0x07, 0xd3, 0x34, 0x8e, 0x77,
+ 0xe0, 0xc2, 0x6e, 0xae, 0x02, 0x5d, 0x48, 0x4f, 0xa4, 0xd2, 0x21, 0xb6, 0x36, 0xfd, 0x2a, 0x35,
+ 0x43, 0x7c, 0x6b, 0xdf, 0x80, 0x87, 0x0b, 0x15, 0xf0, 0x76, 0x32, 0x00, 0xb4, 0xce, 0xb5, 0x67,
+ 0xa4, 0x2f, 0x2f, 0x20, 0x1b, 0x9c, 0x54, 0x9e, 0x83, 0x3f, 0x1f, 0x5f, 0x14, 0x95, 0x62, 0x82,
+ 0x0f, 0x22, 0x41, 0x22, 0x1f, 0x70, 0xb3, 0xf3, 0xf7, 0x42, 0xde, 0x6c, 0x51, 0xcd, 0x4b, 0xf8,
+ 0x21, 0xac, 0x9b, 0x3b, 0x8c, 0xb1, 0xe5, 0xe6, 0x28, 0x8f, 0xce, 0x2a, 0x8a, 0xf9, 0xaa, 0x52,
+ 0x4d, 0x8c, 0x5b, 0x77, 0xba, 0x4d, 0x5a, 0x58, 0xdb, 0xbb, 0x6a, 0x04, 0xcc, 0x52, 0x1e, 0x9d,
+ 0xe2, 0x28, 0x37, 0x0e, 0xbb, 0xe7, 0x0e, 0x91, 0xc7, 0xf8, 0xdb, 0xf1, 0x81, 0x98, 0xeb, 0xcd,
+ 0x37, 0xb3, 0x0e, 0xab, 0x65, 0xd3, 0x62, 0xec, 0x3a, 0xa5, 0x76, 0xeb, 0x13, 0xa8, 0x35, 0x93,
+ 0xc9, 0x2e, 0x0a, 0x01, 0xec, 0xc0, 0xe8, 0xcc, 0x3d, 0x7e, 0xb6, 0xeb, 0xe2, 0xc1, 0xec, 0xd3,
+ 0x14, 0x92, 0x82, 0x66, 0x87, 0x50, 0xdc, 0xfd, 0x50, 0x97, 0xac, 0xb3, 0x4a, 0x76, 0x73, 0x06,
+ 0xc4, 0x86, 0x11, 0x3a, 0xb3, 0x5f, 0x43, 0x04, 0x52, 0x6f, 0xea, 0xb3, 0xd0, 0x74, 0x36, 0x4c,
+ 0xca, 0xf1, 0x1b, 0x79, 0x84, 0x37, 0x70, 0x63, 0xad, 0x74, 0xb9, 0xaa, 0x0e, 0xf3, 0x98, 0xb0,
+ 0x86, 0x08, 0xeb, 0xdb, 0xe0, 0x1f, 0x8c, 0x10, 0xf2, 0x39, 0x64, 0x9b, 0xae, 0x4f, 0x0a, 0x2c,
+ 0x92, 0x8a, 0x4f, 0x18, 0xb5, 0x91, 0xe5, 0x8d, 0x1a, 0x93, 0x5f, 0x1f, 0xae, 0xf1, 0xa6, 0xf0,
+ 0x2e, 0x97, 0xd0, 0xd2, 0xf6, 0x2b, 0x3c, 0x0a
+ };
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyImageTimestampVerify (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ BOOLEAN Status;
+ EFI_TIME SigningTime;
+
+ Status = FALSE;
+
+ //
+ // Verify RFC3161 Timestamp CounterSignature.
+ //
+ Status = ImageTimestampVerify (
+ AuthenticodeWithTS,
+ sizeof (AuthenticodeWithTS),
+ TSTrustedCert,
+ sizeof (TSTrustedCert),
+ &SigningTime
+ );
+ UT_ASSERT_TRUE (Status);
+
+ UT_ASSERT_EQUAL (SigningTime.Year, 2014);
+ UT_ASSERT_EQUAL (SigningTime.Month, 7);
+ UT_ASSERT_EQUAL (SigningTime.Day, 28);
+ UT_ASSERT_EQUAL (SigningTime.Hour, 8);
+ UT_ASSERT_EQUAL (SigningTime.Minute, 50);
+ UT_ASSERT_EQUAL (SigningTime.Second, 3);
+
+ return Status;
+}
+
+TEST_DESC mImageTimestampTest[] = {
+ //
+ // -----Description--------------------------------------Class----------------------------Function-----------------Pre---Post--Context
+ //
+ {"TestVerifyImageTimestampVerify()", "CryptoPkg.BaseCryptLib.ImageTimestamp", TestVerifyImageTimestampVerify, NULL, NULL, NULL},
+};
+
+UINTN mImageTimestampTestNum = ARRAY_SIZE(mImageTimestampTest);
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
new file mode 100644
index 00000000000..b44ab35772c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
@@ -0,0 +1,124 @@
+/** @file
+ Application for Cryptographic Primitives Validation.
+
+Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __CRYPTEST_H__
+#define __CRYPTEST_H__
+
+#include <PiPei.h>
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/PrintLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+//#include <UnitTestTypes.h>
+#include <Library/UnitTestLib.h>
+//#include <Library/UnitTestAssertLib.h>
+
+#define UNIT_TEST_NAME "BaseCryptLib Unit Test"
+#define UNIT_TEST_VERSION "1.0"
+
+typedef struct {
+ CHAR8 *Description;
+ CHAR8 *ClassName;
+ UNIT_TEST_FUNCTION Func;
+ UNIT_TEST_PREREQUISITE PreReq;
+ UNIT_TEST_CLEANUP CleanUp;
+ UNIT_TEST_CONTEXT Context;
+} TEST_DESC;
+
+typedef struct {
+ CHAR8 *Title;
+ CHAR8 *Package;
+ UNIT_TEST_SUITE_SETUP Sup;
+ UNIT_TEST_SUITE_TEARDOWN Tdn;
+ UINTN *TestNum;
+ TEST_DESC *TestDesc;
+} SUITE_DESC;
+
+extern UINTN mPkcs7EkuTestNum;
+extern TEST_DESC mPkcs7EkuTest[];
+
+extern UINTN mHashTestNum;
+extern TEST_DESC mHashTest[];
+
+extern UINTN mHmacTestNum;
+extern TEST_DESC mHmacTest[];
+
+extern UINTN mBlockCipherTestNum;
+extern TEST_DESC mBlockCipherTest[];
+
+extern UINTN mRsaTestNum;
+extern TEST_DESC mRsaTest[];
+
+extern UINTN mRsaCertTestNum;
+extern TEST_DESC mRsaCertTest[];
+
+extern UINTN mPkcs7TestNum;
+extern TEST_DESC mPkcs7Test[];
+
+extern UINTN mPkcs5TestNum;
+extern TEST_DESC mPkcs5Test[];
+
+extern UINTN mAuthenticodeTestNum;
+extern TEST_DESC mAuthenticodeTest[];
+
+extern UINTN mImageTimestampTestNum;
+extern TEST_DESC mImageTimestampTest[];
+
+extern UINTN mDhTestNum;
+extern TEST_DESC mDhTest[];
+
+extern UINTN mPrngTestNum;
+extern TEST_DESC mPrngTest[];
+
+extern UINTN mOaepTestNum;
+extern TEST_DESC mOaepTest[];
+
+extern UINTN mRsaPssTestNum;
+extern TEST_DESC mRsaPssTest[];
+
+/** Creates a framework you can use */
+EFI_STATUS
+EFIAPI
+CreateUnitTest (
+ IN CHAR8* UnitTestName,
+ IN CHAR8* UnitTestVersion,
+ IN OUT UNIT_TEST_FRAMEWORK_HANDLE* Framework
+);
+
+/**
+ Validate UEFI-OpenSSL DH Interfaces.
+
+ @retval EFI_SUCCESS Validation succeeded.
+ @retval EFI_ABORTED Validation failed.
+
+**/
+EFI_STATUS
+ValidateCryptDh (
+ VOID
+ );
+
+/**
+ Validate UEFI-OpenSSL pseudorandom number generator interfaces.
+
+ @retval EFI_SUCCESS Validation succeeded.
+ @retval EFI_ABORTED Validation failed.
+
+**/
+EFI_STATUS
+ValidateCryptPrng (
+ VOID
+ );
+
+
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
new file mode 100644
index 00000000000..b28e0b9fb4b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
@@ -0,0 +1,47 @@
+## @file
+# Host-based UnitTest for BaseCryptLib
+#
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCryptLibUnitTestHost
+ FILE_GUID = 0cb84598-824b-4833-b705-bdefdcbba1d5
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ UnitTestMain.c
+ BaseCryptLibUnitTests.c
+ TestBaseCryptLib.h
+ HashTests.c
+ HmacTests.c
+ BlockCipherTests.c
+ RsaTests.c
+ RsaPkcs7Tests.c
+ Pkcs5Pbkdf2Tests.c
+ AuthenticodeTests.c
+ TSTests.c
+ DhTests.c
+ RandTests.c
+ Pkcs7EkuTests.c
+ OaepEncryptTests.c
+ RsaPssTests.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseCryptLib
+ UnitTestLib
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
new file mode 100644
index 00000000000..49683660044
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
@@ -0,0 +1,50 @@
+## @file
+# BaseCryptLib UnitTest built for execution in UEFI Shell.
+#
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = BaseCryptLibUnitTestShell
+ FILE_GUID = ed54ee8c-ef7a-41f2-83d5-0e0d4cd88c21
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = DxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ UnitTestMain.c
+ BaseCryptLibUnitTests.c
+ TestBaseCryptLib.h
+ HashTests.c
+ HmacTests.c
+ BlockCipherTests.c
+ RsaTests.c
+ RsaPkcs7Tests.c
+ Pkcs5Pbkdf2Tests.c
+ AuthenticodeTests.c
+ TSTests.c
+ DhTests.c
+ RandTests.c
+ Pkcs7EkuTests.c
+ OaepEncryptTests.c
+ RsaPssTests.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+ UefiApplicationEntryPoint
+ BaseLib
+ DebugLib
+ UnitTestLib
+ PrintLib
+ BaseCryptLib
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/ChainCreationInstructions.txt b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/ChainCreationInstructions.txt
new file mode 100644
index 00000000000..10bff431eb8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/ChainCreationInstructions.txt
@@ -0,0 +1,92 @@
+--------------------------------------------------------------------------------
+File: ChainCreationInstructions.txt
+
+Description: This folder contains INI files that are required to generate
+ the following test cert chains. Certs will be copied onto the
+ file system AND MY store when they are generated by certreq.exe.
+
+Note that typically certreq.exe operates on INF files, but in this folder
+we use INI files so that our build system does not complain about INF's being
+in the tree, but not in the CryptoPkg.dsc file.
+
+To create your own certificates and signatures for testing, this file demonstrates
+how the test certificate chains and signatures were created.
+
+To create test signatures, run SignFirmwareWithEKUs.cmd (with SignTool.exe in
+your path). You can then use your favorite BinaryToHex converter to convert
+the binary into a byte array that you can include in unit tests.
+
+Copyright (C) Microsoft Corporation. All Rights Reserved.
+--------------------------------------------------------------------------------
+Cert Chain:
+
+ ------------------------------------------
+ | | // Root of trust. ECDSA P521 curve
+ | TestEKUParsingRoot | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+ ------------------------------------------
+ ^
+ |
+ ------------------------------------------
+ | | // Issues subordinate CAs. ECC P384 curve.
+ | TestEKUParsingPolicyCA | // SHA 256 Key Usage:
+ | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+ ------------------------------------------
+ ^
+ |
+ ------------------------------------------
+ | | // Issues end-entity (leaf) signers. ECC P256 curve.
+ | TestEKUParsingIssuingCA | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ | | // Enhanced Key Usage:
+ ------------------------------------------ // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+ ^
+ |
+ --------------------------------------
+ / / // Leaf signer, ECC P256 curve.
+ / TestEKUParsingLeafSigner / // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+ / / // Enhanced Key usages:
+ -------------------------------------- // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+ // 1.3.6.1.4.1.311.76.9.21.1.N, N == Product ID.
+
+
+
+
+---------------------------------------------------------------------------------
+
+
+--- files required ---
+
+TestEKUParsingRoot.ini - This certificate is the root CA under which all CAs live.
+TestEKUParsingPolicyCA.ini - This policy CA will issue subordinate CA's with EKU constraints.
+TestEKUParsingIssuingCA.ini - CA to issue end-entity leafs.
+TestEKUParsingLeafSigner.ini - End-Entity leaf signer.
+TestEKUParsingLeafSignerPid12345.ini - End-Entity, with EKU: 1.3.6.1.4.1.311.76.9.21.1.12345.
+TestEKUParsingNoEKUsInSigner.ini - Leaf with no EKU's specified.
+TestEKUParsingLeafSignerPid1.ini - Test with naming files ini, to get around build complaints.
+--- Commands to execute ---
+
+certreq.exe -new TestEKUParsingRoot.ini TestEKUParsingRoot.cer
+certreq.exe -new -q -cert "TestEKUParsingRoot" TestEKUParsingPolicyCA.ini TestEKUParsingPolicyCA.cer
+certreq.exe -new -q -cert "TestEKUParsingPolicyCA" TestEKUParsingIssuingCA.ini TestEKUParsingIssuingCA.cer
+certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingLeafSigner.ini TestEKUParsingLeafSigner.cer
+certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingLeafSignerPid12345.ini TestEKUParsingLeafSignerPid12345.cer
+certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingNoEKUsInSigner.ini TestEKUParsingNoEKUsInSigner.cer
+certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingLeafSignerPid1.ini TestEKUParsingLeafSignerPid1.cer
+
+---------------------------------------------------------------------------------
+
+Then start mmc->Add certificates, Local Computer/open Personal/Certs and export the keys into the pfx files below.
+Note: You should see a little key on the top left of each cert icon, which means you have the private key
+ for this cert. If you don't see it something is wrong. For each cert, right-click and do all tasks,
+ export. Yes, Export the private key. PCKS#12 format, include all certs in path if possible.
+
+ If we automated the call to certreq above, there is a PowerShell "PKI" cmdlet which has
+ an Export-PfxCertificate command.
+
+Passwords: TestEKUParsingRoot.pfx == TestEKUParsingRoot
+ TestEKUParsingPolicyCA.pfx == TestEKUParsingPolicyCA
+ TestEKUParsingIssuingCA.pfx == TestEKUParsingIssuingCA
+ TestEKUParsingLeafSigner.pfx == TestEKUParsingLeafSigner
+ TestEKUParsingLeafSignerPid12345.pfx == TestEKUParsingLeafSignerPid12345
+ TestEKUParsingNoEKUsInSigner.pfx == TestEKUParsingNoEKUsInSigner
+
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/CreateTestCerts.cmd b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/CreateTestCerts.cmd
new file mode 100644
index 00000000000..6d68afdab77
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/CreateTestCerts.cmd
@@ -0,0 +1,11 @@
+@ECHO OFF
+REM
+REM Use this file to create test certificates.
+REM
+call certreq.exe -new TestEKUParsingRoot.ini TestEKUParsingRoot.cer
+call certreq.exe -new -q -cert "TestEKUParsingRoot" TestEKUParsingPolicyCA.ini TestEKUParsingPolicyCA.cer
+call certreq.exe -new -q -cert "TestEKUParsingPolicyCA" TestEKUParsingIssuingCA.ini TestEKUParsingIssuingCA.cer
+call certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingLeafSigner.ini TestEKUParsingLeafSigner.cer
+call certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingLeafSignerPid12345.ini TestEKUParsingLeafSignerPid12345.cer
+call certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingNoEKUsInSigner.ini TestEKUParsingNoEKUsInSigner.cer
+call certreq.exe -new -q -cert "TestEKUParsingIssuingCA" TestEKUParsingLeafSignerPid1.ini TestEKUParsingLeafSignerPid1.cer
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/SignFirmwareWithEKUs.cmd b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/SignFirmwareWithEKUs.cmd
new file mode 100644
index 00000000000..ce03e33a716
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/SignFirmwareWithEKUs.cmd
@@ -0,0 +1,76 @@
+@ECHO OFF
+REM This script will use various certificates to sign blobs for testing purposes.
+REM
+REM
+REM Our EKU test certificate chain:
+REM ------------------------------------------
+REM | | // Root of trust. ECDSA P521 curve
+REM | TestEKUParsingRoot | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+REM | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+REM ------------------------------------------
+REM ^
+REM |
+REM ------------------------------------------
+REM | | // Issues subordinate CAs. ECC P384 curve.
+REM | TestEKUParsingPolicyCA | // SHA 256 Key Usage:
+REM | | // CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE
+REM ------------------------------------------
+REM ^
+REM |
+REM ------------------------------------------
+REM | | // Issues end-entity (leaf) signers. ECC P256 curve.
+REM | TestEKUParsingIssuingCA | // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+REM | | // Enhanced Key Usage:
+REM ------------------------------------------ // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+REM ^
+REM |
+REM --------------------------------------
+REM / TestEKUParsingLeafSigner && / // Leaf signer, ECC P256 curve.
+REM / TestEKUParsingLeafSignerPid12345 / // SHA 256 Key Usage: CERT_DIGITAL_SIGNATURE_KEY_USAGE
+REM / / // Enhanced Key usages:
+REM -------------------------------------- // 1.3.6.1.4.1.311.76.9.21.1 (Surface firmware signing)
+REM // 1.3.6.1.4.1.311.76.9.21.1.N, N == Product ID.
+REM
+REM
+REM
+REM Dev Note: SignTool.exe must be in your path when running this script.
+
+del *.p7b
+ECHO -------------------------------------------------------------------
+ECHO Press any key 4 times to append time to the test blobs to sign.
+time >> TestSignWithOneEKUInLeafSigner.bin
+time >> TestSignWithTwoEKUsInLeafSignerPid1.bin
+time >> TestSignWithTwoEKUsInLeafSignerPid12345.bin
+time >> TestSignWithNoEKUsInLeafSigner.bin
+
+
+REM
+REM Create a signature with TestEKUParsingLeafSigner.cer which has one EKU in it,
+REM and add the Policy CA in the signature.
+REM
+call signtool.exe sign /fd sha256 /f TestEKUParsingLeafSigner.cer /p7 . /u 1.3.6.1.4.1.311.76.9.21.1 /ac TestEKUParsingPolicyCA.cer /p7co 1.2.840.113549.1.7.1 /p7ce DetachedSignedData /v /debug TestSignWithOneEKUInLeafSigner.bin
+
+REM
+REM Create a signature with two EKU's in the leaf signer. (1.3.6.1.4.1.311.76.9.21.1, and 1.3.6.1.4.1.311.76.9.21.1.1)
+REM
+call signtool.exe sign /fd sha256 /f TestEKUParsingLeafSignerPid1.cer /p7 . /u 1.3.6.1.4.1.311.76.9.21.1.1 /p7co 1.2.840.113549.1.7.1 /p7ce DetachedSignedData /v /debug TestSignWithTwoEKUsInLeafSignerPid1.bin
+
+REM
+REM Create a signature with two EKUs in the leaf (1.3.6.1.4.1.311.76.9.21.1, and 1.3.6.1.4.1.311.76.9.21.1.12345)
+REM
+call signtool.exe sign /fd sha256 /f TestEKUParsingLeafSignerPid12345.cer /p7 . /u 1.3.6.1.4.1.311.76.9.21.1.12345 /p7co 1.2.840.113549.1.7.1 /p7ce DetachedSignedData /v /debug TestSignWithTwoEKUsInLeafSignerPid12345.bin
+
+
+REM
+REM Create a signature with a leaf that does not have any EKUs in the signture.
+REM
+call signtool.exe sign /fd sha256 /f TestEKUParsingNoEKUsInSigner.cer /p7 . /p7co 1.2.840.113549.1.7.1 /p7ce DetachedSignedData /v /debug TestSignWithNoEKUsInLeafSigner.bin
+
+REM
+REM Rename *.p7 to *.p7b
+REM
+rename *.p7 *.p7b
+ECHO ---------------------------------------------------------------------------
+ECHO Now you can use your favorite "Binary To Hex" converter to convert the
+ECHO signatures (P7B files) to byte arrays and add them to AllTestSignatures.h
+ECHO ---------------------------------------------------------------------------
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingIssuingCA.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingIssuingCA.ini
new file mode 100644
index 00000000000..8576783473e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingIssuingCA.ini
@@ -0,0 +1,45 @@
+[Version]
+Signature="$Windows NT$
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; 2.5.29.19 == Basic Constraints for CA
+[Strings]
+szOID_BASIC_CONSTRAINTS2 = "2.5.29.19"
+
+[EnhancedKeyUsageExtension]
+OID = 1.3.6.1.4.1.311.76.9.21.1
+
+[NewRequest]
+Subject = "CN=TestEKUParsingIssuingCA"
+Exportable = true
+KeyLength = 256
+HashAlgorithm = sha256
+KeyUsage = "CERT_KEY_CERT_SIGN_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 20
+ValidityPeriod = Years
+ProviderName = "Microsoft Software Key Storage Provider"
+KeyAlgorithm = "ECDSA_P256"
+
+
+[Extensions]
+%szOID_BASIC_CONSTRAINTS2% = "{text}"
+ _continue_ = "ca=True"
+
+Critical=%szOID_BASIC_CONSTRAINTS2%
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; This extension is so the this CA is only allowed to
+; issue end-entity certs.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[BasicConstraintsExtension]
+PathLength=0
+
+;
+; Surface Firmware Signing EKU
+;
+[Extensions]
+ 2.5.29.37 = "{text}"
+ _continue_ = "1.3.6.1.4.1.311.76.9.21.1"
+
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSigner.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSigner.ini
new file mode 100644
index 00000000000..f501537343c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSigner.ini
@@ -0,0 +1,25 @@
+[Version]
+Signature="$Windows NT$
+
+[EnhancedKeyUsageExtension]
+OID = 1.3.6.1.4.1.311.76.9.21.1
+
+[NewRequest]
+Subject = "CN=TestEKUParsingLeafSigner"
+Exportable = true
+KeyLength = 256
+HashAlgorithm = sha256
+KeyUsage = "CERT_DIGITAL_SIGNATURE_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 20
+ValidityPeriod = Years
+ProviderName = "Microsoft Software Key Storage Provider"
+KeyAlgorithm = "ECDSA_P256"
+
+;
+; Surface test firwmare signing EKU
+;
+[Extensions]
+ _continue_ = "1.3.6.1.4.1.311.76.9.21.1"
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid1.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid1.ini
new file mode 100644
index 00000000000..35aa78c493b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid1.ini
@@ -0,0 +1,24 @@
+[Version]
+Signature="$Windows NT$
+
+[EnhancedKeyUsageExtension]
+OID = 1.3.6.1.4.1.311.76.9.21.1
+OID = 1.3.6.1.4.1.311.76.9.21.1.1
+
+[NewRequest]
+Subject = "CN=TestEKUParsingLeafSignerPid1"
+Exportable = true
+KeyLength = 2048
+HashAlgorithm = sha256
+KeySpec = AT_SIGNATURE
+KeyUsage = "CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 5
+ValidityPeriod = Years
+
+[Extensions]
+ 2.5.29.37 = "{text}"
+ _continue_ = "1.3.6.1.4.1.311.76.9.21.1,"
+ _continue_ = "1.3.6.1.4.1.311.76.9.21.1.1"
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid12345.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid12345.ini
new file mode 100644
index 00000000000..67c5741f4d2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingLeafSignerPid12345.ini
@@ -0,0 +1,27 @@
+[Version]
+Signature="$Windows NT$
+
+[EnhancedKeyUsageExtension]
+OID = 1.3.6.1.4.1.311.76.9.21.1
+OID = 1.3.6.1.4.1.311.76.9.21.1.12345
+
+[NewRequest]
+Subject = "CN=TestEKUParsingLeafSignerPid12345"
+Exportable = true
+KeyLength = 2048
+HashAlgorithm = sha256
+KeySpec = AT_SIGNATURE
+KeyUsage = "CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 5
+ValidityPeriod = Years
+
+[Extensions]
+ 2.5.29.37 = "{text}"
+ _continue_ = "1.3.6.1.4.1.311.76.9.21.1,"
+ _continue_ = "1.3.6.1.4.1.311.76.9.21.1.12345"
+
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingNoEKUsInSigner.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingNoEKUsInSigner.ini
new file mode 100644
index 00000000000..60743b02a94
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingNoEKUsInSigner.ini
@@ -0,0 +1,16 @@
+[Version]
+Signature="$Windows NT$
+
+
+[NewRequest]
+Subject = "CN=TestEKUParsingNoEKUsInSigner"
+Exportable = true
+KeyLength = 2048
+HashAlgorithm = sha256
+KeySpec = AT_SIGNATURE
+KeyUsage = "CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 20
+ValidityPeriod = Years
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingPolicyCA.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingPolicyCA.ini
new file mode 100644
index 00000000000..2ccda66596b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingPolicyCA.ini
@@ -0,0 +1,28 @@
+[Version]
+Signature="$Windows NT$
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; 2.5.29.19 == Basic Constraints for CA
+[Strings]
+szOID_BASIC_CONSTRAINTS2 = "2.5.29.19"
+
+[NewRequest]
+Subject = "CN=TestEKUParsingPolicyCA"
+Exportable = true
+KeyLength = 384
+HashAlgorithm = sha256
+KeyUsage = "CERT_KEY_CERT_SIGN_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 20
+ValidityPeriod = Years
+ProviderName = "Microsoft Software Key Storage Provider"
+KeyAlgorithm = "ECDSA_P384"
+
+
+[Extensions]
+%szOID_BASIC_CONSTRAINTS2% = "{text}"
+ _continue_ = "ca=True"
+
+Critical=%szOID_BASIC_CONSTRAINTS2%
+
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingRoot.ini b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingRoot.ini
new file mode 100644
index 00000000000..d8cd7d1f82a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestEKUCerts/TestEKUParsingRoot.ini
@@ -0,0 +1,28 @@
+[Version]
+Signature="$Windows NT$
+
+[Strings]
+szOID_BASIC_CONSTRAINTS2 = "2.5.29.19"
+
+[NewRequest]
+Subject = "CN=TestEKUParsingRoot"
+Exportable = true
+KeyLength = 521
+HashAlgorithm = sha256
+KeyUsage = "CERT_DIGITAL_SIGNATURE_KEY_USAGE | CERT_KEY_CERT_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE"
+KeyUsageProperty = "NCRYPT_ALLOW_SIGNING_FLAG"
+MachineKeySet = True
+RequestType = cert
+ValidityPeriodUnits = 30
+ValidityPeriod = Years
+ProviderName = "Microsoft Software Key Storage Provider"
+KeyAlgorithm = ECDSA_P521
+
+
+
+
+[Extensions]
+%szOID_BASIC_CONSTRAINTS2% = "{text}"
+ _continue_ = "ca=True"
+
+Critical=%szOID_BASIC_CONSTRAINTS2%
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/UnitTestMain.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/UnitTestMain.c
new file mode 100644
index 00000000000..f13bb6b5145
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/UnitTestMain.c
@@ -0,0 +1,81 @@
+/** @file
+ This is a sample to demostrate the usage of the Unit Test Library that
+ supports the PEI, DXE, SMM, UEFI SHell, and host execution environments.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "TestBaseCryptLib.h"
+
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ sample unit tests and run the unit tests.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+EFI_STATUS
+EFIAPI
+UefiTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+
+ DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION ));
+ CreateUnitTest(UNIT_TEST_NAME, UNIT_TEST_VERSION, &Framework);
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+ if (Framework) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard PEIM entry point for target based unit test execution from PEI.
+**/
+EFI_STATUS
+EFIAPI
+PeiEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ return UefiTestMain ();
+}
+
+/**
+ Standard UEFI entry point for target based unit test execution from DXE, SMM,
+ UEFI Shell.
+**/
+EFI_STATUS
+EFIAPI
+DxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return UefiTestMain ();
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+**/
+int
+main (
+ int argc,
+ char *argv[]
+ )
+{
+ return UefiTestMain ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
index 246df5a2be7..f1b5d4da817 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf
@@ -1,7 +1,7 @@
## @file
# Module to manage the list of available table factories.
#
-# Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+# Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
@@ -41,9 +41,9 @@
UefiDriverEntryPoint
[FixedPcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomDTGenerators
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomACPIGenerators
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomDTGenerators
[Protocols]
gEdkiiDynamicTableFactoryProtocolGuid # PRODUCES
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTables.dsc.inc b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTables.dsc.inc
index 9b173a85fd0..d432e673ae1 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTables.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTables.dsc.inc
@@ -1,7 +1,7 @@
## @file
# Dsc include file for Dynamic Tables Framework.
#
-# Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -10,13 +10,33 @@
[Defines]
[BuildOptions]
- *_*_*_ASL_FLAGS = -tc -li -so
+ RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
[LibraryClasses.common]
+ AmlLib|DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
+ SsdtSerialPortFixupLib|DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
TableHelperLib|DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
[Components.common]
#
+ # Generators
+ #
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiFadtLibArm/AcpiFadtLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiGtdtLibArm/AcpiGtdtLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/AcpiIortLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/AcpiMadtLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiMcfgLibArm/AcpiMcfgLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiPpttLibArm/AcpiPpttLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
+
+ # AML Fixup
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
+ DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
+
+ #
# Dynamic Table Factory Dxe
#
DynamicTablesPkg/Drivers/DynamicTableFactoryDxe/DynamicTableFactoryDxe.inf {
@@ -31,6 +51,10 @@
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiRawLibArm/AcpiRawLibArm.inf
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/AcpiSratLibArm.inf
+
+ # AML Fixup
+ NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
+ NULL|DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
}
#
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.ci.yaml
new file mode 100644
index 00000000000..1f96ffe9a05
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.ci.yaml
@@ -0,0 +1,104 @@
+## @file
+# CI configuration for DynamicTablesPkg
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ ## options defined .pytool/Plugin/CompilerPlugin
+ "CompilerPlugin": {
+ "DscPath": "DynamicTablesPkg.dsc"
+ },
+
+ ## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
+ "HostUnitTestCompilerPlugin": {
+ "DscPath": "" # Don't support this test
+ },
+
+ ## options defined .pytool/Plugin/CharEncodingCheck
+ "CharEncodingCheck": {
+ "IgnoreFiles": []
+ },
+
+ ## options defined .pytool/Plugin/DependencyCheck
+ "DependencyCheck": {
+ "AcceptableDependencies": [
+ "ArmPlatformPkg/ArmPlatformPkg.dec",
+ "EmbeddedPkg/EmbeddedPkg.dec",
+ "DynamicTablesPkg/DynamicTablesPkg.dec",
+ "MdeModulePkg/MdeModulePkg.dec",
+ "MdePkg/MdePkg.dec"
+ ],
+ # For host based unit tests
+ "AcceptableDependencies-HOST_APPLICATION":[
+ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
+ ],
+ # For UEFI shell based apps
+ "AcceptableDependencies-UEFI_APPLICATION":[],
+ "IgnoreInf": []
+ },
+
+ ## options defined .pytool/Plugin/DscCompleteCheck
+ "DscCompleteCheck": {
+ "IgnoreInf": [],
+ "DscPath": "DynamicTablesPkg.dsc"
+ },
+
+ ## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck
+ "HostUnitTestDscCompleteCheck": {
+ "IgnoreInf": [""],
+ "DscPath": "" # Don't support this test
+ },
+
+ ## options defined .pytool/Plugin/GuidCheck
+ "GuidCheck": {
+ "IgnoreGuidName": [],
+ "IgnoreGuidValue": [],
+ "IgnoreFoldersAndFiles": [],
+ "IgnoreDuplicates": [],
+ },
+
+ ## options defined .pytool/Plugin/LibraryClassCheck
+ "LibraryClassCheck": {
+ "IgnoreHeaderFile": []
+ },
+
+ ## options defined .pytool/Plugin/SpellCheck
+ "SpellCheck": {
+ "AuditOnly": False,
+ "IgnoreFiles": [], # use gitignore syntax to ignore errors
+ # in matching files
+ "ExtendWords": [
+ "ARMHB", # ARMHB000
+ "ARMHC", # ARMHC600
+ "ARMLTD",
+ "AMLDBG",
+ "EISAID",
+ "CCIDX",
+ "CCSIDR",
+ "countof",
+ "EOBJECT",
+ "invoc",
+ "GTBLOCK",
+ "lgreater",
+ "lless",
+ "MPIDR",
+ "PERIPHBASE",
+ "pytool",
+ "Roadmap",
+ "ROOTNODEBASE",
+ "ssdtcmn",
+ "ssdtserialporttemplate",
+ "SMMUV",
+ "standardised",
+ "TABLEEX",
+ "TNSID",
+ "Vatos",
+ "WBINVD"
+ ], # words to extend to the dictionary for this package
+ "IgnoreStandardPaths": [], # Standard Plugin defined paths that
+ # should be ignore
+ "AdditionalIncludePaths": [] # Additional paths to spell check
+ # (wildcards supported)
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dec b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dec
index c67f7128d12..a9a6073b2db 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dec
@@ -1,7 +1,7 @@
## @file
# dec file for Dynamic Tables Framework.
#
-# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR>
+# Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -16,8 +16,17 @@
[Includes]
Include
-[Protocols]
+[LibraryClasses]
+ ## @libraryclass Defines a set of APIs for Dynamic AML generation.
+ AmlLib|Include/Library/AmlLib/AmlLib.h
+
+ ## @libraryclass Defines a set of methods for fixing up a SSDT Serial Port.
+ SsdtSerialPortFixupLib|Include/Library/SsdtSerialPortFixupLib.h
+
+ ## @libraryclass Defines a set of helper methods.
+ TableHelperLib|Include/Library/TableHelperLib.h
+[Protocols]
# Configuration Manager Protocol GUID
gEdkiiConfigurationManagerProtocolGuid = { 0xd85a4835, 0x5a82, 0x4894, { 0xac, 0x2, 0x70, 0x6f, 0x43, 0xd5, 0x97, 0x8e } }
@@ -27,11 +36,16 @@
[PcdsFixedAtBuild]
# Maximum number of Custom ACPI Generators
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT16|0xC0000001
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomACPIGenerators|1|UINT16|0xC0000001
# Maximum number of Custom SMBIOS Generators
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UINT16|0xC0000002
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomSMBIOSGenerators|1|UINT16|0xC0000002
# Maximum number of Custom DT Generators
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxCustomDTGenerators|1|UINT16|0xC0000003
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdMaxCustomDTGenerators|1|UINT16|0xC0000003
+
+ # Non BSA Compliant 16550 Serial HID
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdNonBsaCompliant16550SerialHid|""|VOID*|0x40000008
+[Guids]
+ gEdkiiDynamicTablesPkgTokenSpaceGuid = { 0xab226e66, 0x31d8, 0x4613, { 0x87, 0x9d, 0xd2, 0xfa, 0xb6, 0x10, 0x26, 0x3c } }
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dsc b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dsc
index a78f3871487..014508dfbc5 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/DynamicTablesPkg.dsc
@@ -2,7 +2,7 @@
# Dsc file for Dynamic Tables Framework.
#
# Copyright (c) 2019, Linaro Limited. All rights reserved.<BR>
-# Copyright (c) 2019, ARM Limited. All rights reserved.<BR>
+# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -20,6 +20,8 @@
!include DynamicTables.dsc.inc
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
@@ -36,10 +38,12 @@
PL011UartLib|ArmPlatformPkg/Library/PL011UartLib/PL011UartLib.inf
[Components.common]
+ DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
+ DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
DynamicTablesPkg/Library/Common/TableHelperLib/TableHelperLib.inf
[BuildOptions]
- *_*_*_CC_FLAGS = -DDISABLE_NEW_DEPRECATED_INTERFACES
+ *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
!ifdef STATIC_ANALYSIS
# Check all rules
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/AcpiTableGenerator.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/AcpiTableGenerator.h
index 8155d085261..4283a97e7c5 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/AcpiTableGenerator.h
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/AcpiTableGenerator.h
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -55,6 +55,14 @@ The Dynamic Tables Framework implements the following ACPI table generators:
the Configuration Manager and builds the PPTT table.
- SRAT : The SRAT generator collates the system resource affinity information
from the Configuration Manager and builds the SRAT table.
+ - SSDT Serial-Port:
+ The SSDT Serial generator collates the Serial port information
+ from the Configuration Manager and patches the SSDT Serial Port
+ template to build the SSDT Serial port table.
+ - SSDT CMN-600:
+ The SSDT CMN-600 generator collates the CMN-600 information
+ from the Configuration Manager and patches the SSDT CMN-600
+ template to build the SSDT CMN-600 table.
*/
/** The ACPI_TABLE_GENERATOR_ID type describes ACPI table generator ID.
@@ -78,6 +86,8 @@ typedef enum StdAcpiTableId {
EStdAcpiTableIdIort, ///< IORT Generator
EStdAcpiTableIdPptt, ///< PPTT Generator
EStdAcpiTableIdSrat, ///< SRAT Generator
+ EStdAcpiTableIdSsdtSerialPort, ///< SSDT Serial-Port Generator
+ EStdAcpiTableIdSsdtCmn600, ///< SSDT Cmn-600 Generator
EStdAcpiTableIdMax
} ESTD_ACPI_TABLE_ID;
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/ArmNameSpaceObjects.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
index 91a3fdc2a04..0bf48406a6b 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/ArmNameSpaceObjects.h
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -56,6 +56,8 @@ typedef enum ArmObjectID {
EArmObjDeviceHandleAcpi, ///< 32 - Device Handle Acpi
EArmObjDeviceHandlePci, ///< 33 - Device Handle Pci
EArmObjGenericInitiatorAffinityInfo, ///< 34 - Generic Initiator Affinity
+ EArmObjSerialPortInfo, ///< 35 - Generic Serial Port Info
+ EArmObjCmn600Info, ///< 36 - CMN-600 Info
EArmObjMax
} EARM_OBJECT_ID;
@@ -270,7 +272,8 @@ typedef struct CmArmGicItsInfo {
Serial Port information for the Platform.
ID: EArmObjSerialConsolePortInfo or
- EArmObjSerialDebugPortInfo
+ EArmObjSerialDebugPortInfo or
+ EArmObjSerialPortInfo
*/
typedef struct CmArmSerialPortInfo {
/// The physical base address for the serial port
@@ -287,6 +290,12 @@ typedef struct CmArmSerialPortInfo {
/// Serial Port subtype
UINT16 PortSubtype;
+
+ /// The Base address length
+ UINT64 BaseAddressLength;
+
+ /// The access size
+ UINT8 AccessSize;
} CM_ARM_SERIAL_PORT_INFO;
/** A structure that describes the
@@ -460,16 +469,6 @@ typedef struct CmArmItsGroupNode {
} CM_ARM_ITS_GROUP_NODE;
/** A structure that describes the
- GIC ITS Identifiers for an ITS Group node.
-
- ID: EArmObjGicItsIdentifierArray
-*/
-typedef struct CmArmGicItsIdentifier {
- /// The ITS Identifier
- UINT32 ItsId;
-} CM_ARM_ITS_IDENTIFIER;
-
-/** A structure that describes the
Named component node for the Platform.
ID: EArmObjNamedComponent
@@ -631,6 +630,16 @@ typedef struct CmArmPmcgNode {
} CM_ARM_PMCG_NODE;
/** A structure that describes the
+ GIC ITS Identifiers for an ITS Group node.
+
+ ID: EArmObjGicItsIdentifierArray
+*/
+typedef struct CmArmGicItsIdentifier {
+ /// The ITS Identifier
+ UINT32 ItsId;
+} CM_ARM_ITS_IDENTIFIER;
+
+/** A structure that describes the
ID Mappings for the Platform.
ID: EArmObjIdMappingArray
@@ -648,18 +657,35 @@ typedef struct CmArmIdMapping {
UINT32 Flags;
} CM_ARM_ID_MAPPING;
-/** A structure that describes the
- SMMU interrupts for the Platform.
-
- ID: EArmObjSmmuInterruptArray
+/** A structure that describes the Arm
+ Generic Interrupts.
*/
-typedef struct CmArmSmmuInterrupt {
+typedef struct CmArmGenericInterrupt {
/// Interrupt number
UINT32 Interrupt;
/// Flags
UINT32 Flags;
-} CM_ARM_SMMU_INTERRUPT;
+} CM_ARM_GENERIC_INTERRUPT;
+
+/** A structure that describes the SMMU interrupts for the Platform.
+
+ Interrupt Interrupt number.
+ Flags Interrupt flags as defined for SMMU node.
+
+ ID: EArmObjSmmuInterruptArray
+*/
+typedef CM_ARM_GENERIC_INTERRUPT CM_ARM_SMMU_INTERRUPT;
+
+/** A structure that describes the AML Extended Interrupts.
+
+ Interrupt Interrupt number.
+ Flags Interrupt flags as defined by the Interrupt
+ Vector Flags (Byte 3) of the Extended Interrupt
+ resource descriptor.
+ See EFI_ACPI_EXTENDED_INTERRUPT_FLAG_xxx in Acpi10.h
+*/
+typedef CM_ARM_GENERIC_INTERRUPT CM_ARM_EXTENDED_INTERRUPT;
/** A structure that describes the Processor Hierarchy Node (Type 0) in PPTT
@@ -682,7 +708,7 @@ typedef struct CmArmProcHierarchyInfo {
UINT32 NoOfPrivateResources;
/// Token of the array which contains references to the resources private to
/// this CM_ARM_PROC_HIERARCHY_INFO instance. This field is ignored if
- /// the NoOfPrivateResources is 0, in which case it is recomended to set
+ /// the NoOfPrivateResources is 0, in which case it is recommended to set
/// this field to CM_NULL_TOKEN.
CM_OBJECT_TOKEN PrivateResourcesArrayToken;
} CM_ARM_PROC_HIERARCHY_INFO;
@@ -795,7 +821,7 @@ typedef struct CmArmDeviceHandlePci {
/// PCI Bus Number - Max 256 busses (Bits 15:8 of BDF)
UINT8 BusNumber;
- /// PCI Device Mumber - Max 32 devices (Bits 7:3 of BDF)
+ /// PCI Device Number - Max 32 devices (Bits 7:3 of BDF)
UINT8 DeviceNumber;
/// PCI Function Number - Max 8 functions (Bits 2:0 of BDF)
@@ -820,6 +846,38 @@ typedef struct CmArmGenericInitiatorAffinityInfo {
CM_OBJECT_TOKEN DeviceHandleToken;
} CM_ARM_GENERIC_INITIATOR_AFFINITY_INFO;
+/** A structure that describes the CMN-600 hardware.
+
+ ID: EArmObjCmn600Info
+*/
+typedef struct CmArmCmn600Info {
+ /// The PERIPHBASE address.
+ /// Corresponds to the Configuration Node Region (CFGR) base address.
+ UINT64 PeriphBaseAddress;
+
+ /// The PERIPHBASE address length.
+ /// Corresponds to the CFGR base address length.
+ UINT64 PeriphBaseAddressLength;
+
+ /// The ROOTNODEBASE address.
+ /// Corresponds to the Root node (ROOT) base address.
+ UINT64 RootNodeBaseAddress;
+
+ /// The Debug and Trace Logic Controller (DTC) count.
+ /// CMN-600 can have maximum 4 DTCs.
+ UINT8 DtcCount;
+
+ /// DTC Interrupt list.
+ /// The first interrupt resource descriptor pertains to
+ /// DTC[0], the second to DTC[1] and so on.
+ /// DtcCount determines the number of DTC Interrupts that
+ /// are populated. If DTC count is 2 then DtcInterrupt[2]
+ /// and DtcInterrupt[3] are ignored.
+ /// Note: The size of CM_ARM_CMN_600_INFO structure remains
+ /// constant and does not vary with the DTC count.
+ CM_ARM_EXTENDED_INTERRUPT DtcInterrupt[4];
+} CM_ARM_CMN_600_INFO;
+
#pragma pack()
#endif // ARM_NAMESPACE_OBJECTS_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
new file mode 100644
index 00000000000..51fbf40f6c2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -0,0 +1,631 @@
+/** @file
+ AML Lib.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_LIB_H_
+#define AML_LIB_H_
+
+/**
+ @mainpage Dynamic AML Generation
+ @{
+ @par Summary
+ @{
+ ACPI tables are categorized as data tables and definition block
+ tables. Dynamic Tables Framework currently supports generation of ACPI
+ data tables. Generation of definition block tables is difficult as these
+ tables are encoded in ACPI Machine Language (AML), which has a complex
+ grammar.
+
+ Dynamic AML Generation is an extension to the Dynamic tables Framework.
+ One of the techniques used to simplify definition block generation is to
+ fixup a template SSDT table.
+
+ Dynamic AML aims to provide a framework that allows fixing up of an ACPI
+ SSDT template with appropriate information about the hardware.
+
+ This framework consists of an:
+ - AMLLib core that implements a rich set of interfaces to parse, traverse
+ and update AML data.
+ - AMLLib library APIs that provides interfaces to search and updates nodes
+ in the AML namespace.
+ @}
+ @}
+*/
+
+#include <IndustryStandard/Acpi.h>
+
+#ifndef AML_HANDLE
+
+/** Node handle.
+*/
+typedef void* AML_NODE_HANDLE;
+
+/** Root Node handle.
+*/
+typedef void* AML_ROOT_NODE_HANDLE;
+
+/** Object Node handle.
+*/
+typedef void* AML_OBJECT_NODE_HANDLE;
+
+/** Data Node handle.
+*/
+typedef void* AML_DATA_NODE_HANDLE;
+
+#endif // AML_HANDLE
+
+/** Parse the definition block.
+
+ The function parses the whole AML blob. It starts with the ACPI DSDT/SSDT
+ header and then parses the AML bytestream.
+ A tree structure is returned via the RootPtr.
+ The tree must be deleted with the AmlDeleteTree function.
+
+ @ingroup UserApis
+
+ @param [in] DefinitionBlock Pointer to the definition block.
+ @param [out] RootPtr Pointer to the root node of the AML tree.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseDefinitionBlock (
+ IN CONST EFI_ACPI_DESCRIPTION_HEADER * DefinitionBlock,
+ OUT AML_ROOT_NODE_HANDLE * RootPtr
+ );
+
+/** Serialize an AML definition block.
+
+ This functions allocates memory with the "AllocateZeroPool ()"
+ function. This memory is used to serialize the AML tree and is
+ returned in the Table.
+
+ @ingroup UserApis
+
+ @param [in] RootNode Root node of the tree.
+ @param [out] Table On return, hold the serialized
+ definition block.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlSerializeDefinitionBlock (
+ IN AML_ROOT_NODE_HANDLE RootNode,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ );
+
+/** Clone a node and its children (clone a tree branch).
+
+ The cloned branch returned is not attached to any tree.
+
+ @ingroup UserApis
+
+ @param [in] Node Pointer to a node.
+ Node is the head of the branch to clone.
+ @param [out] ClonedNode Pointer holding the head of the created cloned
+ branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCloneTree (
+ IN AML_NODE_HANDLE Node,
+ OUT AML_NODE_HANDLE * ClonedNode
+ );
+
+/** Delete a Node and its children.
+
+ The Node must be removed from the tree first,
+ or must be the root node.
+
+ @ingroup UserApis
+
+ @param [in] Node Pointer to the node to delete.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteTree (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Detach the Node from the tree.
+
+ The function will fail if the Node is in its parent's fixed
+ argument list.
+ The Node is not deleted. The deletion is done separately
+ from the removal.
+
+ @ingroup UserApis
+
+ @param [in] Node Pointer to a Node.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDetachNode (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Find a node in the AML namespace, given an ASL path and a reference Node.
+
+ - The AslPath can be an absolute path, or a relative path from the
+ reference Node;
+ - Node must be a root node or a namespace node;
+ - A root node is expected to be at the top of the tree.
+
+ E.g.:
+ For the following AML namespace, with the ReferenceNode being the node with
+ the name "AAAA":
+ - the node with the name "BBBB" can be found by looking for the ASL
+ path "BBBB";
+ - the root node can be found by looking for the ASL relative path "^",
+ or the absolute path "\\".
+
+ AML namespace:
+ \
+ \-AAAA <- ReferenceNode
+ \-BBBB
+
+ @ingroup NameSpaceApis
+
+ @param [in] ReferenceNode Reference node.
+ If a relative path is given, the
+ search is done from this node. If
+ an absolute path is given, the
+ search is done from the root node.
+ Must be a root node or an object
+ node which is part of the
+ namespace.
+ @param [in] AslPath ASL path to the searched node in
+ the namespace. An ASL path name is
+ NULL terminated. Can be a relative
+ or absolute path.
+ E.g.: "\\_SB.CLU0.CPU0" or "^CPU0"
+ @param [out] OutNode Pointer to the found node.
+ Contains NULL if not found.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlFindNode (
+ IN AML_NODE_HANDLE ReferenceNode,
+ IN CHAR8 * AslPath,
+ OUT AML_NODE_HANDLE * OutNode
+ );
+
+/**
+ @defgroup UserApis User APIs
+ @{
+ User APIs are implemented to ease most common actions that might be done
+ using the AmlLib. They allow to find specific objects like "_UID" or
+ "_CRS" and to update their value. It also shows what can be done using
+ AmlLib functions.
+ @}
+*/
+
+/** Update the name of a DeviceOp object node.
+
+ @ingroup UserApis
+
+ @param [in] DeviceOpNode Object node representing a Device.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ OpCode/SubOpCode.
+ DeviceOp object nodes are defined in ASL
+ using the "Device ()" function.
+ @param [in] NewNameString The new Device's name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeviceOpUpdateName (
+ IN AML_OBJECT_NODE_HANDLE DeviceOpNode,
+ IN CHAR8 * NewNameString
+ );
+
+/** Update an integer value defined by a NameOp object node.
+
+ For compatibility reasons, the NameOpNode must initially
+ contain an integer.
+
+ @ingroup UserApis
+
+ @param [in] NameOpNode NameOp object node.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] NewInt New Integer value to assign.
+ Must be a UINT64.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpUpdateInteger (
+ IN AML_OBJECT_NODE_HANDLE NameOpNode,
+ IN UINT64 NewInt
+ );
+
+/** Update a string value defined by a NameOp object node.
+
+ The NameOpNode must initially contain a string.
+ The EISAID ASL macro converts a string to an integer. This, it is
+ not accepted.
+
+ @ingroup UserApis
+
+ @param [in] NameOpNode NameOp object node.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] NewName New NULL terminated string to assign to
+ the NameOpNode.
+ The input string is copied.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpUpdateString (
+ IN AML_OBJECT_NODE_HANDLE NameOpNode,
+ IN CONST CHAR8 * NewName
+ );
+
+/** Get the first Resource Data element contained in a "_CRS" object.
+
+ In the following ASL code, the function will return the Resource Data
+ node corresponding to the "QWordMemory ()" ASL macro.
+ Name (_CRS, ResourceTemplate() {
+ QWordMemory (...) {...},
+ Interrupt (...) {...}
+ }
+ )
+
+ Note:
+ - The "_CRS" object must be declared using ASL "Name (Declare Named Object)".
+ - "_CRS" declared using ASL "Method (Declare Control Method)" is not
+ supported.
+
+ @ingroup UserApis
+
+ @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [out] OutRdNode Pointer to the first Resource Data element of
+ the "_CRS" object. A Resource Data element
+ is stored in a data node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpCrsGetFirstRdNode (
+ IN AML_OBJECT_NODE_HANDLE NameOpCrsNode,
+ OUT AML_DATA_NODE_HANDLE * OutRdNode
+ );
+
+/** Get the Resource Data element following the CurrRdNode Resource Data.
+
+ In the following ASL code, if CurrRdNode corresponds to the first
+ "QWordMemory ()" ASL macro, the function will return the Resource Data
+ node corresponding to the "Interrupt ()" ASL macro.
+ Name (_CRS, ResourceTemplate() {
+ QwordMemory (...) {...},
+ Interrupt (...) {...}
+ }
+ )
+
+ The CurrRdNode Resource Data node must be defined in an object named "_CRS"
+ and defined by a "Name ()" ASL function.
+
+ @ingroup UserApis
+
+ @param [in] CurrRdNode Pointer to the current Resource Data element of
+ the "_CRS" variable.
+ @param [out] OutRdNode Pointer to the Resource Data element following
+ the CurrRdNode.
+ Contain a NULL pointer if CurrRdNode is the
+ last Resource Data element in the list.
+ The "End Tag" is not considered as a resource
+ data element and is not returned.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpCrsGetNextRdNode (
+ IN AML_DATA_NODE_HANDLE CurrRdNode,
+ OUT AML_DATA_NODE_HANDLE * OutRdNode
+ );
+
+/** Update the first interrupt of an Interrupt resource data node.
+
+ The flags of the Interrupt resource data are left unchanged.
+
+ The InterruptRdNode corresponds to the Resource Data created by the
+ "Interrupt ()" ASL macro. It is an Extended Interrupt Resource Data.
+ See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ @ingroup UserApis
+
+ @param [in] InterruptRdNode Pointer to the an extended interrupt
+ resource data node.
+ @param [in] Irq Interrupt value to update.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRdInterrupt (
+ IN AML_DATA_NODE_HANDLE InterruptRdNode,
+ IN UINT32 Irq
+ );
+
+/** Update the base address and length of a QWord resource data node.
+
+ @ingroup UserApis
+
+ @param [in] QWordRdNode Pointer a QWord resource data
+ node.
+ @param [in] BaseAddress Base address.
+ @param [in] BaseAddressLength Base address length.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRdQWord (
+ IN AML_DATA_NODE_HANDLE QWordRdNode,
+ IN UINT64 BaseAddress,
+ IN UINT64 BaseAddressLength
+ );
+
+/** Add an Interrupt Resource Data node.
+
+ This function creates a Resource Data element corresponding to the
+ "Interrupt ()" ASL function, stores it in an AML Data Node.
+
+ It then adds it after the input CurrRdNode in the list of resource data
+ element.
+
+ The Resource Data effectively created is an Extended Interrupt Resource
+ Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ The Extended Interrupt contains one single interrupt.
+
+ This function allocates memory to create a data node. It is the caller's
+ responsibility to either:
+ - attach this node to an AML tree;
+ - delete this node.
+
+ Note: The _CRS node must be defined using the ASL Name () function.
+ e.g. Name (_CRS, ResourceTemplate () {
+ ...
+ }
+
+ @ingroup UserApis
+
+ @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] ResourceConsumer The device consumes the specified interrupt
+ or produces it for use by a child device.
+ @param [in] EdgeTriggered The interrupt is edge triggered or
+ level triggered.
+ @param [in] ActiveLow The interrupt is active-high or active-low.
+ @param [in] Shared The interrupt can be shared with other
+ devices or not (Exclusive).
+ @param [in] IrqList Interrupt list. Must be non-NULL.
+ @param [in] IrqCount Interrupt count. Must be non-zero.
+
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenCrsAddRdInterrupt (
+ IN AML_OBJECT_NODE_HANDLE NameOpCrsNode,
+ IN BOOLEAN ResourceConsumer,
+ IN BOOLEAN EdgeTriggered,
+ IN BOOLEAN ActiveLow,
+ IN BOOLEAN Shared,
+ IN UINT32 * IrqList,
+ IN UINT8 IrqCount
+ );
+
+/** AML code generation for DefinitionBlock.
+
+ Create a Root Node handle.
+ It is the caller's responsibility to free the allocated memory
+ with the AmlDeleteTree function.
+
+ AmlCodeGenDefinitionBlock (TableSignature, OemId, TableID, OEMRevision) is
+ equivalent to the following ASL code:
+ DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
+ OemId, TableID, OEMRevision) {}
+ with the ComplianceRevision set to 2 and the AMLFileName is ignored.
+
+ @ingroup CodeGenApis
+
+ @param[in] TableSignature 4-character ACPI signature.
+ Must be 'DSDT' or 'SSDT'.
+ @param[in] OemId 6-character string OEM identifier.
+ @param[in] OemTableId 8-character string OEM table identifier.
+ @param[in] OemRevision OEM revision number.
+ @param[out] DefinitionBlockTerm The ASL Term handle representing a
+ Definition Block.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenDefinitionBlock (
+ IN CONST CHAR8 * TableSignature,
+ IN CONST CHAR8 * OemId,
+ IN CONST CHAR8 * OemTableId,
+ IN UINT32 OemRevision,
+ OUT AML_ROOT_NODE_HANDLE * NewRootNode
+ );
+
+/** AML code generation for a Name object node, containing a String.
+
+ AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(_HID, "HID0000")
+
+ @ingroup CodeGenApis
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] String NULL terminated String to associate to the
+ NameString.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameString (
+ IN CONST CHAR8 * NameString,
+ IN CHAR8 * String,
+ IN AML_NODE_HANDLE ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
+ );
+
+/** AML code generation for a Name object node, containing an Integer.
+
+ AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(_UID, One)
+
+ @ingroup CodeGenApis
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] Integer Integer to associate to the NameString.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameInteger (
+ IN CONST CHAR8 * NameString,
+ IN UINT64 Integer,
+ IN AML_NODE_HANDLE ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
+ );
+
+/** AML code generation for a Device object node.
+
+ AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Device(COM0) {}
+
+ @ingroup CodeGenApis
+
+ @param [in] NameString The new Device's name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenDevice (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HANDLE ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
+ );
+
+/** AML code generation for a Scope object node.
+
+ AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Scope(_SB) {}
+
+ @ingroup CodeGenApis
+
+ @param [in] NameString The new Scope's name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenScope (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HANDLE ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE_HANDLE * NewObjectNode OPTIONAL
+ );
+
+#endif // AML_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h
new file mode 100644
index 00000000000..61eefdcfd32
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/SsdtSerialPortFixupLib.h
@@ -0,0 +1,68 @@
+/** @file
+ Ssdt Serial Port Fixup Library
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef SSDT_SERIAL_PORT_LIB_H_
+#define SSDT_SERIAL_PORT_LIB_H_
+
+/** Build a SSDT table describing the input serial port.
+
+ The table created by this function must be freed by FreeSsdtSerialTable.
+
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] SerialPortInfo Serial port to describe in the SSDT table.
+ @param [in] Name The Name to give to the Device.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ @param [in] Uid UID for the Serial Port.
+ @param [out] Table If success, pointer to the created SSDT table.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+BuildSsdtSerialPortTable (
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo,
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
+ IN CONST CHAR8 * Name,
+ IN CONST UINT64 Uid,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ );
+
+/** Free an SSDT table previously created by
+ the BuildSsdtSerialTable function.
+
+ @param [in] Table Pointer to a SSDT table allocated by
+ the BuildSsdtSerialTable function.
+
+ @retval EFI_SUCCESS Success.
+**/
+EFI_STATUS
+EFIAPI
+FreeSsdtSerialPortTable (
+ IN EFI_ACPI_DESCRIPTION_HEADER * Table
+ );
+
+/** Validate the Serial Port Information.
+
+ @param [in] SerialPortInfoTable Table of CM_ARM_SERIAL_PORT_INFO.
+ @param [in] SerialPortCount Count of SerialPort in the table.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+ValidateSerialPortInfo (
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfoTable,
+ IN UINT32 SerialPortCount
+ );
+
+#endif // SSDT_SERIAL_PORT_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/TableHelperLib.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/TableHelperLib.h
index d1c018c29fe..80c44ef9f66 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/TableHelperLib.h
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Include/Library/TableHelperLib.h
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -12,6 +12,18 @@
#ifndef TABLE_HELPER_LIB_H_
#define TABLE_HELPER_LIB_H_
+/** Is a character upper case
+*/
+#define IS_UPPER_CHAR(x) ((x >= 'A') && (x <= 'Z'))
+
+/** Is a character a decimal digit
+*/
+#define IS_DIGIT(x) ((x >= '0') && (x <= '9'))
+
+/** Is a character an upper case hexadecimal digit
+*/
+#define IS_UPPER_HEX(x) (((x >= 'A') && (x <= 'F')) || IS_DIGIT (x))
+
/** The GetCgfMgrInfo function gets the CM_STD_OBJ_CONFIGURATION_MANAGER_INFO
object from the Configuration Manager.
@@ -107,4 +119,41 @@ FindDuplicateValue (
IN PFN_IS_EQUAL EqualTestFunction
);
+/** Convert a hex number to its ASCII code.
+
+ @param [in] x Hex number to convert.
+ Must be 0 <= x < 16.
+
+ @return The ASCII code corresponding to x.
+**/
+UINT8
+EFIAPI
+AsciiFromHex (
+ IN UINT8 x
+ );
+
+/** Check if a HID is a valid PNP ID.
+
+ @param [in] Hid The Hid to validate.
+
+ @retval TRUE The Hid is a valid PNP ID.
+ @retval FALSE The Hid is not a valid PNP ID.
+**/
+BOOLEAN
+IsValidPnpId (
+ IN CONST CHAR8 * Hid
+ );
+
+/** Check if a HID is a valid ACPI ID.
+
+ @param [in] Hid The Hid to validate.
+
+ @retval TRUE The Hid is a valid ACPI ID.
+ @retval FALSE The Hid is not a valid ACPI ID.
+**/
+BOOLEAN
+IsValidAcpiId (
+ IN CONST CHAR8 * Hid
+ );
+
#endif // TABLE_HELPER_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
index b82c8e071f6..d0c863e699a 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/AcpiDbg2LibArm.inf
@@ -1,7 +1,7 @@
## @file
# DBG2 Table Generator
#
-# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
@@ -29,6 +29,7 @@
[LibraryClasses]
BaseLib
PL011UartLib
+ SsdtSerialPortFixupLib
[FixedPcd]
gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
index f59bb065fdc..7b4e9f4ada9 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiDbg2LibArm/Dbg2Generator.c
@@ -1,7 +1,8 @@
/** @file
DBG2 Table Generator
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -12,6 +13,7 @@
#include <IndustryStandard/DebugPort2Table.h>
#include <Library/AcpiLib.h>
#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Library/PL011UartLib.h>
#include <Protocol/AcpiTable.h>
#include <Protocol/SerialIo.h>
@@ -20,6 +22,7 @@
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
+#include <Library/SsdtSerialPortFixupLib.h>
#include <Library/TableHelperLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
@@ -44,17 +47,21 @@ Requirements:
*/
#define DBG2_NUMBER_OF_GENERIC_ADDRESS_REGISTERS 1
-/** The index for the debug port 1 in the Debug port information list.
+/** The index for the debug port 0 in the Debug port information list.
+*/
+#define INDEX_DBG_PORT0 0
+
+/** A string representing the name of the debug port 0.
*/
-#define DBG_PORT_INDEX_PORT1 0
+#define NAME_STR_DBG_PORT0 "COM0"
-/** A string representing the name of the debug port 1.
+/** An UID representing the debug port 0.
*/
-#define NAME_STR_PORT1 "COM1"
+#define UID_DBG_PORT0 0
/** The length of the namespace string.
*/
-#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_PORT1)
+#define DBG2_NAMESPACESTRING_FIELD_SIZE sizeof (NAME_STR_DBG_PORT0)
/** The PL011 UART address range length.
*/
@@ -159,7 +166,7 @@ DBG2_TABLE AcpiDbg2 = {
0, // {Template}: Serial Port Subtype
0, // {Template}: Serial Port Base Address
PL011_UART_LENGTH,
- NAME_STR_PORT1
+ NAME_STR_DBG_PORT0
)
}
};
@@ -217,58 +224,115 @@ SetupDebugUart (
&StopBits
);
- DEBUG ((DEBUG_INFO, "Debug UART Configuration:\n"));
- DEBUG ((DEBUG_INFO, "UART Base = 0x%lx\n", SerialPortInfo->BaseAddress));
- DEBUG ((DEBUG_INFO, "Clock = %d\n", SerialPortInfo->Clock));
- DEBUG ((DEBUG_INFO, "Baudrate = %ld\n", BaudRate));
- DEBUG ((DEBUG_INFO, "Configuring Debug UART. Status = %r\n", Status));
-
ASSERT_EFI_ERROR (Status);
return Status;
}
-/** Construct the DBG2 ACPI table
+/** Free any resources allocated for constructing the tables.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in, out] Table Pointer to an array of pointers
+ to ACPI Table(s).
+ @param [in] TableCount Number of ACPI table(s).
+
+ @retval EFI_SUCCESS The resources were freed successfully.
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeDbg2TableEx (
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
+ IN CONST UINTN TableCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((Table == NULL) ||
+ (*Table == NULL) ||
+ (TableCount != 2)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid Table Pointer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TableList = *Table;
+
+ if ((TableList[1] == NULL) ||
+ (TableList[1]->Signature !=
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: DBG2: Invalid SSDT table pointer.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Only need to free the SSDT table at index 1. The DBG2 table is static.
+ Status = FreeSsdtSerialPortTable (TableList[1]);
+ ASSERT_EFI_ERROR (Status);
+
+ // Free the table list.
+ FreePool (*Table);
- The BuildDbg2Table function is called by the Dynamic Table Manager
- to construct the DBG2 ACPI table.
+ return Status;
+}
+
+/** Construct the DBG2 ACPI table and its associated SSDT table.
This function invokes the Configuration Manager protocol interface
to get the required hardware information for generating the ACPI
table.
If this function allocates any resources then they must be freed
- in the FreeXXXXTableResources function.
-
- @param [in] This Pointer to the table generator.
- @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol Interface.
- @param [out] Table Pointer to the constructed ACPI Table.
-
- @retval EFI_SUCCESS Table generated successfully.
- @retval EFI_INVALID_PARAMETER A parameter is invalid.
- @retval EFI_NOT_FOUND The required object was not found.
- @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
- Manager is less than the Object size for the
- requested object.
+ in the FreeXXXXTableResourcesEx function.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [out] Table Pointer to a list of generated ACPI table(s).
+ @param [out] TableCount Number of generated ACPI table(s).
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for
+ the requested object.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+ @retval EFI_UNSUPPORTED Unsupported configuration.
**/
STATIC
EFI_STATUS
EFIAPI
-BuildDbg2Table (
- IN CONST ACPI_TABLE_GENERATOR * CONST This,
- IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
- IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
- OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table
+BuildDbg2TableEx (
+ IN CONST ACPI_TABLE_GENERATOR * This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
+ OUT UINTN * CONST TableCount
)
{
- EFI_STATUS Status;
- CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
+ EFI_STATUS Status;
+ CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
+ UINT32 SerialPortCount;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
ASSERT (This != NULL);
ASSERT (AcpiTableInfo != NULL);
ASSERT (CfgMgrProtocol != NULL);
ASSERT (Table != NULL);
+ ASSERT (TableCount != NULL);
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
@@ -291,7 +355,7 @@ BuildDbg2Table (
CfgMgrProtocol,
CM_NULL_TOKEN,
&SerialPortInfo,
- NULL
+ &SerialPortCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
@@ -299,34 +363,41 @@ BuildDbg2Table (
"ERROR: DBG2: Failed to get serial port information. Status = %r\n",
Status
));
- goto error_handler;
+ return Status;
}
- if (SerialPortInfo->BaseAddress == 0) {
- Status = EFI_INVALID_PARAMETER;
+ if (SerialPortCount == 0) {
DEBUG ((
DEBUG_ERROR,
- "ERROR: DBG2: Uart port base address is invalid. BaseAddress = 0x%lx\n",
- SerialPortInfo->BaseAddress
+ "ERROR: DBG2: Serial port information not found. Status = %r\n",
+ EFI_NOT_FOUND
));
- goto error_handler;
+ return EFI_NOT_FOUND;
}
- if ((SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {
- Status = EFI_INVALID_PARAMETER;
+ // Only use the first DBG2 port information.
+ Status = ValidateSerialPortInfo (SerialPortInfo, 1);
+ if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
- "ERROR: DBG2: Uart port sybtype is invalid. PortSubtype = 0x%x\n",
- SerialPortInfo->PortSubtype
+ "ERROR: DBG2: Invalid serial port information. Status = %r\n",
+ Status
));
- goto error_handler;
+ return Status;
+ }
+
+ // Allocate a table to store pointers to the DBG2 and SSDT tables.
+ TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
+ AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * 2);
+ if (TableList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: DBG2: Failed to allocate memory for Table List," \
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
}
Status = AddAcpiHeader (
@@ -346,11 +417,33 @@ BuildDbg2Table (
}
// Update the base address
- AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].BaseAddressRegister.Address =
+ AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.Address =
SerialPortInfo->BaseAddress;
+ // Set the access size
+ if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: DBG2: Access size must be <= 3 (DWORD). Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) {
+ // 0 Undefined (legacy reasons)
+ // Default to DWORD access size as the access
+ // size field was introduced at a later date
+ // and some ConfigurationManager implementations
+ // may not be providing this field data
+ AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize =
+ EFI_ACPI_6_3_DWORD;
+ } else {
+ AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].BaseAddressRegister.AccessSize =
+ SerialPortInfo->AccessSize;
+ }
+
// Update the serial port subtype
- AcpiDbg2.Dbg2DeviceInfo[DBG_PORT_INDEX_PORT1].Dbg2Device.PortSubtype =
+ AcpiDbg2.Dbg2DeviceInfo[INDEX_DBG_PORT0].Dbg2Device.PortSubtype =
SerialPortInfo->PortSubtype;
if ((SerialPortInfo->PortSubtype ==
@@ -371,9 +464,35 @@ BuildDbg2Table (
}
}
- *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
+ TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiDbg2;
+
+ // Build a SSDT table describing the serial port.
+ Status = BuildSsdtSerialPortTable (
+ AcpiTableInfo,
+ SerialPortInfo,
+ NAME_STR_DBG_PORT0,
+ UID_DBG_PORT0,
+ &TableList[1]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: DBG2: Failed to build associated SSDT table. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ *TableCount = 2;
+ *Table = TableList;
+
+ return Status;
error_handler:
+ if (TableList != NULL) {
+ FreePool (TableList);
+ }
+
return Status;
}
@@ -391,7 +510,7 @@ ACPI_TABLE_GENERATOR Dbg2Generator = {
// Generator Description
L"ACPI.STD.DBG2.GENERATOR",
// ACPI Table Signature
- EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_DEBUG_PORT_2_TABLE_SIGNATURE,
// ACPI Table Revision supported by this Generator
EFI_ACPI_DBG2_DEBUG_DEVICE_INFORMATION_STRUCT_REVISION,
// Minimum supported ACPI Table Revision
@@ -400,16 +519,14 @@ ACPI_TABLE_GENERATOR Dbg2Generator = {
TABLE_GENERATOR_CREATOR_ID_ARM,
// Creator Revision
DBG2_GENERATOR_REVISION,
- // Build Table function
- BuildDbg2Table,
- // No additional resources are allocated by the generator.
- // Hence the Free Resource function is not required.
+ // Build table function. Use the extended version instead.
NULL,
- // Extended build function not needed
+ // Free table function. Use the extended version instead.
NULL,
- // Extended build function not implemented by the generator.
- // Hence extended free resource function is not required.
- NULL
+ // Extended Build table function.
+ BuildDbg2TableEx,
+ // Extended free function.
+ FreeDbg2TableEx
};
/** Register the Generator with the ACPI Table Factory.
@@ -433,7 +550,6 @@ AcpiDbg2LibConstructor (
Status = RegisterAcpiTableGenerator (&Dbg2Generator);
DEBUG ((DEBUG_INFO, "DBG2: Register Generator. Status = %r\n", Status));
ASSERT_EFI_ERROR (Status);
-
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
index 937a9102888..3dac52c0b7e 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiIortLibArm/IortGenerator.c
@@ -1,7 +1,7 @@
/** @file
IORT Table Generator
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2020, ARM Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -1053,7 +1053,7 @@ AddRootComplexNodes (
**/
STATIC
EFI_STATUS
-AddSmmuInterrruptArray (
+AddSmmuInterruptArray (
IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
IN OUT EFI_ACPI_6_0_IO_REMAPPING_SMMU_INT * InterruptArray,
IN UINT32 InterruptCount,
@@ -1199,7 +1199,7 @@ AddSmmuV1V2Nodes (
SmmuNode->SMMU_NSgCfgIrptFlags = NodeList->SMMU_NSgCfgIrptFlags;
// Add Context Interrupt Array
- Status = AddSmmuInterrruptArray (
+ Status = AddSmmuInterruptArray (
CfgMgrProtocol,
ContextInterruptArray,
SmmuNode->NumContextInterrupts,
@@ -1217,7 +1217,7 @@ AddSmmuV1V2Nodes (
// Add PMU Interrupt Array
if ((SmmuNode->NumPmuInterrupts > 0) &&
(NodeList->PmuInterruptToken != CM_NULL_TOKEN)) {
- Status = AddSmmuInterrruptArray (
+ Status = AddSmmuInterruptArray (
CfgMgrProtocol,
PmuInterruptArray,
SmmuNode->NumPmuInterrupts,
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
index c467be82dc0..fa7654a4740 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiMadtLibArm/MadtGenerator.c
@@ -1,7 +1,7 @@
/** @file
MADT Table Generator
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2020, ARM Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -332,24 +332,24 @@ AddGICMsiFrameInfoList (
/** Update the GIC Redistributor Information.
@param [in] Gicr Pointer to GIC Redistributor structure.
- @param [in] GicRedisributorInfo Pointer to the GIC Redistributor Info.
+ @param [in] GicRedistributorInfo Pointer to the GIC Redistributor Info.
**/
STATIC
VOID
AddGICRedistributor (
IN EFI_ACPI_6_3_GICR_STRUCTURE * CONST Gicr,
- IN CONST CM_ARM_GIC_REDIST_INFO * CONST GicRedisributorInfo
+ IN CONST CM_ARM_GIC_REDIST_INFO * CONST GicRedistributorInfo
)
{
ASSERT (Gicr != NULL);
- ASSERT (GicRedisributorInfo != NULL);
+ ASSERT (GicRedistributorInfo != NULL);
Gicr->Type = EFI_ACPI_6_3_GICR;
Gicr->Length = sizeof (EFI_ACPI_6_3_GICR_STRUCTURE);
Gicr->Reserved = EFI_ACPI_RESERVED_WORD;
Gicr->DiscoveryRangeBaseAddress =
- GicRedisributorInfo->DiscoveryRangeBaseAddress;
- Gicr->DiscoveryRangeLength = GicRedisributorInfo->DiscoveryRangeLength;
+ GicRedistributorInfo->DiscoveryRangeBaseAddress;
+ Gicr->DiscoveryRangeLength = GicRedistributorInfo->DiscoveryRangeLength;
}
/** Add the GIC Redistributor Information to the MADT Table.
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
index fe51b5a10ec..bc3b0d3e4b8 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/AcpiSpcrLibArm.inf
@@ -1,7 +1,7 @@
## @file
# SPCR Table Generator
#
-# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+# Copyright (c) 2017 - 2020, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
@@ -27,6 +27,7 @@
[LibraryClasses]
BaseLib
+ SsdtSerialPortFixupLib
[Pcd]
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
index 4f181e890cf..6c07bfdcbe8 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSpcrLibArm/SpcrGenerator.c
@@ -1,7 +1,8 @@
/** @file
SPCR Table Generator
- Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -14,12 +15,14 @@
#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
#include <Library/AcpiLib.h>
#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Protocol/AcpiTable.h>
// Module specific include files.
#include <AcpiTableGenerator.h>
#include <ConfigurationManagerObject.h>
#include <ConfigurationManagerHelper.h>
+#include <Library/SsdtSerialPortFixupLib.h>
#include <Library/TableHelperLib.h>
#include <Protocol/ConfigurationManagerProtocol.h>
@@ -40,6 +43,14 @@ NOTE: This implementation ignores the possibility that the Serial settings may
#pragma pack(1)
+/** A string representing the name of the SPCR port.
+*/
+#define NAME_STR_SPCR_PORT "COM1"
+
+/** An UID representing the SPCR port.
+*/
+#define UID_SPCR_PORT 1
+
/** This macro defines the no flow control option.
*/
#define SPCR_FLOW_CONTROL_NONE 0
@@ -92,47 +103,111 @@ GET_OBJECT_LIST (
CM_ARM_SERIAL_PORT_INFO
)
-/** Construct the SPCR ACPI table.
+/** Free any resources allocated for constructing the tables.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in, out] Table Pointer to an array of pointers
+ to ACPI Table(s).
+ @param [in] TableCount Number of ACPI table(s).
+
+ @retval EFI_SUCCESS The resources were freed successfully.
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeSpcrTableEx (
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
+ IN CONST UINTN TableCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((Table == NULL) ||
+ (*Table == NULL) ||
+ (TableCount != 2)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid Table Pointer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TableList = *Table;
+
+ if ((TableList[1] == NULL) ||
+ (TableList[1]->Signature !=
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SPCR: Invalid SSDT table pointer.\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Only need to free the SSDT table at index 1. The SPCR table is static.
+ Status = FreeSsdtSerialPortTable (TableList[1]);
+ ASSERT_EFI_ERROR (Status);
+
+ // Free the table list.
+ FreePool (*Table);
+
+ return Status;
+}
+
+/** Construct the SPCR ACPI table and its associated SSDT table.
This function invokes the Configuration Manager protocol interface
to get the required hardware information for generating the ACPI
table.
If this function allocates any resources then they must be freed
- in the FreeXXXXTableResources function.
-
- @param [in] This Pointer to the table generator.
- @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
- @param [in] CfgMgrProtocol Pointer to the Configuration Manager
- Protocol Interface.
- @param [out] Table Pointer to the constructed ACPI Table.
-
- @retval EFI_SUCCESS Table generated successfully.
- @retval EFI_INVALID_PARAMETER A parameter is invalid.
- @retval EFI_NOT_FOUND The required object was not found.
- @retval EFI_UNSUPPORTED An unsupported baudrate was specified by the
- Configuration Manager.
- @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
- Manager is less than the Object size for the
- requested object.
+ in the FreeXXXXTableResourcesEx function.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [out] Table Pointer to a list of generated ACPI table(s).
+ @param [out] TableCount Number of generated ACPI table(s).
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for
+ the requested object.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+ @retval EFI_UNSUPPORTED Unsupported configuration.
**/
STATIC
EFI_STATUS
EFIAPI
-BuildSpcrTable (
- IN CONST ACPI_TABLE_GENERATOR * CONST This,
- IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
- IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
- OUT EFI_ACPI_DESCRIPTION_HEADER ** CONST Table
+BuildSpcrTableEx (
+ IN CONST ACPI_TABLE_GENERATOR * This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
+ OUT UINTN * CONST TableCount
)
{
- EFI_STATUS Status;
- CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
+ EFI_STATUS Status;
+ CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
+ UINT32 SerialPortCount;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
ASSERT (This != NULL);
ASSERT (AcpiTableInfo != NULL);
ASSERT (CfgMgrProtocol != NULL);
ASSERT (Table != NULL);
+ ASSERT (TableCount != NULL);
ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
@@ -155,7 +230,7 @@ BuildSpcrTable (
CfgMgrProtocol,
CM_NULL_TOKEN,
&SerialPortInfo,
- NULL
+ &SerialPortCount
);
if (EFI_ERROR (Status)) {
DEBUG ((
@@ -163,44 +238,46 @@ BuildSpcrTable (
"ERROR: SPCR: Failed to get serial port information. Status = %r\n",
Status
));
- goto error_handler;
+ return Status;
}
- if (SerialPortInfo->BaseAddress == 0) {
- Status = EFI_INVALID_PARAMETER;
+ if (SerialPortCount == 0) {
DEBUG ((
DEBUG_ERROR,
- "ERROR: SPCR: Uart port base address is invalid. BaseAddress = 0x%lx\n",
- SerialPortInfo->BaseAddress
+ "ERROR: SPCR: Serial port information not found. Status = %r\n",
+ EFI_NOT_FOUND
));
- goto error_handler;
+ return EFI_NOT_FOUND;
}
- if ((SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550) &&
- (SerialPortInfo->PortSubtype !=
- EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC)) {
- Status = EFI_INVALID_PARAMETER;
+ // Validate the SerialPort info. Only one SPCR port can be described.
+ // If platform provides description for multiple SPCR ports, use the
+ // first SPCR port information.
+ Status = ValidateSerialPortInfo (SerialPortInfo, 1);
+ if (EFI_ERROR (Status)) {
DEBUG ((
DEBUG_ERROR,
- "ERROR: SPCR: Uart port sybtype is invalid. PortSubtype = 0x%x\n",
- SerialPortInfo->PortSubtype
+ "ERROR: SPCR: Invalid serial port information. Status = %r\n",
+ Status
));
- goto error_handler;
+ return Status;
}
- DEBUG ((DEBUG_INFO, "SPCR UART Configuration:\n"));
- DEBUG ((DEBUG_INFO, " UART Base = 0x%lx\n", SerialPortInfo->BaseAddress));
- DEBUG ((DEBUG_INFO, " Clock = %d\n", SerialPortInfo->Clock));
- DEBUG ((DEBUG_INFO, " Baudrate = %ld\n", SerialPortInfo->BaudRate));
- DEBUG ((DEBUG_INFO, " Interrupt = %d\n", SerialPortInfo->Interrupt));
+ // Allocate a table to store pointers to the SPCR and SSDT tables.
+ TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
+ AllocateZeroPool (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * 2);
+ if (TableList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SPCR: Failed to allocate memory for Table List," \
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+ // Build SPCR table.
Status = AddAcpiHeader (
CfgMgrProtocol,
This,
@@ -224,7 +301,7 @@ BuildSpcrTable (
Status = EFI_INVALID_PARAMETER;
DEBUG ((
DEBUG_ERROR,
- "ERROR: SPCR: Invalid Port Sybtype (must be < 256). Status = %r\n",
+ "ERROR: SPCR: Invalid Port subtype (must be < 256). Status = %r\n",
Status
));
goto error_handler;
@@ -236,6 +313,26 @@ BuildSpcrTable (
// Update the base address
AcpiSpcr.BaseAddress.Address = SerialPortInfo->BaseAddress;
+ // Set the access size
+ if (SerialPortInfo->AccessSize >= EFI_ACPI_6_3_QWORD) {
+ Status = EFI_INVALID_PARAMETER;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SPCR: Access size must be <= 3 (DWORD). Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ } else if (SerialPortInfo->AccessSize == EFI_ACPI_6_3_UNDEFINED) {
+ // 0 Undefined (legacy reasons)
+ // Default to DWORD access size as the access
+ // size field was introduced at a later date
+ // and some ConfigurationManager implementations
+ // may not be providing this field data
+ AcpiSpcr.BaseAddress.AccessSize = EFI_ACPI_6_3_DWORD;
+ } else {
+ AcpiSpcr.BaseAddress.AccessSize = SerialPortInfo->AccessSize;
+ }
+
// Update the UART interrupt
AcpiSpcr.GlobalSystemInterrupt = SerialPortInfo->Interrupt;
@@ -267,9 +364,35 @@ BuildSpcrTable (
goto error_handler;
} // switch
- *Table = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
+ TableList[0] = (EFI_ACPI_DESCRIPTION_HEADER*)&AcpiSpcr;
+
+ // Build a SSDT table describing the serial port.
+ Status = BuildSsdtSerialPortTable (
+ AcpiTableInfo,
+ SerialPortInfo,
+ NAME_STR_SPCR_PORT,
+ UID_SPCR_PORT,
+ &TableList[1]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SPCR: Failed to build associated SSDT table. Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ *TableCount = 2;
+ *Table = TableList;
+
+ return Status;
error_handler:
+ if (TableList != NULL) {
+ FreePool (TableList);
+ }
+
return Status;
}
@@ -287,7 +410,7 @@ ACPI_TABLE_GENERATOR SpcrGenerator = {
// Generator Description
L"ACPI.STD.SPCR.GENERATOR",
// ACPI Table Signature
- EFI_ACPI_6_2_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+ EFI_ACPI_6_3_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
// ACPI Table Revision supported by this Generator
EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
// Minimum supported ACPI Table Revision
@@ -296,16 +419,14 @@ ACPI_TABLE_GENERATOR SpcrGenerator = {
TABLE_GENERATOR_CREATOR_ID_ARM,
// Creator Revision
SPCR_GENERATOR_REVISION,
- // Build Table function
- BuildSpcrTable,
- // No additional resources are allocated by the generator.
- // Hence the Free Resource function is not required.
+ // Build table function. Use the extended version instead.
NULL,
- // Extended build function not needed
+ // Free table function. Use the extended version instead.
NULL,
- // Extended build function not implemented by the generator.
- // Hence extended free resource function is not required.
- NULL
+ // Extended Build table function.
+ BuildSpcrTableEx,
+ // Extended free function.
+ FreeSpcrTableEx
};
/** Register the Generator with the ACPI Table Factory.
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
index aab27f3c0f4..1d723939185 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSratLibArm/SratGenerator.c
@@ -1,7 +1,7 @@
/** @file
SRAT Table Generator
- Copyright (c) 2019, ARM Limited. All rights reserved.
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Reference(s):
@@ -101,13 +101,13 @@ GET_OBJECT_LIST (
/** Return the PCI Device information in BDF format
PCI Bus Number - Max 256 busses (Bits 15:8 of BDF)
- PCI Device Mumber - Max 32 devices (Bits 7:3 of BDF)
+ PCI Device Number - Max 32 devices (Bits 7:3 of BDF)
PCI Function Number - Max 8 functions (Bits 2:0 of BDF)
@param [in] DeviceHandlePci Pointer to the PCI Device Handle.
@retval BDF value corresponding to the PCI Device Handle.
-*/
+**/
STATIC
UINT16
GetBdf (
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.c
new file mode 100644
index 00000000000..a0c4a7facbd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.c
@@ -0,0 +1,708 @@
+/** @file
+ SSDT CMN-600 AML Table Generator.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
+ - Generic ACPI for Arm Components 1.0 Platform Design Document
+**/
+
+#include <IndustryStandard/DebugPort2Table.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+#include "SsdtCmn600Generator.h"
+
+/** C array containing the compiled AML template.
+ This symbol is defined in the auto generated C file
+ containing the AML bytecode array.
+*/
+extern CHAR8 ssdtcmn600template_aml_code[];
+
+/** SSDT CMN-600 Table Generator.
+
+ Requirements:
+ The following Configuration Manager Object(s) are required by
+ this Generator:
+ - EArmObjCmn600Info
+*/
+
+/** This macro expands to a function that retrieves the CMN-600
+ Information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjCmn600Info,
+ CM_ARM_CMN_600_INFO
+ );
+
+/** Check the CMN-600 Information.
+
+ @param [in] Cmn600InfoList Array of CMN-600 information structure.
+ @param [in] Cmn600Count Count of CMN-600 information structure.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ValidateCmn600Info (
+ IN CONST CM_ARM_CMN_600_INFO * Cmn600InfoList,
+ IN CONST UINT32 Cmn600Count
+ )
+{
+ UINT32 Index;
+ UINT32 DtcIndex;
+ CONST CM_ARM_CMN_600_INFO * Cmn600Info;
+ CONST CM_ARM_GENERIC_INTERRUPT * DtcInterrupt;
+
+ if ((Cmn600InfoList == NULL) ||
+ (Cmn600Count == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Validate each Cmn600Info structure.
+ for (Index = 0; Index < Cmn600Count; Index++) {
+ Cmn600Info = &Cmn600InfoList[Index];
+
+ // At least one DTC is required.
+ if ((Cmn600Info->DtcCount == 0) ||
+ (Cmn600Info->DtcCount > MAX_DTC_COUNT)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Invalid DTC configuration:\n"
+ ));
+ goto error_handler;
+ }
+
+ // Check PERIPHBASE and ROOTNODEBASE address spaces are initialized.
+ if ((Cmn600Info->PeriphBaseAddress == 0) ||
+ (Cmn600Info->RootNodeBaseAddress == 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Invalid PERIPHBASE or ROOTNODEBASE.\n"
+ ));
+ goto error_handler;
+ }
+
+ // The PERIPHBASE address must be 64MB aligned for a (X < 4) && (Y < 4)
+ // dimension mesh, and 256MB aligned otherwise.
+ // Check it is a least 64MB aligned.
+ if ((Cmn600Info->PeriphBaseAddress &
+ (PERIPHBASE_MIN_ADDRESS_LENGTH - 1)) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: PERIPHBASE address must be 64MB aligned.\n"
+ ));
+ goto error_handler;
+ }
+
+ // The PERIPHBASE address is at most 64MB for a (X < 4) && (Y < 4)
+ // dimension mesh, and 256MB otherwise. Check it is not more than 256MB.
+ if (Cmn600Info->PeriphBaseAddressLength > PERIPHBASE_MAX_ADDRESS_LENGTH) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: PERIPHBASE address range must be < 256MB.\n"
+ ));
+ goto error_handler;
+ }
+
+ // Check the 16 KB alignment of the ROOTNODEBASE address.
+ if ((Cmn600Info->PeriphBaseAddress &
+ (ROOTNODEBASE_ADDRESS_LENGTH - 1)) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Root base address must be 16KB aligned.\n"
+ ));
+ goto error_handler;
+ }
+
+ // The ROOTNODEBASE address space should be included in the PERIPHBASE
+ // address space.
+ if ((Cmn600Info->PeriphBaseAddress > Cmn600Info->RootNodeBaseAddress) ||
+ ((Cmn600Info->PeriphBaseAddress + Cmn600Info->PeriphBaseAddressLength) <
+ (Cmn600Info->RootNodeBaseAddress + ROOTNODEBASE_ADDRESS_LENGTH))) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600:"
+ " ROOTNODEBASE address space not in PERIPHBASE address space.\n"
+ ));
+ goto error_handler;
+ }
+
+ for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {
+ DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];
+ if (((DtcInterrupt->Flags &
+ EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) == 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: DTC Interrupt must be consumer.\n"
+ ));
+ goto error_handler;
+ }
+ } // for DTC Interrupt
+
+ } //for Cmn600InfoList
+
+ return EFI_SUCCESS;
+
+error_handler:
+
+ DEBUG ((
+ DEBUG_ERROR,
+ "PeriphBaseAddress = 0x%llx\n"
+ "PeriphBaseAddressLength = 0x%llx\n"
+ "RootNodeBaseAddress = 0x%llx\n"
+ "DtcCount = %u\n",
+ Cmn600Info->PeriphBaseAddress,
+ Cmn600Info->PeriphBaseAddressLength,
+ Cmn600Info->RootNodeBaseAddress,
+ Cmn600Info->DtcCount
+ ));
+
+ DEBUG_CODE (
+ for (DtcIndex = 0; DtcIndex < Cmn600Info->DtcCount; DtcIndex++) {
+ DtcInterrupt = &Cmn600Info->DtcInterrupt[DtcIndex];
+ DEBUG ((
+ DEBUG_ERROR,
+ " DTC[%d]:\n",
+ DtcIndex
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ " Interrupt = 0x%lx\n",
+ DtcInterrupt->Interrupt
+ ));
+ DEBUG ((
+ DEBUG_ERROR,
+ " Flags = 0x%lx\n",
+ DtcInterrupt->Flags
+ ));
+ } // for
+ );
+
+ return EFI_INVALID_PARAMETER;
+}
+
+/** Build a SSDT table describing the CMN-600 device.
+
+ The table created by this function must be freed by FreeSsdtCmn600Table.
+
+ @param [in] Cmn600Info Pointer to a Cmn600 structure.
+ @param [in] Name The Name to give to the Device.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ @param [in] Uid UID for the CMN600 device.
+ @param [out] Table If success, pointer to the created SSDT table.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FixupCmn600Info (
+ IN CONST CM_ARM_CMN_600_INFO * Cmn600Info,
+ IN CONST CHAR8 * Name,
+ IN CONST UINT64 Uid,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ UINT8 Index;
+ CONST CM_ARM_GENERIC_INTERRUPT * DtcInt;
+
+ EFI_ACPI_DESCRIPTION_HEADER * SsdtCmn600Template;
+ AML_ROOT_NODE_HANDLE RootNodeHandle;
+ AML_OBJECT_NODE_HANDLE NameOpIdNode;
+ AML_OBJECT_NODE_HANDLE NameOpCrsNode;
+ AML_DATA_NODE_HANDLE CmnPeriphBaseRdNode;
+ AML_DATA_NODE_HANDLE CmnRootNodeBaseRdNode;
+ AML_OBJECT_NODE_HANDLE DeviceNode;
+
+ // Parse the Ssdt CMN-600 Template.
+ SsdtCmn600Template = (EFI_ACPI_DESCRIPTION_HEADER*)
+ ssdtcmn600template_aml_code;
+
+ RootNodeHandle = NULL;
+ Status = AmlParseDefinitionBlock (
+ SsdtCmn600Template,
+ &RootNodeHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Failed to parse SSDT CMN-600 Template."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Get the _UID NameOp object defined by the "Name ()" statement,
+ // and update its value.
+ Status = AmlFindNode (
+ RootNodeHandle,
+ "\\_SB_.CMN0._UID",
+ &NameOpIdNode
+ );
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ Status = AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ // Get the _CRS object defined by the "Name ()" statement.
+ Status = AmlFindNode (
+ RootNodeHandle,
+ "\\_SB.CMN0._CRS",
+ &NameOpCrsNode
+ );
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ // Get the first Rd node in the "_CRS" object.
+ // This is the PERIPHBASE node.
+ Status = AmlNameOpCrsGetFirstRdNode (NameOpCrsNode, &CmnPeriphBaseRdNode);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ if (CmnPeriphBaseRdNode == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ // Update the PERIPHBASE base address and length.
+ Status = AmlUpdateRdQWord (
+ CmnPeriphBaseRdNode,
+ Cmn600Info->PeriphBaseAddress,
+ Cmn600Info->PeriphBaseAddressLength
+ );
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ // Get the QWord node corresponding to the ROOTNODEBASE.
+ // It is the second Resource Data element in the BufferNode's
+ // variable list of arguments.
+ Status = AmlNameOpCrsGetNextRdNode (
+ CmnPeriphBaseRdNode,
+ &CmnRootNodeBaseRdNode
+ );
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ if (CmnRootNodeBaseRdNode == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ // Update the ROOTNODEBASE base address and length.
+ Status = AmlUpdateRdQWord (
+ CmnRootNodeBaseRdNode,
+ Cmn600Info->RootNodeBaseAddress,
+ ROOTNODEBASE_ADDRESS_LENGTH
+ );
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ // Add the Interrupt node(s).
+ // Generate Resource Data node(s) corresponding to the "Interrupt ()"
+ // ASL function and add it at the last position in the list of
+ // Resource Data nodes.
+ for (Index = 0; Index < Cmn600Info->DtcCount; Index++) {
+ DtcInt = &Cmn600Info->DtcInterrupt[Index];
+ Status = AmlCodeGenCrsAddRdInterrupt (
+ NameOpCrsNode,
+ ((DtcInt->Flags &
+ EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK) != 0),
+ ((DtcInt->Flags &
+ EFI_ACPI_EXTENDED_INTERRUPT_FLAG_MODE_MASK) != 0),
+ ((DtcInt->Flags &
+ EFI_ACPI_EXTENDED_INTERRUPT_FLAG_POLARITY_MASK) != 0),
+ ((DtcInt->Flags &
+ EFI_ACPI_EXTENDED_INTERRUPT_FLAG_SHARABLE_MASK) != 0),
+ (UINT32*)&DtcInt->Interrupt,
+ 1
+ );
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+ } // for
+
+ // Fixup the CMN600 device name.
+ // This MUST be done at the end, otherwise AML paths won't be valid anymore.
+ // Get the CMN0 variable defined by the "Device ()" statement.
+ Status = AmlFindNode (RootNodeHandle, "\\_SB_.CMN0", &DeviceNode);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ // Update the CMN600 Device's name.
+ Status = AmlDeviceOpUpdateName (DeviceNode, (CHAR8*)Name);
+ if (EFI_ERROR (Status)) {
+ goto error_handler;
+ }
+
+ // Serialise the definition block
+ Status = AmlSerializeDefinitionBlock (
+ RootNodeHandle,
+ Table
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Failed to Serialize SSDT Table Data."
+ " Status = %r\n",
+ Status
+ ));
+ }
+
+error_handler:
+ // Cleanup
+ if (RootNodeHandle != NULL) {
+ Status1 = AmlDeleteTree (RootNodeHandle);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Failed to cleanup AML tree."
+ " Status = %r\n",
+ Status1
+ ));
+ // If Status was success but we failed to delete the AML Tree
+ // return Status1 else return the original error code, i.e. Status.
+ if (!EFI_ERROR (Status)) {
+ return Status1;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/** Free any resources allocated for constructing the SSDT tables for CMN-600.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in, out] Table Pointer to an array of pointers
+ to ACPI Table(s).
+ @param [in] TableCount Number of ACPI table(s).
+
+ @retval EFI_SUCCESS The resources were freed successfully.
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeSsdtCmn600TableResourcesEx (
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
+ IN CONST UINTN TableCount
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+ UINTN Index;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((Table == NULL) ||
+ (*Table == NULL) ||
+ (TableCount == 0)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SSDT-CMN-600: Invalid Table Pointer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TableList = *Table;
+
+ for (Index = 0; Index < TableCount; Index++) {
+ if ((TableList[Index] != NULL) &&
+ (TableList[Index]->Signature ==
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
+ FreePool (TableList[Index]);
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Could not free SSDT table at index %d."
+ " Status = %r\n",
+ Index,
+ EFI_INVALID_PARAMETER
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+ } //for
+
+ // Free the table list.
+ FreePool (*Table);
+ *Table = NULL;
+ return EFI_SUCCESS;
+}
+
+/** Construct SSDT tables for describing CMN-600 meshes.
+
+ This function invokes the Configuration Manager protocol interface
+ to get the required hardware information for generating the ACPI
+ table.
+
+ If this function allocates any resources then they must be freed
+ in the FreeXXXXTableResourcesEx function.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [out] Table Pointer to a list of generated ACPI table(s).
+ @param [out] TableCount Number of generated ACPI table(s).
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for
+ the requested object.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+ @retval EFI_UNSUPPORTED Unsupported configuration.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtCmn600TableEx (
+ IN CONST ACPI_TABLE_GENERATOR * This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
+ OUT UINTN * CONST TableCount
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Index;
+ CM_ARM_CMN_600_INFO * Cmn600Info;
+ UINT32 Cmn600Count;
+ CHAR8 NewName[5];
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (Table != NULL);
+ ASSERT (TableCount != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ *Table = NULL;
+
+ // Get CMN-600 information.
+ Status = GetEArmObjCmn600Info (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &Cmn600Info,
+ &Cmn600Count
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Failed to get the CMN-600 information."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ if ((Cmn600Count == 0) || (Cmn600Count > MAX_CMN600_DEVICES_SUPPORTED)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: CMN600 peripheral count = %d."
+ " This must be between 1 to 16.\n",
+ Cmn600Count
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Validate the CMN-600 Info.
+ Status = ValidateCmn600Info (Cmn600Info, Cmn600Count);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Invalid CMN600 information. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Allocate a table to store pointers to the SSDT tables.
+ TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
+ AllocateZeroPool (
+ (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * Cmn600Count)
+ );
+ if (TableList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Failed to allocate memory for Table List."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Setup the table list early so that that appropriate cleanup
+ // can be done in case of failure.
+ *Table = TableList;
+
+ NewName[0] = 'C';
+ NewName[1] = 'M';
+ NewName[2] = 'N';
+ NewName[4] = '\0';
+ for (Index = 0; Index < Cmn600Count; Index++) {
+ NewName[3] = AsciiFromHex ((UINT8)(Index));
+
+ // Build a SSDT table describing the CMN600 device.
+ Status = FixupCmn600Info (
+ &Cmn600Info[Index],
+ NewName,
+ Index,
+ &TableList[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-CMN-600: Failed to build associated SSDT table."
+ " Status = %r\n",
+ Status
+ ));
+ break;
+ }
+
+ // Increment the table count here so that appropriate clean-up
+ // can be done in case of failure.
+ *TableCount += 1;
+ } // for
+
+ // Note: Table list and CMN600 device count has been setup. The
+ // framework will invoke FreeSsdtCmn600TableResourcesEx() even
+ // on failure, so appropriate clean-up will be done.
+ return Status;
+}
+
+/** This macro defines the Raw Generator revision.
+*/
+#define SSDT_CMN_600_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the Raw Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR SsdtCmn600Generator = {
+ // Generator ID
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtCmn600),
+ // Generator Description
+ L"ACPI.STD.SSDT.CMN600.GENERATOR",
+ // ACPI Table Signature
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ // ACPI Table Revision - Unused
+ 0,
+ // Minimum ACPI Table Revision - Unused
+ 0,
+ // Creator ID
+ TABLE_GENERATOR_CREATOR_ID_ARM,
+ // Creator Revision
+ SSDT_CMN_600_GENERATOR_REVISION,
+ // Build table function. Use the extended version instead.
+ NULL,
+ // Free table function. Use the extended version instead.
+ NULL,
+ // Build Table function
+ BuildSsdtCmn600TableEx,
+ // Free Resource function
+ FreeSsdtCmn600TableResourcesEx
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is registered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_ALREADY_STARTED The Generator for the Table ID
+ is already registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtCmn600LibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RegisterAcpiTableGenerator (&SsdtCmn600Generator);
+ DEBUG ((
+ DEBUG_INFO,
+ "SSDT-CMN-600: Register Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Deregister the Generator from the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is deregistered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The Generator is not registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtCmn600LibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = DeregisterAcpiTableGenerator (&SsdtCmn600Generator);
+ DEBUG ((
+ DEBUG_INFO,
+ "SSDT-CMN-600: Deregister Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.h
new file mode 100644
index 00000000000..a7ecb940228
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Generator.h
@@ -0,0 +1,51 @@
+/** @file
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Cm or CM - Configuration Manager
+ - Obj or OBJ - Object
+ - Std or STD - Standard
+
+ @par Reference(s):
+ - Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
+ - Generic ACPI for Arm Components 1.0 Platform Design Document
+**/
+
+#ifndef SSDT_CMN600_GENERATOR_H_
+#define SSDT_CMN600_GENERATOR_H_
+
+/** PeriphBase maximum address length is 256MB (0x10000000)
+ for a (X >= 4) || (Y >= 4) dimensions mesh.
+*/
+#define PERIPHBASE_MAX_ADDRESS_LENGTH SIZE_256MB
+
+/** PeriphBase minimum address length is 64MB (0x04000000)
+ for a (X < 4) && (Y < 4) dimensions mesh.
+*/
+#define PERIPHBASE_MIN_ADDRESS_LENGTH SIZE_64MB
+
+/** RootNodeBase address length is 16KB (0x00004000).
+*/
+#define ROOTNODEBASE_ADDRESS_LENGTH SIZE_16KB
+
+/** Maximum number of CMN-600 Debug and Trace Logic Controllers (DTC).
+*/
+#define MAX_DTC_COUNT 4
+
+/** Starting value for the UID to represent the CMN600 devices.
+*/
+#define CMN600_DEVICE_START_UID 0
+
+/** Maximum CMN-600 devices supported by this generator.
+ This generator supports a maximum of 16 CMN-600 devices.
+ Note: This is not a hard limitation and can be extended if needed.
+ Corresponding changes would be needed to support the Name and
+ UID fields describing the serial port.
+
+*/
+#define MAX_CMN600_DEVICES_SUPPORTED 16
+
+#endif // SSDT_CMN600_GENERATOR_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
new file mode 100644
index 00000000000..9f10c987356
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600LibArm.inf
@@ -0,0 +1,34 @@
+## @file
+# Ssdt CMN-600 Table Generator
+#
+# Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SsdtCmn600LibArm
+ FILE_GUID = CEDB450D-8F0E-4ACC-8FB7-F72EC7D216A4
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = NULL|DXE_DRIVER
+ CONSTRUCTOR = AcpiSsdtCmn600LibConstructor
+ DESTRUCTOR = AcpiSsdtCmn600LibDestructor
+
+[Sources]
+ SsdtCmn600Generator.c
+ SsdtCmn600Generator.h
+ SsdtCmn600Template.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+ AmlLib
+ BaseLib
+
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Template.asl b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Template.asl
new file mode 100644
index 00000000000..33c49f8fc17
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtCmn600LibArm/SsdtCmn600Template.asl
@@ -0,0 +1,81 @@
+/** @file
+ SSDT CMN-600 Template
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Arm CoreLink CMN-600 Coherent Mesh Network Technical Reference Manual r3p0
+ - Generic ACPI for Arm Components 1.0 Platform Design Document
+
+ @par Glossary:
+ - {template} - Data fixed up using AML Fixup APIs.
+ - {codegen} - Data generated using AML Codegen APIs.
+**/
+
+DefinitionBlock ("SsdtCmn600.aml", "SSDT", 2, "ARMLTD", "CMN-600", 1) {
+ Scope (_SB) {
+ // CMN-600 device object for a X * Y mesh, where (X >= 4) || (Y >= 4).
+ Device (CMN0) { // {template}
+ Name (_HID, "ARMHC600")
+ Name (_UID, 0x0) // {template}
+
+ Name (_CRS, ResourceTemplate () {
+ // Descriptor for 256 MB of the CFG region at offset PERIPHBASE.
+ QWordMemory (
+ ResourceConsumer, // bit 0 of general flags is 0.
+ PosDecode,
+ MinFixed, // Range is fixed.
+ MaxFixed, // Range is Fixed.
+ NonCacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0xA0000000, // MinAddress // {template}
+ 0xAFFFFFFF, // MaxAddress // {template}
+ 0x00000000, // Translation
+ 0x10000000, // RangeLength // {template}
+ , // ResourceSourceIndex
+ , // ResourceSource
+ CFGR // DescriptorName
+ ) // QWordMemory
+
+ // Descriptor for the root node. This is a 16 KB region at offset
+ // ROOTNODEBASE. In this example, ROOTNODEBASE starts at the 16 KB
+ // aligned offset of PERIPHBASE.
+ QWordMemory (
+ ResourceConsumer, // bit 0 of general flags is 0.
+ PosDecode,
+ MinFixed, // Range is fixed.
+ MaxFixed, // Range is Fixed.
+ NonCacheable,
+ ReadWrite,
+ 0x00000000, // Granularity
+ 0xA0000000, // MinAddress // {template}
+ 0xAFFFFFFF, // MaxAddress // {template}
+ 0x00000000, // Translation
+ 0x10000000, // RangeLength // {template}
+ , // ResourceSourceIndex
+ , // ResourceSource
+ ROOT // DescriptorName
+ ) // QWordMemory
+
+ // The Interrupt information is generated using AmlCodegen.
+ // Interrupt on PMU0 overflow, attached to DTC [0], with GSIV = <gsiv0>.
+ //
+ // Interrupt ( // {codegen}
+ // ResourceConsumer, // ResourceUsage
+ // Level, // EdgeLevel
+ // ActiveHigh, // ActiveLevel
+ // Exclusive, // Shared
+ // , // ResourceSourceIndex
+ // , // ResourceSource
+ // // DescriptorName
+ // ) {
+ // 0xA5 // <gsiv0 >
+ // } // Interrupt
+
+ }) // Name
+ } // Device
+ } // _SB
+} // DefinitionBlock
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c
new file mode 100644
index 00000000000..0af746133d6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortGenerator.c
@@ -0,0 +1,371 @@
+/** @file
+ SSDT Serial Port Table Generator.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <IndustryStandard/DebugPort2Table.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/SsdtSerialPortFixupLib.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+/** ARM standard SSDT Serial Port Table Generator
+
+ Constructs SSDT tables describing serial ports (other than the serial ports
+ used by the SPCR or DBG2 tables).
+
+Requirements:
+ The following Configuration Manager Object(s) are required by
+ this Generator:
+ - EArmObjSerialPortInfo
+*/
+
+/** This macro expands to a function that retrieves the Serial-port
+ information from the Configuration Manager.
+*/
+GET_OBJECT_LIST (
+ EObjNameSpaceArm,
+ EArmObjSerialPortInfo,
+ CM_ARM_SERIAL_PORT_INFO
+ );
+
+/** Starting value for the UID to represent the serial ports.
+ Note: The UID 0 and 1 are reserved for use by DBG2 port and SPCR
+ respectively. So, the UIDs for serial ports for general use
+ start at 2.
+*/
+#define SERIAL_PORT_START_UID 2
+
+/** Maximum serial ports supported by this generator.
+ This generator supports a maximum of 14 (16 - 2) serial ports.
+ The -2 here reflects the reservation for serial ports for the DBG2
+ and SPCR ports regardless of whether the DBG2 or SPCR port is enabled.
+ Note: This is not a hard limitation and can be extended if needed.
+ Corresponding changes would be needed to support the Name and
+ UID fields describing the serial port.
+
+*/
+#define MAX_SERIAL_PORTS_SUPPORTED 14
+
+/** Free any resources allocated for constructing the tables.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI Table Info.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol Interface.
+ @param [in, out] Table Pointer to an array of pointers
+ to ACPI Table(s).
+ @param [in] TableCount Number of ACPI table(s).
+
+ @retval EFI_SUCCESS The resources were freed successfully.
+ @retval EFI_INVALID_PARAMETER The table pointer is NULL or invalid.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FreeSsdtSerialPortTableEx (
+ IN CONST ACPI_TABLE_GENERATOR * CONST This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *** CONST Table,
+ IN CONST UINTN TableCount
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+ UINTN Index;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ if ((Table == NULL) ||
+ (*Table == NULL) ||
+ (TableCount == 0)) {
+ DEBUG ((DEBUG_ERROR, "ERROR: SSDT-SERIAL-PORT: Invalid Table Pointer\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TableList = *Table;
+
+ for (Index = 0; Index < TableCount; Index++) {
+ if ((TableList[Index] != NULL) &&
+ (TableList[Index]->Signature ==
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE)) {
+ Status = FreeSsdtSerialPortTable (TableList[Index]);
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT: Could not free SSDT table at index %d."
+ " Status = %r\n",
+ Index,
+ Status
+ ));
+ return Status;
+ }
+ } //for
+
+ // Free the table list.
+ FreePool (*Table);
+
+ return EFI_SUCCESS;
+}
+
+/** Construct SSDT tables describing serial-ports.
+
+ This function invokes the Configuration Manager protocol interface
+ to get the required hardware information for generating the ACPI
+ table.
+
+ If this function allocates any resources then they must be freed
+ in the FreeXXXXTableResourcesEx function.
+
+ @param [in] This Pointer to the ACPI table generator.
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] CfgMgrProtocol Pointer to the Configuration Manager
+ Protocol interface.
+ @param [out] Table Pointer to a list of generated ACPI table(s).
+ @param [out] TableCount Number of generated ACPI table(s).
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_BAD_BUFFER_SIZE The size returned by the Configuration
+ Manager is less than the Object size for
+ the requested object.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+ @retval EFI_UNSUPPORTED Unsupported configuration.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+BuildSsdtSerialPortTableEx (
+ IN CONST ACPI_TABLE_GENERATOR * This,
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * CONST AcpiTableInfo,
+ IN CONST EDKII_CONFIGURATION_MANAGER_PROTOCOL * CONST CfgMgrProtocol,
+ OUT EFI_ACPI_DESCRIPTION_HEADER *** Table,
+ OUT UINTN * CONST TableCount
+ )
+{
+ EFI_STATUS Status;
+ CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
+ UINT32 SerialPortCount;
+ UINTN Index;
+ CHAR8 NewName[5];
+ UINT64 Uid;
+ EFI_ACPI_DESCRIPTION_HEADER ** TableList;
+
+ ASSERT (This != NULL);
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (CfgMgrProtocol != NULL);
+ ASSERT (Table != NULL);
+ ASSERT (TableCount != NULL);
+ ASSERT (AcpiTableInfo->TableGeneratorId == This->GeneratorID);
+ ASSERT (AcpiTableInfo->AcpiTableSignature == This->AcpiTableSignature);
+
+ *Table = NULL;
+
+ Status = GetEArmObjSerialPortInfo (
+ CfgMgrProtocol,
+ CM_NULL_TOKEN,
+ &SerialPortInfo,
+ &SerialPortCount
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT: Failed to get serial port information."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ if (SerialPortCount > MAX_SERIAL_PORTS_SUPPORTED) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT: Too many serial ports: %d."
+ " Maximum serial ports supported = %d.\n",
+ SerialPortCount,
+ MAX_SERIAL_PORTS_SUPPORTED
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Validate the SerialPort info.
+ Status = ValidateSerialPortInfo (SerialPortInfo, SerialPortCount);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT: Invalid serial port information. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Allocate a table to store pointers to the SSDT tables.
+ TableList = (EFI_ACPI_DESCRIPTION_HEADER**)
+ AllocateZeroPool (
+ (sizeof (EFI_ACPI_DESCRIPTION_HEADER*) * SerialPortCount)
+ );
+ if (TableList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT: Failed to allocate memory for Table List."
+ " Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Setup the table list early so that that appropriate cleanup
+ // can be done in case of failure.
+ *Table = TableList;
+
+ NewName[0] = 'C';
+ NewName[1] = 'O';
+ NewName[2] = 'M';
+ NewName[4] = '\0';
+ for (Index = 0; Index < SerialPortCount; Index++) {
+ Uid = SERIAL_PORT_START_UID + Index;
+ NewName[3] = AsciiFromHex ((UINT8)(Uid));
+
+ // Build a SSDT table describing the serial port.
+ Status = BuildSsdtSerialPortTable (
+ AcpiTableInfo,
+ &SerialPortInfo[Index],
+ NewName,
+ Uid,
+ &TableList[Index]
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT: Failed to build associated SSDT table."
+ " Status = %r\n",
+ Status
+ ));
+ goto error_handler;
+ }
+
+ // Increment the table count here so that appropriate cleanup
+ // can be done in case of failure.
+ *TableCount += 1;
+ } // for
+
+error_handler:
+ // Note: Table list and Serial port count has been setup. The
+ // error handler does nothing here as the framework will invoke
+ // FreeSsdtSerialPortTableEx() even on failure.
+ return Status;
+}
+
+/** This macro defines the SSDT Serial Port Table Generator revision.
+*/
+#define SSDT_SERIAL_GENERATOR_REVISION CREATE_REVISION (1, 0)
+
+/** The interface for the SSDT Serial Port Table Generator.
+*/
+STATIC
+CONST
+ACPI_TABLE_GENERATOR SsdtSerialPortGenerator = {
+ // Generator ID
+ CREATE_STD_ACPI_TABLE_GEN_ID (EStdAcpiTableIdSsdtSerialPort),
+ // Generator Description
+ L"ACPI.STD.SSDT.SERIAL.PORT.GENERATOR",
+ // ACPI Table Signature
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
+ // ACPI Table Revision - Unused
+ 0,
+ // Minimum ACPI Table Revision - Unused
+ 0,
+ // Creator ID
+ TABLE_GENERATOR_CREATOR_ID_ARM,
+ // Creator Revision
+ SSDT_SERIAL_GENERATOR_REVISION,
+ // Build table function. Use the extended version instead.
+ NULL,
+ // Free table function. Use the extended version instead.
+ NULL,
+ // Extended Build table function.
+ BuildSsdtSerialPortTableEx,
+ // Extended free function.
+ FreeSsdtSerialPortTableEx
+};
+
+/** Register the Generator with the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is registered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_ALREADY_STARTED The Generator for the Table ID
+ is already registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtSerialPortLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+ Status = RegisterAcpiTableGenerator (&SsdtSerialPortGenerator);
+ DEBUG ((
+ DEBUG_INFO,
+ "SSDT-SERIAL-PORT: Register Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Deregister the Generator from the ACPI Table Factory.
+
+ @param [in] ImageHandle The handle to the image.
+ @param [in] SystemTable Pointer to the System Table.
+
+ @retval EFI_SUCCESS The Generator is deregistered.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND The Generator is not registered.
+**/
+EFI_STATUS
+EFIAPI
+AcpiSsdtSerialPortLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE * SystemTable
+ )
+{
+ EFI_STATUS Status;
+ Status = DeregisterAcpiTableGenerator (&SsdtSerialPortGenerator);
+ DEBUG ((
+ DEBUG_INFO,
+ "SSDT-SERIAL-PORT: Deregister Generator. Status = %r\n",
+ Status
+ ));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
new file mode 100644
index 00000000000..36907c798d3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Acpi/Arm/AcpiSsdtSerialPortLibArm/SsdtSerialPortLibArm.inf
@@ -0,0 +1,33 @@
+## @file
+# Ssdt Serial Port Table Generator
+#
+# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SsdtSerialPortLibArm
+ FILE_GUID = D1F92325-2DFB-435C-9B4C-A6B864F19230
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = NULL|DXE_DRIVER
+ CONSTRUCTOR = AcpiSsdtSerialPortLibConstructor
+ DESTRUCTOR = AcpiSsdtSerialPortLibDestructor
+
+[Sources]
+ SsdtSerialPortGenerator.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ ArmPlatformPkg/ArmPlatformPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+ AmlLib
+ BaseLib
+ TableHelperLib
+ SsdtSerialPortFixupLib
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h
new file mode 100644
index 00000000000..cd363ccf381
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlCoreInterface.h
@@ -0,0 +1,767 @@
+/** @file
+ AML Core Interface.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_CORE_INTERFACE_H_
+#define AML_CORE_INTERFACE_H_
+
+/* This header file does not include internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions
+ must be included by the caller file. The function prototypes must
+ only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node
+ definitions.
+ This allows to keep the functions defined here both internal and
+ potentially external. If necessary, any function of this file can
+ be exposed externally.
+ The Api folder is internal to the AmlLib, but should only use these
+ functions. They provide a "safe" way to interact with the AmlLib.
+*/
+
+#include <AmlDefines.h>
+#include <Include/Library/AmlLib/AmlLib.h>
+#include <ResourceData/AmlResourceData.h>
+
+/**
+ @defgroup CoreApis Core APIs
+ @ingroup AMLLib
+ @{
+ Core APIs are the main APIs of the library. They allow to:
+ - Create an AML tree;
+ - Delete an AML tree;
+ - Clone an AML tree/node;
+ - Serialize an AML tree (convert the tree to a DSDT/SSDT table).
+ @}
+*/
+
+/** Serialize a tree to create a DSDT/SSDT table.
+
+ If:
+ - the content of BufferSize is >= to the size needed to serialize the
+ definition block;
+ - Buffer is not NULL;
+ first serialize the ACPI DSDT/SSDT header from the root node,
+ then serialize the AML blob from the rest of the tree.
+
+ The content of BufferSize is always updated to the size needed to
+ serialize the definition block.
+
+ @ingroup CoreApis
+
+ @param [in] RootNode Pointer to a root node.
+ @param [in] Buffer Buffer to write the DSDT/SSDT table to.
+ If Buffer is NULL, the size needed to
+ serialize the DSDT/SSDT table is returned
+ in BufferSize.
+ @param [in, out] BufferSize Pointer holding the size of the Buffer.
+ Its content is always updated to the size
+ needed to serialize the DSDT/SSDT table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlSerializeTree (
+ IN AML_ROOT_NODE_HANDLE RootNode,
+ IN UINT8 * Buffer, OPTIONAL
+ IN OUT UINT32 * BufferSize
+ );
+
+/** Clone a node.
+
+ This function does not clone the children nodes.
+ The cloned node returned is not attached to any tree.
+
+ @ingroup CoreApis
+
+ @param [in] Node Pointer to a node.
+ @param [out] ClonedNode Pointer holding the cloned node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCloneNode (
+ IN AML_NODE_HANDLE Node,
+ OUT AML_NODE_HANDLE * ClonedNode
+ );
+
+/**
+ @defgroup TreeModificationApis Tree modification APIs
+ @ingroup AMLLib
+ @{
+ Tree modification APIs allow to add/remove/replace nodes that are in a
+ variable list of arguments.
+
+ No interface is provided to add/remove/replace nodes that are in a fixed
+ list of arguments. Indeed, these nodes are the spine of the tree and a
+ mismanipulation would make the tree inconsistent.
+
+ It is however possible to modify the content of fixed argument nodes via
+ @ref NodeInterfaceApis APIs.
+ @}
+*/
+
+/** Remove the Node from its parent's variable list of arguments.
+
+ The function will fail if the Node is in its parent's fixed
+ argument list.
+ The Node is not deleted. The deletion is done separately
+ from the removal.
+
+ @ingroup TreeModificationApis
+
+ @param [in] Node Pointer to a Node.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlRemoveNodeFromVarArgList (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Add the NewNode to the head of the variable list of arguments
+ of the ParentNode.
+
+ @ingroup TreeModificationApis
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddHead (
+ IN AML_NODE_HANDLE ParentNode,
+ IN AML_NODE_HANDLE NewNode
+ );
+
+/** Add the NewNode to the tail of the variable list of arguments
+ of the ParentNode.
+
+ @ingroup TreeModificationApis
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddTail (
+ IN AML_NODE_HANDLE ParentNode,
+ IN AML_NODE_HANDLE NewNode
+ );
+
+/** Add the NewNode before the Node in the list of variable
+ arguments of the Node's parent.
+
+ @ingroup TreeModificationApis
+
+ @param [in] Node Pointer to a node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddBefore (
+ IN AML_NODE_HANDLE Node,
+ IN AML_NODE_HANDLE NewNode
+ );
+
+/** Add the NewNode after the Node in the variable list of arguments
+ of the Node's parent.
+
+ @ingroup TreeModificationApis
+
+ @param [in] Node Pointer to a node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddAfter (
+ IN AML_NODE_HANDLE Node,
+ IN AML_NODE_HANDLE NewNode
+ );
+
+/** Append a Resource Data node to the BufferOpNode.
+
+ The Resource Data node is added at the end of the variable
+ list of arguments of the BufferOpNode, but before the End Tag.
+ If no End Tag is found, the function returns an error.
+
+ @param [in] BufferOpNode Buffer node containing resource data elements.
+ @param [in] NewRdNode The new Resource Data node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAppendRdNode (
+ IN AML_OBJECT_NODE_HANDLE BufferOpNode,
+ IN AML_DATA_NODE_HANDLE NewRdNode
+ );
+
+/** Replace the OldNode, which is in a variable list of arguments,
+ with the NewNode.
+
+ Note: This function unlinks the OldNode from the tree. It is the callers
+ responsibility to delete the OldNode if needed.
+
+ @ingroup TreeModificationApis
+
+ @param [in] OldNode Pointer to the node to replace.
+ Must be a data node or an object node.
+ @param [in] NewNode The new node to insert.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlReplaceVariableArgument (
+ IN AML_NODE_HANDLE OldNode,
+ IN AML_NODE_HANDLE NewNode
+ );
+
+/**
+ @defgroup NodeInterfaceApis Node Interface APIs
+ @ingroup AMLLib
+ @{
+ Node Interface APIs allow to query information from a node. Some functions
+ expect a specific node type among the root/object/data node types.
+
+ For instance, AmlGetRootNodeInfo expects to receive a root node.
+
+ E.g.: Query the node type, the ACPI header stored in the root node,
+ the OpCode/SubOpCode/PkgLen of an object node, the type of data
+ stored in a data node, etc.
+
+ These APIs also allow to update some information.
+
+ E.g.: The ACPI header stored in the root node, the buffer of a data node.
+
+ The information of object nodes and the data type of data nodes cannot be
+ modified. This prevents the creation of an inconsistent tree.
+
+ It is however possible to remove a node from a variable list of arguments
+ and replace it. Use the @ref TreeModificationApis APIs for this.
+ @}
+*/
+
+/** Returns the tree node type (Root/Object/Data).
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] Node Pointer to a Node.
+
+ @return The node type.
+ EAmlNodeUnknown if invalid parameter.
+**/
+EAML_NODE_TYPE
+EFIAPI
+AmlGetNodeType (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Get the RootNode information.
+ The Node must be a root node.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] RootNode Pointer to a root node.
+ @param [out] SdtHeaderBuffer Buffer to copy the ACPI DSDT/SSDT header to.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetRootNodeInfo (
+ IN AML_ROOT_NODE_HANDLE RootNode,
+ OUT EFI_ACPI_DESCRIPTION_HEADER * SdtHeaderBuffer
+ );
+
+/** Get the ObjectNode information.
+ The Node must be an object node.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [out] OpCode Pointer holding the OpCode.
+ Optional, can be NULL.
+ @param [out] SubOpCode Pointer holding the SubOpCode.
+ Optional, can be NULL.
+ @param [out] PkgLen Pointer holding the PkgLen.
+ The PkgLen is 0 for nodes
+ not having the Pkglen attribute.
+ Optional, can be NULL.
+ @param [out] IsNameSpaceNode Pointer holding TRUE if the node is defining
+ or changing the NameSpace scope.
+ E.g.: The "Name ()" and "Scope ()" ASL
+ statements add/modify the NameSpace scope.
+ Their corresponding node are NameSpace nodes.
+ Optional, can be NULL.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetObjectNodeInfo (
+ IN AML_OBJECT_NODE_HANDLE ObjectNode,
+ OUT UINT8 * OpCode, OPTIONAL
+ OUT UINT8 * SubOpCode, OPTIONAL
+ OUT UINT32 * PkgLen, OPTIONAL
+ OUT BOOLEAN * IsNameSpaceNode OPTIONAL
+ );
+
+/** Returns the count of the fixed arguments for the input Node.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] Node Pointer to an object node.
+
+ @return Number of fixed arguments of the object node.
+ Return 0 if the node is not an object node.
+**/
+UINT8
+AmlGetFixedArgumentCount (
+ IN AML_OBJECT_NODE_HANDLE Node
+ );
+
+/** Get the data type of the DataNode.
+ The Node must be a data node.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] DataNode Pointer to a data node.
+ @param [out] DataType Pointer holding the data type of the data buffer.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetNodeDataType (
+ IN AML_DATA_NODE_HANDLE DataNode,
+ OUT EAML_NODE_DATA_TYPE * DataType
+ );
+
+/** Get the descriptor Id of the resource data element
+ contained in the DataNode.
+
+ The Node must be a data node.
+ The Node must have the resource data type, i.e. have the
+ EAmlNodeDataTypeResourceData data type.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] DataNode Pointer to a data node containing a
+ resource data element.
+ @param [out] ResourceDataType Pointer holding the descriptor Id of
+ the resource data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetResourceDataType (
+ IN AML_DATA_NODE_HANDLE DataNode,
+ OUT AML_RD_HEADER * ResourceDataType
+ );
+
+/** Get the data buffer and size of the DataNode.
+ The Node must be a data node.
+
+ BufferSize is always updated to the size of buffer of the DataNode.
+
+ If:
+ - the content of BufferSize is >= to the DataNode's buffer size;
+ - Buffer is not NULL;
+ then copy the content of the DataNode's buffer in Buffer.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] DataNode Pointer to a data node.
+ @param [out] Buffer Buffer to write the data to.
+ Optional, if NULL, only update BufferSize.
+ @param [in, out] BufferSize Pointer holding:
+ - At entry, the size of the Buffer;
+ - At exit, the size of the DataNode's
+ buffer size.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetDataNodeBuffer (
+ IN AML_DATA_NODE_HANDLE DataNode,
+ OUT UINT8 * Buffer, OPTIONAL
+ IN OUT UINT32 * BufferSize
+ );
+
+/** Update the ACPI DSDT/SSDT table header.
+
+ The input SdtHeader information is copied to the tree RootNode.
+ The table Length field is automatically updated.
+ The checksum field is only updated when serializing the tree.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] RootNode Pointer to a root node.
+ @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT table header.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRootNode (
+ IN AML_ROOT_NODE_HANDLE RootNode,
+ IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader
+ );
+
+/** Update an object node representing an integer with a new value.
+
+ The object node must have one of the following OpCodes:
+ - AML_BYTE_PREFIX
+ - AML_WORD_PREFIX
+ - AML_DWORD_PREFIX
+ - AML_QWORD_PREFIX
+ - AML_ZERO_OP
+ - AML_ONE_OP
+
+ The following OpCode is not supported:
+ - AML_ONES_OP
+
+ @param [in] IntegerOpNode Pointer an object node containing an integer.
+ Must not be an object node with an AML_ONES_OP
+ OpCode.
+ @param [in] NewInteger New integer value to set.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateInteger (
+ IN AML_OBJECT_NODE_HANDLE IntegerOpNode,
+ IN UINT64 NewInteger
+ );
+
+/** Update the buffer of a data node.
+
+ Note: The data type of the buffer's content must match the data type of the
+ DataNode. This is a hard restriction to prevent undesired behaviour.
+
+ @ingroup NodeInterfaceApis
+
+ @param [in] DataNode Pointer to a data node.
+ @param [in] DataType Data type of the Buffer's content.
+ @param [in] Buffer Buffer containing the new data. The content of
+ the Buffer is copied.
+ @param [in] Size Size of the Buffer.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_UNSUPPORTED Operation not supporter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateDataNode (
+ IN AML_DATA_NODE_HANDLE DataNode,
+ IN EAML_NODE_DATA_TYPE DataType,
+ IN UINT8 * Buffer,
+ IN UINT32 Size
+ );
+
+/**
+ @defgroup NavigationApis Navigation APIs
+ @ingroup AMLLib
+ @{
+ Navigation APIs allow to navigate in the AML tree. There are different
+ ways to navigate in the tree by:
+ - Direct relation (@ref CoreNavigationApis);
+ - Enumeration: enumerate all the nodes and call a callback function
+ (@ref EnumerationApis);
+ - Iteration: instantiate an iterator and use it to navigate
+ (@ref IteratorApis);
+ - NameSpace path: use the AML namespace to navigate the tree
+ (@ref NameSpaceApis).
+ @}
+*/
+
+/**
+ @defgroup CoreNavigationApis Core Navigation APIs
+ @ingroup NavigationApis
+ @{
+ Core Navigation APIs allow to get a node by specifying a relation.
+
+ E.g.: Get the parent, the n-th fixed argument, the next variable
+ argument, etc.
+ @}
+*/
+
+/** Get the parent node of the input Node.
+
+ @ingroup CoreNavigationApis
+
+ @param [in] Node Pointer to a node.
+
+ @return The parent node of the input Node.
+ NULL otherwise.
+**/
+AML_NODE_HANDLE
+EFIAPI
+AmlGetParent (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Get the node at the input Index in the fixed argument list of the input
+ ObjectNode.
+
+ @ingroup CoreNavigationApis
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Index The Index of the fixed argument to get.
+
+ @return The node at the input Index in the fixed argument list
+ of the input ObjectNode.
+ NULL otherwise, e.g. if the node is not an object node, or no
+ node is available at this Index.
+**/
+AML_NODE_HANDLE
+EFIAPI
+AmlGetFixedArgument (
+ IN AML_OBJECT_NODE_HANDLE ObjectNode,
+ IN EAML_PARSE_INDEX Index
+ );
+
+/** Get the sibling node among the nodes being in
+ the same variable argument list.
+
+ (ParentNode) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(VarArgNode)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Node must be in a variable list of arguments.
+ Traversal Order: VarArgNode, f, g, NULL
+
+ @ingroup CoreNavigationApis
+
+ @param [in] VarArgNode Pointer to a node.
+ Must be in a variable list of arguments.
+
+ @return The next node after VarArgNode in the variable list of arguments.
+ Return NULL if
+ - VarArgNode is the last node of the list, or
+ - VarArgNode is not part of a variable list of arguments.
+**/
+AML_NODE_HANDLE
+EFIAPI
+AmlGetSiblingVariableArgument (
+ IN AML_NODE_HANDLE VarArgNode
+ );
+
+/** Get the next variable argument.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: e, f, g, NULL
+
+ @ingroup CoreNavigationApis
+
+ @param [in] Node Pointer to a Root node or Object Node.
+ @param [in] CurrVarArg Pointer to the Current Variable Argument.
+
+ @return The node after the CurrVarArg in the variable list of arguments.
+ If CurrVarArg is NULL, return the first node of the
+ variable argument list.
+ Return NULL if
+ - CurrVarArg is the last node of the list, or
+ - Node does not have a variable list of arguments.
+**/
+AML_NODE_HANDLE
+EFIAPI
+AmlGetNextVariableArgument (
+ IN AML_NODE_HANDLE Node,
+ IN AML_NODE_HANDLE CurrVarArg
+ );
+
+/** Get the previous variable argument.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: g, f, e, NULL
+
+ @ingroup CoreNavigationApis
+
+ @param [in] Node Pointer to a root node or an object node.
+ @param [in] CurrVarArg Pointer to the Current Variable Argument.
+
+ @return The node before the CurrVarArg in the variable list of
+ arguments.
+ If CurrVarArg is NULL, return the last node of the
+ variable list of arguments.
+ Return NULL if:
+ - CurrVarArg is the first node of the list, or
+ - Node doesn't have a variable list of arguments.
+**/
+AML_NODE_HANDLE
+EFIAPI
+AmlGetPreviousVariableArgument (
+ IN AML_NODE_HANDLE Node,
+ IN AML_NODE_HANDLE CurrVarArg
+ );
+
+/**
+ @defgroup EnumerationApis Enumeration APIs
+ @ingroup NavigationApis
+ @{
+ Enumeration APIs are navigation APIs, allowing to call a callback function
+ on each node enumerated. Nodes are enumerated in the AML bytestream order,
+ i.e. in a depth first order.
+ @}
+*/
+
+/**
+ Callback function prototype used when iterating through the tree.
+
+ @ingroup EnumerationApis
+
+ @param [in] Node The Node currently being processed.
+ @param [in, out] Context A context for the callback function.
+ Can be optional.
+ @param [in, out] Status End the enumeration if pointing to a value
+ evaluated to TRUE.
+ Can be optional.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+typedef
+BOOLEAN
+(EFIAPI * EDKII_AML_TREE_ENUM_CALLBACK) (
+ IN AML_NODE_HANDLE Node,
+ IN OUT VOID * Context, OPTIONAL
+ IN OUT EFI_STATUS * Status OPTIONAL
+ );
+
+/** Enumerate all nodes of the subtree under the input Node in the AML
+ bytestream order (i.e. in a depth first order), and call the CallBack
+ function with the input Context.
+ The prototype of the Callback function is EDKII_AML_TREE_ENUM_CALLBACK.
+
+ @ingroup EnumerationApis
+
+ @param [in] Node Enumerate nodes of the subtree under this Node.
+ Must be a valid node.
+ @param [in] CallBack Callback function to call on each node.
+ @param [in, out] Context Void pointer used to pass some information
+ to the Callback function.
+ Optional, can be NULL.
+ @param [out] Status Optional parameter that can be used to get
+ the status of the Callback function.
+ If used, need to be init to EFI_SUCCESS.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+BOOLEAN
+EFIAPI
+AmlEnumTree (
+ IN AML_NODE_HANDLE Node,
+ IN EDKII_AML_TREE_ENUM_CALLBACK CallBack,
+ IN OUT VOID * Context, OPTIONAL
+ OUT EFI_STATUS * Status OPTIONAL
+ );
+
+/**
+ @defgroup NameSpaceApis NameSpace APIs
+ @ingroup NavigationApis
+ @{
+ NameSpace APIs allow to find a node from an AML path, and reciprocally
+ get the AML path of a node.
+
+ These APIs only operate on "NameSpace nodes", i.e. nodes that are
+ part of the AML namespace. These are the root node and object nodes
+ acknowledged by AmlGetObjectNodeInfo in @ref NodeInterfaceApis.
+ @}
+*/
+
+/** Build the absolute ASL pathname to Node.
+
+ BufferSize is always updated to the size of the pathname.
+
+ If:
+ - the content of BufferSize is >= to the size of the pathname AND;
+ - Buffer is not NULL;
+ then copy the pathname in the Buffer. A buffer of the size
+ MAX_ASL_NAMESTRING_SIZE is big enough to receive any ASL pathname.
+
+ @ingroup NameSpaceApis
+
+ @param [in] Node Node to build the absolute path to.
+ Must be a root node, or a namespace node.
+ @param [out] Buffer Buffer to write the path to.
+ If NULL, only update *BufferSize.
+ @param [in, out] BufferSize Pointer holding:
+ - At entry, the size of the Buffer;
+ - At exit, the size of the pathname.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetAslPathName (
+ IN AML_NODE_HANDLE Node,
+ OUT CHAR8 * Buffer,
+ IN OUT UINT32 * BufferSize
+ );
+
+#endif // AML_CORE_INTERFACE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c
new file mode 100644
index 00000000000..9986d428465
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.c
@@ -0,0 +1,546 @@
+/** @file
+ AML Print Function.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+#include <AmlDbgPrint/AmlDbgPrint.h>
+
+#include <AmlCoreInterface.h>
+#include <String/AmlString.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTreeTraversal.h>
+
+#if !defined (MDEPKG_NDEBUG)
+
+/** String table representing AML Data types as defined by EAML_NODE_DATA_TYPE.
+*/
+CONST CHAR8 * NodeDataTypeStrTbl[] = {
+ "EAmlNodeDataTypeNone",
+ "EAmlNodeDataTypeReserved1",
+ "EAmlNodeDataTypeReserved2",
+ "EAmlNodeDataTypeReserved3",
+ "EAmlNodeDataTypeReserved4",
+ "EAmlNodeDataTypeReserved5",
+ "EAmlNodeDataTypeNameString",
+ "EAmlNodeDataTypeString",
+ "EAmlNodeDataTypeUInt",
+ "EAmlNodeDataTypeRaw",
+ "EAmlNodeDataTypeResourceData",
+ "EAmlNodeDataTypeFieldPkgLen",
+ "EAmlNodeDataTypeMax"
+};
+
+/** String table representing AML Node types as defined by EAML_NODE_TYPE.
+*/
+CONST CHAR8 * NodeTypeStrTbl[] = {
+ "EAmlNodeUnknown",
+ "EAmlNodeRoot",
+ "EAmlNodeObject",
+ "EAmlNodeData",
+ "EAmlNodeMax"
+};
+
+/** Print Size chars at Buffer address.
+
+ @param [in] ErrorLevel Error level for the DEBUG macro.
+ @param [in] Buffer Buffer containing the chars.
+ @param [in] Size Number of chars to print.
+**/
+VOID
+EFIAPI
+AmlDbgPrintChars (
+ IN UINT32 ErrorLevel,
+ IN CONST CHAR8 * Buffer,
+ IN UINT32 Size
+ )
+{
+ UINT32 i;
+
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return;
+ }
+
+ for (i = 0; i < Size; i++) {
+ DEBUG ((ErrorLevel, "%c", Buffer[i]));
+ }
+}
+
+/** Print an AML NameSeg.
+ Don't print trailing underscores ('_').
+
+ @param [in] Buffer Buffer containing an AML NameSeg.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNameSeg (
+ IN CONST CHAR8 * Buffer
+ )
+{
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO, "%c", Buffer[0]));
+ if ((Buffer[1] == AML_NAME_CHAR__) &&
+ (Buffer[2] == AML_NAME_CHAR__) &&
+ (Buffer[3] == AML_NAME_CHAR__)) {
+ return;
+ }
+ DEBUG ((DEBUG_INFO, "%c", Buffer[1]));
+ if ((Buffer[2] == AML_NAME_CHAR__) &&
+ (Buffer[3] == AML_NAME_CHAR__)) {
+ return;
+ }
+ DEBUG ((DEBUG_INFO, "%c", Buffer[2]));
+ if (Buffer[3] == AML_NAME_CHAR__) {
+ return;
+ }
+ DEBUG ((DEBUG_INFO, "%c", Buffer[3]));
+ return;
+}
+
+/** Print an AML NameString.
+
+ @param [in] Buffer Buffer containing an AML NameString.
+ @param [in] NewLine Print a newline char at the end of the NameString.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNameString (
+ IN CONST CHAR8 * Buffer,
+ IN BOOLEAN NewLine
+ )
+{
+ UINT8 SegCount;
+ UINT8 Index;
+
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return;
+ }
+
+ // Handle Root and Parent(s).
+ if (*Buffer == AML_ROOT_CHAR) {
+ Buffer++;
+ DEBUG ((DEBUG_INFO, "\\"));
+ } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
+ do {
+ Buffer++;
+ DEBUG ((DEBUG_INFO, "^"));
+ } while (*Buffer == AML_PARENT_PREFIX_CHAR);
+ }
+
+ // Handle SegCount(s).
+ if (*Buffer == AML_DUAL_NAME_PREFIX) {
+ Buffer++;
+ SegCount = 2;
+ } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
+ Buffer++;
+ // For multi name prefix the seg count is in the second byte.
+ SegCount = *Buffer;
+ Buffer++;
+ } else if (AmlIsLeadNameChar (*Buffer)) {
+ // Only check the first char first to avoid overflow.
+ // Then the whole NameSeg can be checked.
+ if (!AmlIsNameSeg (Buffer)) {
+ ASSERT (0);
+ return;
+ }
+ SegCount = 1;
+ } else if (*Buffer == AML_ZERO_OP) {
+ SegCount = 0;
+ } else {
+ // Should not be possible.
+ ASSERT (0);
+ return;
+ }
+
+ if (SegCount != 0) {
+ AMLDBG_PRINT_NAMESEG (Buffer);
+ Buffer += AML_NAME_SEG_SIZE;
+ for (Index = 0; Index < SegCount - 1; Index++) {
+ DEBUG ((DEBUG_INFO, "."));
+ AMLDBG_PRINT_NAMESEG (Buffer);
+ Buffer += AML_NAME_SEG_SIZE;
+ }
+ }
+
+ if (NewLine) {
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+
+ return;
+}
+
+/** Print the information contained in the header of the Node.
+
+ @param [in] Node Pointer to a node.
+ @param [in] Level Level of the indentation.
+**/
+STATIC
+VOID
+EFIAPI
+AmlDbgPrintNodeHeader (
+ IN AML_NODE_HEADER * Node,
+ IN UINT8 Level
+ )
+{
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%3d | %-15s | ",
+ Level,
+ NodeTypeStrTbl[Node->NodeType]
+ ));
+}
+
+/** Print fields of a data node.
+
+ @param [in] DataNode Pointer to a data node.
+ @param [in] Level Level of the indentation.
+**/
+STATIC
+VOID
+EFIAPI
+AmlDbgPrintDataNode (
+ IN AML_DATA_NODE * DataNode,
+ IN UINT8 Level
+ )
+{
+ UINT32 Idx;
+
+ if (!IS_AML_DATA_NODE (DataNode)) {
+ ASSERT (0);
+ return;
+ }
+
+ AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)DataNode, Level);
+
+ DEBUG ((DEBUG_INFO, "%-36s | ", NodeDataTypeStrTbl[DataNode->DataType]));
+ DEBUG ((DEBUG_INFO, "0x%04x | ", DataNode->Size));
+
+ if ((DataNode->DataType == EAmlNodeDataTypeNameString) ||
+ (DataNode->DataType == EAmlNodeDataTypeString)) {
+ AMLDBG_PRINT_CHARS (
+ DEBUG_INFO,
+ (CONST CHAR8*)DataNode->Buffer,
+ DataNode->Size
+ );
+ } else if (DataNode->DataType == EAmlNodeDataTypeUInt) {
+ switch (DataNode->Size) {
+ case 1:
+ {
+ DEBUG ((DEBUG_INFO, "0x%0x", *((UINT8*)DataNode->Buffer)));
+ break;
+ }
+ case 2:
+ {
+ DEBUG ((DEBUG_INFO, "0x%0x", *((UINT16*)DataNode->Buffer)));
+ break;
+ }
+ case 4:
+ {
+ DEBUG ((DEBUG_INFO, "0x%0lx", *((UINT32*)DataNode->Buffer)));
+ break;
+ }
+ case 8:
+ {
+ DEBUG ((DEBUG_INFO, "0x%0llx", *((UINT64*)DataNode->Buffer)));
+ break;
+ }
+ default:
+ {
+ ASSERT (0);
+ return;
+ }
+ }
+ } else {
+ // No specific format.
+ for (Idx = 0; Idx < DataNode->Size; Idx++) {
+ DEBUG ((DEBUG_INFO, "%02x ", DataNode->Buffer[Idx]));
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/** Print fields of an object node.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Level Level of the indentation.
+**/
+STATIC
+VOID
+EFIAPI
+AmlDbgPrintObjectNode (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN UINT8 Level
+ )
+{
+ if (!IS_AML_OBJECT_NODE (ObjectNode)) {
+ ASSERT (0);
+ return;
+ }
+
+ AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)ObjectNode, Level);
+
+ DEBUG ((DEBUG_INFO, "0x%02x | ", ObjectNode->AmlByteEncoding->OpCode));
+ DEBUG ((DEBUG_INFO, "0x%02x | ", ObjectNode->AmlByteEncoding->SubOpCode));
+
+ // Print a string corresponding to the field object OpCode/SubOpCode.
+ if (AmlNodeHasAttribute (ObjectNode, AML_IS_FIELD_ELEMENT)) {
+ DEBUG ((DEBUG_INFO, "%-15s ", AmlGetFieldOpCodeStr (
+ ObjectNode->AmlByteEncoding->OpCode,
+ 0
+ )));
+ } else {
+ // Print a string corresponding to the object OpCode/SubOpCode.
+ DEBUG ((DEBUG_INFO, "%-15s | ", AmlGetOpCodeStr (
+ ObjectNode->AmlByteEncoding->OpCode,
+ ObjectNode->AmlByteEncoding->SubOpCode)
+ ));
+ }
+
+ DEBUG ((DEBUG_INFO, "%3d | ", ObjectNode->AmlByteEncoding->MaxIndex));
+ DEBUG ((DEBUG_INFO, "0x%08x | ", ObjectNode->AmlByteEncoding->Attribute));
+ DEBUG ((DEBUG_INFO, "0x%04x | ", ObjectNode->PkgLen));
+ if (AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE)) {
+ AMLDBG_PRINT_NAMESTR (
+ AmlNodeGetName ((CONST AML_OBJECT_NODE*)ObjectNode),
+ FALSE
+ );
+ }
+
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/** Print fields of a root node.
+
+ @param [in] RootNode Pointer to a root node.
+ @param [in] Level Level of the indentation.
+**/
+STATIC
+VOID
+EFIAPI
+AmlDbgPrintRootNode (
+ IN AML_ROOT_NODE * RootNode,
+ IN UINT8 Level
+ )
+{
+ if (!IS_AML_ROOT_NODE (RootNode)) {
+ ASSERT (0);
+ return;
+ }
+
+ AmlDbgPrintNodeHeader ((AML_NODE_HEADER*)RootNode, Level);
+
+ DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->Signature));
+ DEBUG ((DEBUG_INFO, "0x%08x | ", RootNode->SdtHeader->Length));
+ DEBUG ((DEBUG_INFO, "%3d | ", RootNode->SdtHeader->Revision));
+ DEBUG ((DEBUG_INFO, "0x%02x | ", RootNode->SdtHeader->Checksum));
+ DEBUG ((
+ DEBUG_INFO,
+ "%c%c%c%c%c%c | ",
+ RootNode->SdtHeader->OemId[0],
+ RootNode->SdtHeader->OemId[1],
+ RootNode->SdtHeader->OemId[2],
+ RootNode->SdtHeader->OemId[3],
+ RootNode->SdtHeader->OemId[4],
+ RootNode->SdtHeader->OemId[5]
+ ));
+ DEBUG ((DEBUG_INFO, "%-16llx | ", RootNode->SdtHeader->OemTableId));
+ DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->OemRevision));
+ DEBUG ((DEBUG_INFO, "%8x | ", RootNode->SdtHeader->CreatorId));
+ DEBUG ((DEBUG_INFO, "%8x", RootNode->SdtHeader->CreatorRevision));
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+/** Print a header to help interpreting node information.
+**/
+STATIC
+VOID
+EFIAPI
+AmlDbgPrintTableHeader (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "Lvl | Node Type |\n"));
+ DEBUG ((
+ DEBUG_INFO,
+ " | %-15s | Signature| Length | Rev | CSum | OemId | "
+ "OemTableId | OemRev | CreatorId| CreatorRev\n",
+ NodeTypeStrTbl[EAmlNodeRoot]
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ " | %-15s | Op | SubOp| OpName | MaxI| Attribute | "
+ "PkgLen | NodeName (opt)\n",
+ NodeTypeStrTbl[EAmlNodeObject]
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ " | %-15s | Data Type | Size | "
+ "Buffer\n",
+ NodeTypeStrTbl[EAmlNodeData]
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ "---------------------------------------"
+ "---------------------------------------\n"
+ ));
+}
+
+/** Recursively print the subtree under the Node.
+ This is an internal function.
+
+ @param [in] Node Pointer to the root of the subtree to print.
+ Can be a root/object/data node.
+ @param [in] Recurse If TRUE, recurse.
+ @param [in] Level Level in the tree.
+**/
+STATIC
+VOID
+EFIAPI
+AmlDbgPrintTreeInternal (
+ IN AML_NODE_HEADER * Node,
+ IN BOOLEAN Recurse,
+ IN UINT8 Level
+ )
+{
+ AML_NODE_HEADER * ChildNode;
+
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return;
+ }
+
+ if (IS_AML_DATA_NODE (Node)) {
+ AmlDbgPrintDataNode ((AML_DATA_NODE*)Node, Level);
+ return;
+ } else if (IS_AML_OBJECT_NODE (Node)) {
+ AmlDbgPrintObjectNode ((AML_OBJECT_NODE*)Node, Level);
+ } else if (IS_AML_ROOT_NODE (Node)) {
+ AmlDbgPrintRootNode ((AML_ROOT_NODE*)Node, Level);
+ } else {
+ // Should not be possible.
+ ASSERT (0);
+ return;
+ }
+
+ if (!Recurse) {
+ return;
+ }
+
+ // Get the first child node.
+ ChildNode = AmlGetNextSibling (Node, NULL);
+ while (ChildNode != NULL) {
+ ASSERT (Level < MAX_UINT8);
+ AmlDbgPrintTreeInternal (ChildNode, Recurse, (UINT8)(Level + 1));
+ ChildNode = AmlGetNextSibling (Node, ChildNode);
+ }
+}
+
+/** Print Node information.
+
+ @param [in] Node Pointer to the Node to print.
+ Can be a root/object/data node.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNode (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ AmlDbgPrintTableHeader ();
+ AmlDbgPrintTreeInternal (Node, FALSE, 0);
+}
+
+/** Recursively print the subtree under the Node.
+
+ @param [in] Node Pointer to the root of the subtree to print.
+ Can be a root/object/data node.
+**/
+VOID
+EFIAPI
+AmlDbgPrintTree (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ AmlDbgPrintTableHeader ();
+ AmlDbgPrintTreeInternal (Node, TRUE, 0);
+}
+
+/** This function performs a raw data dump of the ACPI table.
+
+ @param [in] Ptr Pointer to the start of the table buffer.
+ @param [in] Length The length of the buffer.
+**/
+VOID
+EFIAPI
+AmlDbgDumpRaw (
+ IN CONST UINT8 * Ptr,
+ IN UINT32 Length
+ )
+{
+ UINT32 ByteCount;
+ UINT32 PartLineChars;
+ UINT32 AsciiBufferIndex;
+ CHAR8 AsciiBuffer[17];
+
+ ByteCount = 0;
+ AsciiBufferIndex = 0;
+
+ DEBUG ((DEBUG_VERBOSE, "Address : 0x%p\n", Ptr));
+ DEBUG ((DEBUG_VERBOSE, "Length : %lld", Length));
+
+ while (ByteCount < Length) {
+ if ((ByteCount & 0x0F) == 0) {
+ AsciiBuffer[AsciiBufferIndex] = '\0';
+ DEBUG ((DEBUG_VERBOSE, " %a\n%08X : ", AsciiBuffer, ByteCount));
+ AsciiBufferIndex = 0;
+ } else if ((ByteCount & 0x07) == 0) {
+ DEBUG ((DEBUG_VERBOSE, "- "));
+ }
+
+ if ((*Ptr >= ' ') && (*Ptr < 0x7F)) {
+ AsciiBuffer[AsciiBufferIndex++] = *Ptr;
+ } else {
+ AsciiBuffer[AsciiBufferIndex++] = '.';
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%02X ", *Ptr++));
+
+ ByteCount++;
+ }
+
+ // Justify the final line using spaces before printing
+ // the ASCII data.
+ PartLineChars = (Length & 0x0F);
+ if (PartLineChars != 0) {
+ PartLineChars = 48 - (PartLineChars * 3);
+ if ((Length & 0x0F) <= 8) {
+ PartLineChars += 2;
+ }
+ while (PartLineChars > 0) {
+ DEBUG ((DEBUG_VERBOSE, " "));
+ PartLineChars--;
+ }
+ }
+
+ // Print ASCII data for the final line.
+ AsciiBuffer[AsciiBufferIndex] = '\0';
+ DEBUG ((DEBUG_VERBOSE, " %a\n\n", AsciiBuffer));
+}
+
+#endif // MDEPKG_NDEBUG
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h
new file mode 100644
index 00000000000..5e43f011d6a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDbgPrint/AmlDbgPrint.h
@@ -0,0 +1,178 @@
+/** @file
+ AML Debug Print.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_PRINT_H_
+#define AML_PRINT_H_
+
+/* This header file does not include internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions
+ must be included by the caller file. The function prototypes must
+ only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node
+ definitions.
+ This allows to keep the functions defined here both internal and
+ potentially external. If necessary, any function of this file can
+ be exposed externally.
+ The Api folder is internal to the AmlLib, but should only use these
+ functions. They provide a "safe" way to interact with the AmlLib.
+*/
+
+#if !defined (MDEPKG_NDEBUG)
+
+#include <AmlInclude.h>
+
+/**
+ @defgroup DbgPrintApis Print APIs for debugging.
+ @ingroup AMLLib
+ @{
+ Print APIs provide a way to print:
+ - A buffer;
+ - A (root/object/data) node;
+ - An AML tree/branch;
+ - The AML NameSpace from the root node.
+ @}
+*/
+
+/** This function performs a raw data dump of the ACPI table.
+
+ @param [in] Ptr Pointer to the start of the table buffer.
+ @param [in] Length The length of the buffer.
+**/
+VOID
+EFIAPI
+AmlDbgDumpRaw (
+ IN CONST UINT8 * Ptr,
+ IN UINT32 Length
+ );
+
+/** Print Size chars at Buffer address.
+
+ @ingroup DbgPrintApis
+
+ @param [in] ErrorLevel Error level for the DEBUG macro.
+ @param [in] Buffer Buffer containing the chars.
+ @param [in] Size Number of chars to print.
+**/
+VOID
+EFIAPI
+AmlDbgPrintChars (
+ IN UINT32 ErrorLevel,
+ IN CONST CHAR8 * Buffer,
+ IN UINT32 Size
+ );
+
+/** Print an AML NameSeg.
+ Don't print trailing underscores ('_').
+
+ @param [in] Buffer Buffer containing an AML NameSeg.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNameSeg (
+ IN CONST CHAR8 * Buffer
+ );
+
+/** Print an AML NameString.
+
+ @param [in] Buffer Buffer containing an AML NameString.
+ @param [in] NewLine Print a newline char at the end of the NameString.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNameString (
+ IN CONST CHAR8 * Buffer,
+ IN BOOLEAN NewLine
+ );
+
+/** Print Node information.
+
+ @ingroup DbgPrintApis
+
+ @param [in] Node Pointer to the Node to print.
+ Can be a root/object/data node.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNode (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Recursively print the subtree under the Node.
+
+ @ingroup DbgPrintApis
+
+ @param [in] Node Pointer to the root of the subtree to print.
+ Can be a root/object/data node.
+**/
+VOID
+EFIAPI
+AmlDbgPrintTree (
+ IN AML_NODE_HANDLE Node
+ );
+
+/** Print the absolute pathnames in the AML namespace of
+ all the nodes in the tree starting from the Root node.
+
+ @ingroup DbgPrintApis
+
+ @param [in] RootNode Pointer to a root node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlDbgPrintNameSpace (
+ IN AML_ROOT_NODE_HANDLE RootNode
+ );
+
+/* Macros to encapsulate Aml Debug Print APIs.
+*/
+
+#define AMLDBG_DUMP_RAW(Ptr, Length) \
+ AmlDbgDumpRaw (Ptr, Length)
+
+#define AMLDBG_PRINT_CHARS(ErrorLevel, Buffer, Size) \
+ AmlDbgPrintChars (ErrorLevel, Buffer, Size)
+
+#define AMLDBG_PRINT_NAMESEG(Buffer) \
+ AmlDbgPrintNameSeg (Buffer)
+
+#define AMLDBG_PRINT_NAMESTR(Buffer,NewLine) \
+ AmlDbgPrintNameString (Buffer,NewLine)
+
+#define AMLDBG_PRINT_NODE(Node) \
+ AmlDbgPrintNode (Node)
+
+#define AMLDBG_PRINT_TREE(Node) \
+ AmlDbgPrintTree (Node)
+
+#define AMLDBG_PRINT_NAMESPACE(RootNode) \
+ AmlDbgPrintNameSpace (RootNode)
+
+#else
+
+#define AMLDBG_DUMP_RAW(Ptr, Length)
+
+#define AMLDBG_PRINT_CHARS(ErrorLevel, Buffer, Size)
+
+#define AMLDBG_PRINT_NAMESEG(Buffer)
+
+#define AMLDBG_PRINT_NAMESTR(Buffer,NewLine)
+
+#define AMLDBG_PRINT_NODE(Node)
+
+#define AMLDBG_PRINT_TREE(Node)
+
+#define AMLDBG_PRINT_NAMESPACE(RootNode)
+
+#endif // MDEPKG_NDEBUG
+
+#endif // AML_PRINT_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h
new file mode 100644
index 00000000000..b58f323e7fe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlDefines.h
@@ -0,0 +1,188 @@
+/** @file
+ AML Defines.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_DEFINES_H_
+#define AML_DEFINES_H_
+
+/**
+ @defgroup TreeStructures Tree structures
+ @ingroup AMLLib
+ @{
+ The AML tree created by the AMLLib relies on enum/define values and
+ structures defined here.
+ @}
+*/
+
+/** AML tree node types.
+
+ Data nodes are tagged with the data type they contain.
+ Some data types cannot be used for data nodes (None, Object).
+ EAmlUIntX types are converted to the EAML_NODE_DATA_TYPE enum type.
+ These types are accessible externally.
+
+ @ingroup TreeStructures
+*/
+typedef enum EAmlNodeDataType {
+ EAmlNodeDataTypeNone = 0, ///< EAmlNone, not accessible.
+ EAmlNodeDataTypeReserved1, ///< EAmlUInt8, converted to the UInt type.
+ EAmlNodeDataTypeReserved2, ///< EAmlUInt16, converted to the UInt type.
+ EAmlNodeDataTypeReserved3, ///< EAmlUInt32, converted to the UInt type.
+ EAmlNodeDataTypeReserved4, ///< EAmlUInt64, converted to the UInt type.
+ EAmlNodeDataTypeReserved5, ///< EAmlObject, not accessible.
+ EAmlNodeDataTypeNameString, ///< EAmlName, name corresponding to the
+ /// NameString keyword in the ACPI
+ /// specification. E.g.: "\_SB_.DEV0"
+ EAmlNodeDataTypeString, ///< EAmlString, NULL terminated string.
+ EAmlNodeDataTypeUInt, ///< Integer data of any length, EAmlUIntX
+ /// are converted to this type.
+ EAmlNodeDataTypeRaw, ///< Raw bytes contained in a buffer.
+ EAmlNodeDataTypeResourceData, ///< Resource data element.
+ EAmlNodeDataTypeFieldPkgLen, ///< FieldPkgLen data element.
+ /// PkgLen are usually stored as
+ /// part of object node structures.
+ /// However, they can be found
+ /// standalone in a FieldList.
+ EAmlNodeDataTypeMax ///< Max enum.
+} EAML_NODE_DATA_TYPE;
+
+/** Indexes of fixed arguments.
+
+ AML objects defined the ACPI 6.3 specification,
+ s20.3 "AML Byte Stream Byte Values" can have at most 6 fixed arguments.
+
+ Method and functions can have at most 7 arguments, cf
+ s19.6.83 "Method (Declare Control Method)". The enum goes to 8 to store the
+ name of the method invocation.
+
+ @ingroup TreeStructures
+*/
+typedef enum EAmlParseIndex {
+ EAmlParseIndexTerm0 = 0, ///< First fixed argument index.
+ EAmlParseIndexTerm1, ///< Second fixed argument index.
+ EAmlParseIndexTerm2, ///< Third fixed argument index.
+ EAmlParseIndexTerm3, ///< Fourth fixed argument index.
+ EAmlParseIndexTerm4, ///< Fifth fixed argument index.
+ EAmlParseIndexTerm5, ///< Sixth fixed argument index.
+ EAmlParseIndexMax ///< Maximum fixed argument index (=6).
+} EAML_PARSE_INDEX;
+
+/** Maximum size of an AML NameString.
+
+ An AML NameString can be at most (255 * 4) + 255 + 2 = 1277 bytes long.
+ Indeed, according to ACPI 6.3 specification, s20.2.2,
+ an AML NameString can be resolved as a MultiNamePath.
+
+ The encoding of this MultiNamePath can be made of at most:
+ - 255 carets ('^'), one for each level in the namespace;
+ - 255 NameSeg of 4 bytes;
+ - 2 bytes for the MultiNamePrefix and SegCount.
+
+ @ingroup TreeStructures
+*/
+#define MAX_AML_NAMESTRING_SIZE 1277U
+
+/** Maximum size of an ASL NameString.
+
+ An ASL NameString can be at most (255 * 4) + 255 + 254 = 1529 bytes long.
+ Cf the ASL grammar available in ACPI 6.3 specification, 19.2.2.
+
+ The encoding of an ASL NameString can be made of at most:
+ - 255 carets ('^'), one for each level in the namespace;
+ - 255 NameSeg of 4 bytes;
+ - 254 NameSeg separators ('.').
+
+ @ingroup TreeStructures
+*/
+#define MAX_ASL_NAMESTRING_SIZE 1529U
+
+/** Pseudo OpCode for method invocations.
+
+ The AML grammar does not attribute an OpCode/SubOpCode couple for
+ method invocations. This library is representing method invocations
+ as if they had one.
+
+ The AML encoding for method invocations in the ACPI specification 6.3 is:
+ MethodInvocation := NameString TermArgList
+ In this library, it is:
+ MethodInvocation := MethodInvocationOp NameString ArgumentCount TermArgList
+ ArgumentCount := ByteData
+
+ When computing the size of a tree or serializing it, the additional data is
+ not taken into account (i.e. the MethodInvocationOp and the ArgumentCount).
+
+ @ingroup TreeStructures
+*/
+#define AML_METHOD_INVOC_OP 0xD0
+
+/** Pseudo OpCode for NamedField field elements.
+
+ The AML grammar does not attribute an OpCode/SubOpCode couple for
+ the NamedField field element. This library is representing NamedField field
+ elements as if they had one.
+
+ The AML encoding for NamedField field elements in the ACPI specification 6.3
+ is:
+ NamedField := NameSeg PkgLength
+ In this library, it is:
+ NamedField := NamedFieldOp NameSeg PkgLength
+
+ When computing the size of a tree or serializing it, the additional data is
+ not taken into account (i.e. the NamedFieldOp).
+
+ @ingroup TreeStructures
+*/
+#define AML_FIELD_NAMED_OP 0x04
+
+/** Size of a NameSeg.
+ Cf. ACPI 6.3 specification, s20.2.
+
+ @ingroup TreeStructures
+*/
+ #define AML_NAME_SEG_SIZE 4U
+
+/** AML object types.
+
+ The ACPI specification defines several object types. They are listed
+ with the definition of ObjectTypeKeyword.
+
+ @ingroup TreeStructures
+*/
+typedef enum EAmlObjType {
+ EAmlObjTypeUnknown = 0x0,
+ EAmlObjTypeInt,
+ EAmlObjTypeStrObj,
+ EAmlObjTypeBuffObj,
+ EAmlObjTypePkgObj,
+ EAmlObjTypeFieldUnitObj,
+ EAmlObjTypeDeviceObj,
+ EAmlObjTypeEventObj,
+ EAmlObjTypeMethodObj,
+ EAmlObjTypeMutexObj,
+ EAmlObjTypeOpRegionObj,
+ EAmlObjTypePowerResObj,
+ EAmlObjTypeProcessorObj,
+ EAmlObjTypeThermalZoneObj,
+ EAmlObjTypeBuffFieldObj,
+ EAmlObjTypeDDBHandleObj,
+} EAML_OBJ_TYPE;
+
+/** Node types.
+
+ @ingroup TreeStructures
+*/
+typedef enum EAmlNodeType {
+ EAmlNodeUnknown, ///< Unknown/Invalid AML Node Type.
+ EAmlNodeRoot, ///< AML Root Node, typically represents a DefinitionBlock.
+ EAmlNodeObject, ///< AML Object Node, typically represents an ASL statement
+ /// or its arguments.
+ EAmlNodeData, ///< AML Data Node, typically represents arguments for an
+ /// ASL statement.
+ EAmlNodeMax ///< Max enum.
+} EAML_NODE_TYPE;
+
+#endif // AML_DEFINES_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c
new file mode 100644
index 00000000000..2027d5d5f8e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.c
@@ -0,0 +1,805 @@
+/** @file
+ AML grammar definitions.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlEncoding/Aml.h>
+
+/** AML grammar encoding table.
+
+ The ASL language is a description language, used to define abstract
+ objects, like devices, thermal zones, etc. and their place in a hierarchical
+ tree. The following table stores the AML grammar definition. It can be used
+ to parse an AML bytestream. Each line corresponds to the definition of an
+ opcode and what is expected to be found with this opcode.
+ See table 20-440 in the ACPI 6.3 specification s20.3, and the AML
+ grammar definitions in s20.2.
+
+ - OpCode/SubOpCode:
+ An OpCode/SubOpCode couple allows to identify an object type.
+ The OpCode and SubOpCode are one byte each. The SubOpCode is
+ used when the Opcode value is 0x5B (extended OpCode). Otherwise
+ the SubOpcode is set to 0. If the SubOpCode is 0 in the table
+ below, there is no SubOpCode in the AML bytestream, only the
+ OpCode is used to identify the object.
+
+ - Fixed arguments:
+ The fixed arguments follow the OpCode and SubOpCode. Their number
+ and type can be found in the table below. There can be at the most
+ 6 fixed arguments for an object.
+ Fixed arguments's type allow to know what is expected in the AML bytestream.
+ Knowing the size of the incoming element, AML bytes can be packed and parsed
+ accordingly. These types can be found in the same table 20-440 in the
+ ACPI 6.3, s20.3 specification.
+ E.g.: An AML object, a UINT8, a NULL terminated string, etc.
+
+ -Attributes:
+ The attribute field gives additional information on each object. This can
+ be the presence of a variable list of arguments, the presence of a PkgLen,
+ etc.
+
+ In summary, an AML object is described as:
+ OpCode [SubOpcode] [PkgLen] [FixedArgs] [VarArgs]
+
+ OpCode {1 byte}
+ [SubOpCode] {1 byte.
+ Only relevant if the OpCode value is
+ 0x5B (extended OpCode prefix).
+ Otherwise 0. Most objects don't have one.}
+ [PkgLen] {Size of the object.
+ It has a special encoding, cf. ACPI 6.3
+ specification, s20.2.4 "Package Length
+ Encoding".
+ Most objects don't have one.}
+ [FixedArgs[0..X]] {Fixed list of arguments.
+ (where X <= 5) Can be other objects or data (a byte,
+ a string, etc.). They belong to the
+ current AML object.
+ The number of fixed arguments varies according
+ to the object, but it is fixed for each kind of
+ object.}
+ [VarArgs] {Variable list of arguments.
+ They also belong to the current object and can
+ be objects or data.
+ Most objects don't have one.}
+ [ByteList] {This is a sub-type of a variable list of
+ arguments. It can only be found in buffer
+ objects.
+ A ByteList is either a list of bytes or
+ a list of resource data elements. Resource
+ data elements have specific opcodes.}
+ [FieldList] {This is a sub-type of a variable list of
+ arguments. It can only be found in Fields,
+ IndexFields and BankFields.
+ A FieldList is made of FieldElements.
+ FieldElements have specific opcodes.}
+*/
+GLOBAL_REMOVE_IF_UNREFERENCED
+STATIC
+CONST
+AML_BYTE_ENCODING mAmlByteEncoding[] = {
+ // Comment Str OpCode SubOpCode MaxIndex NameIndex 0 1 2 3 4 5 Attribute
+ /* 0x00 */ {AML_OPCODE_DEF ("ZeroOp", AML_ZERO_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x01 */ {AML_OPCODE_DEF ("OneOp", AML_ONE_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x06 */ {AML_OPCODE_DEF ("AliasOp", AML_ALIAS_OP), 0, 2, 1, {EAmlName, EAmlName, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x08 */ {AML_OPCODE_DEF ("NameOp", AML_NAME_OP), 0, 2, 0, {EAmlName, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x0A */ {AML_OPCODE_DEF ("BytePrefix", AML_BYTE_PREFIX), 0, 1, 0, {EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x0B */ {AML_OPCODE_DEF ("WordPrefix", AML_WORD_PREFIX), 0, 1, 0, {EAmlUInt16, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x0C */ {AML_OPCODE_DEF ("DWordPrefix", AML_DWORD_PREFIX), 0, 1, 0, {EAmlUInt32, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x0D */ {AML_OPCODE_DEF ("StringPrefix", AML_STRING_PREFIX), 0, 1, 0, {EAmlString, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x0E */ {AML_OPCODE_DEF ("QWordPrefix", AML_QWORD_PREFIX), 0, 1, 0, {EAmlUInt64, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x10 */ {AML_OPCODE_DEF ("ScopeOp", AML_SCOPE_OP), 0, 1, 0, {EAmlName, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE},
+ /* 0x11 */ {AML_OPCODE_DEF ("BufferOp", AML_BUFFER_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_BYTE_LIST},
+ /* 0x12 */ {AML_OPCODE_DEF ("PackageOp", AML_PACKAGE_OP), 0, 1, 0, {EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ},
+ /* 0x13 */ {AML_OPCODE_DEF ("VarPackageOp", AML_VAR_PACKAGE_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ},
+ /* 0x14 */ {AML_OPCODE_DEF ("MethodOp", AML_METHOD_OP), 0, 2, 0, {EAmlName, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE},
+ /* 0x15 */ {AML_OPCODE_DEF ("ExternalOp", AML_EXTERNAL_OP), 0, 3, 0, {EAmlName, EAmlUInt8, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x2E */ {AML_OPCODE_DEF ("DualNamePrefix", AML_DUAL_NAME_PREFIX), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x2F */ {AML_OPCODE_DEF ("MultiNamePrefix", AML_MULTI_NAME_PREFIX), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x41 */ {AML_OPCODE_DEF ("NameChar_A", 'A'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x42 */ {AML_OPCODE_DEF ("NameChar_B", 'B'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x43 */ {AML_OPCODE_DEF ("NameChar_C", 'C'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x44 */ {AML_OPCODE_DEF ("NameChar_D", 'D'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x45 */ {AML_OPCODE_DEF ("NameChar_E", 'E'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x46 */ {AML_OPCODE_DEF ("NameChar_F", 'F'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x47 */ {AML_OPCODE_DEF ("NameChar_G", 'G'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x48 */ {AML_OPCODE_DEF ("NameChar_H", 'H'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x49 */ {AML_OPCODE_DEF ("NameChar_I", 'I'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x4A */ {AML_OPCODE_DEF ("NameChar_J", 'J'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x4B */ {AML_OPCODE_DEF ("NameChar_K", 'K'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x4C */ {AML_OPCODE_DEF ("NameChar_L", 'L'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x4D */ {AML_OPCODE_DEF ("NameChar_M", 'M'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x4E */ {AML_OPCODE_DEF ("NameChar_N", 'N'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x4F */ {AML_OPCODE_DEF ("NameChar_O", 'O'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x50 */ {AML_OPCODE_DEF ("NameChar_P", 'P'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x51 */ {AML_OPCODE_DEF ("NameChar_Q", 'Q'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x52 */ {AML_OPCODE_DEF ("NameChar_R", 'R'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x53 */ {AML_OPCODE_DEF ("NameChar_S", 'S'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x54 */ {AML_OPCODE_DEF ("NameChar_T", 'T'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x55 */ {AML_OPCODE_DEF ("NameChar_U", 'U'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x56 */ {AML_OPCODE_DEF ("NameChar_V", 'V'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x57 */ {AML_OPCODE_DEF ("NameChar_W", 'W'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x58 */ {AML_OPCODE_DEF ("NameChar_X", 'X'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x59 */ {AML_OPCODE_DEF ("NameChar_Y", 'Y'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x5A */ {AML_OPCODE_DEF ("NameChar_Z", 'Z'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x5B 0x01 */ {AML_OPCODE_DEF ("MutexOp", AML_EXT_OP), AML_EXT_MUTEX_OP, 2, 0, {EAmlName, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x5B 0x02 */ {AML_OPCODE_DEF ("EventOp", AML_EXT_OP), AML_EXT_EVENT_OP, 1, 0, {EAmlName, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x5B 0x12 */ {AML_OPCODE_DEF ("CondRefOfOp", AML_EXT_OP), AML_EXT_COND_REF_OF_OP, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x13 */ {AML_OPCODE_DEF ("CreateFieldOp", AML_EXT_OP), AML_EXT_CREATE_FIELD_OP,4, 3, {EAmlObject, EAmlObject, EAmlObject, EAmlName, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x5B 0x1F */ {AML_OPCODE_DEF ("LoadTableOp", AML_EXT_OP), AML_EXT_LOAD_TABLE_OP, 6, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlObject, EAmlObject, EAmlObject}, 0},
+ /* 0x5B 0x20 */ {AML_OPCODE_DEF ("LoadOp", AML_EXT_OP), AML_EXT_LOAD_OP, 2, 0, {EAmlName, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x21 */ {AML_OPCODE_DEF ("StallOp", AML_EXT_OP), AML_EXT_STALL_OP, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x22 */ {AML_OPCODE_DEF ("SleepOp", AML_EXT_OP), AML_EXT_SLEEP_OP, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x23 */ {AML_OPCODE_DEF ("AcquireOp", AML_EXT_OP), AML_EXT_ACQUIRE_OP, 2, 0, {EAmlObject, EAmlUInt16, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x24 */ {AML_OPCODE_DEF ("SignalOp", AML_EXT_OP), AML_EXT_SIGNAL_OP, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x25 */ {AML_OPCODE_DEF ("WaitOp", AML_EXT_OP), AML_EXT_WAIT_OP, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x26 */ {AML_OPCODE_DEF ("ResetOp", AML_EXT_OP), AML_EXT_RESET_OP, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x27 */ {AML_OPCODE_DEF ("ReleaseOp", AML_EXT_OP), AML_EXT_RELEASE_OP, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x28 */ {AML_OPCODE_DEF ("FromBCDOp", AML_EXT_OP), AML_EXT_FROM_BCD_OP, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x29 */ {AML_OPCODE_DEF ("ToBCDOp", AML_EXT_OP), AML_EXT_TO_BCD_OP, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x2A */ {AML_OPCODE_DEF ("UnloadOp", AML_EXT_OP), AML_EXT_UNLOAD_OP, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x30 */ {AML_OPCODE_DEF ("RevisionOp", AML_EXT_OP), AML_EXT_REVISION_OP, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x31 */ {AML_OPCODE_DEF ("DebugOp", AML_EXT_OP), AML_EXT_DEBUG_OP, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x32 */ {AML_OPCODE_DEF ("FatalOp", AML_EXT_OP), AML_EXT_FATAL_OP, 3, 0, {EAmlUInt8, EAmlUInt32, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x33 */ {AML_OPCODE_DEF ("TimerOp", AML_EXT_OP), AML_EXT_TIMER_OP, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x5B 0x80 */ {AML_OPCODE_DEF ("OpRegionOp", AML_EXT_OP), AML_EXT_REGION_OP, 4, 0, {EAmlName, EAmlUInt8, EAmlObject, EAmlObject, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x5B 0x81 */ {AML_OPCODE_DEF ("FieldOp", AML_EXT_OP), AML_EXT_FIELD_OP, 2, 0, {EAmlName, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_FIELD_LIST},
+ /* 0x5B 0x82 */ {AML_OPCODE_DEF ("DeviceOp", AML_EXT_OP), AML_EXT_DEVICE_OP, 1, 0, {EAmlName, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE},
+ /* 0x5B 0x83 */ {AML_OPCODE_DEF ("ProcessorOp", AML_EXT_OP), AML_EXT_PROCESSOR_OP, 4, 0, {EAmlName, EAmlUInt8, EAmlUInt32, EAmlUInt8, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE},
+ /* 0x5B 0x84 */ {AML_OPCODE_DEF ("PowerResOp", AML_EXT_OP), AML_EXT_POWER_RES_OP, 3, 0, {EAmlName, EAmlUInt8, EAmlUInt16, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE},
+ /* 0x5B 0x85 */ {AML_OPCODE_DEF ("ThermalZoneOp", AML_EXT_OP), AML_EXT_THERMAL_ZONE_OP,1, 0, {EAmlName, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ | AML_IN_NAMESPACE},
+ /* 0x5B 0x86 */ {AML_OPCODE_DEF ("IndexFieldOp", AML_EXT_OP), AML_EXT_INDEX_FIELD_OP, 3, 0, {EAmlName, EAmlName, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_FIELD_LIST},
+ /* 0x5B 0x87 */ {AML_OPCODE_DEF ("BankFieldOp", AML_EXT_OP), AML_EXT_BANK_FIELD_OP, 4, 0, {EAmlName, EAmlName, EAmlObject, EAmlUInt8, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_FIELD_LIST},
+ /* 0x5B 0x88 */ {AML_OPCODE_DEF ("DataRegionOp", AML_EXT_OP), AML_EXT_DATA_REGION_OP, 4, 0, {EAmlName, EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x5C */ {AML_OPCODE_DEF ("RootChar", AML_ROOT_CHAR), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x5E */ {AML_OPCODE_DEF ("ParentPrefixChar", AML_PARENT_PREFIX_CHAR), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x5F */ {AML_OPCODE_DEF ("NameChar", '_'), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_NAME_CHAR},
+ /* 0x60 */ {AML_OPCODE_DEF ("Local0Op", AML_LOCAL0), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x61 */ {AML_OPCODE_DEF ("Local1Op", AML_LOCAL1), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x62 */ {AML_OPCODE_DEF ("Local2Op", AML_LOCAL2), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x63 */ {AML_OPCODE_DEF ("Local3Op", AML_LOCAL3), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x64 */ {AML_OPCODE_DEF ("Local4Op", AML_LOCAL4), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x65 */ {AML_OPCODE_DEF ("Local5Op", AML_LOCAL5), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x66 */ {AML_OPCODE_DEF ("Local6Op", AML_LOCAL6), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x67 */ {AML_OPCODE_DEF ("Local7Op", AML_LOCAL7), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x68 */ {AML_OPCODE_DEF ("Arg0Op", AML_ARG0), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x69 */ {AML_OPCODE_DEF ("Arg1Op", AML_ARG1), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x6A */ {AML_OPCODE_DEF ("Arg2Op", AML_ARG2), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x6B */ {AML_OPCODE_DEF ("Arg3Op", AML_ARG3), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x6C */ {AML_OPCODE_DEF ("Arg4Op", AML_ARG4), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x6D */ {AML_OPCODE_DEF ("Arg5Op", AML_ARG5), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x6E */ {AML_OPCODE_DEF ("Arg6Op", AML_ARG6), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x70 */ {AML_OPCODE_DEF ("StoreOp", AML_STORE_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x71 */ {AML_OPCODE_DEF ("RefOfOp", AML_REF_OF_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x72 */ {AML_OPCODE_DEF ("AddOp", AML_ADD_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x73 */ {AML_OPCODE_DEF ("ConcatOp", AML_CONCAT_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x74 */ {AML_OPCODE_DEF ("SubtractOp", AML_SUBTRACT_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x75 */ {AML_OPCODE_DEF ("IncrementOp", AML_INCREMENT_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x76 */ {AML_OPCODE_DEF ("DecrementOp", AML_DECREMENT_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x77 */ {AML_OPCODE_DEF ("MultiplyOp", AML_MULTIPLY_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x78 */ {AML_OPCODE_DEF ("DivideOp", AML_DIVIDE_OP), 0, 4, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone}, 0},
+ /* 0x79 */ {AML_OPCODE_DEF ("ShiftLeftOp", AML_SHIFT_LEFT_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x7A */ {AML_OPCODE_DEF ("ShiftRightOp", AML_SHIFT_RIGHT_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x7B */ {AML_OPCODE_DEF ("AndOp", AML_AND_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x7C */ {AML_OPCODE_DEF ("NAndOp", AML_NAND_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x7D */ {AML_OPCODE_DEF ("OrOp", AML_OR_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x7E */ {AML_OPCODE_DEF ("NorOp", AML_NOR_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x7F */ {AML_OPCODE_DEF ("XOrOp", AML_XOR_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x80 */ {AML_OPCODE_DEF ("NotOp", AML_NOT_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x81 */ {AML_OPCODE_DEF ("FindSetLeftBitOp", AML_FIND_SET_LEFT_BIT_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x82 */ {AML_OPCODE_DEF ("FindSetRightBitOp", AML_FIND_SET_RIGHT_BIT_OP),0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x83 */ {AML_OPCODE_DEF ("DerefOfOp", AML_DEREF_OF_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x84 */ {AML_OPCODE_DEF ("ConcatResOp", AML_CONCAT_RES_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x85 */ {AML_OPCODE_DEF ("ModOp", AML_MOD_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x86 */ {AML_OPCODE_DEF ("NotifyOp", AML_NOTIFY_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x87 */ {AML_OPCODE_DEF ("SizeOfOp", AML_SIZE_OF_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x88 */ {AML_OPCODE_DEF ("IndexOp", AML_INDEX_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x89 */ {AML_OPCODE_DEF ("MatchOp", AML_MATCH_OP), 0, 6, 0, {EAmlObject, EAmlUInt8, EAmlObject, EAmlUInt8, EAmlObject, EAmlObject}, 0},
+ /* 0x8A */ {AML_OPCODE_DEF ("CreateDWordFieldOp", AML_CREATE_DWORD_FIELD_OP),0, 3, 2, {EAmlObject, EAmlObject, EAmlName, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x8B */ {AML_OPCODE_DEF ("CreateWordFieldOp", AML_CREATE_WORD_FIELD_OP), 0, 3, 2, {EAmlObject, EAmlObject, EAmlName, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x8C */ {AML_OPCODE_DEF ("CreateByteFieldOp", AML_CREATE_BYTE_FIELD_OP), 0, 3, 2, {EAmlObject, EAmlObject, EAmlName, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x8D */ {AML_OPCODE_DEF ("CreateBitFieldOp", AML_CREATE_BIT_FIELD_OP), 0, 3, 2, {EAmlObject, EAmlObject, EAmlName, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x8E */ {AML_OPCODE_DEF ("ObjectTypeOp", AML_OBJECT_TYPE_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x8F */ {AML_OPCODE_DEF ("CreateQWordFieldOp", AML_CREATE_QWORD_FIELD_OP),0, 3, 2, {EAmlObject, EAmlObject, EAmlName, EAmlNone, EAmlNone, EAmlNone}, AML_IN_NAMESPACE},
+ /* 0x90 */ {AML_OPCODE_DEF ("LAndOp", AML_LAND_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x91 */ {AML_OPCODE_DEF ("LOrOp", AML_LOR_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x92 */ {AML_OPCODE_DEF ("LNotOp", AML_LNOT_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x93 */ {AML_OPCODE_DEF ("LEqualOp", AML_LEQUAL_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x94 */ {AML_OPCODE_DEF ("LGreaterOp", AML_LGREATER_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x95 */ {AML_OPCODE_DEF ("LLessOp", AML_LLESS_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x96 */ {AML_OPCODE_DEF ("ToBufferOp", AML_TO_BUFFER_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x97 */ {AML_OPCODE_DEF ("ToDecimalStringOp", AML_TO_DEC_STRING_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x98 */ {AML_OPCODE_DEF ("ToHexStringOp", AML_TO_HEX_STRING_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x99 */ {AML_OPCODE_DEF ("ToIntegerOp", AML_TO_INTEGER_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x9C */ {AML_OPCODE_DEF ("ToStringOp", AML_TO_STRING_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x9D */ {AML_OPCODE_DEF ("CopyObjectOp", AML_COPY_OBJECT_OP), 0, 2, 0, {EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x9E */ {AML_OPCODE_DEF ("MidOp", AML_MID_OP), 0, 3, 0, {EAmlObject, EAmlObject, EAmlObject, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0x9F */ {AML_OPCODE_DEF ("ContinueOp", AML_CONTINUE_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0xA0 */ {AML_OPCODE_DEF ("IfOp", AML_IF_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ},
+ /* 0xA1 */ {AML_OPCODE_DEF ("ElseOp", AML_ELSE_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ},
+ /* 0xA2 */ {AML_OPCODE_DEF ("WhileOp", AML_WHILE_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_HAS_PKG_LENGTH | AML_HAS_CHILD_OBJ},
+ /* 0xA3 */ {AML_OPCODE_DEF ("NoopOp", AML_NOOP_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0xA4 */ {AML_OPCODE_DEF ("ReturnOp", AML_RETURN_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0xA5 */ {AML_OPCODE_DEF ("BreakOp", AML_BREAK_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0xCC */ {AML_OPCODE_DEF ("BreakPointOp", AML_BREAK_POINT_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+ /* 0xD0 */ {AML_OPCODE_DEF ("MethodInvocOp", AML_METHOD_INVOC_OP), 0, 2, 0, {EAmlName, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_PSEUDO_OPCODE | AML_HAS_CHILD_OBJ},
+ /* 0xFF */ {AML_OPCODE_DEF ("OnesOp", AML_ONES_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, 0},
+};
+
+/** AML grammar encoding for field elements.
+
+ Some AML objects are expecting a FieldList. They are referred in this library
+ as field nodes. These objects have the following opcodes:
+ - FieldOp;
+ - IndexFieldOp;
+ - BankFieldOp.
+ In the AML grammar encoding table, they have the AML_HAS_FIELD_LIST
+ attribute.
+
+ A field list is made of field elements.
+ According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encoding",
+ field elements can be:
+ - NamedField := NameSeg PkgLength;
+ - ReservedField := 0x00 PkgLength;
+ - AccessField := 0x01 AccessType AccessAttrib;
+ - ConnectField := <0x02 NameString> | <0x02 BufferData>;
+ - ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength.
+
+ A small set of opcodes describes field elements. They are referred in this
+ library as field opcodes.
+ The NamedField field element doesn't have a field opcode. A pseudo
+ OpCode/SubOpCode couple has been created for it.
+
+ Field elements:
+ - don't have a SubOpCode;
+ - have at most 3 fixed arguments (6 for object opcodes,
+ 8 for method invocations);
+ - don't have variable list of arguments;
+ - are not part of the AML namespace, except NamedField field elements.
+*/
+GLOBAL_REMOVE_IF_UNREFERENCED
+STATIC
+CONST
+AML_BYTE_ENCODING mAmlFieldEncoding[] = {
+ // Comment Str OpCode SubOpCode MaxIndex NameIndex 0 1 2 3 4 5 Attribute
+ /* 0x00 */ {AML_OPCODE_DEF ("FieldReservedOp", AML_FIELD_RESERVED_OP), 0, 0, 0, {EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_FIELD_ELEMENT | AML_HAS_PKG_LENGTH},
+ /* 0x01 */ {AML_OPCODE_DEF ("FieldAccessOp", AML_FIELD_ACCESS_OP), 0, 2, 0, {EAmlUInt8, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_FIELD_ELEMENT},
+ /* 0x02 */ {AML_OPCODE_DEF ("FieldConnectionOp", AML_FIELD_CONNECTION_OP), 0, 1, 0, {EAmlObject, EAmlNone, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_FIELD_ELEMENT},
+ /* 0x03 */ {AML_OPCODE_DEF ("FieldExtAccessOp", AML_FIELD_EXT_ACCESS_OP), 0, 3, 0, {EAmlUInt8, EAmlUInt8, EAmlUInt8, EAmlNone, EAmlNone, EAmlNone}, AML_IS_FIELD_ELEMENT},
+ /* 0x04 */ {AML_OPCODE_DEF ("FieldNamed", AML_FIELD_NAMED_OP), 0, 2, 0, {EAmlName, EAmlFieldPkgLen, EAmlNone, EAmlNone, EAmlNone, EAmlNone}, AML_IS_FIELD_ELEMENT | AML_IS_PSEUDO_OPCODE | AML_IN_NAMESPACE}
+};
+
+/** Get the AML_BYTE_ENCODING entry in the AML encoding table.
+
+ Note: For Pseudo OpCodes this function returns NULL.
+
+ @param [in] Buffer Pointer to an OpCode/SubOpCode couple.
+ If *Buffer = 0x5b (extended OpCode),
+ Buffer must be at least two bytes long.
+
+ @return The corresponding AML_BYTE_ENCODING entry.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetByteEncoding (
+ IN CONST UINT8 * Buffer
+ )
+{
+ UINT8 OpCode;
+ UINT8 SubOpCode;
+ UINT32 Index;
+
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // Get OpCode and SubOpCode.
+ OpCode = Buffer[0];
+ if (OpCode == AML_EXT_OP) {
+ SubOpCode = Buffer[1];
+ } else {
+ SubOpCode = 0;
+ }
+
+ // Search the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0]));
+ Index++) {
+ if ((mAmlByteEncoding[Index].OpCode == OpCode) &&
+ (mAmlByteEncoding[Index].SubOpCode == SubOpCode)) {
+ if ((mAmlByteEncoding[Index].Attribute & AML_IS_PSEUDO_OPCODE) ==
+ AML_IS_PSEUDO_OPCODE) {
+ // A pseudo OpCode cannot be parsed as it is internal to this library.
+ // The MethodInvocation encoding can be detected by NameSpace lookup.
+ ASSERT (0);
+ return NULL;
+ }
+ return &mAmlByteEncoding[Index];
+ }
+ }
+
+ return NULL;
+}
+
+/** Get the AML_BYTE_ENCODING entry in the AML encoding table
+ by providing an OpCode/SubOpCode couple.
+
+ @param [in] OpCode OpCode.
+ @param [in] SubOpCode SubOpCode.
+
+ @return The corresponding AML_BYTE_ENCODING entry.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetByteEncodingByOpCode (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ UINT32 Index;
+
+ // Search the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0]));
+ Index++) {
+ if ((mAmlByteEncoding[Index].OpCode == OpCode) &&
+ (mAmlByteEncoding[Index].SubOpCode == SubOpCode)) {
+ return &mAmlByteEncoding[Index];
+ }
+ }
+ return NULL;
+}
+
+/** Get the AML_BYTE_ENCODING entry in the field encoding table.
+
+ Note: For Pseudo OpCodes this function returns NULL.
+
+ @param [in] Buffer Pointer to a field OpCode.
+ No SubOpCode is expected.
+
+ @return The corresponding AML_BYTE_ENCODING entry
+ in the field encoding table.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetFieldEncoding (
+ IN CONST UINT8 * Buffer
+ )
+{
+ UINT8 OpCode;
+ UINT32 Index;
+
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // Get OpCode.
+ OpCode = *Buffer;
+
+ // Search in the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlFieldEncoding) / sizeof (mAmlFieldEncoding[0]));
+ Index++) {
+ if (mAmlFieldEncoding[Index].OpCode == OpCode) {
+ if ((mAmlFieldEncoding[Index].Attribute & AML_IS_PSEUDO_OPCODE) ==
+ AML_IS_PSEUDO_OPCODE) {
+ // A pseudo OpCode cannot be parsed as it is internal to this library.
+ // The NamedField encoding can be detected because it begins with a
+ // char.
+ ASSERT (0);
+ return NULL;
+ }
+ return &mAmlFieldEncoding[Index];
+ }
+ }
+
+ return NULL;
+}
+
+/** Get the AML_BYTE_ENCODING entry in the field encoding table
+ by providing an OpCode/SubOpCode couple.
+
+ @param [in] OpCode OpCode.
+ @param [in] SubOpCode SubOpCode.
+
+ @return The corresponding AML_BYTE_ENCODING entry
+ in the field encoding table.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetFieldEncodingByOpCode (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ UINT32 Index;
+
+ // Search the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlFieldEncoding) / sizeof (mAmlFieldEncoding[0]));
+ Index++) {
+ if ((mAmlFieldEncoding[Index].OpCode == OpCode) &&
+ (mAmlFieldEncoding[Index].SubOpCode == SubOpCode)) {
+ return &mAmlFieldEncoding[Index];
+ }
+ }
+ return NULL;
+}
+
+// Enable this function for debug.
+#if !defined (MDEPKG_NDEBUG)
+/** Look for an OpCode/SubOpCode couple in the AML grammar,
+ and return a corresponding string.
+
+ @param [in] OpCode The OpCode.
+ @param [in] SubOpCode The SubOpCode.
+
+ @return A string describing the OpCode/SubOpCode couple.
+ NULL if not found.
+**/
+CONST
+CHAR8 *
+AmlGetOpCodeStr (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ EAML_PARSE_INDEX Index;
+
+ // Search the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0]));
+ Index++) {
+ if ((mAmlByteEncoding[Index].OpCode == OpCode) &&
+ (mAmlByteEncoding[Index].SubOpCode == SubOpCode)) {
+ return mAmlByteEncoding[Index].Str;
+ }
+ }
+
+ ASSERT (0);
+ return NULL;
+}
+
+/** Look for an OpCode/SubOpCode couple in the AML field element grammar,
+ and return a corresponding string.
+
+ @param [in] OpCode The OpCode.
+ @param [in] SubOpCode The SubOpCode. Must be zero.
+
+ @return A string describing the OpCode/SubOpCode couple.
+ NULL if not found.
+**/
+CONST
+CHAR8 *
+AmlGetFieldOpCodeStr (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ EAML_PARSE_INDEX Index;
+
+ if (SubOpCode != 0) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // Search the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlFieldEncoding) / sizeof (mAmlFieldEncoding[0]));
+ Index++) {
+ if ((mAmlFieldEncoding[Index].OpCode == OpCode)) {
+ return mAmlFieldEncoding[Index].Str;
+ }
+ }
+
+ ASSERT (0);
+ return NULL;
+}
+#endif // MDEPKG_NDEBUG
+
+/** Check whether the OpCode/SubOpcode couple is a valid entry
+ in the AML grammar encoding table.
+
+ @param [in] OpCode OpCode to check.
+ @param [in] SubOpCode SubOpCode to check.
+
+ @retval TRUE The OpCode/SubOpCode couple is valid.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlIsOpCodeValid (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ EAML_PARSE_INDEX Index;
+
+ // Search the table.
+ for (Index = 0;
+ Index < (sizeof (mAmlByteEncoding) / sizeof (mAmlByteEncoding[0]));
+ Index++) {
+ if ((mAmlByteEncoding[Index].OpCode == OpCode) &&
+ (mAmlByteEncoding[Index].SubOpCode == SubOpCode)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/** AML_PARSE_FORMAT to EAML_NODE_DATA_TYPE translation table.
+
+ AML_PARSE_FORMAT describes an internal set of values identifying the types
+ that can be found while parsing an AML bytestream.
+ EAML_NODE_DATA_TYPE describes an external set of values allowing to identify
+ what type of data can be found in data nodes.
+*/
+GLOBAL_REMOVE_IF_UNREFERENCED
+STATIC
+CONST
+EAML_NODE_DATA_TYPE mAmlTypeToNodeDataType[] = {
+ EAmlNodeDataTypeNone, // EAmlNone
+ EAmlNodeDataTypeUInt, // EAmlUInt8
+ EAmlNodeDataTypeUInt, // EAmlUInt16
+ EAmlNodeDataTypeUInt, // EAmlUInt32
+ EAmlNodeDataTypeUInt, // EAmlUInt64
+ EAmlNodeDataTypeReserved5, // EAmlObject
+ EAmlNodeDataTypeNameString, // EAmlName
+ EAmlNodeDataTypeString, // EAmlString
+ EAmlNodeDataTypeFieldPkgLen // EAmlFieldPkgLen
+};
+
+/** Convert an AML_PARSE_FORMAT to its corresponding EAML_NODE_DATA_TYPE.
+
+ @param [in] AmlType Input AML Type.
+
+ @return The corresponding EAML_NODE_DATA_TYPE.
+ EAmlNodeDataTypeNone if not found.
+**/
+EAML_NODE_DATA_TYPE
+EFIAPI
+AmlTypeToNodeDataType (
+ IN AML_PARSE_FORMAT AmlType
+ )
+{
+ if (AmlType >=
+ (sizeof (mAmlTypeToNodeDataType) / sizeof (mAmlTypeToNodeDataType[0]))) {
+ ASSERT (0);
+ return EAmlNodeDataTypeNone;
+ }
+
+ return mAmlTypeToNodeDataType[AmlType];
+}
+
+/** Get the package length from the buffer.
+
+ @param [in] Buffer AML buffer.
+ @param [out] PkgLength The interpreted PkgLen value.
+ Length cannot exceed 2^28.
+
+ @return The number of bytes to represent the package length.
+ 0 if an issue occurred.
+**/
+UINT32
+EFIAPI
+AmlGetPkgLength (
+ IN CONST UINT8 * Buffer,
+ OUT UINT32 * PkgLength
+ )
+{
+ UINT8 LeadByte;
+ UINT8 ByteCount;
+ UINT32 RealLength;
+ UINT32 Offset;
+
+ if ((Buffer == NULL) ||
+ (PkgLength == NULL)) {
+ ASSERT (0);
+ return 0;
+ }
+
+ /* From ACPI 6.3 specification, s20.2.4 "Package Length Encoding":
+
+ PkgLength := PkgLeadByte |
+ <PkgLeadByte ByteData> |
+ <PkgLeadByte ByteData ByteData> |
+ <PkgLeadByte ByteData ByteData ByteData>
+
+ PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
+ <bit 5-4: Only used if PkgLength < 63>
+ <bit 3-0: Least significant package length nibble>
+
+ Note:
+ The high 2 bits of the first byte reveal how many
+ follow bytes are in the PkgLength. If the
+ PkgLength has only one byte, bit 0 through 5 are
+ used to encode the package length (in other
+ words, values 0-63). If the package length value
+ is more than 63, more than one byte must be
+ used for the encoding in which case bit 4 and 5 of
+ the PkgLeadByte are reserved and must be zero.
+ If the multiple bytes encoding is used, bits 0-3 of
+ the PkgLeadByte become the least significant 4
+ bits of the resulting package length value. The next
+ ByteData will become the next least
+ significant 8 bits of the resulting value and so on,
+ up to 3 ByteData bytes. Thus, the maximum
+ package length is 2**28.
+ */
+
+ LeadByte = *Buffer;
+ ByteCount = (LeadByte >> 6) & 0x03U;
+ Offset = ByteCount + 1U;
+ RealLength = 0;
+
+ // Switch on the number of bytes used to store the PkgLen.
+ switch (ByteCount) {
+ case 0:
+ {
+ RealLength = LeadByte;
+ break;
+ }
+ case 1:
+ {
+ RealLength = *(Buffer + 1);
+ RealLength = (RealLength << 4) | (LeadByte & 0xF);
+ break;
+ }
+ case 2:
+ {
+ RealLength = *(Buffer + 1);
+ RealLength |= ((UINT32)(*(Buffer + 2))) << 8;
+ RealLength = (RealLength << 4) | (LeadByte & 0xF);
+ break;
+ }
+ case 3:
+ {
+ RealLength = *(Buffer + 1);
+ RealLength |= ((UINT32)(*(Buffer + 2))) << 8;
+ RealLength |= ((UINT32)(*(Buffer + 3))) << 16;
+ RealLength = (RealLength << 4) | (LeadByte & 0xF);
+ break;
+ }
+ default:
+ {
+ ASSERT (0);
+ Offset = 0;
+ break;
+ }
+ } // switch
+
+ *PkgLength = RealLength;
+
+ return Offset;
+}
+
+/** Convert the Length to the AML PkgLen encoding,
+ then and write it in the Buffer.
+
+ @param [in] Length Length to convert.
+ Length cannot exceed 2^28.
+ @param [out] Buffer Write the result in this Buffer.
+
+ @return The number of bytes used to write the Length.
+**/
+UINT8
+EFIAPI
+AmlSetPkgLength (
+ IN UINT32 Length,
+ OUT UINT8 * Buffer
+ )
+{
+ UINT8 LeadByte;
+ UINT8 Offset;
+ UINT8 CurrentOffset;
+ UINT8 CurrentShift;
+ UINT32 ComputedLength;
+
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return 0;
+ }
+
+ LeadByte = 0;
+ Offset = 0;
+
+ if ((Length < (1 << 6))) {
+ // Length < 2^6, only need one byte to encode it.
+ LeadByte = (UINT8)Length;
+
+ } else {
+ // Need more than one byte to encode it.
+ // Test Length to find how many bytes are needed.
+
+ if (Length >= (1 << 28)) {
+ // Length >= 2^28, should not be possible.
+ ASSERT (0);
+ return 0;
+
+ } else if (Length >= (1 << 20)) {
+ // Length >= 2^20
+ Offset = 3;
+
+ } else if (Length >= (1 << 12)) {
+ // Length >= 2^12
+ Offset = 2;
+
+ } else if (Length >= (1 << 6)) {
+ // Length >= 2^6
+ Offset = 1;
+
+ } else {
+ // Should not be possible.
+ ASSERT (0);
+ return 0;
+ }
+
+ // Set the LeadByte.
+ LeadByte = (UINT8)(Offset << 6);
+ LeadByte = (UINT8)(LeadByte | (Length & 0xF));
+ }
+
+ // Write to the Buffer.
+ *Buffer = LeadByte;
+ CurrentOffset = 1;
+ while (CurrentOffset < (Offset + 1)) {
+ CurrentShift = (UINT8)((CurrentOffset - 1) * 8);
+ ComputedLength = Length & (UINT32)(0x00000FF0 << CurrentShift);
+ ComputedLength = (ComputedLength) >> (4 + CurrentShift);
+ LeadByte = (UINT8)(ComputedLength & 0xFF);
+ *(Buffer + CurrentOffset) = LeadByte;
+ CurrentOffset++;
+ }
+
+ return ++Offset;
+}
+
+/** Compute the number of bytes required to write a package length.
+
+ @param [in] Length The length to convert in the AML package length
+ encoding style.
+ Length cannot exceed 2^28.
+
+ @return The number of bytes required to write the Length.
+**/
+UINT8
+EFIAPI
+AmlComputePkgLengthWidth (
+ IN UINT32 Length
+ )
+{
+ // Length >= 2^28, should not be possible.
+ if (Length >= (1 << 28)) {
+ ASSERT (0);
+ return 0;
+
+ } else if (Length >= (1 << 20)) {
+ // Length >= 2^20
+ return 4;
+
+ } else if (Length >= (1 << 12)) {
+ // Length >= 2^12
+ return 3;
+
+ } else if (Length >= (1 << 6)) {
+ // Length >= 2^6
+ return 2;
+ }
+
+ // Length < 2^6
+ return 1;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h
new file mode 100644
index 00000000000..6b563db05fb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlEncoding/Aml.h
@@ -0,0 +1,330 @@
+/** @file
+ AML grammar definitions.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_H_
+#define AML_H_
+
+#include <AmlDefines.h>
+#include <AmlInclude.h>
+#include <IndustryStandard/AcpiAml.h>
+
+#if !defined (MDEPKG_NDEBUG)
+#define AML_OPCODE_DEF(str, OpCode) str, OpCode
+#else
+#define AML_OPCODE_DEF(str, OpCode) OpCode
+#endif // MDEPKG_NDEBUG
+
+/** AML types.
+
+ In the AML bytestream, data is represented using one of the following types.
+ These types are used in the parsing logic to know what kind of data is
+ expected next in the bytestream. This allows to parse data according
+ to the AML_PARSE_FORMAT type.
+ E.g.: A string will not be parsed in the same way as a UINT8.
+
+ These are internal types.
+*/
+typedef enum EAmlParseFormat {
+ EAmlNone = 0, ///< No data expected.
+ EAmlUInt8, ///< One byte value evaluated as a UINT8.
+ EAmlUInt16, ///< Two byte value evaluated as a UINT16.
+ EAmlUInt32, ///< Four byte value evaluated as a UINT32.
+ EAmlUInt64, ///< Eight byte value evaluated as a UINT64.
+ EAmlObject, ///< AML object, starting with an OpCode/SubOpCode
+ /// couple, potentially followed by package length.
+ /// EAmlName is a subtype of an EAmlObject.
+ /// Indeed, an EAmlName can also be evaluated as
+ /// an EAmlObject in the parsing.
+ EAmlName, ///< Name corresponding to the NameString keyword
+ /// in the ACPI specification. E.g.: "\_SB_.DEV0"
+ EAmlString, ///< NULL terminated string.
+ EAmlFieldPkgLen, ///< A field package length (PkgLen). A data node of this
+ /// type can only be found in a field list, in a
+ /// NamedField statement. The PkgLen is otherwise
+ /// part of the object node structure.
+ EAmlParseFormatMax ///< Max enum.
+} AML_PARSE_FORMAT;
+
+/** AML attributes
+
+ To add some more information to the byte encoding, it is possible to add
+ these attributes.
+*/
+typedef UINT32 AML_OP_ATTRIBUTE;
+
+/** A PkgLength is expected between the OpCode/SubOpCode couple and the first
+ fixed argument of the object.
+*/
+#define AML_HAS_PKG_LENGTH 0x00001U
+
+/** The object's OpCode is actually a character. Encodings with this attribute
+ don't describe objects. The dual/multi name prefix have this attribute,
+ indicating the start of a longer NameString.
+*/
+#define AML_IS_NAME_CHAR 0x00002U
+
+/** A variable list of arguments is following the last fixed argument. Each
+ argument is evaluated as an EAmlObject.
+*/
+#define AML_HAS_CHILD_OBJ 0x00004U
+
+/** This is a sub-type of a variable list of arguments. It can only be
+ found in buffer objects. A ByteList is either a list of
+ bytes or a list of resource data elements. Resource data elements
+ have specific opcodes.
+*/
+#define AML_HAS_BYTE_LIST 0x00008U
+
+/** This is a sub-type of a variable list of arguments. It can only be
+ found in Fields, IndexFields and BankFields.
+ A FieldList is made of FieldElements. FieldElements have specific opcodes.
+*/
+#define AML_HAS_FIELD_LIST 0x00010U
+
+/** This object node is a field element. Its opcode is to be fetched from
+ the field encoding table.
+*/
+#define AML_IS_FIELD_ELEMENT 0x00020U
+
+/** The object has a name and which is part of the AML namespace. The name
+ can be found in the fixed argument list at the NameIndex.
+*/
+#define AML_IN_NAMESPACE 0x10000U
+
+/** Some OpCodes have been created in this library. They are called
+ pseudo opcodes and must stay internal to this library.
+*/
+#define AML_IS_PSEUDO_OPCODE 0x20000U
+
+/** Encoding of an AML object.
+
+ Every AML object has a specific encoding. This encoding information
+ is used to parse AML objects. A table of AML_BYTE_ENCODING entries
+ allows to parse an AML bytestream.
+ This structure is also used to describe field objects.
+
+ Cf. ACPI 6.3 specification, s20.2.
+*/
+typedef struct _AML_BYTE_ENCODING {
+// Enable this field for debug.
+#if !defined (MDEPKG_NDEBUG)
+ /// String field allowing to print the AML object.
+ CONST CHAR8 * Str;
+#endif // MDEPKG_NDEBUG
+
+ /// OpCode of the AML object.
+ UINT8 OpCode;
+
+ /// SubOpCode of the AML object.
+ /// The SubOpcode field has a valid value when the OpCode is 0x5B,
+ /// otherwise this field must be zero.
+ /// For field objects, the SubOpCode is not used.
+ UINT8 SubOpCode;
+
+ /// Number of fixed arguments for the AML statement represented
+ /// by the OpCode & SubOpcode.
+ /// Maximum is 6 for AML objects.
+ /// Maximum is 3 for field objects.
+ EAML_PARSE_INDEX MaxIndex;
+
+ /// If the encoding has the AML_IN_NAMESPACE attribute (cf Attribute
+ /// field below), indicate where to find the name in the fixed list
+ /// of arguments.
+ EAML_PARSE_INDEX NameIndex;
+
+ /// Type of each fixed argument.
+ AML_PARSE_FORMAT Format[EAmlParseIndexMax];
+
+ /// Additional information on the AML object.
+ AML_OP_ATTRIBUTE Attribute;
+} AML_BYTE_ENCODING;
+
+/** Get the AML_BYTE_ENCODING entry in the AML encoding table.
+
+ Note: For Pseudo OpCodes this function returns NULL.
+
+ @param [in] Buffer Pointer to an OpCode/SubOpCode couple.
+ If *Buffer = 0x5b (extended OpCode),
+ Buffer must be at least two bytes long.
+
+ @return The corresponding AML_BYTE_ENCODING entry.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetByteEncoding (
+ IN CONST UINT8 * Buffer
+ );
+
+/** Get the AML_BYTE_ENCODING entry in the AML encoding table
+ by providing an OpCode/SubOpCode couple.
+
+ @param [in] OpCode OpCode.
+ @param [in] SubOpCode SubOpCode.
+
+ @return The corresponding AML_BYTE_ENCODING entry.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetByteEncodingByOpCode (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+
+/** Get the AML_BYTE_ENCODING entry in the field encoding table.
+
+ Note: For Pseudo OpCodes this function returns NULL.
+
+ @param [in] Buffer Pointer to a field OpCode.
+ No SubOpCode is expected.
+
+ @return The corresponding AML_BYTE_ENCODING entry
+ in the field encoding table.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetFieldEncoding (
+ IN CONST UINT8 * Buffer
+ );
+
+/** Get the AML_BYTE_ENCODING entry in the field encoding table
+ by providing an OpCode/SubOpCode couple.
+
+ @param [in] OpCode OpCode.
+ @param [in] SubOpCode SubOpCode.
+
+ @return The corresponding AML_BYTE_ENCODING entry
+ in the field encoding table.
+ NULL if not found.
+**/
+CONST
+AML_BYTE_ENCODING *
+EFIAPI
+AmlGetFieldEncodingByOpCode (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+
+// Enable this function for debug.
+#if !defined (MDEPKG_NDEBUG)
+/** Look for an OpCode/SubOpCode couple in the AML grammar,
+ and return a corresponding string.
+
+ @param [in] OpCode The OpCode.
+ @param [in] SubOpCode The SubOpCode.
+
+ @return A string describing the OpCode/SubOpCode couple.
+ NULL if not found.
+**/
+CONST
+CHAR8 *
+AmlGetOpCodeStr (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+
+/** Look for an OpCode/SubOpCode couple in the AML field element grammar,
+ and return a corresponding string.
+
+ @param [in] OpCode The OpCode.
+ @param [in] SubOpCode The SubOpCode. Must be zero.
+
+ @return A string describing the OpCode/SubOpCode couple.
+ NULL if not found.
+**/
+CONST
+CHAR8 *
+AmlGetFieldOpCodeStr (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+#endif // MDEPKG_NDEBUG
+
+/** Check whether the OpCode/SubOpcode couple is a valid entry
+ in the AML grammar encoding table.
+
+ @param [in] OpCode OpCode to check.
+ @param [in] SubOpCode SubOpCode to check.
+
+ @retval TRUE The OpCode/SubOpCode couple is valid.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlIsOpCodeValid (
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+
+/** Convert an AML_PARSE_FORMAT to its corresponding EAML_NODE_DATA_TYPE.
+
+ @param [in] AmlType Input AML Type.
+
+ @return The corresponding EAML_NODE_DATA_TYPE.
+ EAmlNodeDataTypeNone if not found.
+**/
+EAML_NODE_DATA_TYPE
+EFIAPI
+AmlTypeToNodeDataType (
+ IN AML_PARSE_FORMAT AmlType
+ );
+
+/** Get the package length from the buffer.
+
+ @param [in] Buffer AML buffer.
+ @param [out] PkgLength The interpreted PkgLen value.
+ Length cannot exceed 2^28.
+
+ @return The number of bytes to represent the package length.
+ 0 if an issue occurred.
+**/
+UINT32
+EFIAPI
+AmlGetPkgLength (
+ IN CONST UINT8 * Buffer,
+ OUT UINT32 * PkgLength
+ );
+
+/** Convert the Length to the AML PkgLen encoding,
+ then and write it in the Buffer.
+
+ @param [in] Length Length to convert.
+ Length cannot exceed 2^28.
+ @param [out] Buffer Write the result in this Buffer.
+
+ @return The number of bytes used to write the Length.
+**/
+UINT8
+EFIAPI
+AmlSetPkgLength (
+ IN UINT32 Length,
+ OUT UINT8 * Buffer
+ );
+
+/** Compute the number of bytes required to write a package length.
+
+ @param [in] Length The length to convert in the AML package length
+ encoding style.
+ Length cannot exceed 2^28.
+
+ @return The number of bytes required to write the Length.
+**/
+UINT8
+EFIAPI
+AmlComputePkgLengthWidth (
+ IN UINT32 Length
+ );
+
+#endif // AML_H_
+
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h
new file mode 100644
index 00000000000..9fd94fc3b4b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlInclude.h
@@ -0,0 +1,18 @@
+/** @file
+ AML Include file
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_INCLUDE_H_
+#define AML_INCLUDE_H_
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#endif // AML_INCLUDE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
new file mode 100644
index 00000000000..5e657ef3666
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlLib.inf
@@ -0,0 +1,76 @@
+## @file
+# AML Generation Library
+#
+# Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = DynamicAmlLib
+ FILE_GUID = 23A6AFDA-F2A5-45EC-BEFF-420639D345B9
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = AmlLib
+
+[Sources]
+ AmlCoreInterface.h
+ AmlDefines.h
+ AmlInclude.h
+ AmlNodeDefines.h
+ AmlDbgPrint/AmlDbgPrint.c
+ AmlDbgPrint/AmlDbgPrint.h
+ AmlEncoding/Aml.c
+ AmlEncoding/Aml.h
+ Api/AmlApi.c
+ Api/AmlApiHelper.c
+ Api/AmlApiHelper.h
+ Api/AmlResourceDataApi.c
+ CodeGen/AmlCodeGen.c
+ CodeGen/AmlResourceDataCodeGen.c
+ CodeGen/AmlResourceDataCodeGen.h
+ NameSpace/AmlNameSpace.c
+ NameSpace/AmlNameSpace.h
+ Parser/AmlFieldListParser.c
+ Parser/AmlFieldListParser.h
+ Parser/AmlMethodParser.c
+ Parser/AmlMethodParser.h
+ Parser/AmlParser.c
+ Parser/AmlParser.h
+ Parser/AmlResourceDataParser.c
+ Parser/AmlResourceDataParser.h
+ ResourceData/AmlResourceData.c
+ ResourceData/AmlResourceData.h
+ Serialize/AmlSerialize.c
+ Stream/AmlStream.c
+ Stream/AmlStream.h
+ String/AmlString.c
+ String/AmlString.h
+ Tree/AmlClone.c
+ Tree/AmlTreeIterator.h
+ Tree/AmlNode.c
+ Tree/AmlNode.h
+ Tree/AmlNodeInterface.c
+ Tree/AmlTree.c
+ Tree/AmlTree.h
+ Tree/AmlTreeEnumerator.c
+ Tree/AmlTreeIterator.c
+ Tree/AmlTreeTraversal.c
+ Tree/AmlTreeTraversal.h
+ Utils/AmlUtility.c
+ Utils/AmlUtility.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+ BaseLib
+
+[BuildOptions]
+ *_*_*_CC_FLAGS = -DAML_HANDLE
+
+[Protocols]
+
+[Guids]
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h
new file mode 100644
index 00000000000..79736ad5a30
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/AmlNodeDefines.h
@@ -0,0 +1,183 @@
+/** @file
+ AML Node Definition.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_NODE_DEFINES_H_
+#define AML_NODE_DEFINES_H_
+
+#include <AmlEncoding/Aml.h>
+#include <IndustryStandard/Acpi.h>
+
+/** AML header node.
+
+ This abstract class represents either a root/object/data node.
+ All the enumerated nodes have this same common header.
+*/
+typedef struct AmlNodeHeader {
+ /// This must be the first field in this structure.
+ LIST_ENTRY Link;
+
+ /// Parent of this node. NULL for the root node.
+ struct AmlNodeHeader * Parent;
+
+ /// Node type allowing to identify a root/object/data node.
+ EAML_NODE_TYPE NodeType;
+} AML_NODE_HEADER;
+
+/** Node handle.
+*/
+typedef AML_NODE_HEADER* AML_NODE_HANDLE;
+
+/** AML root node.
+
+ The root node is unique and at the head of of tree. It is a fake node used
+ to maintain the list of AML statements (stored as object nodes) which are
+ at the first scope level.
+*/
+typedef struct AmlRootNode {
+ /// Header information. Must be the first field of the struct.
+ AML_NODE_HEADER NodeHeader;
+
+ /// List of object nodes being at the first scope level.
+ /// These are children and can only be object nodes.
+ LIST_ENTRY VariableArgs;
+
+ /// ACPI DSDT/SSDT header.
+ EFI_ACPI_DESCRIPTION_HEADER * SdtHeader;
+} AML_ROOT_NODE;
+
+/** Root Node handle.
+*/
+typedef AML_ROOT_NODE* AML_ROOT_NODE_HANDLE;
+
+/** AML object node.
+
+ Object nodes match AML statements. They are associated with an
+ OpCode/SubOpCode, and can have children.
+*/
+typedef struct AmlObjectNode {
+ /// Header information. Must be the first field of the struct.
+ AML_NODE_HEADER NodeHeader;
+
+ /// Some object nodes have a variable list of arguments.
+ /// These are children and can only be object/data nodes.
+ /// Cf ACPI specification, s20.3.
+ LIST_ENTRY VariableArgs;
+
+ /// Fixed arguments of this object node.
+ /// These are children and can be object/data nodes.
+ /// Cf ACPI specification, s20.3.
+ AML_NODE_HEADER * FixedArgs[EAmlParseIndexMax];
+
+ /// AML byte encoding. Stores the encoding information:
+ /// (OpCode/SubOpCode/number of fixed arguments/ attributes).
+ CONST AML_BYTE_ENCODING * AmlByteEncoding;
+
+ /// Some nodes have a PkgLen following their OpCode/SubOpCode in the
+ /// AML bytestream. This field stores the decoded value of the PkgLen.
+ UINT32 PkgLen;
+} AML_OBJECT_NODE;
+
+/** Object Node handle.
+*/
+typedef AML_OBJECT_NODE* AML_OBJECT_NODE_HANDLE;
+
+/** AML data node.
+
+ Data nodes store the smallest pieces of information.
+ E.g.: UINT8, UINT64, NULL terminated string, etc.
+ Data node don't have children nodes.
+*/
+typedef struct AmlDataNode {
+ /// Header information. Must be the first field of the struct.
+ AML_NODE_HEADER NodeHeader;
+
+ /// Tag identifying what data is stored in this node.
+ /// E.g. UINT, NULL terminated string, resource data element, etc.
+ EAML_NODE_DATA_TYPE DataType;
+
+ /// Buffer containing the data stored by this node.
+ UINT8 * Buffer;
+
+ /// Size of the Buffer.
+ UINT32 Size;
+} AML_DATA_NODE;
+
+/** Data Node handle.
+*/
+typedef AML_DATA_NODE* AML_DATA_NODE_HANDLE;
+
+/** Check whether a Node has a valid NodeType.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node has a valid NodeType.
+ @retval FALSE Otherwise.
+*/
+#define IS_AML_NODE_VALID(Node) \
+ ((Node != NULL) && \
+ ((((CONST AML_NODE_HEADER*)Node)->NodeType > EAmlNodeUnknown) || \
+ (((CONST AML_NODE_HEADER*)Node)->NodeType < EAmlNodeMax)))
+
+/** Check whether a Node is a root node.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is a root node.
+ @retval FALSE Otherwise.
+*/
+#define IS_AML_ROOT_NODE(Node) \
+ ((Node != NULL) && \
+ (((CONST AML_NODE_HEADER*)Node)->NodeType == EAmlNodeRoot))
+
+/** Check whether a Node is an object node.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is an object node.
+ @retval FALSE Otherwise.
+*/
+#define IS_AML_OBJECT_NODE(Node) \
+ ((Node != NULL) && \
+ (((CONST AML_NODE_HEADER*)Node)->NodeType == EAmlNodeObject))
+
+/** Check whether a Node is a data node.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is a data node.
+ @retval FALSE Otherwise.
+*/
+#define IS_AML_DATA_NODE(Node) \
+ ((Node != NULL) && \
+ (((CONST AML_NODE_HEADER*)Node)->NodeType == EAmlNodeData))
+
+/** Check whether a Node has a parent.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is a data node.
+ @retval FALSE Otherwise.
+*/
+#define AML_NODE_HAS_PARENT(Node) \
+ (IS_AML_NODE_VALID (Node) && \
+ (((CONST AML_NODE_HEADER*)Node)->Parent != NULL))
+
+/** Check that the Node is not attached somewhere.
+ This doesn't mean the node cannot have children.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node has been detached.
+ @retval FALSE Otherwise.
+*/
+#define AML_NODE_IS_DETACHED(Node) \
+ (IS_AML_NODE_VALID (Node) && \
+ IsListEmpty ((CONST LIST_ENTRY*)Node) && \
+ (((CONST AML_NODE_HEADER*)Node)->Parent == NULL))
+
+#endif // AML_NODE_DEFINES_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
new file mode 100644
index 00000000000..076e82169d4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApi.c
@@ -0,0 +1,382 @@
+/** @file
+ AML Api.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+/* Even though this file has access to the internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node
+ handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE,
+ etc.
+ Indeed, the functions in the "Api" folder should be implemented only
+ using the "safe" functions available in the "Include" folder. This
+ makes the functions available in the "Api" folder easy to export.
+*/
+#include <AmlNodeDefines.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlInclude.h>
+#include <Api/AmlApiHelper.h>
+#include <String/AmlString.h>
+
+/** Update the name of a DeviceOp object node.
+
+ @param [in] DeviceOpNode Object node representing a Device.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ OpCode/SubOpCode.
+ DeviceOp object nodes are defined in ASL
+ using the "Device ()" function.
+ @param [in] NewNameString The new Device's name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeviceOpUpdateName (
+ IN AML_OBJECT_NODE_HANDLE DeviceOpNode,
+ IN CHAR8 * NewNameString
+ )
+{
+ EFI_STATUS Status;
+
+ AML_DATA_NODE_HANDLE DeviceNameDataNode;
+ CHAR8 * NewAmlNameString;
+ UINT32 NewAmlNameStringSize;
+
+ // Check the input node is an object node.
+ if ((DeviceOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)DeviceOpNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (DeviceOpNode, AML_EXT_OP, AML_EXT_DEVICE_OP)) ||
+ (NewNameString == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the Device's name, being a data node
+ // which is the 1st fixed argument (i.e. index 0).
+ DeviceNameDataNode = (AML_DATA_NODE_HANDLE)AmlGetFixedArgument (
+ DeviceOpNode,
+ EAmlParseIndexTerm0
+ );
+ if ((DeviceNameDataNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)DeviceNameDataNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (DeviceNameDataNode, EAmlNodeDataTypeNameString))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = ConvertAslNameToAmlName (NewNameString, &NewAmlNameString);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlGetNameStringSize (NewAmlNameString, &NewAmlNameStringSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Update the Device's name node.
+ Status = AmlUpdateDataNode (
+ DeviceNameDataNode,
+ EAmlNodeDataTypeNameString,
+ (UINT8*)NewAmlNameString,
+ NewAmlNameStringSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+exit_handler:
+ FreePool (NewAmlNameString);
+ return Status;
+}
+
+/** Update an integer value defined by a NameOp object node.
+
+ For compatibility reasons, the NameOpNode must initially
+ contain an integer.
+
+ @param [in] NameOpNode NameOp object node.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] NewInt New Integer value to assign.
+ Must be a UINT64.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpUpdateInteger (
+ IN AML_OBJECT_NODE_HANDLE NameOpNode,
+ IN UINT64 NewInt
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE_HANDLE IntegerOpNode;
+
+ if ((NameOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the Integer object node defined by the "Name ()" function:
+ // it must have an Integer OpCode (Byte/Word/DWord/QWord).
+ // It is the 2nd fixed argument (i.e. index 1) of the NameOp node.
+ // This can also be a ZeroOp or OneOp node.
+ IntegerOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+ NameOpNode,
+ EAmlParseIndexTerm1
+ );
+ if ((IntegerOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)IntegerOpNode) != EAmlNodeObject)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the Integer value.
+ Status = AmlUpdateInteger (IntegerOpNode, NewInt);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Update a string value defined by a NameOp object node.
+
+ The NameOpNode must initially contain a string.
+ The EISAID ASL macro converts a string to an integer. This, it is
+ not accepted.
+
+ @param [in] NameOpNode NameOp object node.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] NewName New NULL terminated string to assign to
+ the NameOpNode.
+ The input string is copied.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpUpdateString (
+ IN AML_OBJECT_NODE_HANDLE NameOpNode,
+ IN CONST CHAR8 * NewName
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE_HANDLE StringOpNode;
+ AML_DATA_NODE_HANDLE StringDataNode;
+
+ if ((NameOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the String object node defined by the "Name ()" function:
+ // it must have a string OpCode.
+ // It is the 2nd fixed argument (i.e. index 1) of the NameOp node.
+ StringOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+ NameOpNode,
+ EAmlParseIndexTerm1
+ );
+ if ((StringOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)StringOpNode) != EAmlNodeObject)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the string data node.
+ // It is the 1st fixed argument (i.e. index 0) of the StringOpNode node.
+ StringDataNode = (AML_DATA_NODE_HANDLE)AmlGetFixedArgument (
+ StringOpNode,
+ EAmlParseIndexTerm0
+ );
+ if ((StringDataNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)StringDataNode) != EAmlNodeData)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the string value.
+ Status = AmlUpdateDataNode (
+ StringDataNode,
+ EAmlNodeDataTypeString,
+ (UINT8*)NewName,
+ (UINT32)AsciiStrLen (NewName) + 1
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Get the first Resource Data element contained in a "_CRS" object.
+
+ In the following ASL code, the function will return the Resource Data
+ node corresponding to the "QWordMemory ()" ASL macro.
+ Name (_CRS, ResourceTemplate() {
+ QWordMemory (...) {...},
+ Interrupt (...) {...}
+ }
+ )
+
+ Note:
+ - The "_CRS" object must be declared using ASL "Name (Declare Named Object)".
+ - "_CRS" declared using ASL "Method (Declare Control Method)" is not
+ supported.
+
+ @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [out] OutRdNode Pointer to the first Resource Data element of
+ the "_CRS" object. A Resource Data element
+ is stored in a data node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpCrsGetFirstRdNode (
+ IN AML_OBJECT_NODE_HANDLE NameOpCrsNode,
+ OUT AML_DATA_NODE_HANDLE * OutRdNode
+ )
+{
+ AML_OBJECT_NODE_HANDLE BufferOpNode;
+ AML_DATA_NODE_HANDLE FirstRdNode;
+
+ if ((NameOpCrsNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)NameOpCrsNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0)) ||
+ (!AmlNameOpCompareName (NameOpCrsNode, "_CRS")) ||
+ (OutRdNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutRdNode = NULL;
+
+ // Get the _CRS value which is represented as a BufferOp object node
+ // which is the 2nd fixed argument (i.e. index 1).
+ BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+ NameOpCrsNode,
+ EAmlParseIndexTerm1
+ );
+ if ((BufferOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the first Resource data node in the variable list of
+ // argument of the BufferOp node.
+ FirstRdNode = (AML_DATA_NODE_HANDLE)AmlGetNextVariableArgument (
+ (AML_NODE_HANDLE)BufferOpNode,
+ NULL
+ );
+ if ((FirstRdNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)FirstRdNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (FirstRdNode, EAmlNodeDataTypeResourceData))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutRdNode = FirstRdNode;
+ return EFI_SUCCESS;
+}
+
+/** Get the Resource Data element following the CurrRdNode Resource Data.
+
+ In the following ASL code, if CurrRdNode corresponds to the first
+ "QWordMemory ()" ASL macro, the function will return the Resource Data
+ node corresponding to the "Interrupt ()" ASL macro.
+ Name (_CRS, ResourceTemplate() {
+ QwordMemory (...) {...},
+ Interrupt (...) {...}
+ }
+ )
+
+ The CurrRdNode Resource Data node must be defined in an object named "_CRS"
+ and defined by a "Name ()" ASL function.
+
+ @param [in] CurrRdNode Pointer to the current Resource Data element of
+ the "_CRS" object.
+ @param [out] OutRdNode Pointer to the Resource Data element following
+ the CurrRdNode.
+ Contain a NULL pointer if CurrRdNode is the
+ last Resource Data element in the list.
+ The "End Tag" is not considered as a resource
+ data element and is not returned.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlNameOpCrsGetNextRdNode (
+ IN AML_DATA_NODE_HANDLE CurrRdNode,
+ OUT AML_DATA_NODE_HANDLE * OutRdNode
+ )
+{
+ AML_OBJECT_NODE_HANDLE NameOpCrsNode;
+ AML_OBJECT_NODE_HANDLE BufferOpNode;
+
+ if ((CurrRdNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)CurrRdNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (CurrRdNode, EAmlNodeDataTypeResourceData)) ||
+ (OutRdNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutRdNode = NULL;
+
+ // The parent of the CurrRdNode must be a BufferOp node.
+ BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetParent (
+ (AML_NODE_HANDLE)CurrRdNode
+ );
+ if ((BufferOpNode == NULL) ||
+ (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The parent of the BufferOpNode must be a NameOp node.
+ NameOpCrsNode = (AML_OBJECT_NODE_HANDLE)AmlGetParent (
+ (AML_NODE_HANDLE)BufferOpNode
+ );
+ if ((NameOpCrsNode == NULL) ||
+ (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0)) ||
+ (!AmlNameOpCompareName (NameOpCrsNode, "_CRS"))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutRdNode = (AML_DATA_NODE_HANDLE)AmlGetNextVariableArgument (
+ (AML_NODE_HANDLE)BufferOpNode,
+ (AML_NODE_HANDLE)CurrRdNode
+ );
+
+ // If the Resource Data is an End Tag, return NULL.
+ if (AmlNodeHasRdDataType (
+ *OutRdNode,
+ AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) {
+ *OutRdNode = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c
new file mode 100644
index 00000000000..16904115fed
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.c
@@ -0,0 +1,219 @@
+/** @file
+ AML Helper.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+/* Even though this file has access to the internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node
+ handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE,
+ etc.
+ Indeed, the functions in the "Api" folder should be implemented only
+ using the "safe" functions available in the "Include" folder. This
+ makes the functions available in the "Api" folder easy to export.
+*/
+#include <Api/AmlApiHelper.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlInclude.h>
+#include <String/AmlString.h>
+
+/** Compare the NameString defined by the "Name ()" ASL function,
+ and stored in the NameOpNode, with the input NameString.
+
+ An ASL NameString is expected to be NULL terminated, and can be composed
+ of NameSegs that have less that 4 chars, like "DEV". "DEV" will be expanded
+ as "DEV_".
+
+ An AML NameString is not NULL terminated and is is only composed of
+ 4 chars long NameSegs.
+
+ @param [in] NameOpNode NameOp object node defining a variable.
+ Must have an AML_NAME_OP/0 OpCode/SubOpCode.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] AslName ASL NameString to compare the NameOp's name with.
+ Must be NULL terminated.
+
+ @retval TRUE If the AslName and the AmlName defined by the NameOp node
+ are similar.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNameOpCompareName (
+ IN AML_OBJECT_NODE_HANDLE NameOpNode,
+ IN CHAR8 * AslName
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE_HANDLE NameDataNode;
+
+ CHAR8 * AmlName;
+ UINT32 AmlNameSize;
+
+ BOOLEAN RetVal;
+
+ if ((NameOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)NameOpNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (NameOpNode, AML_NAME_OP, 0)) ||
+ (AslName == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Get the NameOp name, being in a data node
+ // which is the first fixed argument (i.e. index 0).
+ NameDataNode = (AML_DATA_NODE_HANDLE)AmlGetFixedArgument (
+ NameOpNode,
+ EAmlParseIndexTerm0
+ );
+ if ((NameDataNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)NameDataNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (NameDataNode, EAmlNodeDataTypeNameString))) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Get the size of the name.
+ Status = AmlGetDataNodeBuffer (NameDataNode, NULL, &AmlNameSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Allocate memory to fetch the name.
+ AmlName = AllocateZeroPool (AmlNameSize);
+ if (AmlName == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Fetch the name.
+ Status = AmlGetDataNodeBuffer (NameDataNode, (UINT8*)AmlName, &AmlNameSize);
+ if (EFI_ERROR (Status)) {
+ FreePool (AmlName);
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Compare the input AslName and the AmlName stored in the NameOp node.
+ RetVal = CompareAmlWithAslNameString (AmlName, AslName);
+
+ // Free the string buffer.
+ FreePool (AmlName);
+ return RetVal;
+}
+
+/** Check whether ObjectNode has the input OpCode/SubOpcode couple.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] OpCode OpCode to check
+ @param [in] SubOpCode SubOpCode to check
+
+ @retval TRUE The node is an object node and
+ the Opcode and SubOpCode match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasOpCode (
+ IN AML_OBJECT_NODE_HANDLE ObjectNode,
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ EFI_STATUS Status;
+ UINT8 NodeOpCode;
+ UINT8 NodeSubOpCode;
+
+ // Get the Node information.
+ Status = AmlGetObjectNodeInfo (
+ ObjectNode,
+ &NodeOpCode,
+ &NodeSubOpCode,
+ NULL,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Check the OpCode and SubOpCode.
+ if ((OpCode != NodeOpCode) ||
+ (SubOpCode != NodeSubOpCode)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/** Check whether DataNode has the input DataType.
+
+ @param [in] DataNode Pointer to a data node.
+ @param [in] DataType DataType to check.
+
+ @retval TRUE The node is a data node and
+ the DataType match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasDataType (
+ IN AML_DATA_NODE_HANDLE DataNode,
+ IN EAML_NODE_DATA_TYPE DataType
+ )
+{
+ EFI_STATUS Status;
+ EAML_NODE_DATA_TYPE NodeDataType;
+
+ // Get the data type.
+ Status = AmlGetNodeDataType (DataNode, &NodeDataType);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Check the data type.
+ if (NodeDataType != DataType) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/** Check whether RdNode has the input RdDataType.
+
+ @param [in] RdNode Pointer to a data node.
+ @param [in] RdDataType DataType to check.
+
+ @retval TRUE The node is a Resource Data node and
+ the RdDataType match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasRdDataType (
+ IN AML_DATA_NODE_HANDLE RdNode,
+ IN AML_RD_HEADER RdDataType
+ )
+{
+ EFI_STATUS Status;
+ AML_RD_HEADER NodeRdDataType;
+
+ // Get the resource data type.
+ Status = AmlGetResourceDataType (
+ RdNode,
+ &NodeRdDataType
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Check the RdDataType.
+ return AmlRdCompareDescId (&NodeRdDataType, RdDataType);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h
new file mode 100644
index 00000000000..f682d0ec1a2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlApiHelper.h
@@ -0,0 +1,93 @@
+/** @file
+ AML Helper.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_HELPER_H_
+#define AML_HELPER_H_
+
+#include <AmlNodeDefines.h>
+#include <ResourceData/AmlResourceData.h>
+
+/** Compare the NameString defined by the "Name ()" ASL function,
+ and stored in the NameOpNode, with the input NameString.
+
+ An ASL NameString is expected to be NULL terminated, and can be composed
+ of NameSegs that have less that 4 chars, like "DEV". "DEV" will be expanded
+ as "DEV_".
+
+ An AML NameString is not NULL terminated and is is only composed of
+ 4 chars long NameSegs.
+
+ @param [in] NameOpNode NameOp object node defining a variable.
+ Must have an AML_NAME_OP/0 OpCode/SubOpCode.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] AslName ASL NameString to compare the NameOp's name with.
+ Must be NULL terminated.
+
+ @retval TRUE If the AslName and the AmlName defined by the NameOp node
+ are similar.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNameOpCompareName (
+ IN AML_OBJECT_NODE_HANDLE NameOpNode,
+ IN CHAR8 * AslName
+ );
+
+/** Check whether ObjectNode has the input OpCode/SubOpcode couple.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] OpCode OpCode to check
+ @param [in] SubOpCode SubOpCode to check
+
+ @retval TRUE The node is an object node and
+ the Opcode and SubOpCode match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasOpCode (
+ IN AML_OBJECT_NODE_HANDLE ObjectNode,
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+
+/** Check whether DataNode has the input DataType.
+
+ @param [in] DataNode Pointer to a data node.
+ @param [in] DataType DataType to check.
+
+ @retval TRUE The node is a data node and
+ the DataType match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasDataType (
+ IN AML_DATA_NODE_HANDLE DataNode,
+ IN EAML_NODE_DATA_TYPE DataType
+ );
+
+/** Check whether RdNode has the input RdDataType.
+
+ @param [in] RdNode Pointer to a data node.
+ @param [in] RdDataType DataType to check.
+
+ @retval TRUE The node is a Resource Data node and
+ the RdDataType match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasRdDataType (
+ IN AML_DATA_NODE_HANDLE RdNode,
+ IN AML_RD_HEADER RdDataType
+ );
+
+#endif // AML_HELPER_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c
new file mode 100644
index 00000000000..8371a862867
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Api/AmlResourceDataApi.c
@@ -0,0 +1,320 @@
+/** @file
+ AML Update Resource Data.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+/* Even though this file has access to the internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. Only the external node
+ handle types should be used, i.e. AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE,
+ etc.
+ Indeed, the functions in the "Api" folder should be implemented only
+ using the "safe" functions available in the "Include" folder. This
+ makes the functions available in the "Api" folder easy to export.
+*/
+#include <AmlNodeDefines.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlInclude.h>
+#include <Api/AmlApiHelper.h>
+#include <CodeGen/AmlResourceDataCodeGen.h>
+
+/** Update the first interrupt of an Interrupt resource data node.
+
+ The flags of the Interrupt resource data are left unchanged.
+
+ The InterruptRdNode corresponds to the Resource Data created by the
+ "Interrupt ()" ASL macro. It is an Extended Interrupt Resource Data.
+ See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ @param [in] InterruptRdNode Pointer to the an extended interrupt
+ resource data node.
+ @param [in] Irq Interrupt value to update.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRdInterrupt (
+ IN AML_DATA_NODE_HANDLE InterruptRdNode,
+ IN UINT32 Irq
+ )
+{
+ EFI_STATUS Status;
+ UINT32 * FirstInterrupt;
+ UINT8 * QueryBuffer;
+ UINT32 QueryBufferSize;
+
+ if ((InterruptRdNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)InterruptRdNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (
+ InterruptRdNode,
+ EAmlNodeDataTypeResourceData)) ||
+ (!AmlNodeHasRdDataType (
+ InterruptRdNode,
+ AML_RD_BUILD_LARGE_DESC_ID (
+ ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME)))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ QueryBuffer = NULL;
+
+ // Get the size of the InterruptRdNode buffer.
+ Status = AmlGetDataNodeBuffer (
+ InterruptRdNode,
+ NULL,
+ &QueryBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Check the Buffer is large enough.
+ if (QueryBufferSize < sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate a buffer to fetch the data.
+ QueryBuffer = AllocatePool (QueryBufferSize);
+ if (QueryBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Get the data.
+ Status = AmlGetDataNodeBuffer (
+ InterruptRdNode,
+ QueryBuffer,
+ &QueryBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Get the address of the first interrupt field.
+ FirstInterrupt =
+ ((EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR*)QueryBuffer)->InterruptNumber;
+
+ *FirstInterrupt = Irq;
+
+ // Update the InterruptRdNode buffer.
+ Status = AmlUpdateDataNode (
+ InterruptRdNode,
+ EAmlNodeDataTypeResourceData,
+ QueryBuffer,
+ QueryBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+error_handler:
+ if (QueryBuffer != NULL) {
+ FreePool (QueryBuffer);
+ }
+ return Status;
+}
+
+/** Update the interrupt list of an interrupt resource data node.
+
+ The InterruptRdNode corresponds to the Resource Data created by the
+ "Interrupt ()" ASL function. It is an Extended Interrupt Resource Data.
+ See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ @param [in] InterruptRdNode Pointer to the an extended interrupt
+ resource data node.
+ @param [in] ResourceConsumer The device consumes the specified interrupt
+ or produces it for use by a child device.
+ @param [in] EdgeTriggered The interrupt is edge triggered or
+ level triggered.
+ @param [in] ActiveLow The interrupt is active-high or active-low.
+ @param [in] Shared The interrupt can be shared with other
+ devices or not (Exclusive).
+ @param [in] IrqList Interrupt list. Must be non-NULL.
+ @param [in] IrqCount Interrupt count. Must be non-zero.
+
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRdInterruptEx (
+ IN AML_DATA_NODE_HANDLE InterruptRdNode,
+ IN BOOLEAN ResourceConsumer,
+ IN BOOLEAN EdgeTriggered,
+ IN BOOLEAN ActiveLow,
+ IN BOOLEAN Shared,
+ IN UINT32 * IrqList,
+ IN UINT8 IrqCount
+ )
+{
+ EFI_STATUS Status;
+
+ EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR * RdInterrupt;
+ UINT32 * FirstInterrupt;
+ UINT8 * UpdateBuffer;
+ UINT16 UpdateBufferSize;
+
+ if ((InterruptRdNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)InterruptRdNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (
+ InterruptRdNode,
+ EAmlNodeDataTypeResourceData)) ||
+ (!AmlNodeHasRdDataType (
+ InterruptRdNode,
+ AML_RD_BUILD_LARGE_DESC_ID (
+ ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME))) ||
+ (IrqList == NULL) ||
+ (IrqCount == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ UpdateBuffer = NULL;
+ UpdateBufferSize = sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) +
+ ((IrqCount - 1) * sizeof (UINT32));
+
+ // Allocate a buffer to update the data.
+ UpdateBuffer = AllocatePool (UpdateBufferSize);
+ if (UpdateBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Update the Resource Data information (structure size, interrupt count).
+ RdInterrupt = (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR*)UpdateBuffer;
+ RdInterrupt->Header.Header.Byte =
+ AML_RD_BUILD_LARGE_DESC_ID (ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME);
+ RdInterrupt->Header.Length =
+ UpdateBufferSize - sizeof (ACPI_LARGE_RESOURCE_HEADER);
+ RdInterrupt->InterruptTableLength = IrqCount;
+ RdInterrupt->InterruptVectorFlags = (ResourceConsumer ? BIT0 : 0) |
+ (EdgeTriggered ? BIT1 : 0) |
+ (ActiveLow ? BIT2 : 0) |
+ (Shared ? BIT3 : 0);
+
+ // Get the address of the first interrupt field.
+ FirstInterrupt =
+ ((EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR*)UpdateBuffer)->InterruptNumber;
+
+ // Copy the input list of interrupts.
+ CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount));
+
+ // Update the InterruptRdNode buffer.
+ Status = AmlUpdateDataNode (
+ InterruptRdNode,
+ EAmlNodeDataTypeResourceData,
+ UpdateBuffer,
+ UpdateBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ // Cleanup
+ FreePool (UpdateBuffer);
+
+ return Status;
+}
+
+/** Update the base address and length of a QWord resource data node.
+
+ @param [in] QWordRdNode Pointer a QWord resource data
+ node.
+ @param [in] BaseAddress Base address.
+ @param [in] BaseAddressLength Base address length.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRdQWord (
+ IN AML_DATA_NODE_HANDLE QWordRdNode,
+ IN UINT64 BaseAddress,
+ IN UINT64 BaseAddressLength
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR * RdQWord;
+
+ UINT8 * QueryBuffer;
+ UINT32 QueryBufferSize;
+
+ if ((QWordRdNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)QWordRdNode) != EAmlNodeData) ||
+ (!AmlNodeHasDataType (QWordRdNode, EAmlNodeDataTypeResourceData)) ||
+ (!AmlNodeHasRdDataType (
+ QWordRdNode,
+ AML_RD_BUILD_LARGE_DESC_ID (
+ ACPI_LARGE_QWORD_ADDRESS_SPACE_DESCRIPTOR_NAME)))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the size of the QWordRdNode's buffer.
+ Status = AmlGetDataNodeBuffer (
+ QWordRdNode,
+ NULL,
+ &QueryBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Allocate a buffer to fetch the data.
+ QueryBuffer = AllocatePool (QueryBufferSize);
+ if (QueryBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Get the data.
+ Status = AmlGetDataNodeBuffer (
+ QWordRdNode,
+ QueryBuffer,
+ &QueryBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ RdQWord = (EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR*)QueryBuffer;
+
+ // Update the Base Address and Length.
+ RdQWord->AddrRangeMin = BaseAddress;
+ RdQWord->AddrRangeMax = BaseAddress + BaseAddressLength - 1;
+ RdQWord->AddrLen = BaseAddressLength;
+
+ // Update Base Address Resource Data node.
+ Status = AmlUpdateDataNode (
+ QWordRdNode,
+ EAmlNodeDataTypeResourceData,
+ QueryBuffer,
+ QueryBufferSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+error_handler:
+ if (QueryBuffer != NULL) {
+ FreePool (QueryBuffer);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
new file mode 100644
index 00000000000..d7ea7bbee7e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -0,0 +1,701 @@
+/** @file
+ AML Code Generation.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+
+#include <AcpiTableGenerator.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlEncoding/Aml.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+#include <String/AmlString.h>
+#include <Utils/AmlUtility.h>
+
+/** Utility function to link a node when returning from a CodeGen function.
+
+ @param [in] Node Newly created node.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+LinkNode (
+ IN AML_OBJECT_NODE * Node,
+ IN AML_NODE_HEADER * ParentNode,
+ OUT AML_OBJECT_NODE ** NewObjectNode
+ )
+{
+ EFI_STATUS Status;
+
+ if (NewObjectNode != NULL) {
+ *NewObjectNode = Node;
+ }
+
+ // Add RdNode as the last element.
+ if (ParentNode != NULL) {
+ Status = AmlVarListAddTail (ParentNode, (AML_NODE_HEADER*)Node);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** AML code generation for DefinitionBlock.
+
+ Create a Root Node handle.
+ It is the caller's responsibility to free the allocated memory
+ with the AmlDeleteTree function.
+
+ AmlCodeGenDefinitionBlock (TableSignature, OemID, TableID, OEMRevision) is
+ equivalent to the following ASL code:
+ DefinitionBlock (AMLFileName, TableSignature, ComplianceRevision,
+ OemID, TableID, OEMRevision) {}
+ with the ComplianceRevision set to 2 and the AMLFileName is ignored.
+
+ @param[in] TableSignature 4-character ACPI signature.
+ Must be 'DSDT' or 'SSDT'.
+ @param[in] OemId 6-character string OEM identifier.
+ @param[in] OemTableId 8-character string OEM table identifier.
+ @param[in] OemRevision OEM revision number.
+ @param[out] NewRootNode Pointer to the root node representing a
+ Definition Block.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenDefinitionBlock (
+ IN CONST CHAR8 * TableSignature,
+ IN CONST CHAR8 * OemId,
+ IN CONST CHAR8 * OemTableId,
+ IN UINT32 OemRevision,
+ OUT AML_ROOT_NODE ** NewRootNode
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_DESCRIPTION_HEADER AcpiHeader;
+
+ if ((TableSignature == NULL) ||
+ (OemId == NULL) ||
+ (OemTableId == NULL) ||
+ (NewRootNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&AcpiHeader.Signature, TableSignature, 4);
+ AcpiHeader.Length = sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+ AcpiHeader.Revision = 2;
+ CopyMem (&AcpiHeader.OemId, OemId, 6);
+ CopyMem (&AcpiHeader.OemTableId, OemTableId, 8);
+ AcpiHeader.OemRevision = OemRevision;
+ AcpiHeader.CreatorId = TABLE_GENERATOR_CREATOR_ID_ARM;
+ AcpiHeader.CreatorRevision = CREATE_REVISION (1, 0);
+
+ Status = AmlCreateRootNode (&AcpiHeader, NewRootNode);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** AML code generation for a String object node.
+
+ @param [in] String Pointer to a NULL terminated string.
+ @param [out] NewObjectNode If success, contains the created
+ String object node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenString (
+ IN CHAR8 * String,
+ OUT AML_OBJECT_NODE ** NewObjectNode
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+ AML_DATA_NODE * DataNode;
+
+ if ((String == NULL) ||
+ (NewObjectNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ObjectNode = NULL;
+ DataNode = NULL;
+
+ Status = AmlCreateObjectNode (
+ AmlGetByteEncodingByOpCode (AML_STRING_PREFIX, 0),
+ 0,
+ &ObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeString,
+ (UINT8*)String,
+ (UINT32)AsciiStrLen (String) + 1,
+ &DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ Status = AmlSetFixedArgument (
+ ObjectNode,
+ EAmlParseIndexTerm0,
+ (AML_NODE_HEADER*)DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
+ goto error_handler;
+ }
+
+ *NewObjectNode = ObjectNode;
+ return Status;
+
+error_handler:
+ if (ObjectNode != NULL) {
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
+ }
+
+ return Status;
+}
+
+/** AML code generation for an Integer object node.
+
+ @param [in] Integer Integer of the Integer object node.
+ @param [out] NewObjectNode If success, contains the created
+ Integer object node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenInteger (
+ IN UINT64 Integer,
+ OUT AML_OBJECT_NODE ** NewObjectNode
+ )
+{
+ EFI_STATUS Status;
+ INT8 ValueWidthDiff;
+
+ if (NewObjectNode == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Create an object node containing Zero.
+ Status = AmlCreateObjectNode (
+ AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0),
+ 0,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Update the object node with integer value.
+ Status = AmlNodeSetIntegerValue (*NewObjectNode, Integer, &ValueWidthDiff);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)*NewObjectNode);
+ }
+
+ return Status;
+}
+
+/** AML code generation for a Name object node.
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ This input string is copied.
+ @param [in] Object Object associated to the NameString.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCodeGenName (
+ IN CONST CHAR8 * NameString,
+ IN AML_OBJECT_NODE * Object,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+ AML_DATA_NODE * DataNode;
+ CHAR8 * AmlNameString;
+ UINT32 AmlNameStringSize;
+
+ if ((NameString == NULL) ||
+ (Object == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ObjectNode = NULL;
+ DataNode = NULL;
+ AmlNameString = NULL;
+
+ Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler1;
+ }
+
+ Status = AmlCreateObjectNode (
+ AmlGetByteEncodingByOpCode (AML_NAME_OP, 0),
+ 0,
+ &ObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler1;
+ }
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeNameString,
+ (UINT8*)AmlNameString,
+ AmlNameStringSize,
+ &DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ Status = AmlSetFixedArgument (
+ ObjectNode,
+ EAmlParseIndexTerm0,
+ (AML_NODE_HEADER*)DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
+ goto error_handler2;
+ }
+
+ Status = AmlSetFixedArgument (
+ ObjectNode,
+ EAmlParseIndexTerm1,
+ (AML_NODE_HEADER*)Object
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ Status = LinkNode (
+ ObjectNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ // Free AmlNameString before returning as it is copied
+ // in the call to AmlCreateDataNode().
+ goto error_handler1;
+
+error_handler2:
+ if (ObjectNode != NULL) {
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
+ }
+
+error_handler1:
+ if (AmlNameString != NULL) {
+ FreePool (AmlNameString);
+ }
+
+ return Status;
+}
+
+/** AML code generation for a Name object node, containing a String.
+
+ AmlCodeGenNameString ("_HID", "HID0000", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(_HID, "HID0000")
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] String NULL terminated String to associate to the
+ NameString.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameString (
+ IN CONST CHAR8 * NameString,
+ IN CHAR8 * String,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+
+ if ((NameString == NULL) ||
+ (String == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCodeGenString (String, &ObjectNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlCodeGenName (
+ NameString,
+ ObjectNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
+ }
+
+ return Status;
+}
+
+/** AML code generation for a Name object node, containing an Integer.
+
+ AmlCodeGenNameInteger ("_UID", 1, ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Name(_UID, One)
+
+ @param [in] NameString The new variable name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] Integer Integer to associate to the NameString.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenNameInteger (
+ IN CONST CHAR8 * NameString,
+ IN UINT64 Integer,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+
+ if ((NameString == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCodeGenInteger (Integer, &ObjectNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlCodeGenName (
+ NameString,
+ ObjectNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
+ }
+
+ return Status;
+}
+
+/** AML code generation for a Device object node.
+
+ AmlCodeGenDevice ("COM0", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Device(COM0) {}
+
+ @param [in] NameString The new Device's name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenDevice (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+ AML_DATA_NODE * DataNode;
+ CHAR8 * AmlNameString;
+ UINT32 AmlNameStringSize;
+
+ if ((NameString == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ObjectNode = NULL;
+ DataNode = NULL;
+ AmlNameString = NULL;
+
+ Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler1;
+ }
+
+ Status = AmlCreateObjectNode (
+ AmlGetByteEncodingByOpCode (AML_EXT_OP, AML_EXT_DEVICE_OP),
+ AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),
+ &ObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler1;
+ }
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeNameString,
+ (UINT8*)AmlNameString,
+ AmlNameStringSize,
+ &DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ Status = AmlSetFixedArgument (
+ ObjectNode,
+ EAmlParseIndexTerm0,
+ (AML_NODE_HEADER*)DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
+ goto error_handler2;
+ }
+
+ Status = LinkNode (
+ ObjectNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ // Free AmlNameString before returning as it is copied
+ // in the call to AmlCreateDataNode().
+ goto error_handler1;
+
+error_handler2:
+ if (ObjectNode != NULL) {
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
+ }
+
+error_handler1:
+ if (AmlNameString != NULL) {
+ FreePool (AmlNameString);
+ }
+
+ return Status;
+}
+
+/** AML code generation for a Scope object node.
+
+ AmlCodeGenScope ("_SB", ParentNode, NewObjectNode) is
+ equivalent of the following ASL code:
+ Scope(_SB) {}
+
+ @param [in] NameString The new Scope's name.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ The input string is copied.
+ @param [in] ParentNode If provided, set ParentNode as the parent
+ of the node created.
+ @param [out] NewObjectNode If success, contains the created node.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenScope (
+ IN CONST CHAR8 * NameString,
+ IN AML_NODE_HEADER * ParentNode, OPTIONAL
+ OUT AML_OBJECT_NODE ** NewObjectNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+ AML_DATA_NODE * DataNode;
+ CHAR8 * AmlNameString;
+ UINT32 AmlNameStringSize;
+
+ if ((NameString == NULL) ||
+ ((ParentNode == NULL) && (NewObjectNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ObjectNode = NULL;
+ DataNode = NULL;
+ AmlNameString = NULL;
+
+ Status = ConvertAslNameToAmlName (NameString, &AmlNameString);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlGetNameStringSize (AmlNameString, &AmlNameStringSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler1;
+ }
+
+ Status = AmlCreateObjectNode (
+ AmlGetByteEncodingByOpCode (AML_SCOPE_OP, 0),
+ AmlNameStringSize + AmlComputePkgLengthWidth (AmlNameStringSize),
+ &ObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler1;
+ }
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeNameString,
+ (UINT8*)AmlNameString,
+ AmlNameStringSize,
+ &DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ Status = AmlSetFixedArgument (
+ ObjectNode,
+ EAmlParseIndexTerm0,
+ (AML_NODE_HEADER*)DataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)DataNode);
+ goto error_handler2;
+ }
+
+ Status = LinkNode (
+ ObjectNode,
+ ParentNode,
+ NewObjectNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler2;
+ }
+
+ // Free AmlNameString before returning as it is copied
+ // in the call to AmlCreateDataNode().
+ goto error_handler1;
+
+error_handler2:
+ if (ObjectNode != NULL) {
+ AmlDeleteTree ((AML_NODE_HEADER*)ObjectNode);
+ }
+
+error_handler1:
+ if (AmlNameString != NULL) {
+ FreePool (AmlNameString);
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
new file mode 100644
index 00000000000..9db919a2eb9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.c
@@ -0,0 +1,256 @@
+/** @file
+ AML Resource Data Code Generation.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Rd or RD - Resource Data
+ - Rds or RDS - Resource Data Small
+ - Rdl or RDL - Resource Data Large
+**/
+
+#include <AmlNodeDefines.h>
+#include <CodeGen/AmlResourceDataCodeGen.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlDefines.h>
+#include <Api/AmlApiHelper.h>
+#include <Tree/AmlNode.h>
+#include <ResourceData/AmlResourceData.h>
+
+/** If ParentNode is not NULL, append RdNode.
+ If NewRdNode is not NULL, update its value to RdNode.
+
+ @param [in] RdNode Newly created Resource Data node.
+ @param [in] ParentNode If not NULL, add the generated node
+ to the end of the variable list of
+ argument of the ParentNode, but
+ before the "End Tag" Resource Data.
+ Must be a BufferOpNode.
+ @param [out] NewRdNode If not NULL, update the its value to RdNode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+LinkRdNode (
+ IN AML_DATA_NODE * RdNode,
+ IN AML_OBJECT_NODE * ParentNode,
+ OUT AML_DATA_NODE ** NewRdNode
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+
+ if (NewRdNode != NULL) {
+ *NewRdNode = RdNode;
+ }
+
+ // Add RdNode as the last element, but before the EndTag.
+ if (ParentNode != NULL) {
+ Status = AmlAppendRdNode (ParentNode, RdNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ Status1 = AmlDeleteTree ((AML_NODE_HEADER*)RdNode);
+ ASSERT_EFI_ERROR (Status1);
+ // Return original error.
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Code generation for the "Interrupt ()" ASL function.
+
+ This function creates a Resource Data element corresponding to the
+ "Interrupt ()" ASL function and stores it in an AML Data Node.
+
+ The Resource Data effectively created is an Extended Interrupt Resource
+ Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ This function allocates memory to create a data node. It is the caller's
+ responsibility to either:
+ - attach this node to an AML tree;
+ - delete this node.
+
+ @param [in] ResourceConsumer The device consumes the specified interrupt
+ or produces it for use by a child device.
+ @param [in] EdgeTriggered The interrupt is edge triggered or
+ level triggered.
+ @param [in] ActiveLow The interrupt is active-high or active-low.
+ @param [in] Shared The interrupt can be shared with other
+ devices or not (Exclusive).
+ @param [in] IrqList Interrupt list. Must be non-NULL.
+ @param [in] IrqCount Interrupt count. Must be non-zero.
+ @param [in] ParentNode If not NULL, add the generated node
+ to the end of the variable list of
+ argument of the ParentNode, but
+ before the "End Tag" Resource Data.
+ Must be a BufferOpNode.
+ @param [out] NewRdNode If success, contains the generated node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenInterrupt (
+ IN BOOLEAN ResourceConsumer,
+ IN BOOLEAN EdgeTriggered,
+ IN BOOLEAN ActiveLow,
+ IN BOOLEAN Shared,
+ IN UINT32 * IrqList,
+ IN UINT8 IrqCount,
+ IN AML_OBJECT_NODE * ParentNode, OPTIONAL
+ OUT AML_DATA_NODE ** NewRdNode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ AML_DATA_NODE * RdNode;
+ EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR RdInterrupt;
+ UINT32 * FirstInterrupt;
+
+ if ((IrqList == NULL) ||
+ (IrqCount == 0) ||
+ ((ParentNode == NULL) && (NewRdNode == NULL))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RdInterrupt.Header.Header.Bits.Name =
+ ACPI_LARGE_EXTENDED_IRQ_DESCRIPTOR_NAME;
+ RdInterrupt.Header.Header.Bits.Type = ACPI_LARGE_ITEM_FLAG;
+ RdInterrupt.Header.Length = sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR) -
+ sizeof (ACPI_LARGE_RESOURCE_HEADER);
+ RdInterrupt.InterruptVectorFlags = (ResourceConsumer ? BIT0 : 0) |
+ (EdgeTriggered ? BIT1 : 0) |
+ (ActiveLow ? BIT2 : 0) |
+ (Shared ? BIT3 : 0);
+ RdInterrupt.InterruptTableLength = IrqCount;
+
+ // Get the address of the first interrupt field.
+ FirstInterrupt = RdInterrupt.InterruptNumber;
+
+ // Copy the list of interrupts.
+ CopyMem (FirstInterrupt, IrqList, (sizeof (UINT32) * IrqCount));
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeResourceData,
+ (UINT8*)&RdInterrupt,
+ sizeof (EFI_ACPI_EXTENDED_INTERRUPT_DESCRIPTOR),
+ &RdNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ return LinkRdNode (RdNode, ParentNode, NewRdNode);
+}
+
+/** Add an Interrupt Resource Data node.
+
+ This function creates a Resource Data element corresponding to the
+ "Interrupt ()" ASL function, stores it in an AML Data Node.
+
+ It then adds it after the input CurrRdNode in the list of resource data
+ element.
+
+ The Resource Data effectively created is an Extended Interrupt Resource
+ Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ The Extended Interrupt contains one single interrupt.
+
+ This function allocates memory to create a data node. It is the caller's
+ responsibility to either:
+ - attach this node to an AML tree;
+ - delete this node.
+
+ Note: The _CRS node must be defined using the ASL Name () function.
+ e.g. Name (_CRS, ResourceTemplate () {
+ ...
+ }
+
+ @param [in] NameOpCrsNode NameOp object node defining a "_CRS" object.
+ Must have an OpCode=AML_NAME_OP, SubOpCode=0.
+ NameOp object nodes are defined in ASL
+ using the "Name ()" function.
+ @param [in] ResourceConsumer The device consumes the specified interrupt
+ or produces it for use by a child device.
+ @param [in] EdgeTriggered The interrupt is edge triggered or
+ level triggered.
+ @param [in] ActiveLow The interrupt is active-high or active-low.
+ @param [in] Shared The interrupt can be shared with other
+ devices or not (Exclusive).
+ @param [in] IrqList Interrupt list. Must be non-NULL.
+ @param [in] IrqCount Interrupt count. Must be non-zero.
+
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenCrsAddRdInterrupt (
+ IN AML_OBJECT_NODE_HANDLE NameOpCrsNode,
+ IN BOOLEAN ResourceConsumer,
+ IN BOOLEAN EdgeTriggered,
+ IN BOOLEAN ActiveLow,
+ IN BOOLEAN Shared,
+ IN UINT32 * IrqList,
+ IN UINT8 IrqCount
+ )
+{
+ EFI_STATUS Status;
+
+ AML_OBJECT_NODE_HANDLE BufferOpNode;
+
+ if ((IrqList == NULL) ||
+ (IrqCount == 0) ||
+ (!AmlNodeHasOpCode (NameOpCrsNode, AML_NAME_OP, 0)) ||
+ (!AmlNameOpCompareName (NameOpCrsNode, "_CRS"))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the _CRS value which is represented as a BufferOp object node
+ // which is the 2nd fixed argument (i.e. index 1).
+ BufferOpNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+ NameOpCrsNode,
+ EAmlParseIndexTerm1
+ );
+ if ((BufferOpNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)BufferOpNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (BufferOpNode, AML_BUFFER_OP, 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Generate the Extended Interrupt Resource Data node,
+ // and attach it as the last variable argument of the BufferOpNode.
+ Status = AmlCodeGenInterrupt (
+ ResourceConsumer,
+ EdgeTriggered,
+ ActiveLow,
+ Shared,
+ IrqList,
+ IrqCount,
+ BufferOpNode,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h
new file mode 100644
index 00000000000..cf4a98a346d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlResourceDataCodeGen.h
@@ -0,0 +1,59 @@
+/** @file
+ AML Resource Data Code Generation.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_RESOURCE_DATA_CODE_GEN_H_
+#define AML_RESOURCE_DATA_CODE_GEN_H_
+
+/** Code generation for the "Interrupt ()" ASL function.
+
+ This function creates a Resource Data element corresponding to the
+ "Interrupt ()" ASL function and stores it in an AML Data Node.
+
+ The Resource Data effectively created is an Extended Interrupt Resource
+ Data. See ACPI 6.3 specification, s6.4.3.6 "Extended Interrupt Descriptor"
+ for more information about Extended Interrupt Resource Data.
+
+ This function allocates memory to create a data node. It is the caller's
+ responsibility to either:
+ - attach this node to an AML tree;
+ - delete this node.
+
+ @param [in] ResourceConsumer The device consumes the specified interrupt
+ or produces it for use by a child device.
+ @param [in] EdgeTriggered The interrupt is edge triggered or
+ level triggered.
+ @param [in] ActiveLow The interrupt is active-high or active-low.
+ @param [in] Shared The interrupt can be shared with other
+ devices or not (Exclusive).
+ @param [in] IrqList Interrupt list. Must be non-NULL.
+ @param [in] IrqCount Interrupt count. Must be non-zero.
+ @param [in] ParentNode If not NULL, add the generated node
+ to the end of the variable list of
+ argument of the ParentNode, but
+ before the "End Tag" Resource Data.
+ Must be a BufferOpNode.
+ @param [out] NewRdNode If success, contains the generated node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCodeGenInterrupt (
+ IN BOOLEAN ResourceConsumer,
+ IN BOOLEAN EdgeTriggered,
+ IN BOOLEAN ActiveLow,
+ IN BOOLEAN Shared,
+ IN UINT32 * IrqList,
+ IN UINT8 IrqCount,
+ IN AML_OBJECT_NODE * ParentNode, OPTIONAL
+ OUT AML_DATA_NODE ** NewRdNode OPTIONAL
+ );
+
+#endif // AML_RESOURCE_DATA_CODE_GEN_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c
new file mode 100644
index 00000000000..a85e58e0cbb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.c
@@ -0,0 +1,1496 @@
+/** @file
+ AML NameSpace.
+
+ Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+/* Lexicon:
+
+ NameSeg:
+ - An ASL NameSeg is a name made of at most 4 chars.
+ Cf. ACPI 6.3 specification, s19.2.2 'Name and Pathname Terms'.
+ - An AML NameSeg is a name made of 4 chars.
+ Cf. ACPI 6.3 specification, s20.2.2 'Name Objects Encoding'.
+
+ NameString:
+ A NameString is analogous to a pathname. It is made of 0 to 255 NameSegs.
+ A NameString can be prefixed by a root char ('\') or 0 to 255 carets ('^').
+
+ A NameString can be ASL or AML encoded.
+ AML NameStrings can have a NameString prefix (dual or multi-name prefix)
+ between the root/carets and the list of NameSegs. If the prefix is the
+ multi-name prefix, then the number of NameSegs is encoded on one single byte.
+ Cf. ACPI 6.3 specification, s19.2.2 'Name and Pathname Terms'.
+ Cf. ACPI 6.3 specification, s20.2.2 'Name Objects Encoding'.
+
+ Namespace level:
+ One level in the AML Namespace level corresponds to one NameSeg. In ASL,
+ objects names are NameStrings. This means a device can have a name which
+ spans multiple levels.
+ E.g.: The ASL code: Device (CLU0.CPU0) corresponds to 2 levels.
+
+ Namespace node:
+ A namespace node is an object node which has an associated name, and which
+ changes the current scope.
+ E.g.:
+ 1. The "Device ()" ASL statement adds a name to the AML namespace and
+ changes the current scope to the device scope, this is a namespace node.
+ 2. The "Scope ()" ASL statement changes the current scope, this is a
+ namespace node.
+ 3. A method invocation has a name, but does not add nor change the current
+ AML scope. This is not a namespace node.
+
+ - Object nodes with the AML_IN_NAMESPACE attribute are namespace nodes.
+ Buffers (), Packages (), etc. are not part of the namespace. It is however
+ possible to associate them with a name with the Name () ASL statement.
+ - The root node is considered as being part of the namespace.
+ - Some resource data elements can have a name when defining them in
+ an ASL statement. However, this name is stripped by the ASL compiler.
+ Thus, they don't have a name in the AML bytestream, and are therefore
+ not part of the AML namespace.
+ - Field list elements are part of the namespace.
+ Fields created by an CreateXXXField () ASL statement are part of the
+ namespace. The name of these node can be found in the third or fourth
+ fixed argument. The exact index of the name can be found in the NameIndex
+ field of the AML_BYTE_ENCODING array.
+ Field are at the same level as their ASL statement in the namespace.
+ E.g:
+ Scope (\) {
+ OperationRegion (REG0, SystemIO, 0x100, 0x100)
+ Field (REG0, ByteAcc, NoLock, Preserve) {
+ FIE0, 1,
+ FIE1, 5
+ }
+
+ Name (BUF0, Buffer (100) {})
+ CreateField (BUF0, 5, 2, MEM0)
+ }
+
+ produces this namespace:
+ \ (Root)
+ \-REG0
+ \-FIE0
+ \-FIE1
+ \-BUF0
+ \-MEM0
+
+ Raw AML pathname or Raw AML NameString:
+ In order to easily manipulate AML NameStrings, the non-NameSegs chars are
+ removed in raw pathnames/NameStrings. Non-NameSegs chars are the
+ root char ('\'), carets ('^') and NameString prefixes (Dual/Multi name char).
+ E.g. The following terminology is defined in this AML Library.
+ ASL absolute path: "[RootChar]AAAA.BBBB.CCCC\0"
+ AML absolute path: "[RootChar][MultiNamePrefix][3(NameSegs)]AAAABBBBCCCC"
+ Raw absolute path: "AAAABBBBCCCC"
+
+ Multi-name:
+ A NameString with at least 2 NameSegs. A node can have a name which spans
+ multiple namespace levels.
+*/
+
+#include <NameSpace/AmlNameSpace.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlDbgPrint/AmlDbgPrint.h>
+#include <String/AmlString.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+#include <Tree/AmlTreeTraversal.h>
+
+/** Context of the path search callback function.
+
+ The function finding a node from a path and a reference node enumerates
+ the namespace nodes in the tree and compares their absolute path with the
+ searched path. The enumeration function uses a callback function that can
+ receive a context.
+ This structure is used to store the context information required in the
+ callback function.
+*/
+typedef struct AmlPathSearchContext {
+ /// Backward stream holding the raw AML absolute searched path.
+ AML_STREAM * SearchPathBStream;
+
+ /// An empty backward stream holding a pre-allocated buffer. This prevents
+ /// from having to do multiple allocations during the search.
+ /// This stream is used to query the raw AML absolute path of the node
+ /// currently being probed.
+ AML_STREAM * CurrNodePathBStream;
+
+ /// If the node being visited is the node being searched,
+ /// i.e. its path and the searched path match,
+ /// save its reference in this pointer.
+ AML_NODE_HEADER * OutNode;
+} AML_PATH_SEARCH_CONTEXT;
+
+/** Return the first AML namespace node up in the parent hierarchy.
+
+ Return the root node if no namespace node is found is the hierarchy.
+
+ @param [in] Node Node to look at the parents from.
+ If Node is the root node, OutNode is NULL.
+ @param [out] OutNode If a namespace node is found, pointer to the
+ first namespace node of Node's parents.
+ Stop at the root node otherwise.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ **/
+EFI_STATUS
+EFIAPI
+AmlGetFirstAncestorNameSpaceNode (
+ IN CONST AML_NODE_HEADER * Node,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ if (!IS_AML_NODE_VALID (Node) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // If Node is the root node, return NULL.
+ if (IS_AML_ROOT_NODE (Node)) {
+ *OutNode = NULL;
+ return EFI_SUCCESS;
+ } else {
+ // Else, get the parent node.
+ Node = AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ // Continue getting the parent node while no namespace node is encountered.
+ while (TRUE) {
+ if (IS_AML_ROOT_NODE (Node)) {
+ break;
+ } else if (AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE
+ )) {
+ break;
+ } else {
+ Node = AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ } // while
+
+ *OutNode = (AML_NODE_HEADER*)Node;
+ return EFI_SUCCESS;
+}
+
+/** Climb up the AML namespace hierarchy.
+
+ This function get the ancestor namespace node in the AML namespace.
+ If Levels is not zero, skip Levels namespace nodes in the AML namespace.
+ If Levels is zero, return the first ancestor namespace node.
+ I.e. if Levels = n, this function returns the (n + 1) ancestor.
+
+ @param [in] Node Pointer to an object node.
+ @param [in, out] Levels Pointer holding a number of AML namespace levels:
+ - At entry, the number of levels to go up in
+ the AML namespace;
+ - At exit, the number of levels that still need
+ to be climbed in case of a multi-named node.
+ Indeed, if a node with a multi-name is found,
+ and Levels is less than the number of NameSegs
+ in this name, then the function returns with
+ the number of levels that still need to be
+ climbed.
+ E.g.: If the first ancestor node's name is
+ "AAAA.BBBB.CCCC" and
+ Levels = 2 -> i.e go up 3 levels
+ \
+ ...
+ \-"AAAA.BBBB.CCCC" <----- OutNode
+ \-"DDDD" <----- Node (Input)
+
+ The function should ideally return a node
+ with the name "AAAA". However, it is not
+ possible to split the node name
+ "AAAA.BBBB.CCCC" to "AAAA".
+ Thus, OutNode is set to the input node,
+ and Levels = 2.
+ In most cases the number of levels to climb
+ correspond to non multi-name node, and therefore
+ Levels = 0 at exit.
+ @param [out] HasRoot The returned node in OutNode has an AML absolute
+ name, starting with a root char ('\'), or if OutNode
+ is the root node.
+ @param [out] OutNode The Levels+1 namespace ancestor of the input node in
+ the AML namespace. Must be the root node or a
+ namespace node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlGetAncestorNameSpaceNode (
+ IN CONST AML_OBJECT_NODE * Node,
+ IN OUT UINT32 * Levels,
+ OUT UINT32 * HasRoot,
+ OUT CONST AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+
+ CONST AML_NODE_HEADER * NameSpaceNode;
+ CHAR8 * NodeName;
+ UINT32 ParentCnt;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if (!IS_AML_OBJECT_NODE (Node) ||
+ (Levels == NULL) ||
+ (HasRoot == NULL) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentCnt = *Levels;
+ *HasRoot = 0;
+
+ // ParentCnt namespace levels need to be climbed.
+ do {
+ // Get the next namespace node in the hierarchy.
+ Status = AmlGetFirstAncestorNameSpaceNode (
+ (CONST AML_NODE_HEADER*)Node,
+ (AML_NODE_HEADER**)&NameSpaceNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Node = (CONST AML_OBJECT_NODE*)NameSpaceNode;
+
+ if (IS_AML_ROOT_NODE (Node)) {
+ // Node is the root node. It is not possible to go beyond.
+ if (ParentCnt != 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ *HasRoot = 1;
+ break;
+ }
+
+ NodeName = AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node);
+ if (NodeName == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Analyze the node name.
+ Status = AmlParseNameStringInfo (
+ NodeName,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ if (Root != 0) {
+ // NodeName is an absolute pathname.
+ *HasRoot = Root;
+
+ // If the node has Root then it cannot have ParentPrefixes (Carets).
+ if (ParentPrefix != 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (SegCount == ParentCnt) {
+ // There are exactly enough AML namespace levels to consume.
+ // This means the root node was the searched node.
+ Node = (CONST AML_OBJECT_NODE*)AmlGetRootNode (
+ (CONST AML_NODE_HEADER*)Node
+ );
+ if (!IS_AML_ROOT_NODE (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentCnt = 0;
+ break;
+ } else if (ParentCnt < SegCount) {
+ // There are too many AML namespace levels in this name.
+ // ParentCnt has the right value, just return.
+ break;
+ } else {
+ // ParentCnt > SegCount
+ // Return error as there must be at least ParentCnt AML namespace
+ // levels left in the absolute path.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ } else {
+ // Root is 0.
+ if (ParentCnt < SegCount) {
+ // NodeName is a relative path.
+ // NodeName has enough levels to consume all the ParentCnt.
+ // Exit.
+ break;
+ } else if (SegCount == ParentCnt) {
+ // There are exactly enough AML namespace levels to consume.
+ if (ParentPrefix == 0) {
+ // The node name doesn't have any carets. Get the next namespace
+ // node and return.
+ Status = AmlGetFirstAncestorNameSpaceNode (
+ (CONST AML_NODE_HEADER*)Node,
+ (AML_NODE_HEADER**)&NameSpaceNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ Node = (CONST AML_OBJECT_NODE*)NameSpaceNode;
+ ParentCnt = 0;
+ break;
+ } else {
+ // The node name has carets. Need to continue climbing the
+ // AML namespace.
+ ParentCnt = ParentPrefix;
+ }
+ } else {
+ // ParentCnt > SegCount
+ // NodeName doesn't have enough levels to consume all the ParentCnt.
+ // Update ParentCnt: Consume SegCount levels and add ParentPrefix
+ // levels. Continue climbing the tree.
+ ParentCnt = ParentCnt + ParentPrefix - SegCount;
+ }
+ }
+ } while (ParentCnt != 0);
+
+ *OutNode = (CONST AML_NODE_HEADER*)Node;
+ *Levels = ParentCnt;
+
+ return EFI_SUCCESS;
+}
+
+/** Build the raw absolute AML pathname to Node and write it to a stream.
+
+ A raw AML pathname is an AML pathname where the root char ('\'),
+ prefix chars ('^') and NameString prefix byte (e.g.: DualNamePrefix)
+ have been removed. A raw AML pathname is a list of concatenated
+ NameSegs.
+
+ E.g.:
+ ASL absolute path: "[RootChar]AAAA.BBBB.CCCC\0"
+ AML absolute path: "[RootChar][MultiNamePrefix][3(NameSegs)]AAAABBBBCCCC"
+ Raw absolute path: "AAAABBBBCCCC"
+
+ @param [in] Node Node to build the raw absolute path to
+ Must be a root node, or a namespace node.
+ @param [in] InputParent Skip InputParent AML namespace levels before
+ starting building the raw absolute pathname.
+ E.g.: - Node's name being "^AAAA.BBBB.CCCC";
+ - InputParent = 2;
+ "BBBB.CCCC" will be skipped (2
+ levels), and "^AAAA" will remain. The
+ first caret is not related to InputParent.
+ @param [out] RawAbsPathBStream Backward stream to write the raw
+ pathname to.
+ If Node is the root node, the Stream data
+ Buffer will stay empty.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetRawNameSpacePath (
+ IN CONST AML_NODE_HEADER * Node,
+ IN UINT32 InputParent,
+ OUT AML_STREAM * RawAbsPathBStream
+ )
+{
+ EFI_STATUS Status;
+
+ AML_NODE_HEADER * ParentNode;
+ CHAR8 * NodeName;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+ CONST CHAR8 * NameSeg;
+
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE)) ||
+ !IS_STREAM (RawAbsPathBStream) ||
+ IS_END_OF_STREAM (RawAbsPathBStream) ||
+ !IS_STREAM_BACKWARD (RawAbsPathBStream) ||
+ (InputParent > MAX_UINT8)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (1) {
+ if (IS_AML_ROOT_NODE (Node)) {
+ break;
+ }
+
+ NodeName = AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node);
+ if (NodeName == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlParseNameStringInfo (
+ NodeName,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ if (SegCount > InputParent) {
+ // 1.1. If the Node's name has enough levels to consume all the
+ // InputParent carets, write the levels that are left.
+ NameSeg = AmlGetFirstNameSeg (NodeName, Root, ParentPrefix);
+ Status = AmlStreamWrite (
+ RawAbsPathBStream,
+ (CONST UINT8*)NameSeg,
+ (SegCount - InputParent) * AML_NAME_SEG_SIZE
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ InputParent = 0;
+ } else {
+ // (SegCount <= InputParent)
+ // 1.2. Else save the InputParent in TotalParent to climb
+ // them later.
+ InputParent -= SegCount;
+ }
+
+ InputParent += ParentPrefix;
+
+ if (Root != 0) {
+ // 2. The Node's name is an absolute path.
+ // Exit, the root has been reached.
+ if (InputParent != 0) {
+ ASSERT (0);
+ return EFI_NOT_FOUND;
+ }
+ break;
+ }
+
+ Status = AmlGetAncestorNameSpaceNode (
+ (CONST AML_OBJECT_NODE*)Node,
+ &InputParent,
+ &Root,
+ (CONST AML_NODE_HEADER**)&ParentNode
+ );
+ if (EFI_ERROR (Status) ||
+ (!IS_AML_NODE_VALID (ParentNode))) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Node = ParentNode;
+
+ if (IS_AML_ROOT_NODE (Node)) {
+ // 3.1. If the root node has been found while climbing,
+ // no need to write NameSegs.
+ // Exit.
+ break;
+ } else if (Root != 0) {
+ // 3.2. An absolute path has been found while climbing the tree.
+ // If (InputParent != 0), the raw pathname is not the root.
+ // Write the first [SegCount - InputParent] NameSegs of this
+ // absolute path.
+ // Then exit.
+ if (InputParent != 0) {
+ // Get the absolute pathname.
+ NodeName = AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node);
+ if (NodeName == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Analyze the absolute pathname.
+ Status = AmlParseNameStringInfo (
+ NodeName,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Writing the n first NameSegs.
+ // n = SegCount - InputParent
+ NameSeg = AmlGetFirstNameSeg (NodeName, Root, ParentPrefix);
+ Status = AmlStreamWrite (
+ RawAbsPathBStream,
+ (CONST UINT8*)NameSeg,
+ (SegCount - InputParent) * AML_NAME_SEG_SIZE
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ break;
+ } // (InputParent != 0)
+
+ }
+ } // while
+
+ return EFI_SUCCESS;
+}
+
+/** Add the RootChar and prefix byte to the raw AML NameString in the
+ input Stream to create a valid absolute path.
+
+ The prefix byte can be AML_DUAL_NAME_PREFIX, AML_MULTI_NAME_PREFIX
+ or nothing.
+
+ @param [in, out] AmlPathBStream The Stream initially contains a raw
+ NameString (i.e. a list of NameSegs).
+ The Stream can be empty (e.g.: for the
+ root path).
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlAddPrefix (
+ IN OUT AML_STREAM * AmlPathBStream
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NameSegCount;
+ UINT32 NameSegSize;
+
+ // At most 3 bytes are needed for: RootChar + MultiNamePrefix + SegCount.
+ CHAR8 Prefix[3];
+ UINT32 PrefixSize;
+
+ // The Stream contains concatenated NameSegs.
+ if (!IS_STREAM (AmlPathBStream) ||
+ IS_END_OF_STREAM (AmlPathBStream) ||
+ !IS_STREAM_BACKWARD (AmlPathBStream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Its size should be a multiple of AML_NAME_SEG_SIZE.
+ // AML_NAME_SEG_SIZE = 4. Check the 2 lowest bits.
+ NameSegSize = AmlStreamGetIndex (AmlPathBStream);
+ if ((NameSegSize & (AML_NAME_SEG_SIZE - 1)) != 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Each NameSeg is 4 bytes so divide the NameSegSize by 4.
+ NameSegCount = NameSegSize >> 2;
+ if (NameSegCount > MAX_UINT8) {
+ // There can be at most 255 NameSegs.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Prefix[0] = AML_ROOT_CHAR;
+
+ switch (NameSegCount) {
+ case 0:
+ {
+ // Root and parents only NameString (no NameSeg(s)) end with '\0'.
+ Prefix[1] = AML_ZERO_OP;
+ PrefixSize = 2;
+ break;
+ }
+ case 1:
+ {
+ PrefixSize = 1;
+ break;
+ }
+ case 2:
+ {
+ Prefix[1] = AML_DUAL_NAME_PREFIX;
+ PrefixSize = 2;
+ break;
+ }
+ default:
+ {
+ Prefix[1] = AML_MULTI_NAME_PREFIX;
+ Prefix[2] = (UINT8)NameSegCount;
+ PrefixSize = 3;
+ break;
+ }
+ }
+
+ // Add the RootChar + prefix (if needed) at the beginning of the pathname.
+ Status = AmlStreamWrite (AmlPathBStream, (CONST UINT8*)Prefix, PrefixSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ return Status;
+}
+
+/** Remove the prefix bytes of an AML NameString stored in a backward stream
+ to get a raw NameString.
+
+ The AML encoding for '\', '^', Dual name or multi-name prefix are
+ stripped off.
+ E.g: If the ASL path was "\AAAA.BBBB", the AML equivalent would be
+ "{RootChar}{DualNamePrefix}AAAABBBB". So resultant raw NameString
+ is "AAAABBBB".
+
+ @param [in, out] AmlPathBStream Backward stream containing an AML
+ NameString.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlRemovePrefix (
+ IN OUT AML_STREAM * AmlPathBStream
+ )
+{
+ EFI_STATUS Status;
+
+ UINT32 TotalSize;
+ UINT32 RewindSize;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if (!IS_STREAM (AmlPathBStream) ||
+ IS_END_OF_STREAM (AmlPathBStream) ||
+ !IS_STREAM_BACKWARD (AmlPathBStream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlParseNameStringInfo (
+ (CHAR8*)AmlStreamGetCurrPos (AmlPathBStream),
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ TotalSize = AmlComputeNameStringSize (Root, ParentPrefix, SegCount);
+ if (TotalSize == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Rewind the stream of all the bytes that are not SegCounts
+ // to drop the prefix.
+ RewindSize = TotalSize - (SegCount * AML_NAME_SEG_SIZE);
+ if (RewindSize != 0) {
+ Status = AmlStreamRewind (AmlPathBStream, RewindSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Build the absolute ASL pathname to Node.
+
+ BufferSize is always updated to the size of the pathname.
+
+ If:
+ - the content of BufferSize is >= to the size of the pathname AND;
+ - Buffer is not NULL.
+ then copy the pathname in the Buffer. A buffer of the size
+ MAX_ASL_NAMESTRING_SIZE is big enough to receive any ASL pathname.
+
+ @param [in] Node Node to build the absolute path to.
+ Must be a root node, or a namespace node.
+ @param [out] Buffer Buffer to write the path to.
+ If NULL, only update *BufferSize.
+ @param [in, out] BufferSize Pointer holding:
+ - At entry, the size of the Buffer;
+ - At exit, the size of the pathname.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetAslPathName (
+ IN AML_NODE_HEADER * Node,
+ OUT CHAR8 * Buffer,
+ IN OUT UINT32 * BufferSize
+ )
+{
+ EFI_STATUS Status;
+
+ // Backward stream used to build the raw AML absolute path to the node.
+ AML_STREAM RawAmlAbsPathBStream;
+ CHAR8 * RawAmlAbsPathBuffer;
+ UINT32 RawAmlAbsPathBufferSize;
+
+ CHAR8 * AmlPathName;
+ CHAR8 * AslPathName;
+ UINT32 AslPathNameSize;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE)) ||
+ (BufferSize == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AslPathName = NULL;
+
+ // Allocate a Stream to get the raw AML absolute pathname.
+ RawAmlAbsPathBufferSize = MAX_AML_NAMESTRING_SIZE;
+ RawAmlAbsPathBuffer = AllocateZeroPool (RawAmlAbsPathBufferSize);
+ if (RawAmlAbsPathBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmlStreamInit (
+ &RawAmlAbsPathBStream,
+ (UINT8*)RawAmlAbsPathBuffer,
+ RawAmlAbsPathBufferSize,
+ EAmlStreamDirectionBackward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Get the raw pathname of the Node. The raw pathname being an
+ // AML NameString without the RootChar and prefix byte.
+ // It is a list of concatenated NameSegs.
+ Status = AmlGetRawNameSpacePath (Node, 0, &RawAmlAbsPathBStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Add the RootChar and prefix byte.
+ Status = AmlAddPrefix (&RawAmlAbsPathBStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ AmlPathName = (CHAR8*)AmlStreamGetCurrPos (&RawAmlAbsPathBStream);
+
+ // Analyze the NameString.
+ Status = AmlParseNameStringInfo (
+ (CONST CHAR8*)AmlPathName,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Compute the size the ASL pathname will take.
+ AslPathNameSize = AslComputeNameStringSize (Root, ParentPrefix, SegCount);
+ if (AslPathNameSize == 0) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // Input Buffer is large enough. Copy the pathname if the Buffer is valid.
+ if ((Buffer != NULL) && (AslPathNameSize <= *BufferSize)) {
+ Status = ConvertAmlNameToAslName (AmlPathName, &AslPathName);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit_handler;
+ }
+
+ CopyMem (Buffer, AslPathName, AslPathNameSize);
+ }
+
+ *BufferSize = AslPathNameSize;
+
+exit_handler:
+ // Free allocated memory.
+ FreePool (RawAmlAbsPathBuffer);
+ if (AslPathName != NULL) {
+ FreePool (AslPathName);
+ }
+
+ return Status;
+}
+
+#if !defined (MDEPKG_NDEBUG)
+
+/** Recursively print the pathnames in the AML namespace in Node's branch.
+
+ @param [in] Node Pointer to a node.
+ @param [in] Context An empty forward stream holding a pre-allocated
+ buffer. This prevents from having to do multiple
+ allocations during the enumeration.
+ @param [in, out] Status At entry, contains the status returned by the
+ last call to this exact function during the
+ enumeration.
+ As exit, contains the returned status of the
+ call to this function.
+ Optional, can be NULL.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+AmlDbgPrintNameSpaceCallback (
+ IN AML_NODE_HEADER * Node,
+ IN VOID * Context,
+ IN OUT EFI_STATUS * Status OPTIONAL
+ )
+{
+ BOOLEAN ContinueEnum;
+ EFI_STATUS Status1;
+
+ AML_STREAM * CurrNodePathFStream;
+ CHAR8 * CurrNodePathBuffer;
+ UINT32 CurrNodePathBufferSize;
+
+ ContinueEnum = TRUE;
+ Status1 = EFI_SUCCESS;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (Context == NULL)) {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ if (!IS_AML_ROOT_NODE (Node) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE)) {
+ // Skip this node and continue enumeration.
+ goto exit_handler;
+ }
+
+ if (IS_AML_ROOT_NODE (Node)) {
+ DEBUG ((DEBUG_INFO, "\\\n"));
+ } else if (AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE)) {
+
+ CurrNodePathFStream = (AML_STREAM*)Context;
+
+ // Check the Context's content.
+ if (!IS_STREAM (CurrNodePathFStream) ||
+ IS_END_OF_STREAM (CurrNodePathFStream) ||
+ !IS_STREAM_FORWARD (CurrNodePathFStream)) {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ CurrNodePathBuffer = (CHAR8*)AmlStreamGetBuffer (CurrNodePathFStream);
+ CurrNodePathBufferSize = AmlStreamGetMaxBufferSize (CurrNodePathFStream);
+
+ Status1 = AmlGetAslPathName (
+ (AML_NODE_HEADER*)Node,
+ CurrNodePathBuffer,
+ &CurrNodePathBufferSize
+ );
+ if (EFI_ERROR (Status1)) {
+ ASSERT (0);
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a\n", CurrNodePathBuffer));
+
+ } else {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ }
+
+exit_handler:
+ if (Status != NULL) {
+ *Status = Status1;
+ }
+
+ return ContinueEnum;
+}
+
+/** Print the absolute pathnames in the AML namespace of
+ all the nodes in the tree starting from the Root node.
+
+ @param [in] RootNode Pointer to a root node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlDbgPrintNameSpace (
+ IN AML_ROOT_NODE * RootNode
+ )
+{
+ EFI_STATUS Status;
+
+ AML_STREAM CurrNodePathFStream;
+ CHAR8 * CurrNodePathBuffer;
+ UINT32 CurrNodePathBufferSize;
+
+ if (!IS_AML_ROOT_NODE (RootNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "AmlNameSpace: AML namespace:\n"));
+
+ // Allocate memory to build the absolute ASL path to each node.
+ CurrNodePathBufferSize = MAX_AML_NAMESTRING_SIZE;
+ CurrNodePathBuffer = AllocateZeroPool (CurrNodePathBufferSize);
+ if (CurrNodePathBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // An empty forward stream holding a pre-allocated buffer is used
+ // to avoid multiple allocations during the enumeration.
+ Status = AmlStreamInit (
+ &CurrNodePathFStream,
+ (UINT8*)CurrNodePathBuffer,
+ CurrNodePathBufferSize,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ AmlEnumTree (
+ (AML_NODE_HEADER*)RootNode,
+ AmlDbgPrintNameSpaceCallback,
+ (VOID*)&CurrNodePathFStream,
+ &Status
+ );
+ ASSERT_EFI_ERROR (Status);
+
+exit_handler:
+ FreePool (CurrNodePathBuffer);
+
+ return Status;
+}
+
+#endif // MDEPKG_NDEBUG
+
+/** Callback function to find the node corresponding to an absolute pathname.
+
+ For each namespace node, build its raw AML absolute path. Then compare this
+ path with the raw AML absolute path of the search node available in the
+ Context.
+
+ @param [in] Node Pointer to the node to whose pathname is being
+ tested.
+ @param [in, out] Context A pointer to AML_PATH_SEARCH_CONTEXT that has:
+ - The searched path stored in a stream;
+ - An empty stream to query the pathname of the
+ probed node;
+ - A node pointer to store the searched node
+ if found.
+ @param [in, out] Status At entry, contains the status returned by the
+ last call to this exact function during the
+ enumeration.
+ As exit, contains the returned status of the
+ call to this function.
+ Optional, can be NULL.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+AmlEnumeratePathCallback (
+ IN AML_NODE_HEADER * Node,
+ IN OUT VOID * Context,
+ IN OUT EFI_STATUS * Status OPTIONAL
+)
+{
+ BOOLEAN ContinueEnum;
+ EFI_STATUS Status1;
+
+ AML_PATH_SEARCH_CONTEXT * PathSearchContext;
+
+ AML_STREAM * SearchPathBStream;
+
+ AML_STREAM * CurrNodePathBStream;
+ UINT32 CurrNodePathSize;
+
+ ContinueEnum = TRUE;
+ Status1 = EFI_SUCCESS;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (Context == NULL)) {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ if (!AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE)) {
+ goto exit_handler;
+ }
+
+ PathSearchContext = (AML_PATH_SEARCH_CONTEXT*)Context;
+ SearchPathBStream = PathSearchContext->SearchPathBStream;
+ CurrNodePathBStream = PathSearchContext->CurrNodePathBStream;
+
+ // Check the Context's content.
+ if (!IS_STREAM (SearchPathBStream) ||
+ IS_END_OF_STREAM (SearchPathBStream) ||
+ !IS_STREAM_BACKWARD (SearchPathBStream) ||
+ !IS_STREAM (CurrNodePathBStream) ||
+ IS_END_OF_STREAM (CurrNodePathBStream) ||
+ !IS_STREAM_BACKWARD (CurrNodePathBStream)) {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ CurrNodePathSize = AmlStreamGetMaxBufferSize (CurrNodePathBStream);
+ if (CurrNodePathSize == 0) {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ // Get the raw AML absolute pathname of the current node.
+ Status1 = AmlGetRawNameSpacePath (Node, 0, CurrNodePathBStream);
+ if (EFI_ERROR (Status1)) {
+ ASSERT (0);
+ ContinueEnum = FALSE;
+ goto exit_handler;
+ }
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "AmlNameSpace: "
+ "Comparing search path with current node path.\n"
+ ));
+ DEBUG ((DEBUG_VERBOSE, "Search path:"));
+ AMLDBG_PRINT_CHARS (
+ DEBUG_VERBOSE,
+ (CHAR8*)AmlStreamGetCurrPos (SearchPathBStream),
+ AmlStreamGetIndex (SearchPathBStream)
+ );
+ DEBUG ((DEBUG_VERBOSE, "\nPath of the current node: "));
+ AMLDBG_PRINT_CHARS (
+ DEBUG_VERBOSE,
+ (CHAR8*)AmlStreamGetCurrPos (CurrNodePathBStream),
+ AmlStreamGetIndex (CurrNodePathBStream)
+ );
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+
+ // Compare the searched path and Node's path.
+ if ((AmlStreamGetIndex (CurrNodePathBStream) ==
+ AmlStreamGetIndex (SearchPathBStream)) &&
+ (CompareMem (
+ AmlStreamGetCurrPos (CurrNodePathBStream),
+ AmlStreamGetCurrPos (SearchPathBStream),
+ AmlStreamGetIndex (SearchPathBStream)) == 0)) {
+ Status1 = EFI_SUCCESS;
+ ContinueEnum = FALSE;
+ PathSearchContext->OutNode = Node;
+ } else {
+ // If the paths don't match, reset the CurrNodePathStream's content.
+ Status1 = AmlStreamReset (CurrNodePathBStream);
+ if (EFI_ERROR (Status1)) {
+ ASSERT (0);
+ ContinueEnum = FALSE;
+ }
+ }
+
+exit_handler:
+ if (Status != NULL) {
+ *Status = Status1;
+ }
+
+ return ContinueEnum;
+}
+
+/** Build a raw AML absolute path from a reference node and a relative
+ ASL path.
+
+ The AslPath can be a relative path or an absolute path.
+ Node must be a root node or a namespace node.
+ A root node is expected to be at the top of the tree.
+
+ @param [in] ReferenceNode Reference node.
+ If a relative path is given, the
+ search is done from this node. If
+ an absolute path is given, the
+ search is done from the root node.
+ Must be a root node or an object
+ node which is part of the
+ namespace.
+ @param [in] AslPath ASL path to the searched node in
+ the namespace. An ASL path name is
+ NULL terminated. Can be a relative
+ or absolute path.
+ E.g.: "\\_SB.CLU0.CPU0".
+ @param [in, out] RawAmlAbsSearchPathBStream Backward stream to write the
+ raw absolute AML path of the
+ searched node.
+ The stream must not be at
+ its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlBuildAbsoluteAmlPath (
+ IN AML_NODE_HEADER * ReferenceNode,
+ IN CHAR8 * AslPath,
+ IN OUT AML_STREAM * RawAmlAbsSearchPathBStream
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 * AmlPath;
+
+ UINT32 AmlNameStringSize;
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if ((!IS_AML_ROOT_NODE (ReferenceNode) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)ReferenceNode,
+ AML_IN_NAMESPACE)) ||
+ (AslPath == NULL) ||
+ !IS_STREAM (RawAmlAbsSearchPathBStream) ||
+ IS_END_OF_STREAM (RawAmlAbsSearchPathBStream) ||
+ !IS_STREAM_BACKWARD (RawAmlAbsSearchPathBStream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // 1. Validate, analyze and convert the AslPath to an AmlPath.
+ Status = ConvertAslNameToAmlName (AslPath, &AmlPath);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlParseNameStringInfo (AmlPath, &Root, &ParentPrefix, &SegCount);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Not possible to go beyond the root.
+ if (IS_AML_ROOT_NODE (ReferenceNode) && (ParentPrefix != 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ AmlNameStringSize = AmlComputeNameStringSize (Root, ParentPrefix, SegCount);
+ if (AmlNameStringSize == 0) {
+ Status = EFI_INVALID_PARAMETER;
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // 2.1. Write the AML path to the stream.
+ Status = AmlStreamWrite (
+ RawAmlAbsSearchPathBStream,
+ (CONST UINT8*)AmlPath,
+ AmlNameStringSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // 2.2. Then remove the AML prefix (root char, parent prefix, etc.)
+ // to obtain a raw AML NameString. Raw AML NameString are easier
+ // to manipulate.
+ Status = AmlRemovePrefix (RawAmlAbsSearchPathBStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // 3. If AslPath is a relative path and the reference Node is not
+ // the root node, fill the Stream with the absolute path to the
+ // reference node.
+ if ((Root == 0) && !IS_AML_ROOT_NODE (ReferenceNode)) {
+ Status = AmlGetRawNameSpacePath (
+ ReferenceNode,
+ ParentPrefix,
+ RawAmlAbsSearchPathBStream
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ }
+
+exit_handler:
+ // Free allocated memory.
+ FreePool (AmlPath);
+
+ return Status;
+}
+
+/** Find a node in the AML namespace, given an ASL path and a reference Node.
+
+ - The AslPath can be an absolute path, or a relative path from the
+ reference Node;
+ - Node must be a root node or a namespace node;
+ - A root node is expected to be at the top of the tree.
+
+ E.g.:
+ For the following AML namespace, with the ReferenceNode being the node with
+ the name "AAAA":
+ - the node with the name "BBBB" can be found by looking for the ASL
+ path "BBBB";
+ - the root node can be found by looking for the ASL relative path "^",
+ or the absolute path "\\".
+
+ AML namespace:
+ \
+ \-AAAA <- ReferenceNode
+ \-BBBB
+
+ @param [in] ReferenceNode Reference node.
+ If a relative path is given, the
+ search is done from this node. If
+ an absolute path is given, the
+ search is done from the root node.
+ Must be a root node or an object
+ node which is part of the
+ namespace.
+ @param [in] AslPath ASL path to the searched node in
+ the namespace. An ASL path name is
+ NULL terminated. Can be a relative
+ or absolute path.
+ E.g.: "\\_SB.CLU0.CPU0" or "^CPU0"
+ @param [out] OutNode Pointer to the found node.
+ Contains NULL if not found.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlFindNode (
+ IN AML_NODE_HEADER * ReferenceNode,
+ IN CHAR8 * AslPath,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+
+ AML_PATH_SEARCH_CONTEXT PathSearchContext;
+ AML_ROOT_NODE * RootNode;
+
+ // Backward stream used to build the raw AML absolute path to the searched
+ // node.
+ AML_STREAM RawAmlAbsSearchPathBStream;
+ CHAR8 * RawAmlAbsSearchPathBuffer;
+ UINT32 RawAmlAbsSearchPathBufferSize;
+
+ // Backward stream used to store the raw AML absolute path of the node
+ // currently enumerated in the tree. This path can then be compared to the
+ // RawAmlAbsSearchPath.
+ AML_STREAM RawAmlAbsCurrNodePathBStream;
+ CHAR8 * RawAmlAbsCurrNodePathBuffer;
+ UINT32 RawAmlAbsCurrNodePathBufferSize;
+
+ if ((!IS_AML_ROOT_NODE (ReferenceNode) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)ReferenceNode,
+ AML_IN_NAMESPACE)) ||
+ (AslPath == NULL) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutNode = NULL;
+ RawAmlAbsCurrNodePathBuffer = NULL;
+
+ // 1. Build a raw absolute AML path from the reference node and the ASL
+ // path. For this:
+ // 1.1. First initialize a backward stream.
+ RawAmlAbsSearchPathBufferSize = MAX_AML_NAMESTRING_SIZE;
+ RawAmlAbsSearchPathBuffer = AllocateZeroPool (RawAmlAbsSearchPathBufferSize);
+ if (RawAmlAbsSearchPathBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmlStreamInit (
+ &RawAmlAbsSearchPathBStream,
+ (UINT8*)RawAmlAbsSearchPathBuffer,
+ RawAmlAbsSearchPathBufferSize,
+ EAmlStreamDirectionBackward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // 1.2. Then build the raw AML absolute path.
+ Status = AmlBuildAbsoluteAmlPath (
+ ReferenceNode,
+ AslPath,
+ &RawAmlAbsSearchPathBStream
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // 2. Find the root node by climbing up the tree from the reference node.
+ RootNode = AmlGetRootNode (ReferenceNode);
+ if (RootNode == NULL) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // 3. If the searched node is the root node, return.
+ // For the Root Node there is no NameSegs so the length of
+ // the stream will be zero.
+ if (AmlStreamGetIndex (&RawAmlAbsSearchPathBStream) == 0) {
+ *OutNode = (AML_NODE_HEADER*)RootNode;
+ Status = EFI_SUCCESS;
+ goto exit_handler;
+ }
+
+ // 4. Create a backward stream large enough to hold the current node path
+ // during enumeration. This prevents from doing multiple allocation/free
+ // operations.
+ RawAmlAbsCurrNodePathBufferSize = MAX_ASL_NAMESTRING_SIZE;
+ RawAmlAbsCurrNodePathBuffer = AllocateZeroPool (
+ RawAmlAbsCurrNodePathBufferSize
+ );
+ if (RawAmlAbsCurrNodePathBuffer == NULL) {
+ ASSERT (0);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto exit_handler;
+ }
+
+ Status = AmlStreamInit (
+ &RawAmlAbsCurrNodePathBStream,
+ (UINT8*)RawAmlAbsCurrNodePathBuffer,
+ RawAmlAbsCurrNodePathBufferSize,
+ EAmlStreamDirectionBackward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // 5. Fill a path search context structure with:
+ // - SearchPathStream: backward stream containing the raw absolute AML
+ // path to the searched node;
+ // - CurrNodePathStream: backward stream containing the raw absolute AML
+ // of the node currently being enumerated;
+ // - OutNode: node pointer to the store the potentially found node.
+ PathSearchContext.SearchPathBStream = &RawAmlAbsSearchPathBStream;
+ PathSearchContext.CurrNodePathBStream = &RawAmlAbsCurrNodePathBStream;
+ PathSearchContext.OutNode = NULL;
+
+ // 6. Iterate through the namespace nodes of the tree.
+ // For each namespace node, build its raw AML absolute path. Then compare
+ // it with the search path.
+ AmlEnumTree (
+ (AML_NODE_HEADER*)RootNode,
+ AmlEnumeratePathCallback,
+ (VOID*)&PathSearchContext,
+ &Status
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ *OutNode = PathSearchContext.OutNode;
+ if (*OutNode == NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+
+exit_handler:
+ // Free allocated memory.
+ FreePool (RawAmlAbsSearchPathBuffer);
+ if (RawAmlAbsCurrNodePathBuffer != NULL) {
+ FreePool (RawAmlAbsCurrNodePathBuffer);
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h
new file mode 100644
index 00000000000..1148cf02bd8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/NameSpace/AmlNameSpace.h
@@ -0,0 +1,74 @@
+/** @file
+ AML NameSpace.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_NAMESPACE_H_
+#define AML_NAMESPACE_H_
+
+#include <AmlNodeDefines.h>
+#include <Stream/AmlStream.h>
+
+/** Return the first AML namespace node up in the parent hierarchy.
+
+ Return the root node if no namespace node is found is the hierarchy.
+
+ @param [in] Node Node to look at the parents from.
+ If Node is the root node, OutNode is NULL.
+ @param [out] OutNode If a namespace node is found, pointer to the
+ first namespace node of Node's parents.
+ Stop at the root node otherwise.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ **/
+EFI_STATUS
+EFIAPI
+AmlGetFirstAncestorNameSpaceNode (
+ IN CONST AML_NODE_HEADER * Node,
+ OUT AML_NODE_HEADER ** OutNode
+ );
+
+/** Build the raw absolute AML pathname to Node and write it to a stream.
+
+ A raw AML pathname is an AML pathname where the root char ('\'),
+ prefix chars ('^') and NameString prefix byte (e.g.: DualNamePrefix)
+ have been removed. A raw AML pathname is a list of concatenated
+ NameSegs.
+
+ E.g.:
+ ASL absolute path: "[RootChar]AAAA.BBBB.CCCC\0"
+ AML absolute path: "[RootChar][MultiNamePrefix][3(NameSegs)]AAAABBBBCCCC"
+ Raw absolute path: "AAAABBBBCCCC"
+
+ @param [in] Node Node to build the raw absolute path to
+ Must be a root node, or a namespace node.
+ @param [in] InputParent Skip InputParent AML namespace levels before
+ starting building the raw absolute pathname.
+ E.g.: - Node's name being "^AAAA.BBBB.CCCC";
+ - InputParent = 2;
+ "BBBB.CCCC" will be skipped (2
+ levels), and "^AAAA" will remain. The
+ first caret is not related to InputParent.
+ @param [out] RawAbsPathBStream Backward stream to write the raw
+ pathname to.
+ If Node is the root node, the Stream data
+ Buffer will stay empty.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetRawNameSpacePath (
+ IN CONST AML_NODE_HEADER * Node,
+ IN UINT32 InputParent,
+ OUT AML_STREAM * RawAbsPathBStream
+ );
+
+#endif // AML_NAMESPACE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c
new file mode 100644
index 00000000000..3b1bde995b2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.c
@@ -0,0 +1,375 @@
+/** @file
+ AML Field List Parser.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Parser/AmlFieldListParser.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlDbgPrint/AmlDbgPrint.h>
+#include <Parser/AmlMethodParser.h>
+#include <Parser/AmlParser.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+
+/** Parse a field element.
+
+ The field elements this function can parse are one of:
+ - ReservedField;
+ - AccessField;
+ - ConnectField;
+ - ExtendedAccessField.
+ Indeed, the NamedField field element doesn't have an OpCode. Thus it needs
+ to be parsed differently.
+
+ @param [in] FieldByteEncoding Field byte encoding to parse.
+ @param [in, out] FieldNode Field node to attach the field
+ element to.
+ Must have the AML_HAS_FIELD_LIST
+ attribute.
+ @param [in, out] FStream Forward stream pointing to a field
+ element not being a named field.
+ The stream must not be at its end.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes,
+ allowing to associate an absolute
+ path to a node in the tree.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseFieldElement (
+ IN CONST AML_BYTE_ENCODING * FieldByteEncoding,
+ IN OUT AML_OBJECT_NODE * FieldNode,
+ IN OUT AML_STREAM * FStream,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ UINT8 * CurrPos;
+ AML_OBJECT_NODE * NewNode;
+
+ UINT32 PkgLenOffset;
+ UINT32 PkgLenSize;
+
+ // Check whether the node is an Object Node and has a field list.
+ // The byte encoding must be a field element.
+ if ((FieldByteEncoding == NULL) ||
+ ((FieldByteEncoding->Attribute & AML_IS_FIELD_ELEMENT) == 0) ||
+ ((FieldByteEncoding->Attribute & AML_IS_PSEUDO_OPCODE) ==
+ AML_IS_PSEUDO_OPCODE) ||
+ !AmlNodeHasAttribute (FieldNode, AML_HAS_FIELD_LIST) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrPos = AmlStreamGetCurrPos (FStream);
+ if (CurrPos == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Skip the field opcode (1 byte) as it is already in the FieldByteEncoding.
+ AMLDBG_DUMP_RAW (CurrPos, 1);
+ Status = AmlStreamProgress (FStream, 1);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ CurrPos = AmlStreamGetCurrPos (FStream);
+ if (CurrPos == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Parse the PkgLen if available.
+ PkgLenSize = 0;
+ if ((FieldByteEncoding->Attribute & AML_HAS_PKG_LENGTH) ==
+ AML_HAS_PKG_LENGTH) {
+ PkgLenOffset = AmlGetPkgLength (CurrPos, &PkgLenSize);
+ if (PkgLenOffset == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Move stream forward as the PkgLen has been read.
+ AMLDBG_DUMP_RAW (CurrPos, PkgLenOffset);
+ Status = AmlStreamProgress (FStream, PkgLenOffset);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Update the current position as PkgLen has been parsed.
+ CurrPos = AmlStreamGetCurrPos (FStream);
+ }
+
+ Status = AmlCreateObjectNode (
+ FieldByteEncoding,
+ PkgLenSize,
+ &NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the FieldElement to the Variable Argument List.
+ Status = AmlVarListAddTailInternal (
+ (AML_NODE_HEADER*)FieldNode,
+ (AML_NODE_HEADER*)NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ // Delete the sub-tree if the insertion failed.
+ // Otherwise its reference will be lost.
+ AmlDeleteTree ((AML_NODE_HEADER*)NewNode);
+ return Status;
+ }
+
+ // Some field elements do not have fixed arguments.
+ if (!IS_END_OF_STREAM (FStream)) {
+ // Parse the fixed arguments of the field element.
+ Status = AmlParseFixedArguments (
+ NewNode,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ }
+
+ return Status;
+}
+
+/** Parse a named field element.
+
+ Indeed, the NamedField field element doesn't have an OpCode. Thus it needs
+ to be parsed differently. NamedField field element start with a char.
+
+ @param [in] NamedFieldByteEncoding Field byte encoding to parse.
+ @param [in, out] FieldNode Field node to attach the field
+ element to.
+ Must have the AML_HAS_FIELD_LIST
+ attribute.
+ @param [in, out] FStream Forward stream pointing to a named
+ field element.
+ The stream must not be at its end.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes,
+ allowing to associate an absolute
+ path to a node in the tree.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseNamedFieldElement (
+ IN CONST AML_BYTE_ENCODING * NamedFieldByteEncoding,
+ IN OUT AML_OBJECT_NODE * FieldNode,
+ IN OUT AML_STREAM * FStream,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+)
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * NewNode;
+
+ // Check whether the node is an Object Node and has a field list.
+ // The byte encoding must be a char.
+ if ((NamedFieldByteEncoding == NULL) ||
+ ((NamedFieldByteEncoding->Attribute & AML_IS_NAME_CHAR) == 0) ||
+ !AmlNodeHasAttribute (FieldNode, AML_HAS_FIELD_LIST) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Create a NamedField node.
+ Status = AmlCreateObjectNode (
+ AmlGetFieldEncodingByOpCode (AML_FIELD_NAMED_OP, 0),
+ 0,
+ &NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the NamedField node to the variable argument list.
+ Status = AmlVarListAddTailInternal (
+ (AML_NODE_HEADER*)FieldNode,
+ (AML_NODE_HEADER*)NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ // Delete the sub-tree if the insertion failed.
+ // Otherwise its reference will be lost.
+ AmlDeleteTree ((AML_NODE_HEADER*)NewNode);
+ return Status;
+ }
+
+ // Parse the fixed arguments: [0]NameSeg, [1]PkgLen.
+ Status = AmlParseFixedArguments (
+ NewNode,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the NamedField to the namespace reference list.
+ Status = AmlAddNameSpaceReference (
+ NewNode,
+ NameSpaceRefList
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Parse the FieldList contained in the stream.
+
+ Create an object node for each field element parsed in the field list
+ available in the Stream, and add them to the variable list of arguments
+ of the FieldNode.
+
+ Nodes that can have a field list are referred as field nodes. They have the
+ AML_HAS_FIELD_LIST attribute.
+
+ According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encoding",
+ field elements can be:
+ - NamedField := NameSeg PkgLength;
+ - ReservedField := 0x00 PkgLength;
+ - AccessField := 0x01 AccessType AccessAttrib;
+ - ConnectField := <0x02 NameString> | <0x02 BufferData>;
+ - ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength.
+
+ A small set of opcodes describes the field elements. They are referred as
+ field opcodes. An AML_BYTE_ENCODING table has been created for field OpCodes.
+ Field elements:
+ - don't have a SubOpCode;
+ - have at most 3 fixed arguments (as opposed to 6 for standard AML objects);
+ - don't have a variable list of arguments;
+ - only the NamedField field element is part of the AML namespace.
+
+ ConnectField's BufferData is a buffer node containing a single
+ resource data element.
+ NamedField field elements don't have an AML OpCode. NameSeg starts with a
+ Char type and can thus be differentiated from the Opcodes for other fields.
+ A pseudo OpCode has been created to simplify the parser.
+
+ The branch created from parsing a field node is as:
+ (FieldNode)
+ \
+ |- [FixedArg[0]][FixedArg[1]] # Fixed Arguments
+ |- {(FieldElement[0])->(FieldElement[1])->...)} # Variable Arguments
+
+ With FieldElement[n] being one of NamedField, ReservedField, AccessField,
+ ConnectField, ExtendedAccessField.
+
+ @param [in] FieldNode Field node.
+ Must have the AML_HAS_FIELD_LIST
+ attribute.
+ @param [in] FStream Forward stream pointing to a field list.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes,
+ allowing to associate an absolute
+ path to a node in the tree.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseFieldList (
+ IN AML_OBJECT_NODE * FieldNode,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ UINT8 * CurrPos;
+ CONST AML_BYTE_ENCODING * FieldByteEncoding;
+ CONST AML_BYTE_ENCODING * NamedFieldByteEncoding;
+
+ // Check whether the node is an Object Node and has a field list.
+ if (!AmlNodeHasAttribute (FieldNode, AML_HAS_FIELD_LIST) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Iterate through the field elements, creating nodes
+ // and adding them to the variable list of elements of Node.
+ while (!IS_END_OF_STREAM (FStream)) {
+ CurrPos = AmlStreamGetCurrPos (FStream);
+
+ // Check for a field opcode.
+ FieldByteEncoding = AmlGetFieldEncoding (CurrPos);
+ if (FieldByteEncoding != NULL) {
+ Status = AmlParseFieldElement (
+ FieldByteEncoding,
+ FieldNode,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } else {
+ // Handle the case of Pseudo OpCodes.
+ // NamedField has a Pseudo OpCode and starts with a NameChar. Therefore,
+ // call AmlGetByteEncoding() to check that the encoding is NameChar.
+ NamedFieldByteEncoding = AmlGetByteEncoding (CurrPos);
+ if ((NamedFieldByteEncoding != NULL) &&
+ (NamedFieldByteEncoding->Attribute & AML_IS_NAME_CHAR)) {
+ // This is a NamedField field element since it is starting with a char.
+ Status = AmlParseNamedFieldElement (
+ NamedFieldByteEncoding,
+ FieldNode,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } else {
+ // A field opcode or an AML byte encoding is expected.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ } // while
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h
new file mode 100644
index 00000000000..ddd196b59c2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlFieldListParser.h
@@ -0,0 +1,77 @@
+/** @file
+ AML Field List.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_FIELD_LIST_PARSER_H_
+#define AML_FIELD_LIST_PARSER_H_
+
+#include <AmlNodeDefines.h>
+#include <Stream/AmlStream.h>
+
+/** Parse the FieldList contained in the stream.
+
+ Create an object node for each field element parsed in the field list
+ available in the Stream, and add them to the variable list of arguments
+ of the FieldNode.
+
+ Nodes that can have a field list are referred as field nodes. They have the
+ AML_HAS_FIELD_LIST attribute.
+
+ According to the ACPI 6.3 specification, s20.2.5.2 "Named Objects Encoding",
+ field elements can be:
+ - NamedField := NameSeg PkgLength;
+ - ReservedField := 0x00 PkgLength;
+ - AccessField := 0x01 AccessType AccessAttrib;
+ - ConnectField := <0x02 NameString> | <0x02 BufferData>;
+ - ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib AccessLength.
+
+ A small set of opcodes describes the field elements. They are referred as
+ field opcodes. An AML_BYTE_ENCODING table has been created for field OpCodes.
+ Field elements:
+ - don't have a SubOpCode;
+ - have at most 3 fixed arguments (as opposed to 6 for standard AML objects);
+ - don't have a variable list of arguments;
+ - only the NamedField field element is part of the AML namespace.
+
+ ConnectField's BufferData is a buffer node containing a single
+ resource data element.
+ NamedField field elements don't have an AML OpCode. NameSeg starts with a
+ Char type and can thus be differentiated from the Opcodes for other fields.
+ A pseudo OpCode has been created to simplify the parser.
+
+ The branch created from parsing a field node is as:
+ (FieldNode)
+ \
+ |- [FixedArg[0]][FixedArg[1]] # Fixed Arguments
+ |- {(FieldElement[0])->(FieldElement[1])->...)} # Variable Arguments
+
+ With FieldElement[n] being one of NamedField, ReservedField, AccessField,
+ ConnectField, ExtendedAccessField.
+
+ @param [in] FieldNode Field node.
+ Must have the AML_HAS_FIELD_LIST
+ attribute.
+ @param [in] FStream Forward stream pointing to a field list.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes,
+ allowing to associate an absolute
+ path to a node in the tree.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseFieldList (
+ IN AML_OBJECT_NODE * FieldNode,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ );
+
+#endif // AML_FIELD_LIST_PARSER_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c
new file mode 100644
index 00000000000..28fe51b292a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.c
@@ -0,0 +1,1458 @@
+/** @file
+ AML Method Parser.
+
+ Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Parser/AmlMethodParser.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlDbgPrint/AmlDbgPrint.h>
+#include <NameSpace/AmlNameSpace.h>
+#include <Parser/AmlParser.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+#include <String/AmlString.h>
+
+/** Delete a namespace reference node and its pathname.
+
+ It is the caller's responsibility to check the NameSpaceRefNode has been
+ removed from any list the node is part of.
+
+ @param [in] NameSpaceRefNode Pointer to an AML_NAMESPACE_REF_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlDeleteNameSpaceRefNode (
+ IN AML_NAMESPACE_REF_NODE * NameSpaceRefNode
+ )
+{
+ if (NameSpaceRefNode == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (NameSpaceRefNode->RawAbsolutePath != NULL) {
+ FreePool ((CHAR8*)NameSpaceRefNode->RawAbsolutePath);
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (NameSpaceRefNode);
+ return EFI_SUCCESS;
+}
+
+/** Delete a list of namespace reference nodes.
+
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteNameSpaceRefList (
+ IN LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY * CurrentLink;
+
+ if (NameSpaceRefList == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ while (!IsListEmpty (NameSpaceRefList)) {
+ CurrentLink = NameSpaceRefList->ForwardLink;
+ RemoveEntryList (CurrentLink);
+ Status = AmlDeleteNameSpaceRefNode (
+ (AML_NAMESPACE_REF_NODE*)CurrentLink
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // while
+
+ return EFI_SUCCESS;
+}
+
+/** Create an AML_NAMESPACE_REF_NODE.
+
+ A Buffer is allocated to store the raw AML absolute path.
+
+ @param [in] ObjectNode Node being part of the namespace.
+ Must be have the AML_IN_NAMESPACE
+ attribute.
+ @param [in] RawAbsolutePath AML raw absolute path of the ObjectNode.
+ A raw NameString is a concatenated list
+ of 4 chars long names.
+ @param [in] RawAbsolutePathSize Size of the RawAbsolutePath buffer.
+ @param [out] NameSpaceRefNodePtr The created AML_METHOD_REF_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCreateMethodRefNode (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ IN CONST CHAR8 * RawAbsolutePath,
+ IN UINT32 RawAbsolutePathSize,
+ OUT AML_NAMESPACE_REF_NODE ** NameSpaceRefNodePtr
+ )
+{
+ AML_NAMESPACE_REF_NODE * NameSpaceRefNode;
+
+ if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE) ||
+ (RawAbsolutePath == NULL) ||
+ (RawAbsolutePathSize == 0) ||
+ (NameSpaceRefNodePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NameSpaceRefNode = AllocateZeroPool (sizeof (AML_NAMESPACE_REF_NODE));
+ if (NameSpaceRefNode == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NameSpaceRefNode->RawAbsolutePathSize = RawAbsolutePathSize;
+ NameSpaceRefNode->RawAbsolutePath = AllocateCopyPool (
+ RawAbsolutePathSize,
+ RawAbsolutePath
+ );
+ if (NameSpaceRefNode->RawAbsolutePath == NULL) {
+ FreePool (NameSpaceRefNode);
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeListHead (&NameSpaceRefNode->Link);
+
+ NameSpaceRefNode->NodeRef = ObjectNode;
+ *NameSpaceRefNodePtr = NameSpaceRefNode;
+
+ return EFI_SUCCESS;
+}
+
+#if !defined (MDEPKG_NDEBUG)
+
+/** Print the list of raw absolute paths of the NameSpace reference list.
+
+ @param [in] NameSpaceRefList List of NameSpace reference nodes.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNameSpaceRefList (
+ IN CONST LIST_ENTRY * NameSpaceRefList
+ )
+{
+ LIST_ENTRY * CurrLink;
+ AML_NAMESPACE_REF_NODE * CurrNameSpaceNode;
+
+ if (NameSpaceRefList == NULL) {
+ ASSERT (0);
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO, "AmlMethodParser: List of available raw AML paths:\n"));
+
+ CurrLink = NameSpaceRefList->ForwardLink;
+ while (CurrLink != NameSpaceRefList) {
+ CurrNameSpaceNode = (AML_NAMESPACE_REF_NODE*)CurrLink;
+
+ AMLDBG_PRINT_CHARS (
+ DEBUG_INFO,
+ CurrNameSpaceNode->RawAbsolutePath,
+ CurrNameSpaceNode->RawAbsolutePathSize
+ );
+ DEBUG ((DEBUG_INFO, "\n"));
+
+ CurrLink = CurrLink->ForwardLink;
+ }
+
+ DEBUG ((DEBUG_INFO, "\n"));
+}
+
+#endif // MDEPKG_NDEBUG
+
+/** From a forward stream pointing to a NameString,
+ initialize a raw backward stream.
+
+ StartOfStream
+ Fstream: CurrPos EndOfStream
+ v v
+ +-----------------------------------------+
+ |^^^[Multi-name prefix]AAAA.BBBB.CCCC |
+ +-----------------------------------------+
+ ^ ^
+ RawPathNameBStream: EndOfStream CurrPos
+ StartOfStream
+
+ No memory is allocated when initializing the stream.
+
+ @param [in] FStream Forward stream pointing to a NameString.
+ The stream must not be at its end.
+ @param [out] RawPathNameBStream Backward stream containing the
+ raw AML path.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlInitRawPathBStream (
+ IN CONST AML_STREAM * FStream,
+ OUT AML_STREAM * RawPathNameBStream
+ )
+{
+ EFI_STATUS Status;
+
+ UINT8 * RawPathBuffer;
+ CONST CHAR8 * Buffer;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if (!IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (RawPathNameBStream == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (CONST CHAR8*)AmlStreamGetCurrPos (FStream);
+ if (Buffer == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Parse the NameString information.
+ Status = AmlParseNameStringInfo (
+ Buffer,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the beginning of the raw NameString.
+ RawPathBuffer = (UINT8*)AmlGetFirstNameSeg (
+ Buffer,
+ Root,
+ ParentPrefix
+ );
+ if (RawPathBuffer == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Initialize a backward stream containing the raw path.
+ Status = AmlStreamInit (
+ RawPathNameBStream,
+ RawPathBuffer,
+ (SegCount * AML_NAME_SEG_SIZE),
+ EAmlStreamDirectionBackward
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Get the first node in the ParentNode branch that is part of the
+ AML namespace and has its name defined.
+
+ This is different from getting the first namespace node. This function is
+ necessary because an absolute path is built while the tree is not complete
+ yet. The parsing is ongoing.
+
+ For instance, the ASL statement "CreateXXXField ()" adds a field in the
+ AML namespace, but the name it defines is the last fixed argument of the
+ corresponding object.
+ If an AML path is referenced in its first fixed argument, it is not
+ possible to resolve the name of the CreateXXXField object. However, the AML
+ path is not part of the scope created by the CreateXXXField object, so this
+ scope can be skipped.
+
+ In the following ASL code, the method invocation to MET0 is done in the
+ "CreateField" statement. The "CreateField" statement defines the "FIEL"
+ path in the AML namespace. However, MET0 must be not be resolved in the
+ "CreateField" object scope. It needs to be resolved in its parent.
+ ASL code:
+ Method (MET0, 0,,, BuffObj) {
+ Return (Buffer (0x1000) {})
+ }
+ CreateField (MET0(), 0x100, 0x4, FIEL)
+
+ @param [in] Node Node to get the first named node from, in
+ its hierarchy.
+ @param [out] OutNamedNode First named node in Node's hierarchy.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlGetFirstNamedAncestorNode (
+ IN CONST AML_NODE_HEADER * Node,
+ OUT AML_NODE_HEADER ** OutNamedNode
+ )
+{
+ EFI_STATUS Status;
+ CONST AML_NODE_HEADER * NameSpaceNode;
+
+ if ((!IS_AML_OBJECT_NODE (Node) &&
+ !IS_AML_ROOT_NODE (Node)) ||
+ (OutNamedNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // If Node is not the root node and doesn't have a name defined yet,
+ // get the ancestor NameSpace node.
+ while (!IS_AML_ROOT_NODE (Node) &&
+ !(AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IN_NAMESPACE) &&
+ AmlNodeGetName ((CONST AML_OBJECT_NODE*)Node) != NULL)) {
+ Status = AmlGetFirstAncestorNameSpaceNode (
+ Node,
+ (AML_NODE_HEADER**)&NameSpaceNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ // The NameSpaceNode may not have its name defined as yet. In this
+ // case get the next ancestor node.
+ Node = NameSpaceNode;
+ }
+
+ *OutNamedNode = (AML_NODE_HEADER*)Node;
+
+ return EFI_SUCCESS;
+}
+
+/** From a ParentNode and a forward stream pointing to a relative path,
+ build a raw AML absolute path and return it in a backward stream.
+
+ No memory is allocated in this function, the out stream must be initialized
+ with a buffer long enough to hold any raw absolute AML path.
+
+ @param [in] ParentNode Parent node of the namespace
+ node from which the absolute
+ path is built. ParentNode isn't
+ necessarily a namespace node.
+ Must be a root or an object node.
+ @param [in] PathnameFStream Forward stream pointing to the
+ beginning of a pathname (any
+ NameString).
+ The stream must not be at its end.
+ @param [in, out] AbsolutePathBStream Backward stream where the raw
+ absolute path is written. The
+ stream must be already initialized.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlBuildRawMethodAbsolutePath (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN CONST AML_STREAM * PathnameFStream,
+ IN OUT AML_STREAM * AbsolutePathBStream
+ )
+{
+ EFI_STATUS Status;
+
+ AML_NODE_HEADER * NamedParentNode;
+ UINT8 * RawPathBuffer;
+ CONST CHAR8 * CurrPos;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if ((!IS_AML_OBJECT_NODE (ParentNode) &&
+ !IS_AML_ROOT_NODE (ParentNode)) ||
+ !IS_STREAM (PathnameFStream) ||
+ IS_END_OF_STREAM (PathnameFStream) ||
+ !IS_STREAM_FORWARD (PathnameFStream) ||
+ !IS_STREAM (AbsolutePathBStream) ||
+ IS_END_OF_STREAM (AbsolutePathBStream) ||
+ !IS_STREAM_BACKWARD (AbsolutePathBStream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurrPos = (CONST CHAR8*)AmlStreamGetCurrPos (PathnameFStream);
+ if (CurrPos == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Parse the NameString information.
+ Status = AmlParseNameStringInfo (
+ CurrPos,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Copy the method invocation raw relative path at the end of the Stream.
+ if (SegCount != 0) {
+ // Get the beginning of the raw NameString.
+ RawPathBuffer = (UINT8*)AmlGetFirstNameSeg (
+ CurrPos,
+ Root,
+ ParentPrefix
+ );
+
+ Status = AmlStreamWrite (
+ AbsolutePathBStream,
+ RawPathBuffer,
+ SegCount * AML_NAME_SEG_SIZE
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ // If the pathname contained an absolute path, this is finished, return.
+ if (Root) {
+ return Status;
+ }
+
+ // Get the first named node of the parent node in its hierarchy.
+ Status = AmlGetFirstNamedAncestorNode (ParentNode, &NamedParentNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Build the raw absolute path of the namespace node.
+ Status = AmlGetRawNameSpacePath (
+ NamedParentNode,
+ ParentPrefix,
+ AbsolutePathBStream
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Compare two raw NameStrings stored in forward streams.
+ Compare them NameSeg by NameSeg (a NameSeg is 4 bytes long).
+
+ The two raw NameStrings can be of different size.
+
+ @param [in] RawFStream1 First forward stream to compare.
+ Points to the beginning of the raw NameString.
+ @param [in] RawFStream2 Second forward stream to compare.
+ Points to the beginning of the raw NameString.
+ @param [out] CompareCount Count of identic bytes.
+ Must be a multiple of 4 (size of a NameSeg).
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCompareRawNameString (
+ IN CONST AML_STREAM * RawFStream1,
+ IN CONST AML_STREAM * RawFStream2,
+ OUT UINT32 * CompareCount
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Index;
+
+ AML_STREAM RawFStream1Clone;
+ AML_STREAM RawFStream2Clone;
+ UINT32 Stream1Size;
+ UINT32 Stream2Size;
+ UINT32 CompareLen;
+
+ // Raw NameStrings have a size that is a multiple of the size of NameSegs.
+ if (!IS_STREAM (RawFStream1) ||
+ IS_END_OF_STREAM (RawFStream1) ||
+ !IS_STREAM_FORWARD (RawFStream1) ||
+ !IS_STREAM (RawFStream2) ||
+ IS_END_OF_STREAM (RawFStream2) ||
+ (CompareCount == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Stream1Size = AmlStreamGetFreeSpace (RawFStream1);
+ if ((Stream1Size & (AML_NAME_SEG_SIZE - 1)) != 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Stream2Size = AmlStreamGetFreeSpace (RawFStream2);
+ if ((Stream2Size & (AML_NAME_SEG_SIZE - 1)) != 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlStreamClone (RawFStream1, &RawFStream1Clone);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlStreamClone (RawFStream2, &RawFStream2Clone);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ CompareLen = MIN (Stream1Size, Stream2Size);
+ Index = 0;
+ // Check there is enough space for a NameSeg in both Stream1 and Stream2.
+ while (Index < CompareLen) {
+ if (!AmlStreamCmp (
+ &RawFStream1Clone,
+ &RawFStream2Clone,
+ AML_NAME_SEG_SIZE)
+ ) {
+ // NameSegs are different. Break.
+ break;
+ }
+
+ Status = AmlStreamProgress (&RawFStream1Clone, AML_NAME_SEG_SIZE);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ Status = AmlStreamProgress (&RawFStream2Clone, AML_NAME_SEG_SIZE);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Index += AML_NAME_SEG_SIZE;
+ }
+
+ *CompareCount = Index;
+
+ return EFI_SUCCESS;
+}
+
+/** Check whether an alias can be resolved to a method definition.
+
+ Indeed, the following ASL code must be handled:
+ Method (MET0, 1) {
+ Return (0x9)
+ }
+ Alias (\MET0, \ALI0)
+ Alias (\ALI0, \ALI1)
+ \ALI1(0x5)
+ When searching for \ALI1 in the AML NameSpace, it resolves to \ALI0.
+ When searching for \ALI0 in the AML NameSpace, it resolves to \MET0.
+ When searching for \MET0 in the AML NameSpace, it resolves to a method
+ definition.
+
+ This method is a wrapper to recursively call AmlFindMethodDefinition.
+
+ @param [in] AliasNode Pointer to an Alias object node.
+ @param [in] NameSpaceRefList List of NameSpaceRef nodes.
+ @param [out] OutNameSpaceRefNode If success, and if the alias is resolved
+ to a method definition (this can go
+ through other alias indirections),
+ containing the corresponding
+ NameSpaceRef node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlResolveAliasMethod (
+ IN CONST AML_OBJECT_NODE * AliasNode,
+ IN CONST LIST_ENTRY * NameSpaceRefList,
+ OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode
+ )
+{
+ EFI_STATUS Status;
+ AML_STREAM SourceAliasFStream;
+ CONST AML_DATA_NODE * DataNode;
+
+ if (!AmlNodeCompareOpCode (AliasNode, AML_ALIAS_OP, 0) ||
+ (NameSpaceRefList == NULL) ||
+ (OutNameSpaceRefNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The aliased NameString (the source name) is the first fixed argument,
+ // cf. ACPI6.3 spec, s19.6.4: Alias (SourceObject, AliasObject)
+ DataNode = (CONST AML_DATA_NODE*)AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)AliasNode,
+ EAmlParseIndexTerm0
+ );
+ if (DataNode == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Initialize a stream on the source alias NameString.
+ Status = AmlStreamInit (
+ &SourceAliasFStream,
+ DataNode->Buffer,
+ DataNode->Size,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Recursively check whether the source alias NameString
+ // is a method invocation.
+ Status = AmlIsMethodInvocation (
+ AmlGetParent ((AML_NODE_HEADER*)AliasNode),
+ &SourceAliasFStream,
+ NameSpaceRefList,
+ OutNameSpaceRefNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ return Status;
+}
+
+/** Iterate through the MethodList to find the best namespace resolution.
+ If the pathname resolves to a method definition, returns it.
+
+ For instance, if the AML namespace is:
+ \
+ \-MET0 <- Device definition, absolute path: \MET0
+ \-AAAA
+ \-MET0 <- Method definition, absolute path: \AAAA.MET0
+ \-MET1 <- Method definition, absolute path: \AAAA.MET1
+ \-BBBB
+ \-CCCC
+ \-DDDD
+ \-MET0 <- Method definition, absolute path: \AAAA.BBBB.CCCC.DDDD.MET0
+
+ The list of the available pathnames is:
+ [NameSpaceRefList]
+ - \MET0 <- Device definition
+ - \AAAA
+ - \AAAA.MET0 <- Method definition
+ - \AAAA.MET1 <- Method definition
+ - \AAAA.BBBB
+ - \AAAA.BBBB.CCCC
+ - \AAAA.BBBB.CCCC.DDDD
+ - \AAAA.BBBB.CCCC.DDDD.MET0 <- Method definition
+
+ Depending on where the method invocation is done, the method definition
+ referenced changes. If the method call "MET0" is done from
+ \AAAA.BBBB.CCCC:
+ 1. Identify which pathnames end with "MET0":
+ - \MET0 <- Device definition
+ - \AAAA.MET0 <- Method definition
+ - \AAAA.BBBB.CCCC.DDDD.MET0 <- Method definition
+ 2. Resolve the method invocation:
+ - \AAAA.MET0 <- Method definition
+ 3. \AAAA.MET0 is a method definition, so return the corresponding
+ reference node.
+
+ @param [in] RawAbsolutePathFStream Forward stream pointing to a raw
+ absolute path.
+ The stream must not be at its end.
+ @param [in] RawPathNameBStream Backward stream pointing to a raw
+ pathname. This raw pathname is the
+ raw NameString of namespace node.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of NameSpaceRef nodes.
+ @param [out] OutNameSpaceRefNode If the two input paths are
+ referencing a method definition,
+ returns the corresponding
+ NameSpaceRef node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlFindMethodDefinition (
+ IN CONST AML_STREAM * RawAbsolutePathFStream,
+ IN CONST AML_STREAM * RawPathNameBStream,
+ IN CONST LIST_ENTRY * NameSpaceRefList,
+ OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode
+ )
+{
+ EFI_STATUS Status;
+
+ LIST_ENTRY * NextLink;
+
+ // To resolve a pathname, scope levels need to be compared.
+ UINT32 NameSegScopeCount;
+ UINT32 PathNameSegScopeCount;
+ UINT32 ProbedScopeCount;
+ UINT32 BestScopeCount;
+
+ AML_STREAM ProbedRawAbsoluteFStream;
+ AML_STREAM ProbedRawAbsoluteBStream;
+
+ AML_NAMESPACE_REF_NODE * ProbedNameSpaceRefNode;
+ AML_NAMESPACE_REF_NODE * BestNameSpaceRefNode;
+
+ if (!IS_STREAM (RawAbsolutePathFStream) ||
+ IS_END_OF_STREAM (RawAbsolutePathFStream) ||
+ !IS_STREAM_FORWARD (RawAbsolutePathFStream) ||
+ ((AmlStreamGetIndex (RawAbsolutePathFStream) &
+ (AML_NAME_SEG_SIZE - 1)) != 0) ||
+ !IS_STREAM (RawPathNameBStream) ||
+ IS_END_OF_STREAM (RawPathNameBStream) ||
+ !IS_STREAM_BACKWARD (RawPathNameBStream) ||
+ ((AmlStreamGetIndex (RawPathNameBStream) &
+ (AML_NAME_SEG_SIZE - 1)) != 0) ||
+ (NameSpaceRefList == NULL) ||
+ (OutNameSpaceRefNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: Checking absolute name: "));
+ AMLDBG_PRINT_CHARS (
+ DEBUG_VERBOSE,
+ (CONST CHAR8*)AmlStreamGetCurrPos (RawAbsolutePathFStream),
+ AmlStreamGetMaxBufferSize (RawAbsolutePathFStream)
+ );
+ DEBUG ((DEBUG_VERBOSE, ".\n"));
+
+ BestNameSpaceRefNode = NULL;
+ BestScopeCount = 0;
+ NameSegScopeCount = AmlStreamGetMaxBufferSize (RawAbsolutePathFStream);
+ PathNameSegScopeCount = AmlStreamGetMaxBufferSize (RawPathNameBStream);
+
+ // Iterate through the raw AML absolute path to find the best match.
+ DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: Comparing with: "));
+ NextLink = NameSpaceRefList->ForwardLink;
+ while (NextLink != NameSpaceRefList) {
+ ProbedNameSpaceRefNode = (AML_NAMESPACE_REF_NODE*)NextLink;
+
+ // Print the raw absolute path of the probed node.
+ AMLDBG_PRINT_CHARS (
+ DEBUG_VERBOSE,
+ ProbedNameSpaceRefNode->RawAbsolutePath,
+ ProbedNameSpaceRefNode->RawAbsolutePathSize
+ );
+ DEBUG ((DEBUG_VERBOSE, "; "));
+
+ // If the raw AML absolute path of the probed node is longer than the
+ // searched pathname, continue.
+ // E.g.: The method call \MET0 cannot resolve to a method defined at
+ // \AAAA.MET0. The method definition is out of scope.
+ if (PathNameSegScopeCount > ProbedNameSpaceRefNode->RawAbsolutePathSize) {
+ NextLink = NextLink->ForwardLink;
+ continue;
+ }
+
+ // Initialize a backward stream for the probed node.
+ // This stream is used to compare the ending of the pathnames.
+ // E.g. if the method searched ends with "MET0", pathnames not ending with
+ // "MET0" should be skipped.
+ Status = AmlStreamInit (
+ &ProbedRawAbsoluteBStream,
+ (UINT8*)ProbedNameSpaceRefNode->RawAbsolutePath,
+ ProbedNameSpaceRefNode->RawAbsolutePathSize,
+ EAmlStreamDirectionBackward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Compare the pathname endings. If they don't match, continue.
+ if (!AmlStreamCmp (
+ RawPathNameBStream,
+ &ProbedRawAbsoluteBStream,
+ AmlStreamGetMaxBufferSize (RawPathNameBStream))) {
+ NextLink = NextLink->ForwardLink;
+ continue;
+ }
+
+ // Initialize a forward stream for the probed node.
+ // This stream is used to count how many scope levels from the root
+ // are common with the probed node. The more there are, the better it is.
+ // E.g.: For the method invocation \AAAA.BBBB.MET0, if there are 2
+ // pathnames ending with MET0:
+ // - \AAAA.MET0 has 1 NameSeg in common with \AAAA.BBBB.MET0
+ // from the root (this is "AAAA");
+ // - \MET0 has 0 NameSeg in common with \AAAA.BBBB.MET0
+ // from the root;
+ // Thus, the best match is \AAAA.MET0.
+ Status = AmlStreamInit (
+ &ProbedRawAbsoluteFStream,
+ (UINT8*)ProbedNameSpaceRefNode->RawAbsolutePath,
+ ProbedNameSpaceRefNode->RawAbsolutePathSize,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Count how many namespace levels are in common from the root.
+ Status = AmlCompareRawNameString (
+ RawAbsolutePathFStream,
+ &ProbedRawAbsoluteFStream,
+ &ProbedScopeCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (ProbedScopeCount == NameSegScopeCount) {
+ // This is a perfect match. Exit the loop.
+ BestNameSpaceRefNode = ProbedNameSpaceRefNode;
+ break;
+ } else if (ProbedScopeCount > BestScopeCount) {
+ // The probed node has more scope levels in common than the
+ // last best match. Update the best match.
+ BestScopeCount = ProbedScopeCount;
+ BestNameSpaceRefNode = ProbedNameSpaceRefNode;
+ } else if (ProbedScopeCount == BestScopeCount) {
+ // The probed node has the same number of scope levels in
+ // common as the last best match.
+ if (ProbedScopeCount == 0) {
+ // There was not best match previously. Set it.
+ BestNameSpaceRefNode = ProbedNameSpaceRefNode;
+ } else {
+ // (ProbedScopeCount != 0)
+ // If there is an equivalent candidate, the best has the shortest
+ // absolute path. Indeed, a similar ProbedScopeCount and a longer
+ // path means the definition is out of the scope.
+ // E.g.: For the method invocation \AAAA.BBBB.MET0, if there are 2
+ // pathnames ending with MET0:
+ // - \AAAA.MET0 has 1 NameSegs in common with \AAAA.BBBB.MET0
+ // from the root (this is "AAAA");
+ // - \AAAA.CCCC.MET0 has 1 NameSegs in common with
+ // \AAAA.BBBB.MET0 from the root (this is "AAAA");
+ // As \AAAA.CCCC.MET0 is longer than \AAAA.MET0, it means that
+ // the pathname could have matched on more NameSegs, but it
+ // didn't because it is out of scope.
+ // Thus, the best match is \AAAA.MET0.
+ if (AmlStreamGetIndex (&ProbedRawAbsoluteFStream) <
+ BestNameSpaceRefNode->RawAbsolutePathSize) {
+ BestScopeCount = ProbedScopeCount;
+ BestNameSpaceRefNode = ProbedNameSpaceRefNode;
+ } else if (AmlStreamGetIndex (&ProbedRawAbsoluteFStream) ==
+ BestNameSpaceRefNode->RawAbsolutePathSize) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ NextLink = NextLink->ForwardLink;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+
+ // Check whether the BestNameSpaceRefNode is a method definition.
+ if (BestNameSpaceRefNode != NULL) {
+ if (AmlIsMethodDefinitionNode (BestNameSpaceRefNode->NodeRef)) {
+ *OutNameSpaceRefNode = BestNameSpaceRefNode;
+ } else if (AmlNodeCompareOpCode (
+ BestNameSpaceRefNode->NodeRef,
+ AML_ALIAS_OP, 0)) {
+ // The path matches an alias. Resolve the alias and check whether
+ // this is a method defintion.
+ Status = AmlResolveAliasMethod (
+ BestNameSpaceRefNode->NodeRef,
+ NameSpaceRefList,
+ OutNameSpaceRefNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+ } else {
+ // If no, return NULL, even if a matching pathname has been found.
+ *OutNameSpaceRefNode = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Check whether a pathname is a method invocation.
+
+ If there is a matching method definition, returns the corresponding
+ NameSpaceRef node.
+
+ To do so, the NameSpaceRefList is keeping track of every namespace node
+ and its raw AML absolute path.
+ To check whether a pathname is a method invocation, a corresponding raw
+ absolute pathname is built. This raw absolute pathname is then compared
+ to the list of available pathnames. If a pathname defining a method
+ matches the scope of the input pathname, return.
+
+ @param [in] ParentNode Parent node. Node to which the node to be
+ created will be attached.
+ @param [in] FStream Forward stream pointing to the NameString
+ to find.
+ @param [in] NameSpaceRefList List of NameSpaceRef nodes.
+ @param [out] OutNameSpaceRefNode If the NameString pointed by FStream is
+ a method invocation, OutNameSpaceRefNode
+ contains the NameSpaceRef corresponding
+ to the method definition.
+ NULL otherwise.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlIsMethodInvocation (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN CONST AML_STREAM * FStream,
+ IN CONST LIST_ENTRY * NameSpaceRefList,
+ OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode
+ )
+{
+ EFI_STATUS Status;
+
+ AML_STREAM RawPathNameBStream;
+ AML_STREAM RawAbsolutePathFStream;
+
+ AML_STREAM RawAbsolutePathBStream;
+ UINT8 * RawAbsolutePathBuffer;
+ UINT32 RawAbsolutePathBufferSize;
+
+ AML_NAMESPACE_REF_NODE * NameSpaceRefNode;
+
+ if ((!IS_AML_OBJECT_NODE (ParentNode) &&
+ !IS_AML_ROOT_NODE (ParentNode)) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL) ||
+ (OutNameSpaceRefNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // There cannot be a method invocation in a field list. Return.
+ if (AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)ParentNode,
+ AML_HAS_FIELD_LIST)) {
+ *OutNameSpaceRefNode = NULL;
+ return EFI_SUCCESS;
+ }
+
+ // Allocate memory for the raw absolute path.
+ RawAbsolutePathBufferSize = MAX_AML_NAMESTRING_SIZE;
+ RawAbsolutePathBuffer = AllocateZeroPool (RawAbsolutePathBufferSize);
+ if (RawAbsolutePathBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Initialize a backward stream to get the raw absolute path.
+ Status = AmlStreamInit (
+ &RawAbsolutePathBStream,
+ RawAbsolutePathBuffer,
+ RawAbsolutePathBufferSize,
+ EAmlStreamDirectionBackward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Build the raw AML absolute path of the namespace node.
+ Status = AmlBuildRawMethodAbsolutePath (
+ ParentNode,
+ FStream,
+ &RawAbsolutePathBStream
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // If this is the root path: it cannot be a method invocation. Just return.
+ if (AmlStreamGetIndex (&RawAbsolutePathBStream) == 0) {
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "AmlMethodParser: "
+ "Root node cannot be a method invocation\n"
+ ));
+ *OutNameSpaceRefNode = NULL;
+ Status = EFI_SUCCESS;
+ goto exit_handler;
+ }
+
+ // Create a forward stream for the raw absolute path.
+ // This forward stream only contains the raw absolute path with
+ // no extra free space.
+ Status = AmlStreamInit (
+ &RawAbsolutePathFStream,
+ AmlStreamGetCurrPos (&RawAbsolutePathBStream),
+ AmlStreamGetIndex (&RawAbsolutePathBStream),
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Create a backward stream for the node name.
+ Status = AmlInitRawPathBStream (
+ FStream,
+ &RawPathNameBStream
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Go through the NameSpaceRefList elements to check for
+ // a corresponding method definition.
+ NameSpaceRefNode = NULL;
+ Status = AmlFindMethodDefinition (
+ &RawAbsolutePathFStream,
+ &RawPathNameBStream,
+ NameSpaceRefList,
+ &NameSpaceRefNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+#if !defined(MDEPKG_NDEBUG)
+ // Print whether a method definition has been found.
+ if (NameSpaceRefNode != NULL) {
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "AmlMethodParser: Corresponding method definition: "
+ ));
+ AMLDBG_PRINT_CHARS (
+ DEBUG_VERBOSE,
+ NameSpaceRefNode->RawAbsolutePath,
+ NameSpaceRefNode->RawAbsolutePathSize
+ );
+ DEBUG ((DEBUG_VERBOSE, ".\n"));
+
+ } else {
+ DEBUG ((DEBUG_VERBOSE, "AmlMethodParser: No method definition found.\n"));
+ }
+#endif // MDEPKG_NDEBUG
+
+ *OutNameSpaceRefNode = NameSpaceRefNode;
+
+exit_handler:
+ // Free allocated memory.
+ FreePool (RawAbsolutePathBuffer);
+ return Status;
+}
+
+/** Create a namespace reference node and add it to the NameSpaceRefList.
+
+ When a namespace node is encountered, the namespace it defines must be
+ associated to the node. This allow to keep track of the nature of each
+ name present in the AML namespace.
+
+ In the end, this allows to recognize method invocations and parse the right
+ number of arguments after the method name.
+
+ @param [in] Node Namespace node.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddNameSpaceReference (
+ IN CONST AML_OBJECT_NODE * Node,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+ AML_NAMESPACE_REF_NODE * NameSpaceRefNode;
+
+ AML_STREAM NodeNameFStream;
+ EAML_PARSE_INDEX NameIndex;
+ CONST AML_DATA_NODE * NameNode;
+
+ AML_STREAM RawAbsolutePathBStream;
+ UINT32 RawAbsolutePathBStreamSize;
+
+ CHAR8 * AbsolutePathBuffer;
+ UINT32 AbsolutePathBufferSize;
+
+ CONST AML_NODE_HEADER * ParentNode;
+
+ if (!AmlNodeHasAttribute (Node, AML_IN_NAMESPACE) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate a buffer to get the raw AML absolute pathname of the
+ // namespace node.
+ AbsolutePathBufferSize = MAX_AML_NAMESTRING_SIZE;
+ AbsolutePathBuffer = AllocateZeroPool (AbsolutePathBufferSize);
+ if (AbsolutePathBuffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmlStreamInit (
+ &RawAbsolutePathBStream,
+ (UINT8*)AbsolutePathBuffer,
+ AbsolutePathBufferSize,
+ EAmlStreamDirectionBackward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // Get the index where the name of the Node is stored in its
+ // fixed list of arguments.
+ Status = AmlNodeGetNameIndex (Node, &NameIndex);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // Get the Node name.
+ NameNode = (CONST AML_DATA_NODE*)AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)Node,
+ NameIndex
+ );
+ if (!IS_AML_DATA_NODE (NameNode) ||
+ (NameNode->DataType != EAmlNodeDataTypeNameString)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // Initialize a stream on the node name of the namespace node.
+ // This is an AML NameString.
+ Status = AmlStreamInit (
+ &NodeNameFStream,
+ NameNode->Buffer,
+ NameNode->Size,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ ParentNode = AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (ParentNode == NULL) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto exit_handler;
+ }
+
+ // Build the raw AML absolute path of the namespace node.
+ Status = AmlBuildRawMethodAbsolutePath (
+ ParentNode,
+ &NodeNameFStream,
+ &RawAbsolutePathBStream
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ RawAbsolutePathBStreamSize = AmlStreamGetIndex (&RawAbsolutePathBStream);
+ // This is the root path: this cannot be a method invocation.
+ if (RawAbsolutePathBStreamSize == 0) {
+ Status = EFI_SUCCESS;
+ goto exit_handler;
+ }
+
+ // Create a NameSpace reference node.
+ Status = AmlCreateMethodRefNode (
+ Node,
+ (CONST CHAR8*)AmlStreamGetCurrPos (&RawAbsolutePathBStream),
+ RawAbsolutePathBStreamSize,
+ &NameSpaceRefNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto exit_handler;
+ }
+
+ // Add the created NameSpaceRefNode to the list.
+ InsertTailList (NameSpaceRefList, &NameSpaceRefNode->Link);
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "AmlMethodParser: Adding namespace reference with name:\n"
+ ));
+ AMLDBG_PRINT_CHARS (
+ DEBUG_VERBOSE,
+ (CONST CHAR8*)AmlStreamGetCurrPos (&RawAbsolutePathBStream),
+ AmlStreamGetIndex (&RawAbsolutePathBStream)
+ );
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+
+exit_handler:
+ // Free allocated memory.
+ FreePool (AbsolutePathBuffer);
+
+ return Status;
+}
+
+/** Create a method invocation node.
+
+ The AML grammar does not attribute an OpCode/SubOpCode couple for
+ method invocations. This library is representing method invocations
+ as if they had one.
+
+ The AML encoding for method invocations in the ACPI specification 6.3 is:
+ MethodInvocation := NameString TermArgList
+ In this library, it is:
+ MethodInvocation := MethodInvocationOp NameString ArgumentCount TermArgList
+ ArgumentCount := ByteData
+
+ When computing the size of a tree or serializing it, the additional data is
+ not taken into account (i.e. the MethodInvocationOp and the ArgumentCount).
+
+ Method invocation nodes have the AML_METHOD_INVOVATION attribute.
+
+ @param [in] NameSpaceRefNode NameSpaceRef node pointing to the
+ the definition of the invoked
+ method.
+ @param [in] MethodInvocationName Data node containing the method
+ invocation name.
+ @param [out] MethodInvocationNodePtr Created method invocation node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateMethodInvocationNode (
+ IN CONST AML_NAMESPACE_REF_NODE * NameSpaceRefNode,
+ IN AML_DATA_NODE * MethodInvocationName,
+ OUT AML_OBJECT_NODE ** MethodInvocationNodePtr
+ )
+{
+ EFI_STATUS Status;
+
+ UINT8 ArgCount;
+ AML_DATA_NODE * ArgCountNode;
+ AML_NODE_HEADER ** FixedArgs;
+ AML_OBJECT_NODE * MethodDefinitionNode;
+ AML_OBJECT_NODE * MethodInvocationNode;
+
+ if ((NameSpaceRefNode == NULL) ||
+ !AmlIsMethodDefinitionNode (NameSpaceRefNode->NodeRef) ||
+ !IS_AML_DATA_NODE (MethodInvocationName) ||
+ (MethodInvocationName->DataType != EAmlNodeDataTypeNameString) ||
+ (MethodInvocationNodePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the number of arguments of the method.
+ MethodDefinitionNode = (AML_OBJECT_NODE*)NameSpaceRefNode->NodeRef;
+ FixedArgs = MethodDefinitionNode->FixedArgs;
+ // The method definition is an actual method definition.
+ if (AmlNodeCompareOpCode (MethodDefinitionNode, AML_METHOD_OP, 0)) {
+ // Cf ACPI 6.3 specification:
+ // DefMethod := MethodOp PkgLength NameString MethodFlags TermList
+ // MethodOp := 0x14
+ // MethodFlags := ByteData bit 0-2: ArgCount (0-7)
+ // bit 3: SerializeFlag
+ // 0 NotSerialized
+ // 1 Serialized
+ // bit 4-7: SyncLevel (0x00-0x0f)
+
+ // Read the MethodFlags to decode the ArgCount.
+ ArgCountNode = (AML_DATA_NODE*)FixedArgs[EAmlParseIndexTerm1];
+ ArgCount = *((UINT8*)ArgCountNode->Buffer) & 0x7;
+ } else if (AmlNodeCompareOpCode (MethodDefinitionNode, AML_EXTERNAL_OP, 0)) {
+ // The method definition is an external statement.
+ // Cf ACPI 6.3 specification:
+ // DefExternal := ExternalOp NameString ObjectType ArgumentCount
+ // ExternalOp := 0x15
+ // ObjectType := ByteData
+ // ArgumentCount := ByteData (0 - 7)
+
+ // Read the ArgumentCount.
+ ArgCountNode = (AML_DATA_NODE*)FixedArgs[EAmlParseIndexTerm2];
+ ArgCount = *((UINT8*)ArgCountNode->Buffer);
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Create the object node for the method invocation.
+ // MethodInvocation := MethodInvocationOp NameString ArgumentCount
+ // MethodInvocationOp := Pseudo Opcode for Method Invocation
+ // NameString := Method Name
+ // ArgumentCount := ByteData (0 - 7)
+ Status = AmlCreateObjectNode (
+ AmlGetByteEncodingByOpCode (AML_METHOD_INVOC_OP, 0),
+ 0,
+ &MethodInvocationNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // The first fixed argument is the method name.
+ Status = AmlSetFixedArgument (
+ MethodInvocationNode,
+ EAmlParseIndexTerm0,
+ (AML_NODE_HEADER*)MethodInvocationName
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Create a data node holding the number of arguments
+ // of the method invocation.
+ ArgCountNode = NULL;
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeUInt,
+ &ArgCount,
+ sizeof (UINT8),
+ &ArgCountNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // The second fixed argument is the number of arguments.
+ Status = AmlSetFixedArgument (
+ MethodInvocationNode,
+ EAmlParseIndexTerm1,
+ (AML_NODE_HEADER*)ArgCountNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ *MethodInvocationNodePtr = MethodInvocationNode;
+ return Status;
+
+error_handler:
+ // Delete the sub-tree: the method invocation name is already attached.
+ AmlDeleteTree ((AML_NODE_HEADER*)MethodInvocationNode);
+ if (ArgCountNode != NULL) {
+ AmlDeleteNode ((AML_NODE_HEADER*)ArgCountNode);
+ }
+
+ return Status;
+}
+
+/** Get the number of arguments of a method invocation node.
+
+ This function also allow to identify whether a node is a method invocation
+ node. If the input node is not a method invocation node, just return.
+
+ @param [in] MethodInvocationNode Method invocation node.
+ @param [out] IsMethodInvocation Boolean stating whether the input
+ node is a method invocation.
+ @param [out] ArgCount Number of arguments of the method
+ invocation.
+ Set to 0 if MethodInvocationNode
+ is not a method invocation.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetMethodInvocationArgCount (
+ IN CONST AML_OBJECT_NODE * MethodInvocationNode,
+ OUT BOOLEAN * IsMethodInvocation,
+ OUT UINT8 * ArgCount
+ )
+{
+ AML_DATA_NODE * NumArgsNode;
+
+ if (!IS_AML_NODE_VALID (MethodInvocationNode) ||
+ (IsMethodInvocation == NULL) ||
+ (ArgCount == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check whether MethodInvocationNode is a method invocation.
+ if (!AmlNodeCompareOpCode (MethodInvocationNode, AML_METHOD_INVOC_OP, 0)) {
+ *IsMethodInvocation = FALSE;
+ *ArgCount = 0;
+ return EFI_SUCCESS;
+ }
+
+ // MethodInvocation := MethodInvocationOp NameString ArgumentCount
+ // MethodInvocationOp := Pseudo Opcode for Method Invocation
+ // NameString := Method Name
+ // ArgumentCount := ByteData (0 - 7)
+ NumArgsNode = (AML_DATA_NODE*)AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)MethodInvocationNode,
+ EAmlParseIndexTerm1
+ );
+ if (!IS_AML_NODE_VALID (NumArgsNode) ||
+ (NumArgsNode->Buffer == NULL) ||
+ (NumArgsNode->DataType != EAmlNodeDataTypeUInt) ||
+ (NumArgsNode->Size != 1)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ *ArgCount = *NumArgsNode->Buffer;
+
+ *IsMethodInvocation = TRUE;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h
new file mode 100644
index 00000000000..9d6291f704d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlMethodParser.h
@@ -0,0 +1,188 @@
+/** @file
+ AML Method Parser.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_METHOD_PARSER_H_
+#define AML_METHOD_PARSER_H_
+
+#include <AmlNodeDefines.h>
+#include <Stream/AmlStream.h>
+
+/** AML namespace reference node.
+
+ Namespace reference nodes allow to associate an AML absolute pathname
+ to the tree node defining this object in the namespace.
+
+ Namespace reference nodes are stored in a separate list. They are not part of
+ the tree.
+*/
+typedef struct AmlNameSpaceRefNode {
+ /// Double linked list.
+ /// This must be the first field in this structure.
+ LIST_ENTRY Link;
+
+ /// Node part of the AML namespace. It must have the AML_IN_NAMESPACE
+ /// attribute.
+ CONST AML_OBJECT_NODE * NodeRef;
+
+ /// Raw AML absolute pathname of the NodeRef.
+ /// This is a raw AML NameString (cf AmlNameSpace.c: A concatenated list
+ /// of 4 chars long names. The dual/multi NameString prefix have been
+ /// stripped.).
+ CONST CHAR8 * RawAbsolutePath;
+
+ /// Size of the raw AML absolute pathname buffer.
+ UINT32 RawAbsolutePathSize;
+} AML_NAMESPACE_REF_NODE;
+
+/** Delete a list of namespace reference nodes.
+
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteNameSpaceRefList (
+ IN LIST_ENTRY * NameSpaceRefList
+ );
+
+
+#if !defined (MDEPKG_NDEBUG)
+/** Print the list of raw absolute paths of the NameSpace reference list.
+
+ @param [in] NameSpaceRefList List of NameSpace reference nodes.
+**/
+VOID
+EFIAPI
+AmlDbgPrintNameSpaceRefList (
+ IN CONST LIST_ENTRY * NameSpaceRefList
+ );
+
+#endif // MDEPKG_NDEBUG
+
+/** Check whether a pathname is a method invocation.
+
+ If there is a matching method definition, returns the corresponding
+ NameSpaceRef node.
+
+ To do so, the NameSpaceRefList is keeping track of every namespace node
+ and its raw AML absolute path.
+ To check whether a pathname is a method invocation, a corresponding raw
+ absolute pathname is built. This raw absolute pathname is then compared
+ to the list of available pathnames. If a pathname defining a method
+ matches the scope of the input pathname, return.
+
+ @param [in] ParentNode Parent node. Node to which the node to be
+ created will be attached.
+ @param [in] FStream Forward stream pointing to the NameString
+ to find.
+ @param [in] NameSpaceRefList List of NameSpaceRef nodes.
+ @param [out] OutNameSpaceRefNode If the NameString pointed by FStream is
+ a method invocation, OutNameSpaceRefNode
+ contains the NameSpaceRef corresponding
+ to the method definition.
+ NULL otherwise.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlIsMethodInvocation (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN CONST AML_STREAM * FStream,
+ IN CONST LIST_ENTRY * NameSpaceRefList,
+ OUT AML_NAMESPACE_REF_NODE ** OutNameSpaceRefNode
+ );
+
+/** Create a namespace reference node and add it to the NameSpaceRefList.
+
+ When a namespace node is encountered, the namespace it defines must be
+ associated to the node. This allow to keep track of the nature of each
+ name present in the AML namespace.
+
+ In the end, this allows to recognize method invocations and parse the right
+ number of arguments after the method name.
+
+ @param [in] Node Namespace node.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddNameSpaceReference (
+ IN CONST AML_OBJECT_NODE * Node,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+ );
+
+/** Create a method invocation node.
+
+ The AML grammar does not attribute an OpCode/SubOpCode couple for
+ method invocations. This library is representing method invocations
+ as if they had one.
+
+ The AML encoding for method invocations in the ACPI specification 6.3 is:
+ MethodInvocation := NameString TermArgList
+ In this library, it is:
+ MethodInvocation := MethodInvocationOp NameString ArgumentCount TermArgList
+ ArgumentCount := ByteData
+
+ When computing the size of a tree or serializing it, the additional data is
+ not taken into account (i.e. the MethodInvocationOp and the ArgumentCount).
+
+ Method invocation nodes have the AML_METHOD_INVOVATION attribute.
+
+ @param [in] NameSpaceRefNode NameSpaceRef node pointing to the
+ the definition of the invoked
+ method.
+ @param [in] MethodInvocationName Data node containing the method
+ invocation name.
+ @param [out] MethodInvocationNodePtr Created method invocation node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateMethodInvocationNode (
+ IN CONST AML_NAMESPACE_REF_NODE * NameSpaceRefNode,
+ IN AML_DATA_NODE * MethodInvocationName,
+ OUT AML_OBJECT_NODE ** MethodInvocationNodePtr
+ );
+
+/** Get the number of arguments of a method invocation node.
+
+ This function also allow to identify whether a node is a method invocation
+ node. If the input node is not a method invocation node, just return.
+
+ @param [in] MethodInvocationNode Method invocation node.
+ @param [out] IsMethodInvocation Boolean stating whether the input
+ node is a method invocation.
+ @param [out] ArgCount Number of arguments of the method
+ invocation.
+ Set to 0 if MethodInvocationNode
+ is not a method invocation.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+*/
+EFI_STATUS
+EFIAPI
+AmlGetMethodInvocationArgCount (
+ IN CONST AML_OBJECT_NODE * MethodInvocationNode,
+ OUT BOOLEAN * IsMethodInvocation,
+ OUT UINT8 * ArgCount
+ );
+
+#endif // AML_METHOD_PARSER_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c
new file mode 100644
index 00000000000..3a77049d06f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.c
@@ -0,0 +1,1448 @@
+/** @file
+ AML Parser.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Parser/AmlParser.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlDbgPrint/AmlDbgPrint.h>
+#include <Parser/AmlFieldListParser.h>
+#include <Parser/AmlMethodParser.h>
+#include <Parser/AmlResourceDataParser.h>
+#include <String/AmlString.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+
+/*
+ AML Tree
+ --------
+
+ Each ASL Statement is represented in AML as and ObjectNode.
+ Each ObjectNode has an Opcode and has up to six FixedArguments
+ followed by a list of VariableArguments.
+ (ObjectNode)
+ \
+ |- [0][1][2][3][4][5] # Fixed Arguments
+ |- {(VarArg1)->(VarArg2)->(VarArg3)->...N} # Variable Arguments
+
+ A RootNode is a special type of Object Node that does not have an
+ Opcode or Fixed Arguments. It only has a list of VariableArguments
+ (RootNode)
+ \
+ |- {(VarArg1)->(VarArg2)->(VarArg3)->...N} # Variable Arguments
+
+ A DataNode consists of a data buffer.
+
+ A FixedArgument or VariableArgument can be either an ObjectNode or
+ a DataNode.
+
+ Example:
+ ASL code sample:
+ Device (DEV0) {
+ Name (VAR0, 0x6)
+ }
+
+ Tree generated from the ASL code:
+ (RootNode)
+ \
+ |- {(Device statement (ObjectNode))} # Variable Arg of the
+ \ # RootNode
+ |
+ |- [0] - Device Name (DataNode)(="DEV0") # Fixed Arg0 of the
+ | # Device() statement
+ |
+ |- {(Name statement (ObjectNode))} # Variable Arg of the
+ \ # Device() statement
+ |
+ |- [0] - Name statement(DataNode)(="VAR0") # Fixed Arg0 of the
+ | # Name() statement
+ |- [1] - Value(DataNode)(=0x6) # Fixed Arg1 of the
+ # Name() statement
+*/
+
+// Forward declaration.
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseStream (
+ IN AML_NODE_HEADER * Node,
+ IN OUT AML_STREAM * FStream,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+ );
+
+/** Function pointer to parse an AML construct.
+
+ The expected format of the AML construct is passed in the
+ ExpectedFormat argument. The available formats are available in
+ the AML_PARSE_FORMAT enum definition.
+
+ An object node or a data node is created in the function,
+ and returned through the OutNode parameter. This node should
+ be attached after this function returns.
+
+ @param [in] ParentNode Parent node to which the parsed
+ AML construct will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+typedef
+EFI_STATUS
+EFIAPI
+(*AML_PARSE_FUNCTION) (
+ IN CONST AML_NODE_HEADER * Node,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ OUT AML_NODE_HEADER ** OutNode
+ );
+
+/** Parse a UInt<X> (where X=8, 16, 32 or 64).
+
+ A data node is created and returned through the OutNode parameter.
+
+ @param [in] ParentNode Parent node to which the parsed
+ AML construct will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseUIntX (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 UIntXSize;
+
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ ((ExpectedFormat != EAmlUInt8) &&
+ (ExpectedFormat != EAmlUInt16) &&
+ (ExpectedFormat != EAmlUInt32) &&
+ (ExpectedFormat != EAmlUInt64)) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (ExpectedFormat) {
+ case EAmlUInt8:
+ UIntXSize = 1;
+ break;
+ case EAmlUInt16:
+ UIntXSize = 2;
+ break;
+ case EAmlUInt32:
+ UIntXSize = 4;
+ break;
+ case EAmlUInt64:
+ UIntXSize = 8;
+ break;
+ default:
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCreateDataNode (
+ AmlTypeToNodeDataType (ExpectedFormat),
+ AmlStreamGetCurrPos (FStream),
+ UIntXSize,
+ (AML_DATA_NODE**)OutNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ AMLDBG_DUMP_RAW (AmlStreamGetCurrPos (FStream), UIntXSize);
+
+ // Move stream forward by the size of UIntX.
+ Status = AmlStreamProgress (FStream, UIntXSize);
+ if (EFI_ERROR (Status)) {
+ AmlDeleteTree (*OutNode);
+ ASSERT (0);
+ }
+
+ return Status;
+}
+
+/** Parse an AML NameString.
+
+ A data node is created and returned through the OutNode parameter.
+
+ @param [in] ParentNode Parent node to which the parsed
+ AML construct will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseNameString (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+
+ CONST UINT8 * Buffer;
+ CONST AML_BYTE_ENCODING * ByteEncoding;
+ UINT32 StrSize;
+
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ (ExpectedFormat != EAmlName) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (CONST UINT8*)AmlStreamGetCurrPos (FStream);
+ ByteEncoding = AmlGetByteEncoding (Buffer);
+ if ((ByteEncoding == NULL) ||
+ ((ByteEncoding->Attribute & AML_IS_NAME_CHAR) == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Parse the NameString.
+ Status = AmlGetNameStringSize ((CONST CHAR8*)Buffer, &StrSize);
+ if ((EFI_ERROR (Status)) ||
+ (StrSize > AmlStreamGetFreeSpace (FStream))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeNameString,
+ Buffer,
+ StrSize,
+ (AML_DATA_NODE**)OutNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ AMLDBG_DUMP_RAW (AmlStreamGetCurrPos (FStream), StrSize);
+
+ // Move the stream forward by StrSize.
+ Status = AmlStreamProgress (FStream, StrSize);
+ if (EFI_ERROR (Status)) {
+ AmlDeleteTree (*OutNode);
+ ASSERT (0);
+ }
+
+ return Status;
+}
+
+/** Parse an AML String.
+
+ A data node is created and returned through the OutNode parameter.
+
+ @param [in] ParentNode Parent node to which the parsed
+ AML construct will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseString (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 StrSize;
+ UINT8 Byte;
+ CONST UINT8 * Buffer;
+
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ (ExpectedFormat != EAmlString) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (CONST UINT8*)AmlStreamGetCurrPos (FStream);
+ StrSize = 0;
+ // AML String is NULL terminated.
+ do {
+ // Reading the stream moves the stream forward aswell.
+ Status = AmlStreamReadByte (FStream, &Byte);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ StrSize++;
+ } while (Byte != '\0');
+
+ AMLDBG_DUMP_RAW (Buffer, StrSize);
+
+ Status = AmlCreateDataNode (
+ AmlTypeToNodeDataType (ExpectedFormat),
+ Buffer,
+ StrSize,
+ (AML_DATA_NODE**)OutNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Parse an AML object.
+
+ An object can be resolved as an AML object with an OpCode,
+ or a NameString. An object node or a data node is created
+ and returned through the OutNode parameter.
+
+ @param [in] ParentNode Parent node to which the parsed
+ AML construct will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseObject (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+
+ UINT8 OpCodeSize;
+ UINT32 PkgLength;
+ UINT32 PkgOffset;
+ UINT32 FreeSpace;
+
+ CONST AML_BYTE_ENCODING * AmlByteEncoding;
+ CONST UINT8 * Buffer;
+
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ (ExpectedFormat != EAmlObject) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PkgLength = 0;
+
+ // 0. Get the AML Byte encoding.
+ AmlByteEncoding = AmlGetByteEncoding (AmlStreamGetCurrPos (FStream));
+ if (AmlByteEncoding == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // 1. Check for NameString.
+ // Indeed a NameString can be found when an AML object is expected.
+ // e.g. VAR0 = 3 // VAR0 is assigned an object which is a UINT.
+ // VAR1 = VAR2 // VAR2 is a NameString.
+ // If this is a NameString, return. A NameString can be a variable, a
+ // method invocation, etc.
+ if ((AmlByteEncoding->Attribute & AML_IS_NAME_CHAR) != 0) {
+ Status = AmlParseNameString (
+ ParentNode,
+ EAmlName,
+ FStream,
+ OutNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ return Status;
+ }
+
+ // 2. Determine the OpCode size to move the stream forward.
+ Buffer = (CONST UINT8*)AmlStreamGetCurrPos (FStream);
+ if (*Buffer == AML_EXT_OP) {
+ OpCodeSize = 2;
+ } else {
+ OpCodeSize = 1;
+ }
+ Status = AmlStreamProgress (FStream, OpCodeSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Print the opcode.
+ AMLDBG_DUMP_RAW (Buffer, OpCodeSize);
+
+ if (!IS_END_OF_STREAM (FStream)) {
+ // 3. Parse the PkgLength field, if present.
+ if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) != 0) {
+ Buffer = (CONST UINT8*)AmlStreamGetCurrPos (FStream);
+ PkgOffset = AmlGetPkgLength (Buffer, &PkgLength);
+ if (PkgOffset == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Print the package length.
+ AMLDBG_DUMP_RAW (Buffer, PkgOffset);
+
+ // Adjust the size of the stream if it is valid package length.
+ FreeSpace = AmlStreamGetFreeSpace (FStream);
+ if (FreeSpace > PkgLength) {
+ // Reduce the stream size by (FreeSpace - PkgLength) bytes.
+ AmlStreamReduceMaxBufferSize (FStream, FreeSpace - PkgLength);
+ } else if (FreeSpace != PkgLength) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlStreamProgress (FStream, PkgOffset);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+ } else if ((AmlByteEncoding->Attribute & AML_HAS_PKG_LENGTH) != 0) {
+ // The stream terminated unexpectedly. A PkgLen had to be parsed.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // 4. Create an Object Node.
+ Status = AmlCreateObjectNode (
+ AmlByteEncoding,
+ PkgLength,
+ (AML_OBJECT_NODE**)OutNode
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Parse a FieldPkgLen.
+
+ A FieldPkgLen can only be found in a field list, i.e. in a NamedField field
+ element. The PkgLen is otherwise part of the object node structure.
+ A data node is created and returned through the OutNode parameter.
+
+ @param [in] ParentNode Parent node to which the parsed
+ AML construct will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseFieldPkgLen (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ CONST UINT8 * Buffer;
+ UINT32 PkgOffset;
+ UINT32 PkgLength;
+
+ if (!AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)ParentNode,
+ AML_IS_FIELD_ELEMENT
+ ) ||
+ (ExpectedFormat != EAmlFieldPkgLen) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (CONST UINT8*)AmlStreamGetCurrPos (FStream);
+
+ PkgOffset = AmlGetPkgLength (Buffer, &PkgLength);
+ if (PkgOffset == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Warning: Since, updating of field elements is not supported, store the
+ // FieldPkgLength in a Data Node as a raw buffer.
+ Status = AmlCreateDataNode (
+ AmlTypeToNodeDataType (ExpectedFormat),
+ Buffer,
+ PkgOffset,
+ (AML_DATA_NODE**)OutNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ AMLDBG_DUMP_RAW (Buffer, PkgOffset);
+
+ Status = AmlStreamProgress (FStream, PkgOffset);
+ if (EFI_ERROR (Status)) {
+ Status1 = AmlDeleteNode (*OutNode);
+ ASSERT_EFI_ERROR (Status1);
+ ASSERT (0);
+ }
+
+ return Status;
+}
+
+/** Array of functions pointers to parse the AML constructs.
+
+ The AML Byte encoding tables in Aml.c describe the format of the AML
+ statements. The AML_PARSE_FORMAT enum definition lists these constructs
+ and the corresponding parsing functions.
+*/
+AML_PARSE_FUNCTION mParseType[EAmlParseFormatMax] = {
+ NULL, // EAmlNone
+ AmlParseUIntX, // EAmlUInt8
+ AmlParseUIntX, // EAmlUInt16
+ AmlParseUIntX, // EAmlUInt32
+ AmlParseUIntX, // EAmlUInt64
+ AmlParseObject, // EAmlObject
+ AmlParseNameString, // EAmlName
+ AmlParseString, // EAmlString
+ AmlParseFieldPkgLen // EAmlFieldPkgLen
+};
+
+/** Check whether the NameString stored in the data node is a method invocation.
+ If so, create a method invocation node and return it.
+
+ @param [in] ParentNode Node to which the parsed AML construct
+ will be attached.
+ @param [in] DataNode Data node containing a NameString,
+ potentially being a method invocation.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes.
+ @param [out] OutNode Pointer holding the method invocation
+ node if the NameString contained in the
+ data node is a method invocation.
+ NULL otherwise.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlCheckAndParseMethodInvoc (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_DATA_NODE * DataNode,
+ IN OUT LIST_ENTRY * NameSpaceRefList,
+ OUT AML_OBJECT_NODE ** OutNode
+ )
+{
+ EFI_STATUS Status;
+ AML_NAMESPACE_REF_NODE * NameSpaceRefNode;
+ AML_OBJECT_NODE * MethodInvocationNode;
+ AML_STREAM FStream;
+
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ !IS_AML_DATA_NODE (DataNode) ||
+ (DataNode->DataType != EAmlNodeDataTypeNameString) ||
+ (NameSpaceRefList == NULL) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Initialize a stream containing the NameString which is checked.
+ Status = AmlStreamInit (
+ &FStream,
+ DataNode->Buffer,
+ DataNode->Size,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Check whether the NameString is a method invocation.
+ NameSpaceRefNode = NULL;
+ Status = AmlIsMethodInvocation (
+ ParentNode,
+ &FStream,
+ NameSpaceRefList,
+ &NameSpaceRefNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ MethodInvocationNode = NULL;
+ if (NameSpaceRefNode != NULL) {
+ // A matching method definition has been found.
+ // Create a method invocation node.
+ Status = AmlCreateMethodInvocationNode (
+ NameSpaceRefNode,
+ (AML_DATA_NODE*)DataNode,
+ &MethodInvocationNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ *OutNode = MethodInvocationNode;
+
+ return EFI_SUCCESS;
+}
+
+/** Call the appropriate function to parse the AML construct in the stream.
+
+ The ExpectedFormat parameter allows to choose the right parsing function.
+ An object node or a data node is created according to format.
+
+ @param [in] ParentNode Node to which the parsed AML construct
+ will be attached.
+ @param [in] ExpectedFormat Format of the AML construct to parse.
+ @param [in, out] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes.
+ @param [out] OutNode Pointer holding the node created from the
+ parsed AML bytecode.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseArgument (
+ IN CONST AML_NODE_HEADER * ParentNode,
+ IN AML_PARSE_FORMAT ExpectedFormat,
+ IN OUT AML_STREAM * FStream,
+ IN OUT LIST_ENTRY * NameSpaceRefList,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ EFI_STATUS Status;
+ AML_PARSE_FUNCTION ParsingFunction;
+ AML_DATA_NODE * DataNode;
+ AML_OBJECT_NODE * MethodInvocationNode;
+
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ (ExpectedFormat >= EAmlParseFormatMax) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL) ||
+ (OutNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParsingFunction = mParseType[ExpectedFormat];
+ if (ParsingFunction == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Note: The ParsingFunction moves the stream forward as it
+ // consumes the AML bytecode
+ Status = ParsingFunction (
+ ParentNode,
+ ExpectedFormat,
+ FStream,
+ OutNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Check whether the parsed argument is a NameString when an object
+ // is expected. In such case, it could be a method invocation.
+ DataNode = (AML_DATA_NODE*)*OutNode;
+ if (IS_AML_DATA_NODE (DataNode) &&
+ (DataNode->DataType == EAmlNodeDataTypeNameString) &&
+ (ExpectedFormat == EAmlObject)) {
+ Status = AmlCheckAndParseMethodInvoc (
+ ParentNode,
+ (AML_DATA_NODE*)*OutNode,
+ NameSpaceRefList,
+ &MethodInvocationNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // A method invocation node has been created and the DataNode containing
+ // the NameString has been attached to the MethodInvocationNode.
+ // Replace the OutNode with the MethodInvocationNode.
+ if (MethodInvocationNode != NULL) {
+ *OutNode = (AML_NODE_HEADER*)MethodInvocationNode;
+ }
+ }
+
+ return Status;
+}
+
+/** Parse the Bytelist in the stream.
+ According to the content of the stream, create data node(s)
+ and add them to the variable list of arguments.
+ The byte list may be a list of resource data element or a simple byte list.
+
+ @param [in] BufferNode Object node having a byte list.
+ @param [in, out] FStream Forward stream containing the AML bytecode
+ to parse.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseByteList (
+ IN AML_OBJECT_NODE * BufferNode,
+ IN OUT AML_STREAM * FStream
+ )
+{
+ EFI_STATUS Status;
+ AML_NODE_HEADER * NewNode;
+ CONST UINT8 * Buffer;
+ UINT32 BufferSize;
+
+ // Check whether the node is an Object Node and has byte list.
+ if (!AmlNodeHasAttribute (BufferNode, AML_HAS_BYTE_LIST) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The buffer contains a list of resource data elements.
+ if (AmlRdIsResourceDataBuffer (FStream)) {
+ // Parse the resource data elements and add them as data nodes.
+ // AmlParseResourceData() moves the stream forward.
+ Status = AmlParseResourceData (BufferNode, FStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ } else {
+ // The buffer doesn't contain a list of resource data elements.
+ // Create a single node holding the whole buffer data.
+
+ // CreateDataNode checks the Buffer and BufferSize values.
+ Buffer = (CONST UINT8*)AmlStreamGetCurrPos (FStream);
+ BufferSize = AmlStreamGetFreeSpace (FStream);
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeRaw,
+ Buffer,
+ BufferSize,
+ (AML_DATA_NODE**)&NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlVarListAddTailInternal (
+ (AML_NODE_HEADER*)BufferNode,
+ NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree (NewNode);
+ return Status;
+ }
+
+ AMLDBG_DUMP_RAW (Buffer, BufferSize);
+
+ // Move the stream forward as we have consumed the Buffer.
+ Status = AmlStreamProgress (FStream, BufferSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ }
+
+ return Status;
+}
+
+/** Parse the list of fixed arguments of the input ObjectNode.
+
+ For each argument, create a node and add it to the fixed argument list
+ of the Node.
+ If a fixed argument has children, parse them.
+
+ @param [in] ObjectNode Object node to parse the fixed arguments
+ from.
+ @param [in] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseFixedArguments (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ AML_NODE_HEADER * FixedArgNode;
+ AML_STREAM FixedArgFStream;
+
+ EAML_PARSE_INDEX TermIndex;
+ EAML_PARSE_INDEX MaxIndex;
+ CONST AML_PARSE_FORMAT * Format;
+
+ // Fixed arguments of method invocations node are handled differently.
+ if (!IS_AML_OBJECT_NODE (ObjectNode) ||
+ AmlNodeCompareOpCode (ObjectNode, AML_METHOD_INVOC_OP, 0) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TermIndex = EAmlParseIndexTerm0;
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)ObjectNode
+ );
+ if ((ObjectNode->AmlByteEncoding != NULL) &&
+ (ObjectNode->AmlByteEncoding->Format != NULL)) {
+ Format = ObjectNode->AmlByteEncoding->Format;
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Parse all the FixedArgs.
+ while ((TermIndex < MaxIndex) &&
+ !IS_END_OF_STREAM (FStream) &&
+ (Format[TermIndex] != EAmlNone)) {
+ // Initialize a FixedArgStream to parse the current fixed argument.
+ Status = AmlStreamInitSubStream (FStream, &FixedArgFStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Parse the current fixed argument.
+ Status = AmlParseArgument (
+ (CONST AML_NODE_HEADER*)ObjectNode,
+ Format[TermIndex],
+ &FixedArgFStream,
+ NameSpaceRefList,
+ &FixedArgNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the fixed argument to the parent node's fixed argument list.
+ // FixedArgNode can be an object or data node.
+ Status = AmlSetFixedArgument (
+ (AML_OBJECT_NODE*)ObjectNode,
+ TermIndex,
+ FixedArgNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ // Delete the sub-tree if the insertion failed.
+ // Otherwise its reference will be lost.
+ // Use DeleteTree because if the argument was a method invocation,
+ // multiple nodes have been created.
+ AmlDeleteTree (FixedArgNode);
+ return Status;
+ }
+
+ // Parse the AML bytecode of the FixedArgNode if this is an object node.
+ if (IS_AML_OBJECT_NODE (FixedArgNode) &&
+ !IS_END_OF_STREAM (&FixedArgFStream)) {
+ Status = AmlParseStream (
+ FixedArgNode,
+ &FixedArgFStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ // Move the stream forward as we have consumed the sub-stream.
+ Status = AmlStreamProgress (
+ FStream,
+ AmlStreamGetIndex (&FixedArgFStream)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ TermIndex++;
+ } // while
+
+ return EFI_SUCCESS;
+}
+
+/** Parse the variable list of arguments of the input ObjectNode.
+
+ For each variable argument, create a node and add it to the variable list of
+ arguments of the Node.
+ If a variable argument has children, parse them recursively.
+
+ The arguments of method invocation nodes are added to the variable list of
+ arguments of the method invocation node. It is necessary to first get
+ the number of arguments to parse for this kind of node. A method invocation
+ can have at most 7 fixed arguments.
+
+ @param [in] Node Node to parse the variable arguments
+ from.
+ @param [in] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseVariableArguments (
+ IN AML_NODE_HEADER * Node,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ BOOLEAN IsMethodInvocation;
+ UINT8 MethodInvocationArgCount;
+
+ AML_NODE_HEADER * VarArgNode;
+ AML_STREAM VarArgFStream;
+
+ if ((!AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_HAS_CHILD_OBJ
+ ) &&
+ !IS_AML_ROOT_NODE (Node)) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlGetMethodInvocationArgCount (
+ (CONST AML_OBJECT_NODE*)Node,
+ &IsMethodInvocation,
+ &MethodInvocationArgCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Parse variable arguments while the Stream is not empty.
+ while (!IS_END_OF_STREAM (FStream)) {
+ // If the number of variable arguments are counted, decrement the counter.
+ if ((IsMethodInvocation) && (MethodInvocationArgCount-- == 0)) {
+ return EFI_SUCCESS;
+ }
+
+ // Initialize a VarArgStream to parse the current variable argument.
+ Status = AmlStreamInitSubStream (FStream, &VarArgFStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Parse the current variable argument.
+ Status = AmlParseArgument (
+ Node,
+ EAmlObject,
+ &VarArgFStream,
+ NameSpaceRefList,
+ &VarArgNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the variable argument to its parent variable list of arguments.
+ // VarArgNode can be an object or data node.
+ Status = AmlVarListAddTailInternal (
+ (AML_NODE_HEADER*)Node,
+ VarArgNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ // Delete the sub-tree if the insertion failed.
+ // Otherwise its reference will be lost.
+ // Use DeleteTree because if the argument was a method invocation,
+ // multiple nodes have been created.
+ AmlDeleteTree (VarArgNode);
+ return Status;
+ }
+
+ // Parse the AML bytecode of the VarArgNode if this is an object node.
+ if (IS_AML_OBJECT_NODE (VarArgNode) &&
+ (!IS_END_OF_STREAM (&VarArgFStream))) {
+ Status = AmlParseStream (VarArgNode, &VarArgFStream, NameSpaceRefList);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ // Move the stream forward as we have consumed the sub-stream.
+ Status = AmlStreamProgress (
+ FStream,
+ AmlStreamGetIndex (&VarArgFStream)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // while
+
+ // If the number of variable arguments are counted, check all the
+ // MethodInvocationArgCount have been parsed.
+ if (IsMethodInvocation && (MethodInvocationArgCount != 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/** Parse the AML stream and populate the root node.
+
+ @param [in] RootNode RootNode to which the children are
+ added.
+ @param [in, out] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlPopulateRootNode (
+ IN AML_ROOT_NODE * RootNode,
+ IN OUT AML_STREAM * FStream,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ if (!IS_AML_ROOT_NODE (RootNode) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // A Root Node only has variable arguments.
+ Status = AmlParseVariableArguments (
+ (AML_NODE_HEADER*)RootNode,
+ FStream,
+ NameSpaceRefList
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Parse the AML stream an populate the object node.
+
+ @param [in] ObjectNode ObjectNode to which the children are
+ added.
+ @param [in, out] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in, out] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlPopulateObjectNode (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN OUT AML_STREAM * FStream,
+ IN OUT LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ if (!IS_AML_OBJECT_NODE (ObjectNode) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream) ||
+ (NameSpaceRefList == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_SUCCESS;
+
+ // Don't parse the fixed arguments of method invocation nodes.
+ // The AML encoding for method invocations in the ACPI specification 6.3 is:
+ // MethodInvocation := NameString TermArgList
+ // Since the AML specification does not define an OpCode for method
+ // invocation, this AML parser defines a pseudo opcode and redefines the
+ // grammar for simplicity as:
+ // MethodInvocation := MethodInvocationOp NameString ArgumentCount TermArgList
+ // ArgumentCount := ByteData
+ // Due to this difference, the MethodInvocationOp and the fixed argument
+ // i.e. ArgumentCount is not available in the AML stream and need to be
+ // handled differently.
+ if (!AmlNodeCompareOpCode (ObjectNode, AML_METHOD_INVOC_OP, 0)) {
+ // Parse the fixed list of arguments.
+ Status = AmlParseFixedArguments (
+ ObjectNode,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ // Save the association [node reference/pathname] in the NameSpaceRefList.
+ // This allows to identify method invocations from other namespace
+ // paths. Method invocation need to be parsed differently.
+ if (AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)ObjectNode,
+ AML_IN_NAMESPACE)) {
+ Status = AmlAddNameSpaceReference (
+ (CONST AML_OBJECT_NODE*)ObjectNode,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ if (!IS_END_OF_STREAM (FStream)) {
+ // Parse the variable list of arguments if present.
+ if (AmlNodeHasAttribute (ObjectNode, AML_HAS_CHILD_OBJ)) {
+ Status = AmlParseVariableArguments (
+ (AML_NODE_HEADER*)ObjectNode,
+ FStream,
+ NameSpaceRefList
+ );
+ } else if (AmlNodeHasAttribute (ObjectNode, AML_HAS_BYTE_LIST)) {
+ // Parse the byte list if present.
+ Status = AmlParseByteList (
+ ObjectNode,
+ FStream
+ );
+ } else if (AmlNodeHasAttribute (ObjectNode, AML_HAS_FIELD_LIST)) {
+ // Parse the field list if present.
+ Status = AmlParseFieldList (
+ ObjectNode,
+ FStream,
+ NameSpaceRefList
+ );
+ }
+
+ // Check status and assert
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ }
+
+ return Status;
+}
+
+/** Invoke the appropriate parsing functions based on the Node type.
+
+ @param [in] Node Node from which the children are parsed.
+ Must be a root node or an object node.
+ @param [in] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlParseStream (
+ IN AML_NODE_HEADER * Node,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ )
+{
+ EFI_STATUS Status;
+
+ if (IS_AML_ROOT_NODE (Node)) {
+ Status = AmlPopulateRootNode (
+ (AML_ROOT_NODE*)Node,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ } else if (IS_AML_OBJECT_NODE (Node)) {
+ Status = AmlPopulateObjectNode (
+ (AML_OBJECT_NODE*)Node,
+ FStream,
+ NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+
+ } else {
+ // Data node or other.
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/** Parse the definition block.
+
+ This function parses the whole AML blob. It starts with the ACPI DSDT/SSDT
+ header and then parses the AML bytestream.
+ A tree structure is returned via the RootPtr.
+ The tree must be deleted with the AmlDeleteTree function.
+
+ @param [in] DefinitionBlock Pointer to the definition block.
+ @param [out] RootPtr Pointer to the root node of the tree.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseDefinitionBlock (
+ IN CONST EFI_ACPI_DESCRIPTION_HEADER * DefinitionBlock,
+ OUT AML_ROOT_NODE ** RootPtr
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ AML_STREAM Stream;
+ AML_ROOT_NODE * Root;
+
+ LIST_ENTRY NameSpaceRefList;
+
+ UINT8 * Buffer;
+ UINT32 MaxBufferSize;
+
+ if ((DefinitionBlock == NULL) ||
+ (RootPtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = (UINT8*)DefinitionBlock + sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+ if (DefinitionBlock->Length < sizeof (EFI_ACPI_DESCRIPTION_HEADER)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ MaxBufferSize = DefinitionBlock->Length -
+ (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+
+ // Create a root node.
+ Status = AmlCreateRootNode (
+ (EFI_ACPI_DESCRIPTION_HEADER*)DefinitionBlock,
+ &Root
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ *RootPtr = Root;
+
+ if (MaxBufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // Initialize a stream to parse the AML bytecode.
+ Status = AmlStreamInit (
+ &Stream,
+ Buffer,
+ MaxBufferSize,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Initialize the NameSpaceRefList, holding references to nodes declaring
+ // a name in the AML namespace.
+ InitializeListHead (&NameSpaceRefList);
+
+ // Parse the whole AML blob.
+ Status = AmlParseStream (
+ (AML_NODE_HEADER*)Root,
+ &Stream,
+ &NameSpaceRefList
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Check the whole AML blob has been parsed.
+ if (!IS_END_OF_STREAM (&Stream)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ // Print the list of NameSpace reference nodes.
+ // AmlDbgPrintNameSpaceRefList (&NameSpaceRefList);
+
+ // Delete the NameSpaceRefList
+ goto exit_handler;
+
+error_handler:
+ if (Root != NULL) {
+ AmlDeleteTree ((AML_NODE_HEADER*)Root);
+ }
+
+exit_handler:
+ Status1 = AmlDeleteNameSpaceRefList (&NameSpaceRefList);
+ if (EFI_ERROR (Status1)) {
+ ASSERT (0);
+ if (!EFI_ERROR (Status)) {
+ return Status1;
+ }
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h
new file mode 100644
index 00000000000..d512f703954
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlParser.h
@@ -0,0 +1,72 @@
+/** @file
+ AML Parser.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_PARSER_H_
+#define AML_PARSER_H_
+
+#include <AmlNodeDefines.h>
+#include <Stream/AmlStream.h>
+
+/** Parse the list of fixed arguments of the input ObjectNode.
+
+ For each argument, create a node and add it to the fixed argument list
+ of the Node.
+ If a fixed argument has children, parse them.
+
+ @param [in] ObjectNode Object node to parse the fixed arguments
+ from.
+ @param [in] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseFixedArguments (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ );
+
+/** Parse the variable list of arguments of the input ObjectNode.
+
+ For each variable argument, create a node and add it to the variable list of
+ arguments of the Node.
+ If a variable argument has children, parse them recursively.
+
+ The arguments of method invocation nodes are added to the variable list of
+ arguments of the method invocation node. It is necessary to first get
+ the number of arguments to parse for this kind of node. A method invocation
+ can have at most 7 fixed arguments.
+
+ @param [in] Node Node to parse the variable arguments
+ from.
+ @param [in] FStream Forward stream containing the AML
+ bytecode to parse.
+ The stream must not be at its end.
+ @param [in] NameSpaceRefList List of namespace reference nodes.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseVariableArguments (
+ IN AML_NODE_HEADER * Node,
+ IN AML_STREAM * FStream,
+ IN LIST_ENTRY * NameSpaceRefList
+ );
+
+#endif // AML_PARSER_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.c
new file mode 100644
index 00000000000..6209fc65852
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.c
@@ -0,0 +1,328 @@
+/** @file
+ AML Resource Data Parser.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Rd or RD - Resource Data
+ - Rds or RDS - Resource Data Small
+ - Rdl or RDL - Resource Data Large
+**/
+
+#include <Parser/AmlResourceDataParser.h>
+
+#include <AmlCoreInterface.h>
+#include <AmlDbgPrint/AmlDbgPrint.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+
+/** Get the size of a resource data element using a stream.
+
+ If the resource data element is of the large type, the Header
+ is expected to be at least 3 bytes long.
+
+ The use of a stream makes this function safer
+ than the version without stream.
+
+ @param [in] FStream Forward stream pointing to a resource data
+ element.
+ The stream must not be at its end.
+
+ @return The size of the resource data element.
+ Zero if error.
+**/
+UINT32
+EFIAPI
+AmlRdStreamGetRdSize (
+ IN CONST AML_STREAM * FStream
+ )
+{
+ CONST AML_RD_HEADER * CurrRdElement;
+
+ if (!IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream)) {
+ ASSERT (0);
+ return 0;
+ }
+
+ CurrRdElement = (CONST AML_RD_HEADER*)AmlStreamGetCurrPos (FStream);
+ if (CurrRdElement == NULL) {
+ ASSERT (0);
+ return 0;
+ }
+
+ // If the resource data element is of the large type, check for overflow.
+ if (AML_RD_IS_LARGE (CurrRdElement) &&
+ (AmlStreamGetFreeSpace (FStream) <
+ sizeof (ACPI_LARGE_RESOURCE_HEADER))) {
+ return 0;
+ }
+
+ return AmlRdGetSize (CurrRdElement);
+}
+
+/** Check the nesting of resource data elements that are dependent
+ function descriptors.
+
+ @param [in] FStream Forward stream pointing to a resource data
+ element. The stream is not
+ modified/progressing.
+ The stream must not be at its end.
+ @param [in, out] InFunctionDesc Pointer holding the nesting of the
+ resource data buffer.
+ InFunctionDesc holds TRUE if the resource
+ data at the address of Buffer is currently
+ in a dependent function descriptor list.
+
+ @retval FALSE The Header being parsed is ending a function descriptor
+ list when none started. This should not be possible for a
+ resource data buffer.
+ @retval TRUE Otherwise.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+AmlRdCheckFunctionDescNesting (
+ IN CONST AML_STREAM * FStream,
+ IN OUT BOOLEAN * InFunctionDesc
+ )
+{
+ CONST AML_RD_HEADER * CurrRdElement;
+
+ if (!IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ (InFunctionDesc == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ CurrRdElement = AmlStreamGetCurrPos (FStream);
+ if (CurrRdElement == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Starting a dependent function descriptor.
+ // It is possible to start one when one has already started.
+ if (AmlRdCompareDescId (
+ CurrRdElement,
+ AML_RD_BUILD_SMALL_DESC_ID (
+ ACPI_SMALL_START_DEPENDENT_DESCRIPTOR_NAME))) {
+ *InFunctionDesc = TRUE;
+ return TRUE;
+ }
+
+ // Ending a dependent function descriptor.
+ if (AmlRdCompareDescId (
+ CurrRdElement,
+ AML_RD_BUILD_SMALL_DESC_ID (
+ ACPI_SMALL_END_DEPENDENT_DESCRIPTOR_NAME))) {
+ if (*InFunctionDesc) {
+ *InFunctionDesc = FALSE;
+ return TRUE;
+ }
+
+ // It should not be possible to end a dependent function descriptor
+ // when none started.
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/** Check whether the input stream is pointing to a valid list
+ of resource data elements.
+
+ The check is based on the size of resource data elements.
+ This means that a buffer can pass this check with non-existing descriptor Ids
+ that have a correct size.
+
+ A list of resource data elements can contain one unique resource data
+ element, without an end tag resource data. This is the case for
+ a FieldList.
+
+ @param [in] FStream Forward stream ideally pointing to a resource
+ data element. The stream is not
+ modified/progressing.
+ The stream must not be at its end.
+
+ @retval TRUE The buffer is holding a valid list of resource data elements.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlRdIsResourceDataBuffer (
+ IN CONST AML_STREAM * FStream
+ )
+{
+ EFI_STATUS Status;
+ UINT32 FreeSpace;
+ AML_STREAM SubStream;
+ CONST AML_RD_HEADER * CurrRdElement;
+ UINT32 CurrRdElementSize;
+ BOOLEAN InFunctionDesc;
+
+ if (!IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Create a sub-stream from the input stream to leave it untouched.
+ Status = AmlStreamInitSubStream (FStream, &SubStream);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ CurrRdElement = AmlStreamGetCurrPos (&SubStream);
+ if (CurrRdElement == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // The first element cannot be an end tag.
+ if (AmlRdCompareDescId (
+ CurrRdElement,
+ AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) {
+ return FALSE;
+ }
+
+ InFunctionDesc = FALSE;
+ while (TRUE) {
+ FreeSpace = AmlStreamGetFreeSpace (&SubStream);
+ CurrRdElement = AmlStreamGetCurrPos (&SubStream);
+ CurrRdElementSize = AmlRdStreamGetRdSize (&SubStream);
+ if ((FreeSpace == 0) ||
+ (CurrRdElement == NULL) ||
+ (CurrRdElementSize == 0)) {
+ return FALSE;
+ }
+
+ if (!AmlRdCheckFunctionDescNesting (&SubStream, &InFunctionDesc)) {
+ return FALSE;
+ }
+
+ if (CurrRdElementSize > FreeSpace) {
+ return FALSE;
+ } else if (CurrRdElementSize == FreeSpace) {
+ return TRUE;
+ }
+
+ // @todo Might want to check the CRC when available.
+ // An end tag resource data element must be the last element of the list.
+ // Thus the function should have already returned.
+ if (AmlRdCompareDescId (
+ CurrRdElement,
+ AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) {
+ return FALSE;
+ }
+
+ Status = AmlStreamProgress (&SubStream, CurrRdElementSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+ } // while
+
+ return FALSE;
+}
+
+/** Parse a ResourceDataBuffer.
+
+ For each resource data element, create a data node
+ and add them to the variable list of arguments of the BufferNode.
+
+ The input stream is expected to point to a valid list of resource data
+ elements. A function is available to check it for the caller.
+
+ @param [in] BufferNode Buffer node.
+ @param [in] FStream Forward stream pointing to a resource data
+ element.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseResourceData (
+ IN AML_OBJECT_NODE * BufferNode,
+ IN AML_STREAM * FStream
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * NewNode;
+ UINT32 FreeSpace;
+ CONST AML_RD_HEADER * CurrRdElement;
+ UINT32 CurrRdElementSize;
+
+ // Check that BufferNode is an ObjectNode and has a ByteList.
+ if (!AmlNodeHasAttribute (BufferNode, AML_HAS_BYTE_LIST) ||
+ !IS_STREAM (FStream) ||
+ IS_END_OF_STREAM (FStream) ||
+ !IS_STREAM_FORWARD (FStream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Iterate through the resource data elements and create nodes.
+ // We assume the Buffer has already been validated as a list of
+ // resource data elements, so less checks are made.
+ while (TRUE) {
+ FreeSpace = AmlStreamGetFreeSpace (FStream);
+ if (FreeSpace == 0) {
+ break;
+ }
+
+ CurrRdElement = (CONST AML_RD_HEADER*)AmlStreamGetCurrPos (FStream);
+ CurrRdElementSize = AmlRdStreamGetRdSize (FStream);
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeResourceData,
+ (CONST UINT8*)CurrRdElement,
+ CurrRdElementSize,
+ &NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlVarListAddTailInternal (
+ (AML_NODE_HEADER*)BufferNode,
+ (AML_NODE_HEADER*)NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ AmlDeleteTree ((AML_NODE_HEADER*)NewNode);
+ return Status;
+ }
+
+ Status = AmlStreamProgress (FStream, CurrRdElementSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ AMLDBG_DUMP_RAW (CurrRdElement, CurrRdElementSize);
+
+ // Exit the loop when finding the resource data end tag.
+ if (AmlRdCompareDescId (
+ CurrRdElement,
+ AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) {
+ if (FreeSpace != CurrRdElementSize) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+ } // while
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.h
new file mode 100644
index 00000000000..b0eb7084df4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Parser/AmlResourceDataParser.h
@@ -0,0 +1,71 @@
+/** @file
+ AML Resource Data Parser.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Rd or RD - Resource Data
+ - Rds or RDS - Resource Data Small
+ - Rdl or RDL - Resource Data Large
+**/
+
+#ifndef AML_RESOURCE_DATA_PARSER_H_
+#define AML_RESOURCE_DATA_PARSER_H_
+
+#include <AmlNodeDefines.h>
+#include <Stream/AmlStream.h>
+#include <ResourceData/AmlResourceData.h>
+
+/** Check whether the input stream is pointing to a valid list
+ of resource data elements.
+
+ The check is based on the size of resource data elements.
+ This means that a buffer can pass this check with non-existing descriptor Ids
+ that have a correct size.
+
+ A list of resource data elements can contain one unique resource data
+ element, without an end tag resource data. This is the case for
+ a FieldList.
+
+ @param [in] FStream Forward stream ideally pointing to a resource
+ data element. The stream is not
+ modified/progressing.
+ The stream must not be at its end.
+
+ @retval TRUE The buffer is holding a valid list of resource data elements.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlRdIsResourceDataBuffer (
+ IN CONST AML_STREAM * FStream
+ );
+
+/** Parse a ResourceDataBuffer.
+
+ For each resource data element, create a data node
+ and add them to the variable list of arguments of the BufferNode.
+
+ The input stream is expected to point to a valid list of resource data
+ elements. A function is available to check it for the caller.
+
+ @param [in] BufferNode Buffer node.
+ @param [in] FStream Forward stream pointing to a resource data
+ element.
+ The stream must not be at its end.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseResourceData (
+ IN AML_OBJECT_NODE * BufferNode,
+ IN AML_STREAM * FStream
+ );
+
+#endif // AML_RESOURCE_DATA_PARSER_H_
+
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.c
new file mode 100644
index 00000000000..06446feb3d3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.c
@@ -0,0 +1,103 @@
+/** @file
+ AML Resource Data.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Rd or RD - Resource Data
+ - Rds or RDS - Resource Data Small
+ - Rdl or RDL - Resource Data Large
+**/
+
+#include <ResourceData/AmlResourceData.h>
+
+/** Check whether the resource data has the input descriptor Id.
+
+ The small/large bit is included in the descriptor Id,
+ but the size bits are not included for small resource data elements.
+
+ @param [in] Header Pointer to the first byte of a resource data
+ element.
+ @param [in] DescriptorId The descriptor to check against.
+
+ @retval TRUE The resource data has the descriptor Id.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlRdCompareDescId (
+ IN CONST AML_RD_HEADER * Header,
+ IN AML_RD_HEADER DescriptorId
+ )
+{
+ if (Header == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ if (AML_RD_IS_LARGE (Header)) {
+ return ((*Header ^ DescriptorId) == 0);
+ } else {
+ return (((*Header & AML_RD_SMALL_ID_MASK) ^ DescriptorId) == 0);
+ }
+}
+
+/** Get the descriptor Id of the resource data.
+
+ The small/large bit is included in the descriptor Id,
+ but the size bits are not included for small resource data elements.
+
+ @param [in] Header Pointer to the first byte of a resource data.
+
+ @return A descriptor Id.
+**/
+AML_RD_HEADER
+EFIAPI
+AmlRdGetDescId (
+ IN CONST AML_RD_HEADER * Header
+ )
+{
+ if (Header == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ if (AML_RD_IS_LARGE (Header)) {
+ return *Header;
+ }
+
+ // Header is a small resource data element.
+ return *Header & AML_RD_SMALL_ID_MASK;
+}
+
+/** Get the size of a resource data element.
+
+ If the resource data element is of the large type, the Header
+ is expected to be at least 3 bytes long.
+
+ @param [in] Header Pointer to the first byte of a resource data.
+
+ @return The size of the resource data element.
+**/
+UINT32
+EFIAPI
+AmlRdGetSize (
+ IN CONST AML_RD_HEADER * Header
+ )
+{
+ if (Header == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ if (AML_RD_IS_LARGE (Header)) {
+ return ((ACPI_LARGE_RESOURCE_HEADER*)Header)->Length +
+ sizeof (ACPI_LARGE_RESOURCE_HEADER);
+ }
+
+ // Header is a small resource data element.
+ return ((ACPI_SMALL_RESOURCE_HEADER*)Header)->Bits.Length +
+ sizeof (ACPI_SMALL_RESOURCE_HEADER);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.h
new file mode 100644
index 00000000000..757c2a44ef1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/ResourceData/AmlResourceData.h
@@ -0,0 +1,174 @@
+/** @file
+ AML Resource Data.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Rd or RD - Resource Data
+ - Rds or RDS - Resource Data Small
+ - Rdl or RDL - Resource Data Large
+**/
+
+#ifndef AML_RESOURCE_DATA_H_
+#define AML_RESOURCE_DATA_H_
+
+/* This header file does not include internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions
+ must be included by the caller file. The function prototypes must
+ only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node
+ definitions.
+ This allows to keep the functions defined here both internal and
+ potentially external. If necessary, any function of this file can
+ be exposed externally.
+ The Api folder is internal to the AmlLib, but should only use these
+ functions. They provide a "safe" way to interact with the AmlLib.
+*/
+
+#include <AmlInclude.h>
+#include <IndustryStandard/Acpi.h>
+
+/**
+ @defgroup ResourceDataLibrary Resource data library
+ @ingroup AMLLib
+ @{
+ Resource data are defined in the ACPI 6.3 specification,
+ s6.4 "Resource Data Types for ACPI". They can be created in ASL via the
+ ResourceTemplate () statement, cf s19.3.3 "ASL Resource Templates".
+
+ Resource data can be of the small or large type. The difference between
+ small and large resource data elements is their encoding.
+
+ Resource data are stored in the variable list of arguments of object
+ nodes.
+ @}
+*/
+
+/** Resource Descriptor header for Small/Large Resource Data Object.
+ This is the first byte of a Small/Large Resource Data element.
+
+ Can be a ACPI_SMALL_RESOURCE_HEADER or ACPI_LARGE_RESOURCE_HEADER.
+
+ @ingroup ResourceDataStructures
+*/
+typedef UINT8 AML_RD_HEADER;
+
+/** Mask for the small resource data size.
+
+ @ingroup ResourceDataStructures
+*/
+#define AML_RD_SMALL_SIZE_MASK (0x7U)
+
+/** Mask for the small resource data ID.
+
+ @ingroup ResourceDataStructures
+*/
+#define AML_RD_SMALL_ID_MASK (0xFU << 3)
+
+/** Mask for the large resource data ID.
+
+ @ingroup ResourceDataStructures
+*/
+#define AML_RD_LARGE_ID_MASK (0x7FU)
+
+/**
+ @defgroup ResourceDataApis Resource data APIs
+ @ingroup ResourceDataLibrary
+ @{
+ Resource data APIs allow to manipulate/decode resource data elements.
+ @}
+*/
+
+/** Check whether a resource data is of the large type.
+
+ @ingroup ResourceDataApis
+
+ @param [in] Header Pointer to the first byte of a resource data.
+
+ @retval TRUE If the resource data is of the large type.
+ @retval FALSE Otherwise.
+**/
+#define AML_RD_IS_LARGE(Header) \
+ (((ACPI_SMALL_RESOURCE_HEADER*)Header)->Bits.Type == \
+ ACPI_LARGE_ITEM_FLAG)
+
+/** Build a small resource data descriptor Id.
+ The small/large bit is included in the descriptor Id,
+ but the size bits are not included.
+
+ @ingroup ResourceDataApis
+
+ @param [in] Id Descriptor Id.
+
+ @return A descriptor Id.
+**/
+#define AML_RD_BUILD_SMALL_DESC_ID(Id) ((AML_RD_HEADER)((Id & 0xF) << 3))
+
+/** Build a large resource data descriptor Id.
+ The small/large bit is included in the descriptor Id.
+
+ @ingroup ResourceDataApis
+
+ @param [in] Id Id of the descriptor.
+
+ @return A descriptor Id.
+**/
+#define AML_RD_BUILD_LARGE_DESC_ID(Id) ((AML_RD_HEADER)((BIT7) | Id))
+
+/** Check whether the resource data has the input descriptor Id.
+
+ The small/large bit is included in the descriptor Id,
+ but the size bits are not included for small resource data elements.
+
+ @ingroup ResourceDataApis
+
+ @param [in] Header Pointer to the first byte of a resource data
+ element.
+ @param [in] DescriptorId The descriptor to check against.
+
+ @retval TRUE The resource data has the descriptor Id.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlRdCompareDescId (
+ IN CONST AML_RD_HEADER * Header,
+ IN AML_RD_HEADER DescriptorId
+ );
+
+/** Get the descriptor Id of the resource data.
+
+ The small/large bit is included in the descriptor Id,
+ but the size bits are not included for small resource data elements.
+
+ @ingroup ResourceDataApis
+
+ @param [in] Header Pointer to the first byte of a resource data.
+
+ @return A descriptor Id.
+**/
+AML_RD_HEADER
+EFIAPI
+AmlRdGetDescId (
+ IN CONST AML_RD_HEADER * Header
+ );
+
+/** Get the size of a resource data element.
+
+ If the resource data element is of the large type, the Header
+ is expected to be at least 3 bytes long.
+
+ @ingroup ResourceDataApis
+
+ @param [in] Header Pointer to the first byte of a resource data.
+
+ @return The size of the resource data element.
+**/
+UINT32
+EFIAPI
+AmlRdGetSize (
+ IN CONST AML_RD_HEADER * Header
+ );
+
+#endif // AML_RESOURCE_DATA_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c
new file mode 100644
index 00000000000..7f86d646a4c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Serialize/AmlSerialize.c
@@ -0,0 +1,324 @@
+/** @file
+ AML Serialize.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+
+#include <AmlCoreInterface.h>
+#include <Stream/AmlStream.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+#include <Utils/AmlUtility.h>
+
+/** Callback function to copy the AML bytecodes contained in a node
+ to the Stream stored in the Context.
+ The SDT header data contained in the root node is not serialized
+ by this function.
+
+ @param [in] Node Pointer to the node to copy the AML bytecodes
+ from.
+ @param [in, out] Context Contains a forward Stream to write to.
+ (AML_STREAM*)Context.
+ @param [in, out] Status At entry, contains the status returned by the
+ last call to this exact function during the
+ enumeration.
+ As exit, contains the returned status of the
+ call to this function.
+ Optional, can be NULL.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+AmlSerializeNodeCallback (
+ IN AML_NODE_HEADER * Node,
+ IN OUT VOID * Context, OPTIONAL
+ IN OUT EFI_STATUS * Status OPTIONAL
+ )
+{
+ EFI_STATUS Status1;
+
+ CONST AML_DATA_NODE * DataNode;
+ CONST AML_OBJECT_NODE * ObjectNode;
+ AML_STREAM * FStream;
+
+ // Bytes needed to store OpCode[1] + SubOpcode[1] + MaxPkgLen[4] = 6 bytes.
+ UINT8 ObjectNodeInfoArray[6];
+ UINT32 Index;
+ BOOLEAN ContinueEnum;
+
+ CONST AML_OBJECT_NODE * ParentNode;
+ EAML_PARSE_INDEX IndexPtr;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (Context == NULL)) {
+ ASSERT (0);
+ Status1 = EFI_INVALID_PARAMETER;
+ ContinueEnum = FALSE;
+ goto error_handler;
+ }
+
+ // Ignore the second fixed argument of method invocation nodes
+ // as the information stored there (the argument count) is not in the
+ // ACPI specification.
+ ParentNode = (CONST AML_OBJECT_NODE*)AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (IS_AML_OBJECT_NODE (ParentNode) &&
+ AmlNodeCompareOpCode (ParentNode, AML_METHOD_INVOC_OP, 0) &&
+ AmlIsNodeFixedArgument (Node, &IndexPtr)) {
+ if (IndexPtr == EAmlParseIndexTerm1) {
+ if (Status != NULL) {
+ *Status = EFI_SUCCESS;
+ }
+ return TRUE;
+ }
+ }
+
+ Status1 = EFI_SUCCESS;
+ ContinueEnum = TRUE;
+ FStream = (AML_STREAM*)Context;
+
+ if (IS_AML_DATA_NODE (Node)) {
+ // Copy the content of the Buffer for a DataNode.
+ DataNode = (AML_DATA_NODE*)Node;
+ Status1 = AmlStreamWrite (
+ FStream,
+ DataNode->Buffer,
+ DataNode->Size
+ );
+ if (EFI_ERROR (Status1)) {
+ ASSERT (0);
+ ContinueEnum = FALSE;
+ goto error_handler;
+ }
+
+ } else if (IS_AML_OBJECT_NODE (Node) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IS_PSEUDO_OPCODE)) {
+ // Ignore pseudo-opcodes as they are not part of the
+ // ACPI specification.
+
+ ObjectNode = (AML_OBJECT_NODE*)Node;
+
+ Index = 0;
+ // Copy the opcode(s).
+ ObjectNodeInfoArray[Index++] = ObjectNode->AmlByteEncoding->OpCode;
+ if (ObjectNode->AmlByteEncoding->OpCode == AML_EXT_OP) {
+ ObjectNodeInfoArray[Index++] = ObjectNode->AmlByteEncoding->SubOpCode;
+ }
+
+ // Copy the PkgLen.
+ if (AmlNodeHasAttribute (ObjectNode, AML_HAS_PKG_LENGTH)) {
+ Index += AmlSetPkgLength (
+ ObjectNode->PkgLen,
+ &ObjectNodeInfoArray[Index]
+ );
+ }
+
+ Status1 = AmlStreamWrite (
+ FStream,
+ ObjectNodeInfoArray,
+ Index
+ );
+ if (EFI_ERROR (Status1)) {
+ ASSERT (0);
+ ContinueEnum = FALSE;
+ goto error_handler;
+ }
+ } // IS_AML_OBJECT_NODE (Node)
+
+error_handler:
+ if (Status != NULL) {
+ *Status = Status1;
+ }
+ return ContinueEnum;
+}
+
+/** Serialize a tree to create an ACPI DSDT/SSDT table.
+
+ If:
+ - the content of BufferSize is >= to the size needed to serialize the
+ definition block;
+ - Buffer is not NULL;
+ first serialize the ACPI DSDT/SSDT header from the root node,
+ then serialize the AML blob from the rest of the tree.
+
+ The content of BufferSize is always updated to the size needed to
+ serialize the definition block.
+
+ @param [in] RootNode Pointer to a root node.
+ @param [in] Buffer Buffer to write the DSDT/SSDT table to.
+ If Buffer is NULL, the size needed to
+ serialize the DSDT/SSDT table is returned
+ in BufferSize.
+ @param [in, out] BufferSize Pointer holding the size of the Buffer.
+ Its content is always updated to the size
+ needed to serialize the DSDT/SSDT table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlSerializeTree (
+ IN AML_ROOT_NODE * RootNode,
+ IN UINT8 * Buffer, OPTIONAL
+ IN OUT UINT32 * BufferSize
+ )
+{
+ EFI_STATUS Status;
+ AML_STREAM FStream;
+ UINT32 TableSize;
+
+ if (!IS_AML_ROOT_NODE (RootNode) ||
+ (BufferSize == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Compute the total size of the AML blob.
+ Status = AmlComputeSize (
+ (CONST AML_NODE_HEADER*)RootNode,
+ &TableSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Add the size of the ACPI header.
+ TableSize += (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+
+ // Check the size against the SDT header.
+ // The Length field in the SDT Header is updated if the tree has
+ // been modified.
+ if (TableSize != RootNode->SdtHeader->Length) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Buffer is not big enough, or NULL.
+ if ((TableSize < *BufferSize) || (Buffer == NULL)) {
+ *BufferSize = TableSize;
+ return EFI_SUCCESS;
+ }
+
+ // Initialize the stream to the TableSize that is needed.
+ Status = AmlStreamInit (
+ &FStream,
+ Buffer,
+ TableSize,
+ EAmlStreamDirectionForward
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Serialize the header.
+ Status = AmlStreamWrite (
+ &FStream,
+ (UINT8*)RootNode->SdtHeader,
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER)
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = EFI_SUCCESS;
+ AmlEnumTree (
+ (AML_NODE_HEADER*)RootNode,
+ AmlSerializeNodeCallback,
+ (VOID*)&FStream,
+ &Status
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Update the checksum.
+ return AcpiPlatformChecksum ((EFI_ACPI_DESCRIPTION_HEADER*)Buffer);
+}
+
+/** Serialize an AML definition block.
+
+ This functions allocates memory with the "AllocateZeroPool ()"
+ function. This memory is used to serialize the AML tree and is
+ returned in the Table.
+
+ @param [in] RootNode Root node of the tree.
+ @param [out] Table On return, hold the serialized
+ definition block.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlSerializeDefinitionBlock (
+ IN AML_ROOT_NODE * RootNode,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ )
+{
+ EFI_STATUS Status;
+ UINT8 * TableBuffer;
+ UINT32 TableSize;
+
+ if (!IS_AML_ROOT_NODE (RootNode) ||
+ (Table == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Table = NULL;
+ TableBuffer = NULL;
+ TableSize = 0;
+
+ // Get the size of the SSDT table.
+ Status = AmlSerializeTree (
+ RootNode,
+ TableBuffer,
+ &TableSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ TableBuffer = (UINT8*)AllocateZeroPool (TableSize);
+ if (TableBuffer == NULL) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: Failed to allocate memory for Table Buffer."
+ ));
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Serialize the tree to a SSDT table.
+ Status = AmlSerializeTree (
+ RootNode,
+ TableBuffer,
+ &TableSize
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (TableBuffer);
+ ASSERT (0);
+ } else {
+ // Save the allocated Table buffer in the table list
+ *Table = (EFI_ACPI_DESCRIPTION_HEADER*)TableBuffer;
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c
new file mode 100644
index 00000000000..db5a9a135b8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.c
@@ -0,0 +1,665 @@
+/** @file
+ AML Stream.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Stream/AmlStream.h>
+
+/** Initialize a stream.
+
+ @param [in, out] Stream Pointer to the stream to initialize.
+ @param [in] Buffer Buffer to initialize Stream with.
+ Point to the beginning of the Buffer.
+ @param [in] MaxBufferSize Maximum size of Buffer.
+ @param [in] Direction Direction Stream is progressing
+ (forward, backward).
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamInit (
+ IN OUT AML_STREAM * Stream,
+ IN UINT8 * Buffer,
+ IN UINT32 MaxBufferSize,
+ IN EAML_STREAM_DIRECTION Direction
+ )
+{
+ if ((Stream == NULL) ||
+ (Buffer == NULL) ||
+ (MaxBufferSize == 0) ||
+ ((Direction != EAmlStreamDirectionForward) &&
+ (Direction != EAmlStreamDirectionBackward))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Stream->Buffer = Buffer;
+ Stream->MaxBufferSize = MaxBufferSize;
+ Stream->Index = 0;
+ Stream->Direction = Direction;
+
+ return EFI_SUCCESS;
+}
+
+/** Clone a stream.
+
+ Cloning a stream means copying all the values of the input Stream
+ in the ClonedStream.
+
+ @param [in] Stream Pointer to the stream to clone.
+ @param [out] ClonedStream Pointer to the stream to initialize.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamClone (
+ IN CONST AML_STREAM * Stream,
+ OUT AML_STREAM * ClonedStream
+ )
+{
+ if (!IS_STREAM (Stream) ||
+ (ClonedStream == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ClonedStream->Buffer = Stream->Buffer;
+ ClonedStream->MaxBufferSize = Stream->MaxBufferSize;
+ ClonedStream->Index = Stream->Index;
+ ClonedStream->Direction = Stream->Direction;
+
+ return EFI_SUCCESS;
+}
+
+/** Initialize a sub-stream from a stream.
+
+ A sub-stream is a stream initialized at the current position of the input
+ stream:
+ - the Buffer field points to the current position of the input stream;
+ - the Index field is set to 0;
+ - the MaxBufferSize field is set to the remaining size of the input stream;
+ - the direction is conserved;
+
+ E.g.: For a forward stream:
+ +----------------+----------------+
+ |ABCD.........XYZ| Free Space |
+ +----------------+----------------+
+ ^ ^ ^
+ Stream: Buffer CurrPos EndOfBuff
+ Sub-stream: Buffer/CurrPos EndOfBuff
+
+ @param [in] Stream Pointer to the stream from which a sub-stream is
+ created.
+ @param [out] SubStream Pointer to the stream to initialize.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamInitSubStream (
+ IN CONST AML_STREAM * Stream,
+ OUT AML_STREAM * SubStream
+ )
+{
+ if (!IS_STREAM (Stream) ||
+ (SubStream == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IS_STREAM_FORWARD (Stream)) {
+ SubStream->Buffer = AmlStreamGetCurrPos (Stream);
+ } else if (IS_STREAM_BACKWARD (Stream)) {
+ SubStream->Buffer = Stream->Buffer;
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SubStream->MaxBufferSize = AmlStreamGetFreeSpace (Stream);
+ SubStream->Index = 0;
+ SubStream->Direction = Stream->Direction;
+
+ return EFI_SUCCESS;
+}
+
+/** Get the buffer of a stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return The stream's Buffer.
+ NULL otherwise.
+**/
+UINT8 *
+EFIAPI
+AmlStreamGetBuffer (
+ IN CONST AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return NULL;
+ }
+ return Stream->Buffer;
+}
+
+/** Get the size of Stream's Buffer.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return The Size of Stream's Buffer.
+ Return 0 if Stream is invalid.
+**/
+UINT32
+EFIAPI
+AmlStreamGetMaxBufferSize (
+ IN CONST AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return 0;
+ }
+ return Stream->MaxBufferSize;
+}
+
+/** Reduce the maximal size of Stream's Buffer (MaxBufferSize field).
+
+ @param [in] Stream Pointer to a stream.
+ @param [in] Diff Value to subtract to the Stream's MaxBufferSize.
+ 0 < x < MaxBufferSize - Index.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamReduceMaxBufferSize (
+ IN AML_STREAM * Stream,
+ IN UINT32 Diff
+ )
+{
+ if (!IS_STREAM (Stream) ||
+ (Diff == 0) ||
+ ((Stream->MaxBufferSize - Diff) <= Stream->Index)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Stream->MaxBufferSize -= Diff;
+ return EFI_SUCCESS;
+}
+
+/** Get Stream's Index.
+
+ Stream's Index is incremented when writing data, reading data,
+ or moving the position in the Stream.
+ It can be seen as an index:
+ - starting at the beginning of Stream's Buffer if the stream goes forward;
+ - starting at the end of Stream's Buffer if the stream goes backward.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return Stream's Index.
+ Return 0 if Stream is invalid.
+**/
+UINT32
+EFIAPI
+AmlStreamGetIndex (
+ IN CONST AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return 0;
+ }
+ return Stream->Index;
+}
+
+/** Get Stream's Direction.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return Stream's Direction.
+ Return EAmlStreamDirectionUnknown if Stream is invalid.
+**/
+EAML_STREAM_DIRECTION
+EFIAPI
+AmlStreamGetDirection (
+ IN CONST AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return EAmlStreamDirectionInvalid;
+ }
+ return Stream->Direction;
+}
+
+/** Return a pointer to the current position in the stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return The current position in the stream.
+ Return NULL if error.
+**/
+UINT8 *
+EFIAPI
+AmlStreamGetCurrPos (
+ IN CONST AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ if (IS_STREAM_FORWARD (Stream)) {
+ return Stream->Buffer + Stream->Index;
+ } else if (IS_STREAM_BACKWARD (Stream)) {
+ return Stream->Buffer + (Stream->MaxBufferSize - 1) - Stream->Index;
+ } else {
+ ASSERT (0);
+ return NULL;
+ }
+}
+
+/** Get the space available in the stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return Remaining space available in the stream.
+ Zero in case of error or if the stream is at its end.
+**/
+UINT32
+EFIAPI
+AmlStreamGetFreeSpace (
+ IN CONST AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return 0;
+ }
+
+ if (Stream->Index > Stream->MaxBufferSize) {
+ ASSERT (0);
+ return 0;
+ }
+
+ return Stream->MaxBufferSize - Stream->Index;
+}
+
+/** Move Stream by Offset bytes.
+
+ The stream current position is moved according to the stream direction
+ (forward, backward).
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [in] Offset Offset to move the stream of.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamProgress (
+ IN AML_STREAM * Stream,
+ IN UINT32 Offset
+ )
+{
+ if (!IS_STREAM (Stream) ||
+ IS_END_OF_STREAM (Stream) ||
+ (Offset == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (AmlStreamGetFreeSpace (Stream) < Offset) {
+ ASSERT (0);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Stream->Index += Offset;
+
+ return EFI_SUCCESS;
+}
+
+/** Rewind Stream of Offset bytes.
+
+ The stream current position is rewound according to the stream direction
+ (forward, backward). A stream going forward will be rewound backward.
+
+ @param [in] Stream Pointer to a stream.
+ @param [in] Offset Offset to rewind the stream of.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamRewind (
+ IN AML_STREAM * Stream,
+ IN UINT32 Offset
+ )
+{
+ if (!IS_STREAM (Stream) ||
+ (Offset == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (AmlStreamGetIndex (Stream) < Offset) {
+ ASSERT (0);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ Stream->Index -= Offset;
+
+ return EFI_SUCCESS;
+}
+
+/** Reset the Stream (move the current position to the initial position).
+
+ @param [in] Stream Pointer to a stream.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamReset (
+ IN AML_STREAM * Stream
+ )
+{
+ if (!IS_STREAM (Stream)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Stream->Index = 0;
+
+ return EFI_SUCCESS;
+}
+
+/** Peek one byte at Stream's current position.
+
+ Stream's position is not moved when peeking.
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [out] OutByte Pointer holding the byte value of
+ the stream current position.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamPeekByte (
+ IN AML_STREAM * Stream,
+ OUT UINT8 * OutByte
+ )
+{
+ UINT8 * CurPos;
+
+ if (!IS_STREAM (Stream) ||
+ IS_END_OF_STREAM (Stream) ||
+ (OutByte == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CurPos = AmlStreamGetCurrPos (Stream);
+ if (CurPos == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutByte = *CurPos;
+ return EFI_SUCCESS;
+}
+
+/** Read one byte at Stream's current position.
+
+ The stream current position is moved when reading.
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [out] OutByte Pointer holding the byte value of
+ the stream current position.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamReadByte (
+ IN AML_STREAM * Stream,
+ OUT UINT8 * OutByte
+ )
+{
+ EFI_STATUS Status;
+
+ if (!IS_STREAM (Stream) ||
+ IS_END_OF_STREAM (Stream) ||
+ (OutByte == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Stream is checked in the function call.
+ Status = AmlStreamPeekByte (Stream, OutByte);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlStreamProgress (Stream, 1);
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Write Size bytes in the stream.
+
+ If the stream goes backward (toward lower addresses), the bytes written
+ to the stream are not reverted.
+ In the example below, writing "Hello" to the stream will not revert
+ the string. The end of the stream buffer will contain "Hello world!".
+ Stream buffer:
+ +---------------+-----+-----+-----+-----+-----+-----+---- +------+
+ | ..... | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' |
+ +---------------+-----+-----+-----+-----+-----+-----+---- +------+
+ ^
+ Current position.
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [in] Buffer Pointer to the data to write.
+ @param [in] Size Number of bytes to write.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamWrite (
+ IN AML_STREAM * Stream,
+ IN CONST UINT8 * Buffer,
+ IN UINT32 Size
+ )
+{
+ UINT8 * CurrPos;
+
+ if (!IS_STREAM (Stream) ||
+ IS_END_OF_STREAM (Stream) ||
+ (Buffer == NULL) ||
+ (Size == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (AmlStreamGetFreeSpace (Stream) < Size) {
+ ASSERT (0);
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CurrPos = AmlStreamGetCurrPos (Stream);
+
+ // If the Stream goes backward, prepare some space to copy the data.
+ if (IS_STREAM_BACKWARD (Stream)) {
+ CurrPos -= Size;
+ }
+
+ CopyMem (CurrPos, Buffer, Size);
+ Stream->Index += Size;
+
+ return EFI_SUCCESS;
+}
+
+/** Compare Size bytes between Stream1 and Stream2 from their
+ respective current position.
+
+ Stream1 and Stream2 must go in the same direction.
+ Stream1 and Stream2 are left unchanged.
+
+ @param [in] Stream1 First stream to compare.
+ The stream must not be at its end.
+ @param [in] Stream2 Second stream to compare.
+ The stream must not be at its end.
+ @param [in] Size Number of bytes to compare.
+ Must be lower than the minimum remaining space of
+ Stream1 and Stream2.
+ Must be non-zero.
+
+ @retval TRUE If Stream1 and Stream2 have Size bytes equal,
+ from their respective current position.
+ The function completed successfully.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlStreamCmp (
+ IN CONST AML_STREAM * Stream1,
+ IN CONST AML_STREAM * Stream2,
+ IN UINT32 Size
+ )
+{
+ UINT32 MinSize;
+ UINT8 * CurrPosStream1;
+ UINT8 * CurrPosStream2;
+
+ if (!IS_STREAM (Stream1) ||
+ IS_END_OF_STREAM (Stream1) ||
+ !IS_STREAM (Stream2) ||
+ IS_END_OF_STREAM (Stream2) ||
+ (Stream1->Direction != Stream2->Direction) ||
+ (Size == 0)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Check the Size is not longer than the remaining size of
+ // Stream1 and Stream2.
+ MinSize = MIN (
+ AmlStreamGetFreeSpace (Stream1),
+ AmlStreamGetFreeSpace (Stream2)
+ );
+ if (MinSize < Size) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ CurrPosStream1 = AmlStreamGetCurrPos (Stream1);
+ if (CurrPosStream1 == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+ CurrPosStream2 = AmlStreamGetCurrPos (Stream2);
+ if (CurrPosStream2 == NULL) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ if (Stream1->Direction == EAmlStreamDirectionForward) {
+ return (0 == CompareMem (CurrPosStream1, CurrPosStream2, MinSize));
+ }
+
+ // The stream is already pointing on the last byte, thus the (-1).
+ // +---------------------+
+ // BStream | | | | | | | |M|E|T|0|
+ // +---------------------+
+ // ^
+ // CurrPos
+ return (0 == CompareMem (
+ CurrPosStream1 - (MinSize - 1),
+ CurrPosStream2 - (MinSize - 1),
+ MinSize
+ ));
+}
+
+/** Copy Size bytes of the stream's data to DstBuffer.
+
+ For a backward stream, the bytes are copied starting from the
+ current stream position.
+
+ @param [out] DstBuffer Destination Buffer to copy the data to.
+ @param [in] MaxDstBufferSize Maximum size of DstBuffer.
+ Must be non-zero.
+ @param [in] Stream Pointer to the stream to copy the data from.
+ @param [in] Size Number of bytes to copy from the stream
+ buffer.
+ Must be lower than MaxDstBufferSize.
+ Must be lower than Stream's MaxBufferSize.
+ Return success if zero.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamCpyS (
+ OUT CHAR8 * DstBuffer,
+ IN UINT32 MaxDstBufferSize,
+ IN AML_STREAM * Stream,
+ IN UINT32 Size
+ )
+{
+ CHAR8 * StreamBufferStart;
+
+ // Stream is checked in the function call.
+ if ((DstBuffer == NULL) ||
+ (MaxDstBufferSize == 0) ||
+ (Size > MaxDstBufferSize) ||
+ (Size > AmlStreamGetMaxBufferSize (Stream))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Size == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // Find the address at which the data is starting.
+ StreamBufferStart = (CHAR8*)(IS_STREAM_FORWARD (Stream) ?
+ Stream->Buffer :
+ AmlStreamGetCurrPos (Stream));
+
+ CopyMem (DstBuffer, StreamBufferStart, Size);
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h
new file mode 100644
index 00000000000..7b72e1d638b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Stream/AmlStream.h
@@ -0,0 +1,451 @@
+/** @file
+ AML Stream.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_STREAM_H_
+#define AML_STREAM_H_
+
+#include <AmlInclude.h>
+
+/** Stream direction.
+
+ Enum to choose the direction the stream is progressing.
+*/
+typedef enum EAmlStreamDirection {
+ EAmlStreamDirectionInvalid, ///< Invalid AML Stream direction.
+ EAmlStreamDirectionForward, ///< Forward direction.
+ /// The Stream goes toward higher addresses.
+ EAmlStreamDirectionBackward, ///< Forward direction.
+ /// The Stream goes toward lower addresses.
+ EAmlStreamDirectionMax, ///< Max enum.
+} EAML_STREAM_DIRECTION;
+
+/** Stream.
+
+ This structure is used as a wrapper around a buffer. It allows to do common
+ buffer manipulations (read, write, etc.) while preventing buffer overflows.
+*/
+typedef struct AmlStream {
+ /// Pointer to a buffer.
+ UINT8 * Buffer;
+
+ /// Size of Buffer.
+ UINT32 MaxBufferSize;
+
+ /// Index in the Buffer.
+ /// The Index field allows to keep track of how many bytes have been
+ /// read/written in the Buffer, and to retrieve the current stream position.
+ /// 0 <= Index <= MaxBufferSize.
+ /// If Index == MaxBufferSize, no more action is allowed on the stream.
+ UINT32 Index;
+
+ /// The direction the stream is progressing.
+ /// If the stream goes backward (toward lower addresses), the bytes written
+ /// to the stream are not reverted.
+ /// In the example below, writing "Hello" to the stream will not revert
+ /// the string. The end of the stream buffer will contain "Hello world!".
+ /// Similarly, moving the stream position will be done according to the
+ /// direction of the stream.
+ /// Stream buffer:
+ /// +---------------+-----+-----+-----+-----+-----+-----+---- +------+
+ /// |-------------- | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' |
+ /// +---------------+-----+-----+-----+-----+-----+-----+---- +------+
+ /// ^
+ /// Current position.
+ EAML_STREAM_DIRECTION Direction;
+} AML_STREAM;
+
+/** Check whether a StreamPtr is a valid Stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @retval TRUE Stream is a pointer to a stream.
+ @retval FALSE Otherwise.
+*/
+#define IS_STREAM(Stream) ( \
+ (((AML_STREAM*)Stream) != NULL) && \
+ (((AML_STREAM*)Stream)->Buffer != NULL))
+
+/** Check whether a Stream is at the end of its buffer.
+
+ @param [in] Stream Pointer to a stream.
+
+ @retval TRUE Stream is a pointer to a non-full stream.
+ @retval FALSE Otherwise.
+*/
+#define IS_END_OF_STREAM(Stream) ( \
+ (((AML_STREAM*)Stream)->Index == \
+ ((AML_STREAM*)Stream)->MaxBufferSize))
+
+/** Check Stream goes forward.
+
+ @param [in] Stream Pointer to a stream.
+
+ @retval TRUE Stream goes forward.
+ @retval FALSE Otherwise.
+*/
+#define IS_STREAM_FORWARD(Stream) ( \
+ ((AML_STREAM*)Stream)->Direction == EAmlStreamDirectionForward)
+
+/** Check Stream goes backward.
+
+ @param [in] Stream Pointer to a stream.
+
+ @retval TRUE Stream goes backward.
+ @retval FALSE Otherwise.
+*/
+#define IS_STREAM_BACKWARD(Stream) ( \
+ ((AML_STREAM*)Stream)->Direction == EAmlStreamDirectionBackward)
+
+/** Initialize a stream.
+
+ @param [in, out] Stream Pointer to the stream to initialize.
+ @param [in] Buffer Buffer to initialize Stream with.
+ Point to the beginning of the Buffer.
+ @param [in] MaxBufferSize Maximum size of Buffer.
+ @param [in] Direction Direction Stream is progressing
+ (forward, backward).
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamInit (
+ IN OUT AML_STREAM * Stream,
+ IN UINT8 * Buffer,
+ IN UINT32 MaxBufferSize,
+ IN EAML_STREAM_DIRECTION Direction
+ );
+
+/** Clone a stream.
+
+ Cloning a stream means copying all the values of the input Stream
+ in the ClonedStream.
+
+ @param [in] Stream Pointer to the stream to clone.
+ @param [in] ClonedStream Pointer to the stream to initialize.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamClone (
+ IN CONST AML_STREAM * Stream,
+ OUT AML_STREAM * ClonedStream
+ );
+
+/** Initialize a sub-stream from a stream.
+
+ A sub-stream is a stream initialized at the current position of the input
+ stream:
+ - the Buffer field points to the current position of the input stream;
+ - the Index field is set to 0;
+ - the MaxBufferSize field is set to the remaining size of the input stream;
+ - the direction is conserved;
+
+ E.g.: For a forward stream:
+ +----------------+----------------+
+ |ABCD.........XYZ| Free Space |
+ +----------------+----------------+
+ ^ ^ ^
+ Stream: Buffer CurrPos EndOfBuff
+ Sub-stream: Buffer/CurrPos EndOfBuff
+
+ @param [in] Stream Pointer to the stream from which a sub-stream is
+ created.
+ @param [in] SubStream Pointer to the stream to initialize.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamInitSubStream (
+ IN CONST AML_STREAM * Stream,
+ OUT AML_STREAM * SubStream
+ );
+
+/** Get the buffer of a stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return The stream's Buffer.
+ NULL otherwise.
+**/
+UINT8 *
+EFIAPI
+AmlStreamGetBuffer (
+ IN CONST AML_STREAM * Stream
+ );
+
+/** Get the size of Stream's Buffer.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return The Size of Stream's Buffer.
+ Return 0 if Stream is invalid.
+**/
+UINT32
+EFIAPI
+AmlStreamGetMaxBufferSize (
+ IN CONST AML_STREAM * Stream
+ );
+
+/** Reduce the maximal size of Stream's Buffer (MaxBufferSize field).
+
+ @param [in] Stream Pointer to a stream.
+ @param [in] Diff Value to subtract to the Stream's MaxBufferSize.
+ 0 < x < MaxBufferSize - Index.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamReduceMaxBufferSize (
+ IN AML_STREAM * Stream,
+ IN UINT32 Diff
+ );
+
+/** Get Stream's Index.
+
+ Stream's Index is incremented when writing data, reading data,
+ or moving the position in the Stream.
+ It can be seen as an index:
+ - starting at the beginning of Stream's Buffer if the stream goes forward;
+ - starting at the end of Stream's Buffer if the stream goes backward.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return Stream's Index.
+ Return 0 if Stream is invalid.
+**/
+UINT32
+EFIAPI
+AmlStreamGetIndex (
+ IN CONST AML_STREAM * Stream
+ );
+
+/** Get Stream's Direction.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return Stream's Direction.
+ Return EAmlStreamDirectionUnknown if Stream is invalid.
+**/
+EAML_STREAM_DIRECTION
+EFIAPI
+AmlStreamGetDirection (
+ IN CONST AML_STREAM * Stream
+ );
+
+/** Return a pointer to the current position in the stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return The current position in the stream.
+ Return NULL if error.
+**/
+UINT8 *
+EFIAPI
+AmlStreamGetCurrPos (
+ IN CONST AML_STREAM * Stream
+ );
+
+/** Get the space available in the stream.
+
+ @param [in] Stream Pointer to a stream.
+
+ @return Remaining space available in the stream.
+ Zero in case of error or if the stream is at its end.
+**/
+UINT32
+EFIAPI
+AmlStreamGetFreeSpace (
+ IN CONST AML_STREAM * Stream
+ );
+
+/** Move Stream by Offset bytes.
+
+ The stream current position is moved according to the stream direction
+ (forward, backward).
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [in] Offset Offset to move the stream of.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamProgress (
+ IN AML_STREAM * Stream,
+ IN UINT32 Offset
+ );
+
+/** Rewind Stream of Offset bytes.
+
+ The stream current position is rewound according to the stream direction
+ (forward, backward). A stream going forward will be rewound backward.
+
+ @param [in] Stream Pointer to a stream.
+ @param [in] Offset Offset to rewind the stream of.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamRewind (
+ IN AML_STREAM * Stream,
+ IN UINT32 Offset
+ );
+
+/** Reset the Stream (move the current position to the initial position).
+
+ @param [in] Stream Pointer to a stream.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamReset (
+ IN AML_STREAM * Stream
+ );
+
+/** Peek one byte at Stream's current position.
+
+ Stream's position is not moved when peeking.
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [out] OutByte Pointer holding the byte value of
+ the stream current position.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamPeekByte (
+ IN AML_STREAM * Stream,
+ OUT UINT8 * OutByte
+ );
+
+/** Read one byte at Stream's current position.
+
+ The stream current position is moved when reading.
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [out] OutByte Pointer holding the byte value of
+ the stream current position.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamReadByte (
+ IN AML_STREAM * Stream,
+ OUT UINT8 * OutByte
+ );
+
+/** Write Size bytes in the stream.
+
+ If the stream goes backward (toward lower addresses), the bytes written
+ to the stream are not reverted.
+ In the example below, writing "Hello" to the stream will not revert
+ the string. The end of the stream buffer will contain "Hello world!".
+ Stream buffer:
+ +---------------+-----+-----+-----+-----+-----+-----+---- +------+
+ | ..... | ' ' | 'w' | 'o' | 'r' | 'l' | 'd' | '!' | '\0' |
+ +---------------+-----+-----+-----+-----+-----+-----+---- +------+
+ ^
+ Current position.
+
+ @param [in] Stream Pointer to a stream.
+ The stream must not be at its end.
+ @param [in] Buffer Pointer to the data to write.
+ @param [in] Size Number of bytes to write.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_BUFFER_TOO_SMALL No space left in the buffer.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamWrite (
+ IN AML_STREAM * Stream,
+ IN CONST UINT8 * Buffer,
+ IN UINT32 Size
+ );
+
+/** Compare Size bytes between Stream1 and Stream2 from their
+ respective current position.
+
+ Stream1 and Stream2 must go in the same direction.
+ Stream1 and Stream2 are left unchanged.
+
+ @param [in] Stream1 First stream to compare.
+ The stream must not be at its end.
+ @param [in] Stream2 Second stream to compare.
+ The stream must not be at its end.
+ @param [in] Size Number of bytes to compare.
+ Must be lower than the minimum remaining space of
+ Stream1 and Stream2.
+ Must be non-zero.
+
+ @retval TRUE If Stream1 and Stream2 have Size bytes equal,
+ from their respective current position.
+ The function completed successfully.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlStreamCmp (
+ IN CONST AML_STREAM * Stream1,
+ IN CONST AML_STREAM * Stream2,
+ IN UINT32 Size
+ );
+
+/** Copy Size bytes of the stream's data to DstBuffer.
+
+ For a backward stream, the bytes are copied starting from the
+ current stream position.
+
+ @param [out] DstBuffer Destination Buffer to copy the data to.
+ @param [in] MaxDstBufferSize Maximum size of DstBuffer.
+ Must be non-zero.
+ @param [in] Stream Pointer to the stream to copy the data from.
+ @param [in] Size Number of bytes to copy from the stream
+ buffer.
+ Must be lower than MaxDstBufferSize.
+ Must be lower than Stream's MaxBufferSize.
+ Return success if zero.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlStreamCpyS (
+ OUT CHAR8 * DstBuffer,
+ IN UINT32 MaxDstBufferSize,
+ IN AML_STREAM * Stream,
+ IN UINT32 Size
+ );
+
+#endif // AML_STREAM_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c
new file mode 100644
index 00000000000..41e626c846c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.c
@@ -0,0 +1,1022 @@
+/** @file
+ AML String.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <String/AmlString.h>
+
+#include <AmlDefines.h>
+#include <IndustryStandard/AcpiAml.h>
+
+/** Check NameString/path information is valid.
+
+ Root, ParentPrefix and SegCount cannot be 0 at the same time.
+ This function works for ASL and AML name strings.
+
+ @param [in] Root Number of root char.
+ Must be 0 or 1.
+ @param [in] ParentPrefix Number of carets char ('^').
+ Must be [0-255].
+ @param [in] SegCount Number of NameSeg (s).
+ Must be [0-255].
+
+ @retval TRUE id the input information is in the right boundaries.
+ FALSE otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNameString (
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix,
+ IN UINT32 SegCount
+ )
+{
+ if (((Root == 0) || (Root == 1)) &&
+ (ParentPrefix <= MAX_UINT8) &&
+ (!((ParentPrefix != 0) && (Root != 0))) &&
+ (SegCount <= MAX_UINT8) &&
+ ((SegCount + Root + ParentPrefix) != 0)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/** Copy bytes from SrcBuffer to DstBuffer and convert to upper case.
+ Don't copy more than MaxDstBufferSize bytes.
+
+ @param [out] DstBuffer Destination buffer.
+ @param [in] MaxDstBufferSize Maximum size of DstBuffer.
+ Must be non-zero.
+ @param [in] SrcBuffer Source buffer.
+ @param [in] Count Count of bytes to copy from SrcBuffer.
+ Return success if 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpperCaseMemCpyS (
+ OUT CHAR8 * DstBuffer,
+ IN UINT32 MaxDstBufferSize,
+ IN CONST CHAR8 * SrcBuffer,
+ IN UINT32 Count
+ )
+{
+ UINT32 Index;
+
+ if ((DstBuffer == NULL) ||
+ (SrcBuffer == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Count == 0) {
+ return EFI_SUCCESS;
+ }
+
+ if (Count > MaxDstBufferSize) {
+ Count = MaxDstBufferSize;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ if ((SrcBuffer[Index] >= 'a') && (SrcBuffer[Index] <= 'z')) {
+ DstBuffer[Index] = (CHAR8)((UINT8)SrcBuffer[Index] - ('a' - 'A'));
+ } else {
+ DstBuffer[Index] = SrcBuffer[Index];
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Check whether Buffer is a root path ('\').
+
+ This function works for both ASL and AML pathnames.
+ Buffer must be at least 2 bytes long.
+
+ @param [in] Buffer An ASL/AML path.
+
+ @retval TRUE Buffer is a root path
+ @retval FALSE Buffer is not a root path.
+**/
+BOOLEAN
+EFIAPI
+AmlIsRootPath (
+ IN CONST CHAR8 * Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return FALSE;
+ }
+
+ if ((Buffer[0] == AML_ROOT_CHAR) && (Buffer[1] == '\0')) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/** Check whether Ch is an ASL/AML LeadName.
+
+ This function works for both ASL and AML pathnames.
+
+ ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms":
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+
+ ACPI 6.3 specification, s20.2.2. "Name Objects Encoding":
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+
+ @param [in] Ch The char to test.
+
+ @retval TRUE Ch is an ASL/AML LeadName.
+ @retval FALSE Ch is not an ASL/AML LeadName.
+**/
+BOOLEAN
+EFIAPI
+AmlIsLeadNameChar (
+ IN CHAR8 Ch
+ )
+{
+ if ((Ch == '_') || (Ch >= 'A' && Ch <= 'Z') || (Ch >= 'a' && Ch <= 'z')) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/** Check whether Ch is an ASL/AML NameChar.
+
+ This function works for both ASL and AML pathnames.
+
+ ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms":
+ NameChar := DigitChar | LeadNameChar
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+ DigitChar := '0'-'9'
+
+ ACPI 6.3 specification, s20.2.2. "Name Objects Encoding":
+ NameChar := DigitChar | LeadNameChar
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+ DigitChar := '0'-'9'
+
+ @param [in] Ch The char to test.
+
+ @retval TRUE Ch is an ASL/AML NameChar.
+ @retval FALSE Ch is not an ASL/AML NameChar.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNameChar (
+ IN CHAR8 Ch
+ )
+{
+ if (AmlIsLeadNameChar (Ch) || (Ch >= '0' && Ch <= '9')) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/** Check whether AslBuffer is an ASL NameSeg.
+
+ This function only works for ASL NameStrings/pathnames.
+ ASL NameStrings/pathnames are at most 4 chars long.
+
+ @param [in] AslBuffer Pointer in an ASL NameString/pathname.
+ @param [out] Size Size of the NameSeg.
+
+ @retval TRUE AslBuffer is an ASL NameSeg.
+ @retval FALSE AslBuffer is not an ASL NameSeg.
+**/
+BOOLEAN
+EFIAPI
+AslIsNameSeg (
+ IN CONST CHAR8 * AslBuffer,
+ OUT UINT32 * Size
+ )
+{
+ UINT32 Index;
+
+ if ((AslBuffer == NULL) ||
+ (Size == NULL)) {
+ return FALSE;
+ }
+
+ if (!AmlIsLeadNameChar (AslBuffer[0])) {
+ return FALSE;
+ }
+
+ for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) {
+ if ((AslBuffer[Index] == '.') ||
+ (AslBuffer[Index] == '\0')) {
+ *Size = Index;
+ return TRUE;
+ } else if (!AmlIsNameChar (AslBuffer[Index])) {
+ return FALSE;
+ }
+ }
+
+ *Size = Index;
+ return TRUE;
+}
+
+/** Check whether AmlBuffer is an AML NameSeg.
+
+ This function only works for AML NameStrings/pathnames.
+ AML NameStrings/pathnames must be 4 chars long.
+
+ @param [in] AmlBuffer Pointer in an AML NameString/pathname.
+
+ @retval TRUE AmlBuffer is an AML NameSeg.
+ @retval FALSE AmlBuffer is not an AML NameSeg.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNameSeg (
+ IN CONST CHAR8 * AmlBuffer
+ )
+{
+ UINT32 Index;
+
+ if (AmlBuffer == NULL) {
+ return FALSE;
+ }
+
+ if (!AmlIsLeadNameChar (AmlBuffer[0])) {
+ return FALSE;
+ }
+
+ for (Index = 1; Index < AML_NAME_SEG_SIZE; Index++) {
+ if (!AmlIsNameChar (AmlBuffer[Index])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/** Parse an ASL NameString/path.
+
+ An ASL NameString/path must be NULL terminated.
+ Information found in the ASL NameString/path is returned via pointers:
+ Root, ParentPrefix, SegCount.
+
+ @param [in] Buffer ASL NameString/path.
+ @param [out] Root Pointer holding the number of root char.
+ Can be 0 or 1.
+ @param [out] ParentPrefix Pointer holding the number of carets char ('^').
+ Can be [0-255].
+ @param [out] SegCount Pointer holding the number of NameSeg (s).
+ Can be [0-255].
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AslParseNameStringInfo (
+ IN CONST CHAR8 * Buffer,
+ OUT UINT32 * Root,
+ OUT UINT32 * ParentPrefix,
+ OUT UINT32 * SegCount
+ )
+{
+ UINT32 NameSegSize;
+
+ if ((Buffer == NULL) ||
+ (Root == NULL) ||
+ (ParentPrefix == NULL) ||
+ (SegCount == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Root = 0;
+ *ParentPrefix = 0;
+ *SegCount = 0;
+
+ // Handle Root and ParentPrefix(s).
+ if (*Buffer == AML_ROOT_CHAR) {
+ *Root = 1;
+ Buffer++;
+ } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
+ do {
+ Buffer++;
+ (*ParentPrefix)++;
+ } while (*Buffer == AML_PARENT_PREFIX_CHAR);
+ }
+
+ // Handle SegCount(s).
+ while (AslIsNameSeg (Buffer, &NameSegSize)) {
+ // Safety checks on NameSegSize.
+ if ((NameSegSize == 0) || (NameSegSize > AML_NAME_SEG_SIZE)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Increment the NameSeg count.
+ (*SegCount)++;
+ Buffer += NameSegSize;
+
+ // Skip the '.' separator if present.
+ if (*Buffer == '.') {
+ Buffer++;
+ }
+ } // while
+
+ // An ASL NameString/path must be NULL terminated.
+ if (*Buffer != '\0') {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!AmlIsNameString (*Root, *ParentPrefix, *SegCount)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Parse an AML NameString/path.
+
+ It is possible to determine the size of an AML NameString/path just
+ by sight reading it. So no overflow can occur.
+ Information found in the AML NameString/path is returned via pointers:
+ Root, ParentPrefix, SegCount.
+
+ @param [in] Buffer AML NameString/path.
+ @param [out] Root Pointer holding the number of root char.
+ Can be 0 or 1.
+ @param [out] ParentPrefix Pointer holding the number of carets char ('^').
+ Can be [0-255].
+ @param [out] SegCount Pointer holding the number of NameSeg(s).
+ Can be [0-255].
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseNameStringInfo (
+ IN CONST CHAR8 * Buffer,
+ OUT UINT32 * Root,
+ OUT UINT32 * ParentPrefix,
+ OUT UINT32 * SegCount
+ )
+{
+ if ((Buffer == NULL) ||
+ (Root == NULL) ||
+ (ParentPrefix == NULL) ||
+ (SegCount == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Root = 0;
+ *ParentPrefix = 0;
+ *SegCount = 0;
+
+ // Handle Root and ParentPrefix(s).
+ if (*Buffer == AML_ROOT_CHAR) {
+ *Root = 1;
+ Buffer++;
+ } else if (*Buffer == AML_PARENT_PREFIX_CHAR) {
+ do {
+ Buffer++;
+ (*ParentPrefix)++;
+ } while (*Buffer == AML_PARENT_PREFIX_CHAR);
+ }
+
+ // Handle SegCount(s).
+ if (*Buffer == AML_DUAL_NAME_PREFIX) {
+ *SegCount = 2;
+ } else if (*Buffer == AML_MULTI_NAME_PREFIX) {
+ *SegCount = *((UINT8*)(Buffer + 1));
+ } else if (AmlIsNameSeg (Buffer)) {
+ *SegCount = 1;
+ } else if (*Buffer == AML_ZERO_OP) {
+ *SegCount = 0;
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Safety checks on exit.
+ if (!AmlIsNameString (*Root, *ParentPrefix, *SegCount)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Compute the ASL NameString/path size from NameString
+ information (Root, ParentPrefix, SegCount).
+
+ @param [in] Root Number of root char.
+ Can be 0 or 1.
+ @param [in] ParentPrefix Number of carets char ('^').
+ Can be [0-255].
+ @param [in] SegCount Pointer holding the number of NameSeg(s).
+ Can be [0-255].
+
+ @return Size of the ASL NameString/path.
+**/
+UINT32
+EFIAPI
+AslComputeNameStringSize (
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix,
+ IN UINT32 SegCount
+ )
+{
+ UINT32 TotalSize;
+
+ if (!AmlIsNameString (Root, ParentPrefix, SegCount)) {
+ ASSERT (0);
+ return 0;
+ }
+
+ // Root and ParentPrefix(s).
+ TotalSize = Root + ParentPrefix;
+
+ // Add size required for NameSeg(s).
+ TotalSize += (SegCount * AML_NAME_SEG_SIZE);
+
+ // Add size required for '.' separator(s).
+ TotalSize += (SegCount > 1) ? (SegCount - 1) : 0;
+
+ // Add 1 byte for NULL termination '\0'.
+ TotalSize += 1;
+
+ return TotalSize;
+}
+
+/** Compute the AML NameString/path size from NameString
+ information (Root, ParentPrefix, SegCount).
+
+ @param [in] Root Number of root char.
+ Can be 0 or 1.
+ @param [in] ParentPrefix Number of carets char ('^').
+ Can be [0-255].
+ @param [in] SegCount Pointer holding the number of NameSeg(s).
+ Can be [0-255].
+
+ @return Size of the AML NameString/path.
+**/
+UINT32
+EFIAPI
+AmlComputeNameStringSize (
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix,
+ IN UINT32 SegCount
+ )
+{
+ UINT32 TotalSize;
+
+ if (!AmlIsNameString (Root, ParentPrefix, SegCount)) {
+ ASSERT (0);
+ return 0;
+ }
+
+ // Root and ParentPrefix(s).
+ TotalSize = Root + ParentPrefix;
+
+ // If SegCount == 0, '\0' must end the AML NameString/path.
+ TotalSize += (SegCount == 0) ? 1 : (SegCount * AML_NAME_SEG_SIZE);
+
+ // AML prefix. SegCount > 2 = MultiNamePrefix, SegCount = 2 DualNamePrefix.
+ TotalSize += (SegCount > 2) ? 2 : ((SegCount == 2) ? 1 : 0);
+
+ return TotalSize;
+}
+
+/** Get the ASL NameString/path size.
+
+ @param [in] AslPath An ASL NameString/path.
+ @param [out] AslPathSizePtr Pointer holding the ASL NameString/path size.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AslGetNameStringSize (
+ IN CONST CHAR8 * AslPath,
+ OUT UINT32 * AslPathSizePtr
+ )
+{
+ if ((AslPath == NULL) ||
+ (AslPathSizePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *AslPathSizePtr = 0;
+ do {
+ (*AslPathSizePtr)++;
+ AslPath++;
+ } while (*AslPath != '\0');
+
+ return EFI_SUCCESS;
+}
+
+/** Get the AML NameString/path size.
+
+ @param [in] AmlPath An AML NameString/path.
+ @param [out] AmlPathSizePtr Pointer holding the AML NameString/path size.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetNameStringSize (
+ IN CONST CHAR8 * AmlPath,
+ OUT UINT32 * AmlPathSizePtr
+ )
+{
+ EFI_STATUS Status;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+
+ if ((AmlPath == NULL) ||
+ (AmlPathSizePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlParseNameStringInfo (
+ AmlPath,
+ &Root,
+ &ParentPrefix,
+ &SegCount
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ *AmlPathSizePtr = AmlComputeNameStringSize (Root, ParentPrefix, SegCount);
+ if (*AmlPathSizePtr == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/** Convert an ASL NameString/path to an AML NameString/path.
+ The caller must free the memory allocated in this function
+ for AmlPath using FreePool ().
+
+ @param [in] AslPath An ASL NameString/path.
+ @param [out] OutAmlPath Buffer containing the AML path.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+ConvertAslNameToAmlName (
+ IN CONST CHAR8 * AslPath,
+ OUT CHAR8 ** OutAmlPath
+ )
+{
+ EFI_STATUS Status;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+ UINT32 TotalSize;
+ UINT32 NameSegSize;
+
+ CONST CHAR8 * AslBuffer;
+ CHAR8 * AmlBuffer;
+ CHAR8 * AmlPath;
+
+ if ((AslPath == NULL) ||
+ (OutAmlPath == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Analyze AslPath. AslPath is checked in the call.
+ Status = AslParseNameStringInfo (AslPath, &Root, &ParentPrefix, &SegCount);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Compute TotalSize.
+ TotalSize = AmlComputeNameStringSize (Root, ParentPrefix, SegCount);
+ if (TotalSize == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate memory.
+ AmlPath = AllocateZeroPool (TotalSize);
+ if (AmlPath == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AmlBuffer = AmlPath;
+ AslBuffer = AslPath;
+
+ // Handle Root and ParentPrefix(s).
+ if (Root == 1) {
+ *AmlBuffer = AML_ROOT_CHAR;
+ AmlBuffer++;
+ AslBuffer++;
+ } else if (ParentPrefix > 0) {
+ SetMem (AmlBuffer, ParentPrefix, AML_PARENT_PREFIX_CHAR);
+ AmlBuffer += ParentPrefix;
+ AslBuffer += ParentPrefix;
+ }
+
+ // Handle prefix and SegCount(s).
+ if (SegCount > 2) {
+ *AmlBuffer = AML_MULTI_NAME_PREFIX;
+ AmlBuffer++;
+ *AmlBuffer = (UINT8)SegCount;
+ AmlBuffer++;
+ } else if (SegCount == 2) {
+ *AmlBuffer = AML_DUAL_NAME_PREFIX;
+ AmlBuffer++;
+ }
+
+ if (SegCount != 0) {
+ // Write NameSeg(s).
+ while (1) {
+ SegCount--;
+
+ // Get the NameSeg size.
+ if (!AslIsNameSeg (AslBuffer, &NameSegSize)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ // Convert to Upper case and copy.
+ Status = AmlUpperCaseMemCpyS (
+ AmlBuffer,
+ TotalSize,
+ AslBuffer,
+ NameSegSize
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Complete the NameSeg with an underscore ('_') if shorter than 4 bytes.
+ SetMem (
+ AmlBuffer + NameSegSize,
+ AML_NAME_SEG_SIZE - NameSegSize,
+ AML_NAME_CHAR__
+ );
+
+ // Go to the next NameSeg.
+ AmlBuffer += AML_NAME_SEG_SIZE;
+ AslBuffer += NameSegSize;
+
+ // Skip the '.' separator.
+ if (SegCount != 0) {
+ if (*AslBuffer == '.') {
+ AslBuffer++;
+ } else {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+ } else {
+ // (SegCount == 0)
+ if (*AslBuffer == '\0') {
+ break;
+ } else {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+ }
+ } // while
+
+ } else {
+ // (SegCount == 0)
+ // '\0' needs to end the AML NameString/path.
+ *AmlBuffer = AML_ZERO_OP;
+ AmlBuffer++;
+ }
+
+ // Safety checks on exit.
+ // Check that AmlPath has been filled with TotalSize bytes.
+ if ((SegCount != 0) ||
+ (*AslBuffer != AML_ZERO_OP) ||
+ (((UINT32)(AmlBuffer - AmlPath)) != TotalSize)) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ *OutAmlPath = AmlPath;
+ return EFI_SUCCESS;
+
+error_handler:
+ FreePool (AmlPath);
+ return Status;
+}
+
+/** Convert an AML NameString/path to an ASL NameString/path.
+ The caller must free the memory allocated in this function.
+ using FreePool ().
+
+ @param [in] AmlPath An AML NameString/path.
+ @param [out] OutAslPath Buffer containing the ASL path.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+ConvertAmlNameToAslName (
+ IN CONST CHAR8 * AmlPath,
+ OUT CHAR8 ** OutAslPath
+ )
+{
+ EFI_STATUS Status;
+
+ UINT32 Root;
+ UINT32 ParentPrefix;
+ UINT32 SegCount;
+ UINT32 TotalSize;
+
+ CONST CHAR8 * AmlBuffer;
+ CHAR8 * AslBuffer;
+ CHAR8 * AslPath;
+
+ if ((AmlPath == NULL) ||
+ (OutAslPath == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Analyze AslPath. AmlPath is checked in the call.
+ Status = AmlParseNameStringInfo (AmlPath, &Root, &ParentPrefix, &SegCount);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Compute TotalSize.
+ TotalSize = AslComputeNameStringSize (Root, ParentPrefix, SegCount);
+ if (TotalSize == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate memory.
+ AslPath = AllocateZeroPool (TotalSize);
+ if (AslPath == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AmlBuffer = AmlPath;
+ AslBuffer = AslPath;
+
+ // Handle prefix and SegCount(s).
+ if (Root == 1) {
+ *AslBuffer = AML_ROOT_CHAR;
+ AslBuffer++;
+ AmlBuffer++;
+ } else if (ParentPrefix > 0) {
+ SetMem (AslBuffer, ParentPrefix, AML_PARENT_PREFIX_CHAR);
+ AslBuffer += ParentPrefix;
+ AmlBuffer += ParentPrefix;
+ }
+
+ // Handle Root and Parent(s).
+ // Skip the MultiName or DualName prefix chars.
+ if (SegCount > 2) {
+ AmlBuffer += 2;
+ } else if (SegCount == 2) {
+ AmlBuffer += 1;
+ }
+
+ // Write NameSeg(s).
+ while (SegCount) {
+ // NameSeg is already in upper case and always 4 bytes long.
+ CopyMem (AslBuffer, AmlBuffer, AML_NAME_SEG_SIZE);
+ AslBuffer += AML_NAME_SEG_SIZE;
+ AmlBuffer += AML_NAME_SEG_SIZE;
+
+ SegCount--;
+
+ // Write the '.' separator if there is another NameSeg following.
+ if (SegCount != 0) {
+ *AslBuffer = '.';
+ AslBuffer++;
+ }
+ } // while
+
+ // NULL terminate the ASL NameString.
+ *AslBuffer = '\0';
+ AslBuffer++;
+
+ // Safety checks on exit.
+ // Check that AslPath has been filled with TotalSize bytes.
+ if (((UINT32)(AslBuffer - AslPath)) != TotalSize) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ *OutAslPath = AslPath;
+ return EFI_SUCCESS;
+
+error_handler:
+ FreePool (AslPath);
+ return Status;
+}
+
+/** Compare two ASL NameStrings.
+
+ @param [in] AslName1 First NameString to compare.
+ @param [in] AslName2 Second NameString to compare.
+
+ @retval TRUE if the two strings are identical.
+ @retval FALSE otherwise, or if error.
+**/
+BOOLEAN
+EFIAPI
+AslCompareNameString (
+ IN CONST CHAR8 * AslName1,
+ IN CONST CHAR8 * AslName2
+ )
+{
+ EFI_STATUS Status;
+ UINT32 AslName1Len;
+ UINT32 AslName2Len;
+
+ if ((AslName1 == NULL) ||
+ (AslName2 == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ Status = AslGetNameStringSize (AslName1, &AslName1Len);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ Status = AslGetNameStringSize (AslName2, &AslName2Len);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // AslName1 and AslName2 don't have the same length
+ if (AslName1Len != AslName2Len) {
+ return FALSE;
+ }
+
+ return (CompareMem (AslName1, AslName2, AslName1Len) == 0);
+}
+
+/** Compare two AML NameStrings.
+
+ @param [in] AmlName1 First NameString to compare.
+ @param [in] AmlName2 Second NameString to compare.
+
+ @retval TRUE if the two strings are identical.
+ @retval FALSE otherwise, or if error.
+**/
+BOOLEAN
+EFIAPI
+AmlCompareNameString (
+ IN CONST CHAR8 * AmlName1,
+ IN CONST CHAR8 * AmlName2
+ )
+{
+ EFI_STATUS Status;
+ UINT32 AmlName1Len;
+ UINT32 AmlName2Len;
+
+ if ((AmlName1 == NULL) ||
+ (AmlName2 == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ Status = AmlGetNameStringSize (AmlName1, &AmlName1Len);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ Status = AmlGetNameStringSize (AmlName2, &AmlName2Len);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // AmlName1 and AmlName2 don't have the same length
+ if (AmlName1Len != AmlName2Len) {
+ return FALSE;
+ }
+
+ return (CompareMem (AmlName1, AmlName2, AmlName1Len) == 0);
+}
+
+/** Compare an AML NameString and an ASL NameString.
+
+ The ASL NameString is converted to an AML NameString before
+ being compared with the ASL NameString. This allows to expand
+ NameSegs shorter than 4 chars.
+ E.g.: AslName: "DEV" will be expanded to "DEV_" before being
+ compared.
+
+ @param [in] AmlName1 AML NameString to compare.
+ @param [in] AslName2 ASL NameString to compare.
+
+ @retval TRUE if the two strings are identical.
+ @retval FALSE otherwise, or if error.
+**/
+BOOLEAN
+EFIAPI
+CompareAmlWithAslNameString (
+ IN CONST CHAR8 * AmlName1,
+ IN CONST CHAR8 * AslName2
+ )
+{
+ EFI_STATUS Status;
+
+ CHAR8 * AmlName2;
+ BOOLEAN RetVal;
+
+ if ((AmlName1 == NULL) ||
+ (AslName2 == NULL)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Convert the AslName2 to an AmlName2.
+ // AmlName2 must be freed.
+ Status = ConvertAmlNameToAslName (AslName2, &AmlName2);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ RetVal = AmlCompareNameString (AmlName1, AmlName2);
+
+ // Free AmlName2.
+ FreePool (AmlName2);
+
+ return RetVal;
+}
+/** Given an AmlPath, return the address of the first NameSeg.
+
+ It is possible to determine the size of an AML NameString/path just
+ by sight reading it. So no overflow can occur.
+
+ @param [in] AmlPath The AML pathname.
+ @param [in] Root The AML pathname starts with a root char.
+ It is an absolute path.
+ @param [in] ParentPrefix The AML pathname has ParentPrefix
+ carets in its name.
+
+ @return Pointer to the first NameSeg of the NameString.
+ Return NULL if AmlPath is NULL.
+**/
+CONST
+CHAR8 *
+EFIAPI
+AmlGetFirstNameSeg (
+ IN CONST CHAR8 * AmlPath,
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix
+ )
+{
+ if (AmlPath == NULL) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ AmlPath += Root;
+ AmlPath += ParentPrefix;
+ AmlPath += ((*AmlPath == AML_MULTI_NAME_PREFIX) ? 2
+ : (*AmlPath == AML_DUAL_NAME_PREFIX) ? 1 : 0);
+ return AmlPath;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h
new file mode 100644
index 00000000000..a5d0a67aa3f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/String/AmlString.h
@@ -0,0 +1,401 @@
+/** @file
+ AML String.
+
+ Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_STRING_H_
+#define AML_STRING_H_
+
+/* This header file does not include internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions
+ must be included by the caller file. The function prototypes must
+ only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node
+ definitions.
+ This allows to keep the functions defined here both internal and
+ potentially external. If necessary, any function of this file can
+ be exposed externally.
+ The Api folder is internal to the AmlLib, but should only use these
+ functions. They provide a "safe" way to interact with the AmlLib.
+*/
+
+#include <AmlInclude.h>
+
+/** Check NameString/path information is valid.
+
+ Root, ParentPrefix and SegCount cannot be 0 at the same time.
+ This function works for ASL and AML name strings.
+
+ @param [in] Root Number of root char.
+ Must be 0 or 1.
+ @param [in] ParentPrefix Number of carets char ('^').
+ Must be [0-255].
+ @param [in] SegCount Number of NameSeg (s).
+ Must be [0-255].
+
+ @retval TRUE id the input information is in the right boundaries.
+ FALSE otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNameString (
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix,
+ IN UINT32 SegCount
+ );
+
+/** Copy bytes from SrcBuffer to DstBuffer and convert to upper case.
+ Don't copy more than MaxDstBufferSize bytes.
+
+ @param [out] DstBuffer Destination buffer.
+ @param [in] MaxDstBufferSize Maximum size of DstBuffer.
+ Must be non-zero.
+ @param [in] SrcBuffer Source buffer.
+ @param [in] Count Count of bytes to copy from SrcBuffer.
+ Return success if 0.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpperCaseMemCpyS (
+ OUT CHAR8 * DstBuffer,
+ IN UINT32 MaxDstBufferSize,
+ IN CONST CHAR8 * SrcBuffer,
+ IN UINT32 Count
+ );
+
+/** Check whether Buffer is a root path ('\').
+
+ This function works for both ASL and AML pathnames.
+ Buffer must be at least 2 bytes long.
+
+ @param [in] Buffer An ASL/AML path.
+
+ @retval TRUE Buffer is a root path
+ @retval FALSE Buffer is not a root path.
+**/
+BOOLEAN
+EFIAPI
+AmlIsRootPath (
+ IN CONST CHAR8 * Buffer
+ );
+
+/** Check whether Ch is an ASL/AML LeadName.
+
+ This function works for both ASL and AML pathnames.
+
+ ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms":
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+
+ ACPI 6.3 specification, s20.2.2. "Name Objects Encoding":
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+
+ @param [in] Ch The char to test.
+
+ @retval TRUE Ch is an ASL/AML LeadName.
+ @retval FALSE Ch is not an ASL/AML LeadName.
+**/
+BOOLEAN
+EFIAPI
+AmlIsLeadNameChar (
+ IN CHAR8 Ch
+ );
+
+/** Check whether Ch is an ASL/AML NameChar.
+
+ This function works for both ASL and AML pathnames.
+
+ ACPI 6.3 specification, s19.2.2. "ASL Name and Pathname Terms":
+ NameChar := DigitChar | LeadNameChar
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+ DigitChar := '0'-'9'
+
+ ACPI 6.3 specification, s20.2.2. "Name Objects Encoding":
+ NameChar := DigitChar | LeadNameChar
+ LeadNameChar := 'A'-'Z' | 'a'-'z' | '_'
+ DigitChar := '0'-'9'
+
+ @param [in] Ch The char to test.
+
+ @retval TRUE Ch is an ASL/AML NameChar.
+ @retval FALSE Ch is not an ASL/AML NameChar.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNameChar (
+ IN CHAR8 Ch
+ );
+
+/** Check whether AslBuffer is an ASL NameSeg.
+
+ This function only works for ASL NameStrings/pathnames.
+ ASL NameStrings/pathnames are at most 4 chars long.
+
+ @param [in] AslBuffer Pointer in an ASL NameString/pathname.
+ @param [out] Size Size of the NameSeg.
+
+ @retval TRUE AslBuffer is an ASL NameSeg.
+ @retval FALSE AslBuffer is not an ASL NameSeg.
+**/
+BOOLEAN
+EFIAPI
+AslIsNameSeg (
+ IN CONST CHAR8 * AslBuffer,
+ OUT UINT32 * Size
+ );
+
+/** Check whether AmlBuffer is an AML NameSeg.
+
+ This function only works for AML NameStrings/pathnames.
+ AML NameStrings/pathnames must be 4 chars long.
+
+ @param [in] AmlBuffer Pointer in an AML NameString/pathname.
+
+ @retval TRUE AmlBuffer is an AML NameSeg.
+ @retval FALSE AmlBuffer is not an AML NameSeg.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNameSeg (
+ IN CONST CHAR8 * AmlBuffer
+ );
+
+/** Parse an ASL NameString/path.
+
+ An ASL NameString/path must be NULL terminated.
+ Information found in the ASL NameString/path is returned via pointers:
+ Root, ParentPrefix, SegCount.
+
+ @param [in] Buffer ASL NameString/path.
+ @param [out] Root Pointer holding the number of root char.
+ Can be 0 or 1.
+ @param [out] ParentPrefix Pointer holding the number of carets char ('^').
+ Can be [0-255].
+ @param [out] SegCount Pointer holding the number of NameSeg (s).
+ Can be [0-255].
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AslParseNameStringInfo (
+ IN CONST CHAR8 * Buffer,
+ OUT UINT32 * Root,
+ OUT UINT32 * ParentPrefix,
+ OUT UINT32 * SegCount
+ );
+
+/** Parse an AML NameString/path.
+
+ It is possible to determine the size of an AML NameString/path just
+ by sight reading it. So no overflow can occur.
+ Information found in the AML NameString/path is returned via pointers:
+ Root, ParentPrefix, SegCount.
+
+ @param [in] Buffer AML NameString/path.
+ @param [out] Root Pointer holding the number of root char.
+ Can be 0 or 1.
+ @param [out] ParentPrefix Pointer holding the number of carets char ('^').
+ Can be [0-255].
+ @param [out] SegCount Pointer holding the number of NameSeg(s).
+ Can be [0-255].
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlParseNameStringInfo (
+ IN CONST CHAR8 * Buffer,
+ OUT UINT32 * Root,
+ OUT UINT32 * ParentPrefix,
+ OUT UINT32 * SegCount
+ );
+
+/** Compute the ASL NameString/path size from NameString
+ information (Root, ParentPrefix, SegCount).
+
+ @param [in] Root Number of root char.
+ Can be 0 or 1.
+ @param [in] ParentPrefix Number of carets char ('^').
+ Can be [0-255].
+ @param [in] SegCount Pointer holding the number of NameSeg(s).
+ Can be [0-255].
+
+ @return Size of the ASL NameString/path.
+**/
+UINT32
+EFIAPI
+AslComputeNameStringSize (
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix,
+ IN UINT32 SegCount
+ );
+
+/** Compute the AML NameString/path size from NameString
+ information (Root, ParentPrefix, SegCount).
+
+ @param [in] Root Number of root char.
+ Can be 0 or 1.
+ @param [in] ParentPrefix Number of carets char ('^').
+ Can be [0-255].
+ @param [in] SegCount Pointer holding the number of NameSeg(s).
+ Can be [0-255].
+
+ @return Size of the AML NameString/path.
+**/
+UINT32
+EFIAPI
+AmlComputeNameStringSize (
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix,
+ IN UINT32 SegCount
+ );
+
+/** Get the ASL NameString/path size.
+
+ @param [in] AslPath An ASL NameString/path.
+ @param [out] AslPathSizePtr Pointer holding the ASL NameString/path size.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AslGetNameStringSize (
+ IN CONST CHAR8 * AslPath,
+ OUT UINT32 * AslPathSizePtr
+ );
+
+/** Get the AML NameString/path size.
+
+ @param [in] AmlPath An AML NameString/path.
+ @param [out] AmlPathSizePtr Pointer holding the AML NameString/path size.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetNameStringSize (
+ IN CONST CHAR8 * AmlPath,
+ OUT UINT32 * AmlPathSizePtr
+ );
+
+/** Convert an ASL NameString/path to an AML NameString/path.
+ The caller must free the memory allocated in this function
+ for AmlPath using FreePool ().
+
+ @param [in] AslPath An ASL NameString/path.
+ @param [out] OutAmlPath Buffer containing the AML path.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+ConvertAslNameToAmlName (
+ IN CONST CHAR8 * AslPath,
+ OUT CHAR8 ** OutAmlPath
+ );
+
+/** Convert an AML NameString/path to an ASL NameString/path.
+ The caller must free the memory allocated in this function.
+ using FreePool ().
+
+ @param [in] AmlPath An AML NameString/path.
+ @param [out] OutAslPath Buffer containing the ASL path.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+ConvertAmlNameToAslName (
+ IN CONST CHAR8 * AmlPath,
+ OUT CHAR8 ** OutAslPath
+ );
+
+/** Compare two ASL NameStrings.
+
+ @param [in] AslName1 First NameString to compare.
+ @param [in] AslName2 Second NameString to compare.
+
+ @retval TRUE if the two strings are identical.
+ @retval FALSE otherwise, or if error.
+**/
+BOOLEAN
+EFIAPI
+AslCompareNameString (
+ IN CONST CHAR8 * AslName1,
+ IN CONST CHAR8 * AslName2
+ );
+
+/** Compare two AML NameStrings.
+
+ @param [in] AmlName1 First NameString to compare.
+ @param [in] AmlName2 Second NameString to compare.
+
+ @retval TRUE if the two strings are identical.
+ @retval FALSE otherwise, or if error.
+**/
+BOOLEAN
+EFIAPI
+AmlCompareNameString (
+ IN CONST CHAR8 * AmlName1,
+ IN CONST CHAR8 * AmlName2
+ );
+
+/** Compare an AML NameString and an ASL NameString.
+
+ The ASL NameString is converted to an AML NameString before
+ being compared with the ASL NameString. This allows to expand
+ NameSegs shorter than 4 chars.
+ E.g.: AslName: "DEV" will be expanded to "DEV_" before being
+ compared.
+
+ @param [in] AmlName1 AML NameString to compare.
+ @param [in] AslName2 ASL NameString to compare.
+
+ @retval TRUE if the two strings are identical.
+ @retval FALSE otherwise, or if error.
+**/
+BOOLEAN
+EFIAPI
+CompareAmlWithAslNameString (
+ IN CONST CHAR8 * AmlName1,
+ IN CONST CHAR8 * AslName2
+ );
+
+/** Given an AmlPath, return the address of the first NameSeg.
+
+ It is possible to determine the size of an AML NameString/path just
+ by sight reading it. So no overflow can occur.
+
+ @param [in] AmlPath The AML pathname.
+ @param [in] Root The AML pathname starts with a root char.
+ It is an absolute path.
+ @param [in] ParentPrefix The AML pathname has ParentPrefix
+ carets in its name.
+
+ @return Pointer to the first NameSeg of the NameString.
+ Return NULL if AmlPath is NULL.
+**/
+CONST
+CHAR8 *
+EFIAPI
+AmlGetFirstNameSeg (
+ IN CONST CHAR8 * AmlPath,
+ IN UINT32 Root,
+ IN UINT32 ParentPrefix
+ );
+
+#endif // AML_STRING_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c
new file mode 100644
index 00000000000..5e2b09f909d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlClone.c
@@ -0,0 +1,205 @@
+/** @file
+ AML Clone.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+
+/** Clone a node.
+
+ This function does not clone the children nodes.
+ The cloned node returned is not attached to any tree.
+
+ @param [in] Node Pointer to a node.
+ @param [out] ClonedNode Pointer holding the cloned node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCloneNode (
+ IN AML_NODE_HEADER * Node,
+ OUT AML_NODE_HEADER ** ClonedNode
+ )
+{
+ EFI_STATUS Status;
+
+ AML_OBJECT_NODE * ObjectNode;
+ AML_DATA_NODE * DataNode;
+ AML_ROOT_NODE * RootNode;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (ClonedNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ClonedNode = NULL;
+
+ if (IS_AML_DATA_NODE (Node)) {
+ DataNode = (AML_DATA_NODE*)Node;
+ Status = AmlCreateDataNode (
+ DataNode->DataType,
+ DataNode->Buffer,
+ DataNode->Size,
+ (AML_DATA_NODE**)ClonedNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ } else if (IS_AML_OBJECT_NODE (Node)) {
+ ObjectNode = (AML_OBJECT_NODE*)Node;
+
+ Status = AmlCreateObjectNode (
+ ObjectNode->AmlByteEncoding,
+ ObjectNode->PkgLen,
+ (AML_OBJECT_NODE**)ClonedNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ } else if (IS_AML_ROOT_NODE (Node)) {
+ RootNode = (AML_ROOT_NODE*)Node;
+
+ Status = AmlCreateRootNode (
+ RootNode->SdtHeader,
+ (AML_ROOT_NODE**)ClonedNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+/** Clone a node and its children (clone a tree branch).
+
+ The cloned branch returned is not attached to any tree.
+
+ @param [in] Node Pointer to a node.
+ Node is the head of the branch to clone.
+ @param [out] ClonedNode Pointer holding the head of the created cloned
+ branch.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCloneTree (
+ IN AML_NODE_HEADER * Node,
+ OUT AML_NODE_HEADER ** ClonedNode
+ )
+{
+ EFI_STATUS Status;
+
+ AML_NODE_HEADER * HeadNode;
+ AML_NODE_HEADER * ClonedChildNode;
+ AML_NODE_HEADER * FixedArgNode;
+
+ EAML_PARSE_INDEX Index;
+ EAML_PARSE_INDEX MaxIndex;
+
+ LIST_ENTRY * StartLink;
+ LIST_ENTRY * CurrentLink;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (ClonedNode == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCloneNode (Node, &HeadNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Clone the fixed arguments and bind them to their parent.
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)Node
+ );
+ for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
+ FixedArgNode = AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index);
+ if (FixedArgNode == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Clone child.
+ Status = AmlCloneTree (
+ FixedArgNode,
+ &ClonedChildNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Bind child.
+ Status = AmlSetFixedArgument (
+ (AML_OBJECT_NODE*)HeadNode,
+ Index,
+ ClonedChildNode
+ );
+ if (EFI_ERROR (Status)) {
+ AmlDeleteTree (ClonedChildNode);
+ ASSERT (0);
+ goto error_handler;
+ }
+ } // for
+
+ // Clone the variable arguments and bind them to their parent.
+ StartLink = AmlNodeGetVariableArgList (Node);
+ if (StartLink != NULL) {
+ CurrentLink = StartLink->ForwardLink;
+ while (CurrentLink != StartLink) {
+ // Clone child.
+ Status = AmlCloneTree ((AML_NODE_HEADER*)CurrentLink, &ClonedChildNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ // Bind child.
+ Status = AmlVarListAddTailInternal (
+ HeadNode,
+ ClonedChildNode
+ );
+ if (EFI_ERROR (Status)) {
+ AmlDeleteTree (ClonedChildNode);
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ } // while
+ }
+
+ *ClonedNode = HeadNode;
+ return Status;
+
+error_handler:
+ *ClonedNode = NULL;
+
+ if (HeadNode != NULL) {
+ AmlDeleteTree (HeadNode);
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c
new file mode 100644
index 00000000000..00dd77bc110
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.c
@@ -0,0 +1,673 @@
+/** @file
+ AML Node.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Tree/AmlNode.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlTree.h>
+
+/** Initialize an AML_NODE_HEADER structure.
+
+ @param [in] Node Pointer to a node header.
+ @param [in] NodeType NodeType to initialize the Node with.
+ Must be an EAML_NODE_TYPE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlInitializeNodeHeader (
+ IN AML_NODE_HEADER * Node,
+ IN EAML_NODE_TYPE NodeType
+ )
+{
+ if (Node == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InitializeListHead (&Node->Link);
+
+ Node->Parent = NULL;
+ Node->NodeType = NodeType;
+
+ return EFI_SUCCESS;
+}
+
+/** Delete a root node and its ACPI DSDT/SSDT header.
+
+ It is the caller's responsibility to check the RootNode has been removed
+ from the tree and is not referencing any other node in the tree.
+
+ @param [in] RootNode Pointer to a root node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlDeleteRootNode (
+ IN AML_ROOT_NODE * RootNode
+ )
+{
+ if (!IS_AML_ROOT_NODE (RootNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((RootNode->SdtHeader != NULL)) {
+ FreePool (RootNode->SdtHeader);
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (RootNode);
+ return EFI_SUCCESS;
+}
+
+/** Create an AML_ROOT_NODE.
+ This node will be the root of the tree.
+
+ @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT header to copy
+ the data from.
+ @param [out] NewRootNodePtr The created AML_ROOT_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateRootNode (
+ IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader,
+ OUT AML_ROOT_NODE ** NewRootNodePtr
+ )
+{
+ EFI_STATUS Status;
+ AML_ROOT_NODE * RootNode;
+
+ if ((SdtHeader == NULL) ||
+ (NewRootNodePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RootNode = AllocateZeroPool (sizeof (AML_ROOT_NODE));
+ if (RootNode == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmlInitializeNodeHeader (&RootNode->NodeHeader, EAmlNodeRoot);
+ if (EFI_ERROR (Status)) {
+ FreePool (RootNode);
+ ASSERT (0);
+ return Status;
+ }
+
+ InitializeListHead (&RootNode->VariableArgs);
+
+ RootNode->SdtHeader = AllocateCopyPool (
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER),
+ SdtHeader
+ );
+ if (RootNode->SdtHeader == NULL) {
+ ASSERT (0);
+ AmlDeleteRootNode (RootNode);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *NewRootNodePtr = RootNode;
+
+ return EFI_SUCCESS;
+}
+
+/** Delete an object node.
+
+ It is the caller's responsibility to check the ObjectNode has been removed
+ from the tree and is not referencing any other node in the tree.
+
+ @param [in] ObjectNode Pointer to an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlDeleteObjectNode (
+ IN AML_OBJECT_NODE * ObjectNode
+ )
+{
+ if (!IS_AML_OBJECT_NODE (ObjectNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (ObjectNode);
+ return EFI_SUCCESS;
+}
+
+/** Create an AML_OBJECT_NODE.
+
+ @param [in] AmlByteEncoding Byte encoding entry.
+ @param [in] PkgLength PkgLength of the node if the AmlByteEncoding
+ has the PkgLen attribute.
+ 0 otherwise.
+ @param [out] NewObjectNodePtr The created AML_OBJECT_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateObjectNode (
+ IN CONST AML_BYTE_ENCODING * AmlByteEncoding,
+ IN UINT32 PkgLength,
+ OUT AML_OBJECT_NODE ** NewObjectNodePtr
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+
+ if ((AmlByteEncoding == NULL) ||
+ (NewObjectNodePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ObjectNode = AllocateZeroPool (sizeof (AML_OBJECT_NODE));
+ if (ObjectNode == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmlInitializeNodeHeader (&ObjectNode->NodeHeader, EAmlNodeObject);
+ if (EFI_ERROR (Status)) {
+ FreePool (ObjectNode);
+ ASSERT (0);
+ return Status;
+ }
+
+ InitializeListHead (&ObjectNode->VariableArgs);
+
+ // ObjectNode->FixedArgs[...] is already initialised to NULL as the
+ // ObjectNode is Zero allocated.
+ ObjectNode->AmlByteEncoding = AmlByteEncoding;
+ ObjectNode->PkgLen = PkgLength;
+
+ *NewObjectNodePtr = ObjectNode;
+
+ return EFI_SUCCESS;
+}
+
+/** Delete a data node and its buffer.
+
+ It is the caller's responsibility to check the DataNode has been removed
+ from the tree and is not referencing any other node in the tree.
+
+ @param [in] DataNode Pointer to a data node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlDeleteDataNode (
+ IN AML_DATA_NODE * DataNode
+ )
+{
+ if (!IS_AML_DATA_NODE (DataNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DataNode->Buffer != NULL) {
+ FreePool (DataNode->Buffer);
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (DataNode);
+ return EFI_SUCCESS;
+}
+
+/** Create an AML_DATA_NODE.
+
+ @param [in] DataType DataType of the node.
+ @param [in] Data Pointer to the AML bytecode corresponding to
+ this node. Data is copied from there.
+ @param [in] DataSize Number of bytes to consider at the address
+ pointed by Data.
+ @param [out] NewDataNodePtr The created AML_DATA_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateDataNode (
+ IN EAML_NODE_DATA_TYPE DataType,
+ IN CONST UINT8 * Data,
+ IN UINT32 DataSize,
+ OUT AML_DATA_NODE ** NewDataNodePtr
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * DataNode;
+
+ // A data node must not be created for certain data types.
+ if ((DataType == EAmlNodeDataTypeNone) ||
+ (DataType == EAmlNodeDataTypeReserved1) ||
+ (DataType == EAmlNodeDataTypeReserved2) ||
+ (DataType == EAmlNodeDataTypeReserved3) ||
+ (DataType == EAmlNodeDataTypeReserved4) ||
+ (DataType == EAmlNodeDataTypeReserved5) ||
+ (Data == NULL) ||
+ (DataSize == 0) ||
+ (NewDataNodePtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DataNode = AllocateZeroPool (sizeof (AML_DATA_NODE));
+ if (DataNode == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AmlInitializeNodeHeader (&DataNode->NodeHeader, EAmlNodeData);
+ if (EFI_ERROR (Status)) {
+ FreePool (DataNode);
+ ASSERT (0);
+ return Status;
+ }
+
+ DataNode->Buffer = AllocateCopyPool (DataSize, Data);
+ if (DataNode->Buffer == NULL) {
+ AmlDeleteDataNode (DataNode);
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DataNode->DataType = DataType;
+ DataNode->Size = DataSize;
+
+ *NewDataNodePtr = DataNode;
+
+ return EFI_SUCCESS;
+}
+
+/** Delete a Node.
+
+ @param [in] Node Pointer to a Node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteNode (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ EFI_STATUS Status;
+ EAML_PARSE_INDEX Index;
+
+ // Check that the node being deleted is unlinked.
+ // When removing the node, its parent and list are reset
+ // with InitializeListHead. Thus it must be empty.
+ if (!IS_AML_NODE_VALID (Node) ||
+ !AML_NODE_IS_DETACHED (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Node->NodeType) {
+ case EAmlNodeRoot:
+ {
+ // Check the variable list of arguments has been cleaned.
+ if (!IsListEmpty (AmlNodeGetVariableArgList (Node))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlDeleteRootNode ((AML_ROOT_NODE*)Node);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ break;
+ }
+
+ case EAmlNodeObject:
+ {
+ // Check the variable list of arguments has been cleaned.
+ if (!IsListEmpty (AmlNodeGetVariableArgList (Node))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check the fixed argument list has been cleaned.
+ for (Index = EAmlParseIndexTerm0; Index < EAmlParseIndexMax; Index++) {
+ if (((AML_OBJECT_NODE*)Node)->FixedArgs[Index] != NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ Status = AmlDeleteObjectNode ((AML_OBJECT_NODE*)Node);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ break;
+ }
+
+ case EAmlNodeData:
+ {
+ Status = AmlDeleteDataNode ((AML_DATA_NODE*)Node);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ break;
+ }
+
+ default:
+ {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ break;
+ }
+ } // switch
+
+ return Status;
+}
+
+/** Check whether ObjectNode has the input attribute.
+ This function can be used to check ObjectNode is an object node
+ at the same time.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Attribute Attribute to check for.
+
+ @retval TRUE The node is an AML object and the attribute is present.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasAttribute (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ IN AML_OP_ATTRIBUTE Attribute
+ )
+{
+ if (!IS_AML_OBJECT_NODE (ObjectNode) ||
+ (ObjectNode->AmlByteEncoding == NULL)) {
+ return FALSE;
+ }
+
+ return ((ObjectNode->AmlByteEncoding->Attribute &
+ Attribute) == 0 ? FALSE : TRUE);
+}
+
+/** Check whether ObjectNode has the input OpCode/SubOpcode couple.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] OpCode OpCode to check
+ @param [in] SubOpCode SubOpCode to check
+
+ @retval TRUE The node is an AML object and
+ the Opcode and the SubOpCode match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeCompareOpCode (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ )
+{
+ if (!IS_AML_OBJECT_NODE (ObjectNode) ||
+ (ObjectNode->AmlByteEncoding == NULL)) {
+ return FALSE;
+ }
+
+ ASSERT (AmlIsOpCodeValid (OpCode, SubOpCode));
+
+ return ((ObjectNode->AmlByteEncoding->OpCode == OpCode) &&
+ (ObjectNode->AmlByteEncoding->SubOpCode == SubOpCode)) ?
+ TRUE : FALSE;
+}
+
+/** Check whether a Node is an integer node.
+
+ By integer node we mean an object node having one of the following opcode:
+ - AML_BYTE_PREFIX;
+ - AML_WORD_PREFIX;
+ - AML_DWORD_PREFIX;
+ - AML_QWORD_PREFIX.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is an integer node.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IsIntegerNode (
+ IN AML_OBJECT_NODE * Node
+ )
+{
+ UINT8 OpCode;
+
+ if (!IS_AML_OBJECT_NODE (Node) ||
+ (Node->AmlByteEncoding == NULL)) {
+ return FALSE;
+ }
+
+ // Check Node is an integer node.
+ OpCode = Node->AmlByteEncoding->OpCode;
+ if ((OpCode != AML_BYTE_PREFIX) &&
+ (OpCode != AML_WORD_PREFIX) &&
+ (OpCode != AML_DWORD_PREFIX) &&
+ (OpCode != AML_QWORD_PREFIX)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/** Check whether a Node is a ZeroOp, a OneOp or a OnesOp.
+
+ These two objects don't have a data node holding
+ a value. This require special handling.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is a ZeroOp or OneOp.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+IsSpecialIntegerNode (
+ IN AML_OBJECT_NODE * Node
+ )
+{
+ UINT8 OpCode;
+
+ if (!IS_AML_OBJECT_NODE (Node) ||
+ (Node->AmlByteEncoding == NULL)) {
+ return FALSE;
+ }
+
+ OpCode = Node->AmlByteEncoding->OpCode;
+
+ if ((OpCode != AML_ZERO_OP) &&
+ (OpCode != AML_ONE_OP) &&
+ (OpCode != AML_ONES_OP)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/** Check whether Node corresponds to a method definition.
+
+ A method definition can be introduced:
+ - By a method object, having an AML_METHOD_OP OpCode;
+ - By an external definition of a method, having an AML_EXTERNAL_OP OpCode
+ and an ObjectType byte set to the MethodObj.
+
+ Note:
+ An alias node, having an AML_ALIAS_OP, can be resolved to a method
+ definition. This function doesn't handle this case.
+
+ @param [in] Node Node to check whether it is a method definition.
+
+ @retval TRUE The Node is a method definition.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlIsMethodDefinitionNode (
+ IN CONST AML_OBJECT_NODE * Node
+ )
+{
+ AML_DATA_NODE * ObjectType;
+
+ // Node is checked to be an object node aswell.
+ if (AmlNodeCompareOpCode (Node, AML_METHOD_OP, 0)) {
+ return TRUE;
+ } else if (AmlNodeCompareOpCode (Node, AML_EXTERNAL_OP, 0)) {
+ // If the node is an external definition, check this is a method.
+ // DefExternal := ExternalOp NameString ObjectType ArgumentCount
+ // ExternalOp := 0x15
+ // ObjectType := ByteData
+ // ArgumentCount := ByteData (0 - 7)
+ ObjectType = (AML_DATA_NODE*)AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)Node,
+ EAmlParseIndexTerm1
+ );
+ if (IS_AML_DATA_NODE (ObjectType) &&
+ (ObjectType->DataType == EAmlNodeDataTypeUInt) &&
+ ((ObjectType->Size == 1))) {
+ if (*((UINT8*)ObjectType->Buffer) == (UINT8)EAmlObjTypeMethodObj) {
+ // The external definition is a method.
+ return TRUE;
+ } else {
+ // The external definition is not a method.
+ return FALSE;
+ }
+ } else {
+ // The tree is inconsistent.
+ ASSERT (0);
+ return FALSE;
+ }
+ }
+
+ // This is not a method definition.
+ return FALSE;
+}
+
+/** Get the index at which the name of the node is stored.
+
+ @param [in] ObjectNode Pointer to an object node.
+ Must have the AML_IN_NAMESPACE attribute.
+ @param [out] Index Index of the name in the fixed list of arguments.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+AmlNodeGetNameIndex (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ OUT EAML_PARSE_INDEX * Index
+ )
+{
+ EAML_PARSE_INDEX NameIndex;
+
+ if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE) ||
+ (ObjectNode->AmlByteEncoding == NULL) ||
+ (Index == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NameIndex = ObjectNode->AmlByteEncoding->NameIndex;
+
+ if ((NameIndex > ObjectNode->AmlByteEncoding->MaxIndex) ||
+ (ObjectNode->AmlByteEncoding->Format[NameIndex] != EAmlName)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Index = NameIndex;
+
+ return EFI_SUCCESS;
+}
+
+/** Get the name of the Node.
+
+ Node must be part of the namespace.
+
+ @param [in] ObjectNode Pointer to an object node,
+ which is part of the namespace.
+
+ @return A pointer to the name.
+ NULL otherwise.
+ Return NULL for the root node.
+**/
+CHAR8 *
+EFIAPI
+AmlNodeGetName (
+ IN CONST AML_OBJECT_NODE * ObjectNode
+ )
+{
+ EFI_STATUS Status;
+ EAML_PARSE_INDEX NameIndex;
+ AML_DATA_NODE * DataNode;
+
+ if (!AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // Get the index at which the name is stored in the fixed arguments list.
+ Status = AmlNodeGetNameIndex (ObjectNode, &NameIndex);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // The name is stored in a Data node.
+ DataNode = (AML_DATA_NODE*)ObjectNode->FixedArgs[NameIndex];
+ if (IS_AML_DATA_NODE (DataNode) &&
+ (DataNode->DataType == EAmlNodeDataTypeNameString)) {
+ return (CHAR8*)DataNode->Buffer;
+ }
+
+ /* Return NULL if no name is found.
+ This can occur if the name of a node is defined as a further
+ fixed argument.
+ E.g.: CreateField (BD03, 0x28, Add (ID03 + 0x08), BF33)
+ ^
+ The parser is here.
+ The parent of the Add statement is the CreateField statement. This
+ statement defines a name in the AML namespace. This name defined as
+ the fourth fixed argument. It hasn't been parsed yet.
+ */
+ return NULL;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h
new file mode 100644
index 00000000000..6e680949080
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNode.h
@@ -0,0 +1,212 @@
+/** @file
+ AML Node.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_NODE_H_
+#define AML_NODE_H_
+
+#include <AmlNodeDefines.h>
+#include <IndustryStandard/Acpi.h>
+
+/** Create an AML_ROOT_NODE.
+ This node will be the root of the tree.
+
+ @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT header to copy
+ the data from.
+ @param [out] NewRootNodePtr The created AML_ROOT_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateRootNode (
+ IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader,
+ OUT AML_ROOT_NODE ** NewRootNodePtr
+ );
+
+/** Create an AML_OBJECT_NODE.
+
+ @param [in] AmlByteEncoding Byte encoding entry.
+ @param [in] PkgLength PkgLength of the node if the AmlByteEncoding
+ has the PkgLen attribute.
+ 0 otherwise.
+ @param [out] NewObjectNodePtr The created AML_OBJECT_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateObjectNode (
+ IN CONST AML_BYTE_ENCODING * AmlByteEncoding,
+ IN UINT32 PkgLength,
+ OUT AML_OBJECT_NODE ** NewObjectNodePtr
+ );
+
+/** Create an AML_DATA_NODE.
+
+ @param [in] DataType DataType of the node.
+ @param [in] Data Pointer to the AML bytecode corresponding to
+ this node. Data is copied from there.
+ @param [in] DataSize Number of bytes to consider at the address
+ pointed by Data.
+ @param [out] NewDataNodePtr The created AML_DATA_NODE.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlCreateDataNode (
+ IN EAML_NODE_DATA_TYPE DataType,
+ IN CONST UINT8 * Data,
+ IN UINT32 DataSize,
+ OUT AML_DATA_NODE ** NewDataNodePtr
+ );
+
+/** Delete a Node.
+
+ @param [in] Node Pointer to a Node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteNode (
+ IN AML_NODE_HEADER * Node
+ );
+
+/** Check whether ObjectNode has the input attribute.
+ This function can be used to check ObjectNode is an object node
+ at the same time.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Attribute Attribute to check for.
+
+ @retval TRUE The node is an AML object and the attribute is present.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeHasAttribute (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ IN AML_OP_ATTRIBUTE Attribute
+ );
+
+/** Check whether ObjectNode has the input OpCode/SubOpcode couple.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] OpCode OpCode to check
+ @param [in] SubOpCode SubOpCode to check
+
+ @retval TRUE The node is an AML object and
+ the Opcode and the SubOpCode match.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlNodeCompareOpCode (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ IN UINT8 OpCode,
+ IN UINT8 SubOpCode
+ );
+
+/** Check whether a Node is an integer node.
+
+ By integer node we mean an object node having one of the following opcode:
+ - AML_BYTE_PREFIX;
+ - AML_WORD_PREFIX;
+ - AML_DWORD_PREFIX;
+ - AML_QWORD_PREFIX.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is an integer node.
+ @retval FALSE Otherwise.
+*/
+BOOLEAN
+EFIAPI
+IsIntegerNode (
+ IN AML_OBJECT_NODE * Node
+ );
+
+/** Check whether a Node is a ZeroOp, a OneOp or a OnesOp.
+
+ These two objects don't have a data node holding
+ a value. This require special handling.
+
+ @param [in] Node The node to check.
+
+ @retval TRUE The Node is a ZeroOp or OneOp.
+ @retval FALSE Otherwise.
+*/
+BOOLEAN
+EFIAPI
+IsSpecialIntegerNode (
+ IN AML_OBJECT_NODE * Node
+ );
+
+/** Check whether Node corresponds to a method definition.
+
+ A method definition can be introduced:
+ - By a method object, having an AML_METHOD_OP OpCode;
+ - By an external definition of a method, having an AML_EXTERNAL_OP OpCode
+ and an ObjectType byte set to the MethodObj.
+
+ Note:
+ An alias node, having an AML_ALIAS_OP, can be resolved to a method
+ definition. This function doesn't handle this case.
+
+ @param [in] Node Node to check whether it is a method definition.
+
+ @retval TRUE The Node is a method definition.
+ @retval FALSE Otherwise.
+**/
+BOOLEAN
+EFIAPI
+AmlIsMethodDefinitionNode (
+ IN CONST AML_OBJECT_NODE * Node
+ );
+
+/** Get the index at which the name of the node is stored.
+
+ @param [in] ObjectNode Pointer to an object node.
+ Must have the AML_IN_NAMESPACE attribute.
+ @param [out] Index Index of the name in the fixed list of arguments.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+AmlNodeGetNameIndex (
+ IN CONST AML_OBJECT_NODE * ObjectNode,
+ OUT EAML_PARSE_INDEX * Index
+ );
+
+/** Get the name of the Node.
+
+ Node must be part of the namespace.
+
+ @param [in] ObjectNode Pointer to an object node,
+ which is part of the namespace.
+
+ @return A pointer to the name.
+ NULL otherwise.
+ Return NULL for the root node.
+**/
+CHAR8 *
+EFIAPI
+AmlNodeGetName (
+ IN CONST AML_OBJECT_NODE * ObjectNode
+ );
+
+#endif // AML_NODE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c
new file mode 100644
index 00000000000..97e65e71d99
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlNodeInterface.c
@@ -0,0 +1,566 @@
+/** @file
+ AML Node Interface.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+
+#include <AmlCoreInterface.h>
+#include <ResourceData/AmlResourceData.h>
+#include <String/AmlString.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+#include <Utils/AmlUtility.h>
+
+/** Returns the tree node type (Root/Object/Data).
+
+ @param [in] Node Pointer to a Node.
+
+ @return The node type.
+ EAmlNodeUnknown if invalid parameter.
+**/
+EAML_NODE_TYPE
+EFIAPI
+AmlGetNodeType (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return EAmlNodeUnknown;
+ }
+
+ return Node->NodeType;
+}
+
+/** Get the RootNode information.
+ The Node must be a root node.
+
+ @param [in] RootNode Pointer to a root node.
+ @param [out] SdtHeaderBuffer Buffer to copy the ACPI DSDT/SSDT header to.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetRootNodeInfo (
+ IN AML_ROOT_NODE * RootNode,
+ OUT EFI_ACPI_DESCRIPTION_HEADER * SdtHeaderBuffer
+ )
+{
+ if (!IS_AML_ROOT_NODE (RootNode) ||
+ (SdtHeaderBuffer == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (
+ SdtHeaderBuffer,
+ RootNode->SdtHeader,
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/** Get the ObjectNode information.
+ The Node must be an object node.
+
+ @ingroup NodeInterfaceApi
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [out] OpCode Pointer holding the OpCode.
+ Optional, can be NULL.
+ @param [out] SubOpCode Pointer holding the SubOpCode.
+ Optional, can be NULL.
+ @param [out] PkgLen Pointer holding the PkgLen.
+ The PkgLen is 0 for nodes
+ not having the Pkglen attribute.
+ Optional, can be NULL.
+ @param [out] IsNameSpaceNode Pointer holding TRUE if the node is defining
+ or changing the NameSpace scope.
+ E.g.: The "Name ()" and "Scope ()" ASL
+ statements add/modify the NameSpace scope.
+ Their corresponding node are NameSpace nodes.
+ Optional, can be NULL.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetObjectNodeInfo (
+ IN AML_OBJECT_NODE * ObjectNode,
+ OUT UINT8 * OpCode, OPTIONAL
+ OUT UINT8 * SubOpCode, OPTIONAL
+ OUT UINT32 * PkgLen, OPTIONAL
+ OUT BOOLEAN * IsNameSpaceNode OPTIONAL
+ )
+{
+ if (!IS_AML_OBJECT_NODE (ObjectNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (OpCode != NULL) {
+ *OpCode = ObjectNode->AmlByteEncoding->OpCode;
+ }
+ if (SubOpCode != NULL) {
+ *SubOpCode = ObjectNode->AmlByteEncoding->SubOpCode;
+ }
+ if (PkgLen != NULL) {
+ *PkgLen = ObjectNode->PkgLen;
+ }
+ if (IsNameSpaceNode != NULL) {
+ *IsNameSpaceNode = AmlNodeHasAttribute (ObjectNode, AML_IN_NAMESPACE);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Returns the count of the fixed arguments for the input Node.
+
+ @param [in] Node Pointer to an object node.
+
+ @return Number of fixed arguments of the object node.
+ Return 0 if the node is not an object node.
+**/
+UINT8
+AmlGetFixedArgumentCount (
+ IN AML_OBJECT_NODE * Node
+ )
+{
+ if (IS_AML_OBJECT_NODE (Node) &&
+ (Node->AmlByteEncoding != NULL)) {
+ return (UINT8)Node->AmlByteEncoding->MaxIndex;
+ }
+
+ return 0;
+}
+
+/** Get the data type of the DataNode.
+ The Node must be a data node.
+
+ @param [in] DataNode Pointer to a data node.
+ @param [out] DataType Pointer holding the data type of the data buffer.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetNodeDataType (
+ IN AML_DATA_NODE * DataNode,
+ OUT EAML_NODE_DATA_TYPE * DataType
+ )
+{
+ if (!IS_AML_DATA_NODE (DataNode) ||
+ (DataType == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *DataType = DataNode->DataType;
+
+ return EFI_SUCCESS;
+}
+
+/** Get the descriptor Id of the resource data element
+ contained in the DataNode.
+
+ The Node must be a data node.
+ The Node must have the resource data type, i.e. have the
+ EAmlNodeDataTypeResourceData data type.
+
+ @param [in] DataNode Pointer to a data node containing a
+ resource data element.
+ @param [out] ResourceDataType Pointer holding the descriptor Id of
+ the resource data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetResourceDataType (
+ IN AML_DATA_NODE * DataNode,
+ OUT AML_RD_HEADER * ResourceDataType
+ )
+{
+ if (!IS_AML_DATA_NODE (DataNode) ||
+ (ResourceDataType == NULL) ||
+ (DataNode->DataType != EAmlNodeDataTypeResourceData)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ResourceDataType = AmlRdGetDescId (DataNode->Buffer);
+
+ return EFI_SUCCESS;
+}
+
+/** Get the data buffer and size of the DataNode.
+ The Node must be a data node.
+
+ BufferSize is always updated to the size of buffer of the DataNode.
+
+ If:
+ - the content of BufferSize is >= to the DataNode's buffer size;
+ - Buffer is not NULL;
+ then copy the content of the DataNode's buffer in Buffer.
+
+ @param [in] DataNode Pointer to a data node.
+ @param [out] Buffer Buffer to write the data to.
+ Optional, if NULL, only update BufferSize.
+ @param [in, out] BufferSize Pointer holding:
+ - At entry, the size of the Buffer;
+ - At exit, the size of the DataNode's
+ buffer size.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlGetDataNodeBuffer (
+ IN AML_DATA_NODE * DataNode,
+ OUT UINT8 * Buffer, OPTIONAL
+ IN OUT UINT32 * BufferSize
+ )
+{
+ if (!IS_AML_DATA_NODE (DataNode) ||
+ (BufferSize == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*BufferSize >= DataNode->Size) &&
+ (Buffer != NULL)) {
+ CopyMem (Buffer, DataNode->Buffer, DataNode->Size);
+ }
+
+ *BufferSize = DataNode->Size;
+
+ return EFI_SUCCESS;
+}
+
+/** Update the ACPI DSDT/SSDT table header.
+
+ The input SdtHeader information is copied to the tree RootNode.
+ The table Length field is automatically updated.
+ The checksum field is only updated when serializing the tree.
+
+ @param [in] RootNode Pointer to a root node.
+ @param [in] SdtHeader Pointer to an ACPI DSDT/SSDT table header.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateRootNode (
+ IN AML_ROOT_NODE * RootNode,
+ IN CONST EFI_ACPI_DESCRIPTION_HEADER * SdtHeader
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Length;
+
+ if (!IS_AML_ROOT_NODE (RootNode) ||
+ (SdtHeader == NULL) ||
+ ((SdtHeader->Signature !=
+ EFI_ACPI_6_3_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) &&
+ (SdtHeader->Signature !=
+ EFI_ACPI_6_3_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (
+ RootNode->SdtHeader,
+ SdtHeader,
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER)
+ );
+
+ // Update the Length field.
+ Status = AmlComputeSize ((AML_NODE_HEADER*)RootNode, &Length);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ RootNode->SdtHeader->Length = Length +
+ (UINT32)sizeof (EFI_ACPI_DESCRIPTION_HEADER);
+
+ return Status;
+}
+
+/** Update an object node representing an integer with a new value.
+
+ The object node must have one of the following OpCodes:
+ - AML_BYTE_PREFIX
+ - AML_WORD_PREFIX
+ - AML_DWORD_PREFIX
+ - AML_QWORD_PREFIX
+ - AML_ZERO_OP
+ - AML_ONE_OP
+
+ The following OpCode is not supported:
+ - AML_ONES_OP
+
+ @param [in] IntegerOpNode Pointer an object node containing an integer.
+ Must not be an object node with an AML_ONES_OP
+ OpCode.
+ @param [in] NewInteger New integer value to set.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateInteger (
+ IN AML_OBJECT_NODE * IntegerOpNode,
+ IN UINT64 NewInteger
+ )
+{
+ EFI_STATUS Status;
+
+ INT8 ValueWidthDiff;
+
+ if (!IS_AML_OBJECT_NODE (IntegerOpNode) ||
+ (!IsIntegerNode (IntegerOpNode) &&
+ !IsSpecialIntegerNode (IntegerOpNode)) ||
+ AmlNodeCompareOpCode (IntegerOpNode, AML_ONES_OP, 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlNodeSetIntegerValue (IntegerOpNode, NewInteger, &ValueWidthDiff);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // If the new size is different from the old size, propagate the new size.
+ if (ValueWidthDiff != 0) {
+ // Propagate the information.
+ Status = AmlPropagateInformation (
+ (AML_NODE_HEADER*)IntegerOpNode,
+ (ValueWidthDiff > 0) ? TRUE : FALSE,
+ ABS (ValueWidthDiff),
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ }
+
+ return Status;
+}
+
+/** Update the buffer of a data node.
+
+ Note: The data type of the buffer's content must match the data type of the
+ DataNode. This is a hard restriction to prevent undesired behaviour.
+
+ @param [in] DataNode Pointer to a data node.
+ @param [in] DataType Data type of the Buffer's content.
+ @param [in] Buffer Buffer containing the new data. The content of
+ the Buffer is copied.
+ @param [in] Size Size of the Buffer.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_UNSUPPORTED Operation not supporter.
+**/
+EFI_STATUS
+EFIAPI
+AmlUpdateDataNode (
+ IN AML_DATA_NODE * DataNode,
+ IN EAML_NODE_DATA_TYPE DataType,
+ IN UINT8 * Buffer,
+ IN UINT32 Size
+ )
+{
+ EFI_STATUS Status;
+
+ UINT32 ExpectedSize;
+ AML_OBJECT_NODE * ParentNode;
+ EAML_NODE_DATA_TYPE ExpectedArgType;
+ EAML_PARSE_INDEX Index;
+
+ if (!IS_AML_DATA_NODE (DataNode) ||
+ (DataType > EAmlNodeDataTypeMax) ||
+ (Buffer == NULL) ||
+ (Size == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentNode = (AML_OBJECT_NODE*)AmlGetParent ((AML_NODE_HEADER*)DataNode);
+ if (!IS_AML_OBJECT_NODE (ParentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The NewNode and OldNode must have the same type.
+ // We do not allow to change the argument type of a data node.
+ // If required, the initial ASL template should be modified
+ // accordingly.
+ // It is however possible to interchange a raw buffer and a
+ // resource data element, since raw data can be misinterpreted
+ // as a resource data element.
+ ExpectedArgType = DataNode->DataType;
+ if ((ExpectedArgType != DataType) &&
+ (((ExpectedArgType != EAmlNodeDataTypeRaw) &&
+ (ExpectedArgType != EAmlNodeDataTypeResourceData)) ||
+ ((DataType != EAmlNodeDataTypeRaw) &&
+ (DataType != EAmlNodeDataTypeResourceData)))) {
+ ASSERT (0);
+ return EFI_UNSUPPORTED;
+ }
+
+ // Perform some compatibility checks.
+ switch (DataType) {
+ case EAmlNodeDataTypeNameString:
+ {
+ // Check the name contained in the Buffer is an AML name
+ // with the right size.
+ Status = AmlGetNameStringSize ((CONST CHAR8*)Buffer, &ExpectedSize);
+ if (EFI_ERROR (Status) ||
+ (Size != ExpectedSize)) {
+ ASSERT (0);
+ return Status;
+ }
+ break;
+ }
+ case EAmlNodeDataTypeString:
+ {
+ ExpectedSize = 0;
+ while (ExpectedSize < Size) {
+ // Cf ACPI 6.3 specification 20.2.3 Data Objects Encoding.
+ // AsciiCharList := Nothing | <AsciiChar AsciiCharList>
+ // AsciiChar := 0x01 - 0x7F
+ // NullChar := 0x00
+ if (Buffer[ExpectedSize] > 0x7F) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ ExpectedSize++;
+ }
+
+ if (ExpectedSize != Size) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+ case EAmlNodeDataTypeUInt:
+ {
+ if (AmlIsNodeFixedArgument ((CONST AML_NODE_HEADER*)DataNode, &Index)) {
+ if ((ParentNode->AmlByteEncoding == NULL) ||
+ (ParentNode->AmlByteEncoding->Format == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // It is not possible to change the size of a fixed length UintX.
+ // E.g. for PackageOp the first fixed argument is of type EAmlUInt8
+ // and represents the count of elements. This type cannot be changed.
+ if ((ParentNode->AmlByteEncoding->Format[Index] != EAmlObject) &&
+ (DataNode->Size != Size)) {
+ ASSERT (0);
+ return EFI_UNSUPPORTED;
+ }
+ }
+ break;
+ }
+ case EAmlNodeDataTypeRaw:
+ {
+ // Check if the parent node has the byte list flag set.
+ if (!AmlNodeHasAttribute (ParentNode, AML_HAS_BYTE_LIST)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+ case EAmlNodeDataTypeResourceData:
+ {
+ // The resource data can be either small or large resource data.
+ // Small resource data must be at least 1 byte.
+ // Large resource data must be at least as long as the header
+ // of a large resource data.
+ if (AML_RD_IS_LARGE (Buffer) &&
+ (Size < sizeof (ACPI_LARGE_RESOURCE_HEADER))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the parent node has the byte list flag set.
+ if (!AmlNodeHasAttribute (ParentNode, AML_HAS_BYTE_LIST)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check the size of the buffer is equal to the resource data size
+ // encoded in the input buffer.
+ ExpectedSize = AmlRdGetSize (Buffer);
+ if (ExpectedSize != Size) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+ case EAmlNodeDataTypeFieldPkgLen:
+ {
+ // Check the parent is a FieldNamed field element.
+ if (!AmlNodeCompareOpCode (ParentNode, AML_FIELD_NAMED_OP, 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+ // None and reserved types.
+ default:
+ {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+ } // switch
+
+ // If the new size is different from the old size, propagate the new size.
+ if (DataNode->Size != Size) {
+ // Propagate the information.
+ Status = AmlPropagateInformation (
+ DataNode->NodeHeader.Parent,
+ (Size > DataNode->Size) ? TRUE : FALSE,
+ (Size > DataNode->Size) ?
+ (Size - DataNode->Size) :
+ (DataNode->Size - Size),
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Free the old DataNode buffer and allocate a new buffer to store the
+ // new data.
+ FreePool (DataNode->Buffer);
+ DataNode->Buffer = AllocateZeroPool (Size);
+ if (DataNode->Buffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DataNode->Size = Size;
+ }
+
+ CopyMem (DataNode->Buffer, Buffer, Size);
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c
new file mode 100644
index 00000000000..a6cd229aa6c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.c
@@ -0,0 +1,1047 @@
+/** @file
+ AML Tree.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Tree/AmlTree.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTreeTraversal.h>
+#include <Utils/AmlUtility.h>
+
+/** Get the parent node of the input Node.
+
+ @param [in] Node Pointer to a node.
+
+ @return The parent node of the input Node.
+ NULL otherwise.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetParent (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ if (IS_AML_DATA_NODE (Node) ||
+ IS_AML_OBJECT_NODE (Node)) {
+ return Node->Parent;
+ }
+
+ return NULL;
+}
+
+/** Get the root node from any node of the tree.
+ This is done by climbing up the tree until the root node is reached.
+
+ @param [in] Node Pointer to a node.
+
+ @return The root node of the tree.
+ NULL if error.
+**/
+AML_ROOT_NODE *
+EFIAPI
+AmlGetRootNode (
+ IN CONST AML_NODE_HEADER * Node
+ )
+{
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ while (!IS_AML_ROOT_NODE (Node)) {
+ Node = Node->Parent;
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return NULL;
+ }
+ }
+ return (AML_ROOT_NODE*)Node;
+}
+
+/** Get the node at the input Index in the fixed argument list of the input
+ ObjectNode.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Index The Index of the fixed argument to get.
+
+ @return The node at the input Index in the fixed argument list
+ of the input ObjectNode.
+ NULL otherwise, e.g. if the node is not an object node, or no
+ node is available at this Index.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetFixedArgument (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN EAML_PARSE_INDEX Index
+ )
+{
+ if (IS_AML_OBJECT_NODE (ObjectNode)) {
+ if (Index < (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (ObjectNode)) {
+ return ObjectNode->FixedArgs[Index];
+ }
+ }
+
+ return NULL;
+}
+
+/** Check whether the input Node is in the fixed argument list of its parent
+ node.
+
+ If so, IndexPtr contains this Index.
+
+ @param [in] Node Pointer to a Node.
+ @param [out] IndexPtr Pointer holding the Index of the Node in
+ its parent's fixed argument list.
+
+ @retval TRUE The node is a fixed argument and the index
+ in IndexPtr is valid.
+ @retval FALSE The node is not a fixed argument.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNodeFixedArgument (
+ IN CONST AML_NODE_HEADER * Node,
+ OUT EAML_PARSE_INDEX * IndexPtr
+ )
+{
+ AML_NODE_HEADER * ParentNode;
+
+ EAML_PARSE_INDEX Index;
+ EAML_PARSE_INDEX MaxIndex;
+
+ if ((IndexPtr == NULL) ||
+ (!IS_AML_DATA_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node))) {
+ ASSERT (0);
+ return FALSE;
+ }
+
+ ParentNode = AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (IS_AML_ROOT_NODE (ParentNode)) {
+ return FALSE;
+ } else if (IS_AML_DATA_NODE (ParentNode)) {
+ // Tree is inconsistent.
+ ASSERT (0);
+ return FALSE;
+ }
+
+ // Check whether the Node is in the fixed argument list.
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)ParentNode
+ );
+ for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
+ if (AmlGetFixedArgument ((AML_OBJECT_NODE*)ParentNode, Index) == Node) {
+ *IndexPtr = Index;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/** Set the fixed argument of the ObjectNode at the Index to the NewNode.
+
+ It is the caller's responsibility to save the old node, if desired,
+ otherwise the reference to the old node will be lost.
+ If NewNode is not NULL, set its parent to ObjectNode.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Index Index in the fixed argument list of
+ the ObjectNode to set.
+ @param [in] NewNode Pointer to the NewNode.
+ Can be NULL, a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlSetFixedArgument (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN EAML_PARSE_INDEX Index,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ if (IS_AML_OBJECT_NODE (ObjectNode) &&
+ (Index <= (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (ObjectNode)) &&
+ ((NewNode == NULL) ||
+ IS_AML_OBJECT_NODE (NewNode) ||
+ IS_AML_DATA_NODE (NewNode))) {
+ ObjectNode->FixedArgs[Index] = NewNode;
+
+ // If NewNode is a data node or an object node, set its parent.
+ if (NewNode != NULL) {
+ NewNode->Parent = (AML_NODE_HEADER*)ObjectNode;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+}
+
+/** If the given AML_NODE_HEADER has a variable list of arguments,
+ return a pointer to this list.
+ Return NULL otherwise.
+
+ @param [in] Node Pointer to the AML_NODE_HEADER to check.
+
+ @return The list of variable arguments if there is one.
+ NULL otherwise.
+**/
+LIST_ENTRY *
+EFIAPI
+AmlNodeGetVariableArgList (
+ IN CONST AML_NODE_HEADER * Node
+ )
+{
+ if (IS_AML_ROOT_NODE (Node)) {
+ return &(((AML_ROOT_NODE*)Node)->VariableArgs);
+ } else if (IS_AML_OBJECT_NODE (Node)) {
+ return &(((AML_OBJECT_NODE*)Node)->VariableArgs);
+ }
+ return NULL;
+}
+
+/** Remove the Node from its parent's variable list of arguments.
+
+ The function will fail if the Node is in its parent's fixed
+ argument list.
+ The Node is not deleted. The deletion is done separately
+ from the removal.
+
+ @param [in] Node Pointer to a Node.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlRemoveNodeFromVarArgList (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ EFI_STATUS Status;
+ AML_NODE_HEADER * ParentNode;
+ UINT32 Size;
+
+ if ((!IS_AML_DATA_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentNode = AmlGetParent (Node);
+ if (!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check the node is in its parent variable list of arguments.
+ if (!IsNodeInList (
+ AmlNodeGetVariableArgList (ParentNode),
+ &Node->Link)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Unlink Node from the tree.
+ RemoveEntryList (&Node->Link);
+ InitializeListHead (&Node->Link);
+ Node->Parent = NULL;
+
+ // Get the size of the node removed.
+ Status = AmlComputeSize (Node, &Size);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the information.
+ Status = AmlPropagateInformation (ParentNode, FALSE, Size, 1);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Detach the Node from the tree.
+
+ The function will fail if the Node is in its parent's fixed
+ argument list.
+ The Node is not deleted. The deletion is done separately
+ from the removal.
+
+ @param [in] Node Pointer to a Node.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDetachNode (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ return AmlRemoveNodeFromVarArgList (Node);
+}
+
+/** Add the NewNode to the head of the variable list of arguments
+ of the ParentNode.
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddHead (
+ IN AML_NODE_HEADER * ParentNode,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NewSize;
+ LIST_ENTRY * ChildrenList;
+
+ // Check arguments and that NewNode is not already attached to a tree.
+ // ParentNode != Data Node AND NewNode != Root Node AND NewNode != attached.
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ (!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Insert it at the head of the list.
+ ChildrenList = AmlNodeGetVariableArgList (ParentNode);
+ if (ChildrenList == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InsertHeadList (ChildrenList, &NewNode->Link);
+ NewNode->Parent = ParentNode;
+
+ // Get the size of the NewNode.
+ Status = AmlComputeSize (NewNode, &NewSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the new information.
+ Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Add the NewNode to the tail of the variable list of arguments
+ of the ParentNode.
+
+ NOTE: This is an internal function which does not propagate the size
+ when a new node is added.
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddTailInternal (
+ IN AML_NODE_HEADER * ParentNode,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ LIST_ENTRY * ChildrenList;
+
+ // Check arguments and that NewNode is not already attached to a tree.
+ // ParentNode != Data Node AND NewNode != Root Node AND NewNode != attached.
+ if ((!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) ||
+ (!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Insert it at the tail of the list.
+ ChildrenList = AmlNodeGetVariableArgList (ParentNode);
+ if (ChildrenList == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ InsertTailList (ChildrenList, &NewNode->Link);
+ NewNode->Parent = ParentNode;
+
+ return EFI_SUCCESS;
+}
+
+/** Add the NewNode to the tail of the variable list of arguments
+ of the ParentNode.
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddTail (
+ IN AML_NODE_HEADER * ParentNode,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NewSize;
+
+ // Add the NewNode and check arguments.
+ Status = AmlVarListAddTailInternal (ParentNode, NewNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the size of the NewNode.
+ Status = AmlComputeSize (NewNode, &NewSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the new information.
+ Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Add the NewNode before the Node in the list of variable
+ arguments of the Node's parent.
+
+ @param [in] Node Pointer to a node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddBefore (
+ IN AML_NODE_HEADER * Node,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+ AML_NODE_HEADER * ParentNode;
+ UINT32 NewSize;
+
+ // Check arguments and that NewNode is not already attached to a tree.
+ if ((!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentNode = AmlGetParent (Node);
+ if (!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Insert it before the input Node.
+ InsertTailList (&Node->Link, &NewNode->Link);
+ NewNode->Parent = ParentNode;
+
+ // Get the size of the NewNode.
+ Status = AmlComputeSize (NewNode, &NewSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the new information.
+ Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Add the NewNode after the Node in the variable list of arguments
+ of the Node's parent.
+
+ @param [in] Node Pointer to a node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddAfter (
+ IN AML_NODE_HEADER * Node,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+ AML_NODE_HEADER * ParentNode;
+ UINT32 NewSize;
+
+ // Check arguments and that NewNode is not already attached to a tree.
+ if ((!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentNode = AmlGetParent (Node);
+ if (!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Insert the new node after the input Node.
+ InsertHeadList (&Node->Link, &NewNode->Link);
+ NewNode->Parent = ParentNode;
+
+ // Get the size of the NewNode.
+ Status = AmlComputeSize (NewNode, &NewSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the new information.
+ Status = AmlPropagateInformation (ParentNode, TRUE, NewSize, 1);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Append a Resource Data node to the BufferOpNode.
+
+ The Resource Data node is added at the end of the variable
+ list of arguments of the BufferOpNode, but before the End Tag.
+ If no End Tag is found, the function returns an error.
+
+ @param [in] BufferOpNode Buffer node containing resource data elements.
+ @param [in] NewRdNode The new Resource Data node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlAppendRdNode (
+ IN AML_OBJECT_NODE * BufferOpNode,
+ IN AML_DATA_NODE * NewRdNode
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * CurrRdNode;
+ AML_RD_HEADER RdDataType;
+
+ if (!AmlNodeCompareOpCode (BufferOpNode, AML_BUFFER_OP, 0) ||
+ !IS_AML_DATA_NODE (NewRdNode) ||
+ (NewRdNode->DataType != EAmlNodeDataTypeResourceData)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the first Resource data node in the variable list of
+ // argument of the BufferOp node.
+ CurrRdNode = (AML_DATA_NODE*)AmlGetNextVariableArgument (
+ (AML_NODE_HEADER*)BufferOpNode,
+ NULL
+ );
+ if ((CurrRdNode == NULL) ||
+ !IS_AML_DATA_NODE (CurrRdNode) ||
+ (CurrRdNode->DataType != EAmlNodeDataTypeResourceData)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Iterate through the Resource Data nodes to find the End Tag.
+ while (TRUE) {
+ Status = AmlGetResourceDataType (CurrRdNode, &RdDataType);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // If the Resource Data is an End Tag,
+ // add the new node before and return.
+ if (AmlRdCompareDescId (
+ &RdDataType,
+ AML_RD_BUILD_SMALL_DESC_ID (ACPI_SMALL_END_TAG_DESCRIPTOR_NAME))) {
+ Status = AmlVarListAddBefore (
+ (AML_NODE_HEADER*)CurrRdNode,
+ (AML_NODE_HEADER*)NewRdNode)
+ ;
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ }
+ return Status;
+ }
+
+ // Get the next Resource Data node.
+ // If this was the last node and no End Tag was found, return error.
+ // It is possible to have only one Resource Data in a BufferOp,
+ // but it should not be possible to add a new Resource Data in the list
+ // in this case.
+ CurrRdNode = (AML_DATA_NODE*)AmlGetSiblingVariableArgument (
+ (AML_NODE_HEADER*)CurrRdNode
+ );
+ if (!IS_AML_DATA_NODE (CurrRdNode) ||
+ (CurrRdNode->DataType != EAmlNodeDataTypeResourceData)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ } // while
+}
+
+/** Replace the fixed argument at the Index of the ParentNode with the NewNode.
+
+ Note: This function unlinks the OldNode from the tree. It is the callers
+ responsibility to delete the OldNode if needed.
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be an object node.
+ @param [in] Index Index of the fixed argument to replace.
+ @param [in] NewNode The new node to insert.
+ Must be an object node or a data node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlReplaceFixedArgument (
+ IN AML_OBJECT_NODE * ParentNode,
+ IN EAML_PARSE_INDEX Index,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+
+ AML_NODE_HEADER * OldNode;
+ UINT32 NewSize;
+ UINT32 OldSize;
+ AML_PARSE_FORMAT FixedArgType;
+
+ // Check arguments and that NewNode is not already attached to a tree.
+ if (!IS_AML_OBJECT_NODE (ParentNode) ||
+ (!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Perform some compatibility checks between NewNode and OldNode.
+ FixedArgType = ParentNode->AmlByteEncoding->Format[Index];
+ switch (FixedArgType) {
+ case EAmlFieldPkgLen:
+ {
+ // A FieldPkgLen can only have a parent node with the
+ // AML_IS_FIELD_ELEMENT flag.
+ if (!AmlNodeHasAttribute (
+ (AML_OBJECT_NODE*)ParentNode,
+ AML_HAS_FIELD_LIST)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ // Fall through.
+ }
+
+ case EAmlUInt8:
+ case EAmlUInt16:
+ case EAmlUInt32:
+ case EAmlUInt64:
+ case EAmlName:
+ case EAmlString:
+ {
+ // A uint, a name, a string and a FieldPkgLen can only be replaced by a
+ // data node of the same type.
+ // Note: This condition might be too strict, but safer.
+ if (!IS_AML_DATA_NODE (NewNode) ||
+ (((AML_DATA_NODE*)NewNode)->DataType !=
+ AmlTypeToNodeDataType (FixedArgType))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ case EAmlObject:
+ {
+ // If it's an object node, the grammar is too complex to do any check.
+ break;
+ }
+
+ case EAmlNone:
+ default:
+ {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ break;
+ }
+ } // switch
+
+ // Replace the OldNode with the NewNode.
+ OldNode = AmlGetFixedArgument (ParentNode, Index);
+ if (!IS_AML_NODE_VALID (OldNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Unlink the old node.
+ // Note: This function unlinks the OldNode from the tree. It is the callers
+ // responsibility to delete the OldNode if needed.
+ OldNode->Parent = NULL;
+
+ Status = AmlSetFixedArgument (ParentNode, Index, NewNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the size of the OldNode.
+ Status = AmlComputeSize (OldNode, &OldSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the size of the NewNode.
+ Status = AmlComputeSize (NewNode, &NewSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the new information.
+ Status = AmlPropagateInformation (
+ (AML_NODE_HEADER*)ParentNode,
+ (NewSize > OldSize) ? TRUE : FALSE,
+ (NewSize > OldSize) ? (NewSize - OldSize) : (OldSize - NewSize),
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Replace the OldNode, which is in a variable list of arguments,
+ with the NewNode.
+
+ Note: This function unlinks the OldNode from the tree. It is the callers
+ responsibility to delete the OldNode if needed.
+
+ @param [in] OldNode Pointer to the node to replace.
+ Must be a data node or an object node.
+ @param [in] NewNode The new node to insert.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlReplaceVariableArgument (
+ IN AML_NODE_HEADER * OldNode,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NewSize;
+ UINT32 OldSize;
+ EAML_PARSE_INDEX Index;
+
+ AML_DATA_NODE * NewDataNode;
+ AML_NODE_HEADER * ParentNode;
+ LIST_ENTRY * NextLink;
+
+ // Check arguments, that NewNode is not already attached to a tree,
+ // and that OldNode is attached and not in a fixed list of arguments.
+ if ((!IS_AML_DATA_NODE (OldNode) &&
+ !IS_AML_OBJECT_NODE (OldNode)) ||
+ (!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode) ||
+ AML_NODE_IS_DETACHED (OldNode) ||
+ AmlIsNodeFixedArgument (OldNode, &Index)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentNode = AmlGetParent (OldNode);
+ if (!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NewDataNode = (AML_DATA_NODE*)NewNode;
+
+ // Check attributes if the parent node is an object node.
+ if (IS_AML_OBJECT_NODE (ParentNode)) {
+ // A child node of a node with the HAS_CHILD flag must be either a
+ // data node or an object node. This has already been checked. So,
+ // check for other cases.
+
+ if (AmlNodeHasAttribute ((AML_OBJECT_NODE*)ParentNode, AML_HAS_BYTE_LIST)) {
+ if (!IS_AML_DATA_NODE (NewNode) ||
+ ((NewDataNode->DataType != EAmlNodeDataTypeRaw) &&
+ (NewDataNode->DataType != EAmlNodeDataTypeResourceData))) {
+ // A child node of a node with the BYTE_LIST flag must be a data node,
+ // containing raw data or a resource data.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ } else if (AmlNodeHasAttribute (
+ (AML_OBJECT_NODE*)ParentNode,
+ AML_HAS_FIELD_LIST)) {
+ if (!AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)NewNode,
+ AML_IS_FIELD_ELEMENT)) {
+ // A child node of a node with the FIELD_LIST flag must be an object
+ // node with AML_IS_FIELD_ELEMENT flag.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ } else {
+ // Parent node is a root node.
+ // A root node cannot have a data node as its child.
+ if (!IS_AML_DATA_NODE (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ // Unlink OldNode from the tree.
+ NextLink = RemoveEntryList (&OldNode->Link);
+ InitializeListHead (&OldNode->Link);
+ OldNode->Parent = NULL;
+
+ // Add the NewNode.
+ InsertHeadList (NextLink, &NewNode->Link);
+ NewNode->Parent = ParentNode;
+
+ // Get the size of the OldNode.
+ Status = AmlComputeSize (OldNode, &OldSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Get the size of the NewNode.
+ Status = AmlComputeSize (NewNode, &NewSize);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the new information.
+ Status = AmlPropagateInformation (
+ ParentNode,
+ (NewSize > OldSize) ? TRUE : FALSE,
+ (NewSize > OldSize) ? (NewSize - OldSize) : (OldSize - NewSize),
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/** Replace the OldNode by the NewNode.
+
+ Note: This function unlinks the OldNode from the tree. It is the callers
+ responsibility to delete the OldNode if needed.
+
+ @param [in] OldNode Pointer to the node to replace.
+ Must be a data node or an object node.
+ @param [in] NewNode The new node to insert.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlReplaceArgument (
+ IN AML_NODE_HEADER * OldNode,
+ IN AML_NODE_HEADER * NewNode
+ )
+{
+ EFI_STATUS Status;
+ AML_NODE_HEADER * ParentNode;
+ EAML_PARSE_INDEX Index;
+
+ // Check arguments and that NewNode is not already attached to a tree.
+ if ((!IS_AML_DATA_NODE (OldNode) &&
+ !IS_AML_OBJECT_NODE (OldNode)) ||
+ (!IS_AML_DATA_NODE (NewNode) &&
+ !IS_AML_OBJECT_NODE (NewNode)) ||
+ !AML_NODE_IS_DETACHED (NewNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // ParentNode can be a root node or an object node.
+ ParentNode = AmlGetParent (OldNode);
+ if (!IS_AML_ROOT_NODE (ParentNode) &&
+ !IS_AML_OBJECT_NODE (ParentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (AmlIsNodeFixedArgument (OldNode, &Index)) {
+ // OldNode is in its parent's fixed argument list at the Index.
+ Status = AmlReplaceFixedArgument (
+ (AML_OBJECT_NODE*)ParentNode,
+ Index,
+ NewNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } else {
+ // OldNode is not in its parent's fixed argument list.
+ // It must be in its variable list of arguments.
+ Status = AmlReplaceVariableArgument (OldNode, NewNode);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/** Delete a Node and its children.
+
+ The Node must be removed from the tree first,
+ or must be the root node.
+
+ @param [in] Node Pointer to the node to delete.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteTree (
+ IN AML_NODE_HEADER * Node
+ )
+{
+ EFI_STATUS Status;
+
+ EAML_PARSE_INDEX Index;
+ EAML_PARSE_INDEX MaxIndex;
+
+ AML_NODE_HEADER * Arg;
+ LIST_ENTRY * StartLink;
+ LIST_ENTRY * CurrentLink;
+ LIST_ENTRY * NextLink;
+
+ // Check that the node being deleted is unlinked.
+ // When removing the node, its parent pointer and
+ // its lists data structure are reset with
+ // InitializeListHead. Thus it must be detached
+ // from the tree to avoid memory leaks.
+ if (!IS_AML_NODE_VALID (Node) ||
+ !AML_NODE_IS_DETACHED (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // 1. Recursively detach and delete the fixed arguments.
+ // Iterate through the fixed list of arguments.
+ if (IS_AML_OBJECT_NODE (Node)) {
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)Node
+ );
+ for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
+ Arg = AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index);
+ if (Arg == NULL) {
+ // A fixed argument is missing. The tree is inconsistent.
+ // Note: During CodeGeneration, the fixed arguments should be set
+ // with an incrementing index, and then the variable arguments
+ // should be added. This allows to free as many nodes as
+ // possible if a crash occurs.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Remove the node from the fixed argument list.
+ Arg->Parent = NULL;
+ Status = AmlSetFixedArgument ((AML_OBJECT_NODE*)Node, Index, NULL);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ Status = AmlDeleteTree (Arg);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+ }
+
+ // 2. Recursively detach and delete the variable arguments.
+ // Iterate through the variable list of arguments.
+ StartLink = AmlNodeGetVariableArgList (Node);
+ if (StartLink != NULL) {
+ NextLink = StartLink->ForwardLink;
+ while (NextLink != StartLink) {
+ CurrentLink = NextLink;
+
+ // Unlink the node from the tree.
+ NextLink = RemoveEntryList (CurrentLink);
+ InitializeListHead (CurrentLink);
+ ((AML_NODE_HEADER*)CurrentLink)->Parent = NULL;
+
+ Status = AmlDeleteTree ((AML_NODE_HEADER*)CurrentLink);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ } // while
+ }
+
+ // 3. Delete the node.
+ Status = AmlDeleteNode (Node);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h
new file mode 100644
index 00000000000..101cb08ca39
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTree.h
@@ -0,0 +1,127 @@
+/** @file
+ AML Tree.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_TREE_H_
+#define AML_TREE_H_
+
+#include <AmlNodeDefines.h>
+
+/** Get the root node from any node of the tree.
+ This is done by climbing up the tree until the root node is reached.
+
+ @param [in] Node Pointer to a node.
+
+ @return The root node of the tree.
+ NULL if error.
+*/
+AML_ROOT_NODE *
+EFIAPI
+AmlGetRootNode (
+ IN CONST AML_NODE_HEADER * Node
+ );
+
+/** Check whether the input Node is in the fixed argument list of its parent
+ node.
+
+ If so, IndexPtr contains this Index.
+
+ @param [in] Node Pointer to a Node.
+ @param [out] IndexPtr Pointer holding the Index of the Node in
+ its parent's fixed argument list.
+
+ @retval TRUE The node is a fixed argument and the index
+ in IndexPtr is valid.
+ @retval FALSE The node is not a fixed argument.
+**/
+BOOLEAN
+EFIAPI
+AmlIsNodeFixedArgument (
+ IN CONST AML_NODE_HEADER * Node,
+ OUT EAML_PARSE_INDEX * IndexPtr
+ );
+
+/** Set the fixed argument of the ObjectNode at the Index to the NewNode.
+
+ It is the caller's responsibility to save the old node, if desired,
+ otherwise the reference to the old node will be lost.
+ If NewNode is not NULL, set its parent to ObjectNode.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] Index Index in the fixed argument list of
+ the ObjectNode to set.
+ @param [in] NewNode Pointer to the NewNode.
+ Can be NULL, a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlSetFixedArgument (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN EAML_PARSE_INDEX Index,
+ IN AML_NODE_HEADER * NewNode
+ );
+
+/** If the given AML_NODE_HEADER has a variable list of arguments,
+ return a pointer to this list.
+ Return NULL otherwise.
+
+ @param [in] Node Pointer to the AML_NODE_HEADER to check.
+
+ @return The list of variable arguments if there is one.
+ NULL otherwise.
+**/
+LIST_ENTRY *
+EFIAPI
+AmlNodeGetVariableArgList (
+ IN CONST AML_NODE_HEADER * Node
+ );
+
+/** Add the NewNode to the tail of the variable list of arguments
+ of the ParentNode.
+
+ NOTE: This is an internal function which does not propagate the size
+ when a new node is added.
+
+ @param [in] ParentNode Pointer to the parent node.
+ Must be a root or an object node.
+ @param [in] NewNode Pointer to the node to add.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlVarListAddTailInternal (
+ IN AML_NODE_HEADER * ParentNode,
+ IN AML_NODE_HEADER * NewNode
+ );
+
+/** Replace the OldNode by the NewNode.
+
+ Note: This function unlinks the OldNode from the tree. It is the callers
+ responsibility to delete the OldNode if needed.
+
+ @param [in] OldNode Pointer to the node to replace.
+ Must be a data node or an object node.
+ @param [in] NewNode The new node to insert.
+ Must be a data node or an object node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlReplaceArgument (
+ IN AML_NODE_HEADER * OldNode,
+ IN AML_NODE_HEADER * NewNode
+ );
+
+#endif // AML_TREE_H_
+
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c
new file mode 100644
index 00000000000..297c0fe837e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeEnumerator.c
@@ -0,0 +1,98 @@
+/** @file
+ AML Tree Enumerator.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlTree.h>
+
+/** Enumerate all nodes of the subtree under the input Node in the AML
+ bytestream order (i.e. in a depth first order), and call the CallBack
+ function with the input Context.
+ The prototype of the Callback function is EDKII_AML_TREE_ENUM_CALLBACK.
+
+ @param [in] Node Enumerate nodes of the subtree under this Node.
+ Must be a valid node.
+ @param [in] CallBack Callback function to call on each node.
+ @param [in, out] Context Void pointer used to pass some information
+ to the Callback function.
+ Optional, can be NULL.
+ @param [out] Status Optional parameter that can be used to get
+ the status of the Callback function.
+ If used, need to be init to EFI_SUCCESS.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+BOOLEAN
+EFIAPI
+AmlEnumTree (
+ IN AML_NODE_HEADER * Node,
+ IN EDKII_AML_TREE_ENUM_CALLBACK CallBack,
+ IN OUT VOID * Context, OPTIONAL
+ OUT EFI_STATUS * Status OPTIONAL
+ )
+{
+ BOOLEAN ContinueEnum;
+
+ EAML_PARSE_INDEX Index;
+ EAML_PARSE_INDEX MaxIndex;
+
+ LIST_ENTRY * StartLink;
+ LIST_ENTRY * CurrentLink;
+
+ if (!IS_AML_NODE_VALID (Node) || (CallBack == NULL)) {
+ ASSERT (0);
+ if (Status != NULL) {
+ *Status = EFI_INVALID_PARAMETER;
+ }
+ return FALSE;
+ }
+
+ ContinueEnum = (*CallBack)(Node, Context, Status);
+ if (ContinueEnum == FALSE) {
+ return ContinueEnum;
+ }
+
+ // Iterate through the fixed list of arguments.
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)Node
+ );
+ for (Index = EAmlParseIndexTerm0; Index < MaxIndex; Index++) {
+ ContinueEnum = AmlEnumTree (
+ AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index),
+ CallBack,
+ Context,
+ Status
+ );
+ if (ContinueEnum == FALSE) {
+ return ContinueEnum;
+ }
+ }
+
+ // Iterate through the variable list of arguments.
+ StartLink = AmlNodeGetVariableArgList (Node);
+ if (StartLink != NULL) {
+ CurrentLink = StartLink->ForwardLink;
+ while (CurrentLink != StartLink) {
+ ContinueEnum = AmlEnumTree (
+ (AML_NODE_HEADER*)CurrentLink,
+ CallBack,
+ Context,
+ Status
+ );
+ if (ContinueEnum == FALSE) {
+ return ContinueEnum;
+ }
+ CurrentLink = CurrentLink->ForwardLink;
+ } // while
+ }
+
+ return ContinueEnum;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c
new file mode 100644
index 00000000000..f8b84d67e11
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.c
@@ -0,0 +1,353 @@
+/** @file
+ AML Tree Iterator.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <AmlNodeDefines.h>
+#include <Tree/AmlTreeIterator.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlTreeTraversal.h>
+
+/** Iterator to traverse the tree.
+
+ This is an internal structure.
+*/
+typedef struct AmlTreeInternalIterator {
+ /// External iterator structure, containing the external APIs.
+ /// Must be the first field.
+ AML_TREE_ITERATOR Iterator;
+
+ // Note: The following members of this structure are opaque to the users
+ // of the Tree iterator APIs.
+
+ /// Pointer to the node on which the iterator has been initialized.
+ CONST AML_NODE_HEADER * InitialNode;
+
+ /// Pointer to the current node.
+ CONST AML_NODE_HEADER * CurrentNode;
+
+ /// Iteration mode.
+ /// Allow to choose how to traverse the tree/choose which node is next.
+ EAML_ITERATOR_MODE Mode;
+} AML_TREE_ITERATOR_INTERNAL;
+
+/** Get the current node of an iterator.
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] OutNode Pointer holding the current node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlIteratorGetNode (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HEADER ** OutNode
+ )
+{
+ AML_TREE_ITERATOR_INTERNAL * InternalIterator;
+
+ InternalIterator = (AML_TREE_ITERATOR_INTERNAL*)Iterator;
+
+ // CurrentNode can be NULL, but InitialNode cannot.
+ if ((OutNode == NULL) ||
+ (InternalIterator == NULL) ||
+ (InternalIterator->Mode <= EAmlIteratorUnknown) ||
+ (InternalIterator->Mode >= EAmlIteratorModeMax) ||
+ !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||
+ ((InternalIterator->CurrentNode != NULL) &&
+ !IS_AML_NODE_VALID (InternalIterator->CurrentNode))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *OutNode = (AML_NODE_HEADER*)InternalIterator->CurrentNode;
+
+ return EFI_SUCCESS;
+}
+
+/** Move the current node of the iterator to the next node,
+ according to the iteration mode selected.
+
+ If NextNode is not NULL, return the next node.
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] NextNode If not NULL, updated to the next node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlIteratorGetNextLinear (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HEADER ** NextNode
+ )
+{
+ AML_TREE_ITERATOR_INTERNAL * InternalIterator;
+
+ InternalIterator = (AML_TREE_ITERATOR_INTERNAL*)Iterator;
+
+ // CurrentNode can be NULL, but InitialNode cannot.
+ if ((InternalIterator == NULL) ||
+ (InternalIterator->Mode != EAmlIteratorLinear) ||
+ !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||
+ !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the next node according to the iteration mode.
+ InternalIterator->CurrentNode = AmlGetNextNode (
+ InternalIterator->CurrentNode
+ );
+
+ if (NextNode != NULL) {
+ *NextNode = (AML_NODE_HEADER*)InternalIterator->CurrentNode;
+ }
+ return EFI_SUCCESS;
+}
+
+/** Move the current node of the iterator to the previous node,
+ according to the iteration mode selected.
+
+ If PrevNode is not NULL, return the previous node.
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] PrevNode If not NULL, updated to the previous node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlIteratorGetPreviousLinear (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HEADER ** PrevNode
+ )
+{
+ AML_TREE_ITERATOR_INTERNAL * InternalIterator;
+
+ InternalIterator = (AML_TREE_ITERATOR_INTERNAL*)Iterator;
+
+ // CurrentNode can be NULL, but InitialNode cannot.
+ if ((InternalIterator == NULL) ||
+ (InternalIterator->Mode != EAmlIteratorLinear) ||
+ !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||
+ !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the previous node according to the iteration mode.
+ InternalIterator->CurrentNode = AmlGetPreviousNode (
+ InternalIterator->CurrentNode
+ );
+ if (PrevNode != NULL) {
+ *PrevNode = (AML_NODE_HEADER*)InternalIterator->CurrentNode;
+ }
+ return EFI_SUCCESS;
+}
+
+/** Move the current node of the iterator to the next node,
+ according to the iteration mode selected.
+
+ If NextNode is not NULL, return the next node.
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] NextNode If not NULL, updated to the next node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlIteratorGetNextBranch (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HEADER ** NextNode
+ )
+{
+ AML_TREE_ITERATOR_INTERNAL * InternalIterator;
+ AML_NODE_HEADER * Node;
+
+ InternalIterator = (AML_TREE_ITERATOR_INTERNAL*)Iterator;
+
+ // CurrentNode can be NULL, but InitialNode cannot.
+ if ((InternalIterator == NULL) ||
+ (InternalIterator->Mode != EAmlIteratorBranch) ||
+ !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||
+ !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Node = AmlGetNextNode (InternalIterator->CurrentNode);
+ // Check whether NextNode is a sibling of InitialNode.
+ if (AmlGetParent (Node) ==
+ AmlGetParent ((AML_NODE_HEADER*)InternalIterator->InitialNode)) {
+ Node = NULL;
+ }
+
+ InternalIterator->CurrentNode = Node;
+
+ if (NextNode != NULL) {
+ *NextNode = Node;
+ }
+ return EFI_SUCCESS;
+}
+
+/** Move the current node of the iterator to the previous node,
+ according to the iteration mode selected.
+
+ If PrevNode is not NULL, return the previous node.
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] PrevNode If not NULL, updated to the previous node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlIteratorGetPreviousBranch (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HEADER ** PrevNode
+ )
+{
+ AML_TREE_ITERATOR_INTERNAL * InternalIterator;
+ AML_NODE_HEADER * Node;
+
+ InternalIterator = (AML_TREE_ITERATOR_INTERNAL*)Iterator;
+
+ // CurrentNode can be NULL, but InitialNode cannot.
+ if ((InternalIterator == NULL) ||
+ (InternalIterator->Mode != EAmlIteratorBranch) ||
+ !IS_AML_NODE_VALID (InternalIterator->InitialNode) ||
+ !IS_AML_NODE_VALID (InternalIterator->CurrentNode)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Node = AmlGetPreviousNode (InternalIterator->CurrentNode);
+ // Check whether PreviousNode is a sibling of InitialNode.
+ if (AmlGetParent (Node) ==
+ AmlGetParent ((AML_NODE_HEADER*)InternalIterator->InitialNode)) {
+ Node = NULL;
+ }
+
+ InternalIterator->CurrentNode = Node;
+
+ if (PrevNode != NULL) {
+ *PrevNode = Node;
+ }
+ return EFI_SUCCESS;
+}
+
+/** Initialize an iterator.
+
+ Note: The caller must call AmlDeleteIterator () to free the memory
+ allocated for the iterator.
+
+ @param [in] Node Pointer to the node.
+ @param [in] IteratorMode Selected mode to traverse the tree.
+ @param [out] IteratorPtr Pointer holding the created iterator.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlInitializeIterator (
+ IN AML_NODE_HEADER * Node,
+ IN EAML_ITERATOR_MODE IteratorMode,
+ OUT AML_TREE_ITERATOR ** IteratorPtr
+ )
+{
+ AML_TREE_ITERATOR_INTERNAL * InternalIterator;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (IteratorMode <= EAmlIteratorUnknown) ||
+ (IteratorMode >= EAmlIteratorModeMax) ||
+ (IteratorPtr == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *IteratorPtr = NULL;
+ InternalIterator = (AML_TREE_ITERATOR_INTERNAL*)AllocateZeroPool (
+ sizeof (
+ AML_TREE_ITERATOR_INTERNAL
+ )
+ );
+ if (InternalIterator == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InternalIterator->InitialNode = Node;
+ InternalIterator->CurrentNode = Node;
+ InternalIterator->Mode = IteratorMode;
+ InternalIterator->Iterator.GetNode = AmlIteratorGetNode;
+
+ switch (InternalIterator->Mode) {
+ case EAmlIteratorLinear:
+ {
+ InternalIterator->Iterator.GetNext = AmlIteratorGetNextLinear;
+ InternalIterator->Iterator.GetPrevious = AmlIteratorGetPreviousLinear;
+ break;
+ }
+ case EAmlIteratorBranch:
+ {
+ InternalIterator->Iterator.GetNext = AmlIteratorGetNextBranch;
+ InternalIterator->Iterator.GetPrevious = AmlIteratorGetPreviousBranch;
+ break;
+ }
+ default:
+ {
+ ASSERT (0);
+ FreePool (InternalIterator);
+ return EFI_INVALID_PARAMETER;
+ }
+ } // switch
+
+ *IteratorPtr = &InternalIterator->Iterator;
+
+ return EFI_SUCCESS;
+}
+
+/** Delete an iterator.
+
+ Note: The caller must have first initialized the iterator with the
+ AmlInitializeIterator () function.
+
+ @param [in] Iterator Pointer to an iterator.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteIterator (
+ IN AML_TREE_ITERATOR * Iterator
+ )
+{
+ if (Iterator == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ FreePool (Iterator);
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h
new file mode 100644
index 00000000000..797ec1291f7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeIterator.h
@@ -0,0 +1,220 @@
+/** @file
+ AML Iterator.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_ITERATOR_H_
+#define AML_ITERATOR_H_
+
+/* This header file does not include internal Node definition,
+ i.e. AML_ROOT_NODE, AML_OBJECT_NODE, etc. The node definitions
+ must be included by the caller file. The function prototypes must
+ only expose AML_NODE_HANDLE, AML_ROOT_NODE_HANDLE, etc. node
+ definitions.
+ This allows to keep the functions defined here both internal and
+ potentially external. If necessary, any function of this file can
+ be exposed externally.
+ The Api folder is internal to the AmlLib, but should only use these
+ functions. They provide a "safe" way to interact with the AmlLib.
+*/
+
+/**
+ @defgroup IteratorLibrary Iterator library
+ @ingroup NavigationApis
+ @{
+ The iterator library allow to navigate in the AML tree using an iterator.
+ It is possible to initialize/delete an iterator.
+
+ This iterator can progress in the tree by different orders:
+ - Linear progression: Iterate following the AML bytestream order
+ (depth first).
+ - Branch progression: Iterate following the AML bytestream order
+ (depth first), but stop iterating at the
+ end of the branch.
+
+ An iterator has the following features:
+ - GetNode: Get the current node pointed by the iterator.
+ - GetNext: Move the current node of the iterator to the next
+ node, according to the iteration mode selected.
+ - GetPrevious: Move the current node of the iterator to the previous
+ node, according to the iteration mode selected.
+ @}
+*/
+
+/**
+ @defgroup IteratorApis Iterator APIs
+ @ingroup IteratorLibrary
+ @{
+ Iterator APIs defines the action that can be done on an iterator:
+ - Initialization;
+ - Deletion;
+ - Getting the node currently pointed by the iterator;
+ - Moving to the next node;
+ - Moving to the previous node.
+ @}
+*/
+
+/**
+ @defgroup IteratorStructures Iterator structures
+ @ingroup IteratorLibrary
+ @{
+ Iterator structures define the enum/define values and structures related
+ to iterators.
+ @}
+*/
+
+/** Iterator mode.
+
+ Modes to choose how the iterator is progressing in the tree.
+ A
+ \-B <- Iterator initialized with this node.
+ | \-C
+ | | \-D
+ | \-E
+ | \-F
+ | \-G
+ \-H
+ \-I
+
+ @ingroup IteratorStructures
+*/
+typedef enum EAmlIteratorMode {
+ EAmlIteratorUnknown, ///< Unknown/Invalid AML IteratorMode
+ EAmlIteratorLinear, ///< Iterate following the AML bytestream order
+ /// (depth first).
+ /// The order followed by the iterator would be:
+ /// B, C, D, E, F, G, H, I, NULL.
+ EAmlIteratorBranch, ///< Iterate through the node of a branch.
+ /// The iteration follows the AML bytestream
+ /// order but within the branch B.
+ /// The order followed by the iterator would be:
+ /// B, C, D, E, F, G, NULL.
+ EAmlIteratorModeMax ///< Max enum.
+} EAML_ITERATOR_MODE;
+
+/** Iterator.
+
+ Allows to traverse the tree in different orders.
+
+ @ingroup IteratorStructures
+*/
+typedef struct AmlTreeIterator AML_TREE_ITERATOR;
+
+/** Function pointer to a get the current node of the iterator.
+
+ @ingroup IteratorApis
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] OutNode Pointer holding the current node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EDKII_AML_TREE_ITERATOR_GET_NODE) (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HANDLE * OutNode
+ );
+
+/** Function pointer to move the current node of the iterator to the
+ next node, according to the iteration mode selected.
+
+ If NextNode is not NULL, return the next node.
+
+ @ingroup IteratorApis
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] NextNode If not NULL, updated to the next node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EDKII_AML_TREE_ITERATOR_GET_NEXT) (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HANDLE * NextNode
+ );
+
+/** Function pointer to move the current node of the iterator to the
+ previous node, according to the iteration mode selected.
+
+ If PrevNode is not NULL, return the previous node.
+
+ @ingroup IteratorApis
+
+ @param [in] Iterator Pointer to an iterator.
+ @param [out] PrevNode If not NULL, updated to the previous node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+*/
+typedef
+EFI_STATUS
+(EFIAPI * EDKII_AML_TREE_ITERATOR_GET_PREVIOUS) (
+ IN AML_TREE_ITERATOR * Iterator,
+ OUT AML_NODE_HANDLE * PrevNode
+ );
+
+/** Iterator structure to traverse the tree.
+
+ @ingroup IteratorStructures
+*/
+typedef struct AmlTreeIterator {
+ /// Get the current node of the iterator.
+ EDKII_AML_TREE_ITERATOR_GET_NODE GetNode;
+
+ /// Update the current node of the iterator with the next node.
+ EDKII_AML_TREE_ITERATOR_GET_NEXT GetNext;
+
+ /// Update the current node of the iterator with the previous node.
+ EDKII_AML_TREE_ITERATOR_GET_PREVIOUS GetPrevious;
+} AML_TREE_ITERATOR;
+
+
+/** Initialize an iterator.
+
+ Note: The caller must call AmlDeleteIterator () to free the memory
+ allocated for the iterator.
+
+ @ingroup IteratorApis
+
+ @param [in] Node Pointer to the node.
+ @param [in] IteratorMode Selected mode to traverse the tree.
+ @param [out] IteratorPtr Pointer holding the created iterator.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlInitializeIterator (
+ IN AML_NODE_HANDLE Node,
+ IN EAML_ITERATOR_MODE IteratorMode,
+ OUT AML_TREE_ITERATOR ** IteratorPtr
+ );
+
+/** Delete an iterator.
+
+ Note: The caller must have first initialized the iterator with the
+ AmlInitializeIterator () function.
+
+ @ingroup IteratorApis
+
+ @param [in] Iterator Pointer to an iterator.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlDeleteIterator (
+ IN AML_TREE_ITERATOR * Iterator
+ );
+
+#endif // AML_ITERATOR_H_
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c
new file mode 100644
index 00000000000..ea4d0db0511
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.c
@@ -0,0 +1,548 @@
+/** @file
+ AML Tree Traversal.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Tree/AmlTreeTraversal.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlTree.h>
+
+/** Get the sibling node among the nodes being in
+ the same variable argument list.
+
+ (ParentNode) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(VarArgNode)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Node must be in a variable list of arguments.
+ Traversal Order: VarArgNode, f, g, NULL
+
+ @ingroup CoreNavigationApis
+
+ @param [in] VarArgNode Pointer to a node.
+ Must be in a variable list of arguments.
+
+ @return The next node after VarArgNode in the variable list of arguments.
+ Return NULL if
+ - VarArgNode is the last node of the list, or
+ - VarArgNode is not part of a variable list of arguments.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetSiblingVariableArgument (
+ IN AML_NODE_HEADER * VarArgNode
+ )
+{
+ EAML_PARSE_INDEX Index;
+ AML_NODE_HEADER * ParentNode;
+
+ // VarArgNode must be an object node or a data node,
+ // and be in a variable list of arguments.
+ if ((!IS_AML_OBJECT_NODE (VarArgNode) &&
+ !IS_AML_DATA_NODE (VarArgNode)) ||
+ AmlIsNodeFixedArgument (VarArgNode, &Index)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ ParentNode = AmlGetParent (VarArgNode);
+ if (!IS_AML_NODE_VALID (ParentNode)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ return AmlGetNextVariableArgument (ParentNode, VarArgNode);
+}
+
+/** Get the next variable argument.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: e, f, g, NULL
+
+ @param [in] Node Pointer to a Root node or Object Node.
+ @param [in] CurrVarArg Pointer to the Current Variable Argument.
+
+ @return The node after the CurrVarArg in the variable list of arguments.
+ If CurrVarArg is NULL, return the first node of the
+ variable argument list.
+ Return NULL if
+ - CurrVarArg is the last node of the list, or
+ - Node does not have a variable list of arguments.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetNextVariableArgument (
+ IN AML_NODE_HEADER * Node,
+ IN AML_NODE_HEADER * CurrVarArg
+ )
+{
+ CONST LIST_ENTRY * StartLink;
+ CONST LIST_ENTRY * NextLink;
+
+ // Node must be a RootNode or an Object Node
+ // and the CurrVarArg must not be a Root Node.
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node)) ||
+ ((CurrVarArg != NULL) &&
+ (!IS_AML_OBJECT_NODE (CurrVarArg) &&
+ !IS_AML_DATA_NODE (CurrVarArg)))) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ StartLink = AmlNodeGetVariableArgList (Node);
+ if (StartLink == NULL) {
+ return NULL;
+ }
+
+ // Get the first child of the variable list of arguments.
+ if (CurrVarArg == NULL) {
+ NextLink = StartLink->ForwardLink;
+ if (NextLink != StartLink) {
+ return (AML_NODE_HEADER*)NextLink;
+ }
+ // List is empty.
+ return NULL;
+ }
+
+ // Check if CurrVarArg is in the VariableArgument List.
+ if (!IsNodeInList (StartLink, &CurrVarArg->Link)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // Get the node following the CurrVarArg.
+ NextLink = CurrVarArg->Link.ForwardLink;
+ if (NextLink != StartLink) {
+ return (AML_NODE_HEADER*)NextLink;
+ }
+
+ // End of the list has been reached.
+ return NULL;
+}
+
+/** Get the previous variable argument.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: g, f, e, NULL
+
+ @param [in] Node Pointer to a root node or an object node.
+ @param [in] CurrVarArg Pointer to the Current Variable Argument.
+
+ @return The node before the CurrVarArg in the variable list of
+ arguments.
+ If CurrVarArg is NULL, return the last node of the
+ variable list of arguments.
+ Return NULL if:
+ - CurrVarArg is the first node of the list, or
+ - Node doesn't have a variable list of arguments.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetPreviousVariableArgument (
+ IN AML_NODE_HEADER * Node,
+ IN AML_NODE_HEADER * CurrVarArg
+ )
+{
+ CONST LIST_ENTRY * StartLink;
+ CONST LIST_ENTRY * PreviousLink;
+
+ // Node must be a RootNode or an Object Node
+ // and the CurrVarArg must not be a Root Node.
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node)) ||
+ ((CurrVarArg != NULL) &&
+ (!IS_AML_OBJECT_NODE (CurrVarArg) &&
+ !IS_AML_DATA_NODE (CurrVarArg)))) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ StartLink = AmlNodeGetVariableArgList (Node);
+ if (StartLink == NULL) {
+ return NULL;
+ }
+
+ // Get the last child of the variable list of arguments.
+ if (CurrVarArg == NULL) {
+ PreviousLink = StartLink->BackLink;
+ if (PreviousLink != StartLink) {
+ return (AML_NODE_HEADER*)PreviousLink;
+ }
+ // List is empty.
+ return NULL;
+ }
+
+ // Check if CurrVarArg is in the VariableArgument List.
+ if (!IsNodeInList (StartLink, &CurrVarArg->Link)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ // Get the node before the CurrVarArg.
+ PreviousLink = CurrVarArg->Link.BackLink;
+ if (PreviousLink != StartLink) {
+ return (AML_NODE_HEADER*)PreviousLink;
+ }
+
+ // We have reached the beginning of the list.
+ return NULL;
+}
+
+/** Get the next sibling node among the children of the input Node.
+
+ This function traverses the FixedArguments followed by the
+ VariableArguments at the same level in the hierarchy.
+
+ Fixed arguments are before variable arguments.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: a, b, c, d, e, f, g, NULL
+
+
+ @param [in] Node Pointer to a root node or an object node.
+ @param [in] ChildNode Get the node after the ChildNode.
+
+ @return The node after the ChildNode among the children of the input Node.
+ - If ChildNode is NULL, return the first available node among
+ the fixed argument list then variable list of arguments;
+ - If ChildNode is the last node of the fixed argument list,
+ return the first argument of the variable list of arguments;
+ - If ChildNode is the last node of the variable list of arguments,
+ return NULL.
+
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetNextSibling (
+ IN CONST AML_NODE_HEADER * Node,
+ IN CONST AML_NODE_HEADER * ChildNode
+ )
+{
+ EAML_PARSE_INDEX Index;
+ AML_NODE_HEADER * CandidateNode;
+
+ // Node must be a RootNode or an Object Node
+ // and the CurrVarArg must not be a Root Node.
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node)) ||
+ ((ChildNode != NULL) &&
+ (!IS_AML_OBJECT_NODE (ChildNode) &&
+ !IS_AML_DATA_NODE (ChildNode)))) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ if (IS_AML_OBJECT_NODE (Node)) {
+ if (ChildNode == NULL) {
+ // Get the fixed argument at index 0 of the ChildNode.
+ CandidateNode = AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)Node,
+ EAmlParseIndexTerm0
+ );
+ if (CandidateNode != NULL) {
+ return CandidateNode;
+ }
+ } else {
+ // (ChildNode != NULL)
+ if (AmlIsNodeFixedArgument (ChildNode, &Index)) {
+ // Increment index to point to the next fixed argument.
+ Index++;
+ // The node is part of the list of fixed arguments.
+ if (Index == (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)Node)
+ ) {
+ // It is at the last argument of the fixed argument list.
+ // Get the first argument of the variable list of arguments.
+ ChildNode = NULL;
+ } else {
+ // Else return the next node in the list of fixed arguments.
+ return AmlGetFixedArgument ((AML_OBJECT_NODE*)Node, Index);
+ }
+ }
+ }
+ } // IS_AML_OBJECT_NODE (Node)
+
+ // Else, get the next node in the variable list of arguments.
+ return AmlGetNextVariableArgument (
+ (AML_NODE_HEADER*)Node,
+ (AML_NODE_HEADER*)ChildNode
+ );
+}
+
+/** Get the previous sibling node among the children of the input Node.
+
+ This function traverses the FixedArguments followed by the
+ VariableArguments at the same level in the hierarchy.
+
+ Fixed arguments are before variable arguments.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: g, f, e, d, c, b, a, NULL
+
+ @param [in] Node The node to get the fixed argument from.
+ @param [in] ChildNode Get the node before the ChildNode.
+
+ @return The node before the ChildNode among the children of the input Node.
+ - If ChildNode is NULL, return the last available node among
+ the variable list of arguments then fixed argument list;
+ - If ChildNode is the first node of the variable list of arguments,
+ return the last argument of the fixed argument list;
+ - If ChildNode is the first node of the fixed argument list,
+ return NULL.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetPreviousSibling (
+ IN CONST AML_NODE_HEADER * Node,
+ IN CONST AML_NODE_HEADER * ChildNode
+ )
+{
+ EAML_PARSE_INDEX Index;
+ EAML_PARSE_INDEX MaxIndex;
+
+ AML_NODE_HEADER * CandidateNode;
+
+ // Node must be a Root Node or an Object Node
+ // and the ChildNode must not be a Root Node.
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node)) ||
+ ((ChildNode != NULL) &&
+ (!IS_AML_OBJECT_NODE (ChildNode) &&
+ !IS_AML_DATA_NODE (ChildNode)))) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ MaxIndex = (EAML_PARSE_INDEX)AmlGetFixedArgumentCount (
+ (AML_OBJECT_NODE*)Node
+ );
+
+ // Get the last variable argument if no ChildNode.
+ // Otherwise the fixed argument list is checked first.
+ if ((ChildNode != NULL) &&
+ IS_AML_OBJECT_NODE (Node) &&
+ (MaxIndex != EAmlParseIndexTerm0)) {
+ if (AmlIsNodeFixedArgument (ChildNode, &Index)) {
+ // The node is part of the list of fixed arguments.
+ if (Index == EAmlParseIndexTerm0) {
+ // The node is the first fixed argument, return NULL.
+ return NULL;
+ } else {
+ // Return the previous node in the fixed argument list.
+ return AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)Node,
+ (EAML_PARSE_INDEX)(Index - 1)
+ );
+ }
+ }
+ }
+
+ // ChildNode is in the variable list of arguments.
+ CandidateNode = AmlGetPreviousVariableArgument (
+ (AML_NODE_HEADER*)Node,
+ (AML_NODE_HEADER*)ChildNode
+ );
+ if (CandidateNode != NULL) {
+ if (!IS_AML_NODE_VALID (CandidateNode)) {
+ ASSERT (0);
+ return NULL;
+ }
+ // A Node has been found
+ return CandidateNode;
+ } else if (MaxIndex != EAmlParseIndexTerm0) {
+ // ChildNode was the first node of the variable list of arguments.
+ return AmlGetFixedArgument (
+ (AML_OBJECT_NODE*)Node,
+ (EAML_PARSE_INDEX)(MaxIndex - 1)
+ );
+ } else {
+ // No fixed arguments or variable arguments.
+ return NULL;
+ }
+}
+
+/** Iterate through the nodes in the same order as the AML bytestream.
+
+ The iteration is similar to a depth-first path.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: a, b, i, c, d, e, h, f, g, NULL
+ Note: The branch i and h will be traversed if it has any children.
+
+ @param [in] Node Pointer to a node.
+
+ @return The next node in the AML bytestream order.
+ Return NULL if Node is the Node corresponding to the last
+ bytecode of the tree.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetNextNode (
+ IN CONST AML_NODE_HEADER * Node
+ )
+{
+ AML_NODE_HEADER * ParentNode;
+ AML_NODE_HEADER * CandidateNode;
+
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ if (IS_AML_ROOT_NODE (Node) || IS_AML_OBJECT_NODE (Node)) {
+ // The node has children. Get the first child.
+ CandidateNode = AmlGetNextSibling (Node, NULL);
+ if (CandidateNode != NULL) {
+ if (!IS_AML_NODE_VALID (CandidateNode)) {
+ ASSERT (0);
+ return NULL;
+ }
+ // A Node has been found
+ return CandidateNode;
+ } else if (IS_AML_ROOT_NODE (Node)) {
+ // The node is the root node and it doesn't have children.
+ return NULL;
+ }
+ }
+
+ // We have traversed the current branch, go to the parent node
+ // and start traversing the next branch.
+ // Keep going up the tree until you reach the root node.
+ while (1) {
+ if (IS_AML_ROOT_NODE (Node)) {
+ // This is the last node of the tree.
+ return NULL;
+ }
+
+ ParentNode = AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (!IS_AML_NODE_VALID (ParentNode)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ CandidateNode = AmlGetNextSibling (ParentNode, Node);
+ if (CandidateNode != NULL) {
+ if (!IS_AML_NODE_VALID (CandidateNode)) {
+ ASSERT (0);
+ return NULL;
+ }
+ // A Node has been found
+ return CandidateNode;
+ }
+
+ Node = ParentNode;
+ } // while
+
+ return NULL;
+}
+
+/** Iterate through the nodes in the reverse order of the AML bytestream.
+
+ The iteration is similar to a depth-first path,
+ but done in a reverse order.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: g, f, h, e, d, c, i, b, a, NULL
+ Note: The branch i and h will be traversed if it has any children.
+
+ @param [in] Node Pointer to a node.
+
+ @return The previous node in the AML bytestream order.
+ Return NULL if Node is the Node corresponding to the last
+ bytecode of the tree.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetPreviousNode (
+ IN CONST AML_NODE_HEADER * Node
+ )
+{
+ AML_NODE_HEADER * ParentNode;
+ AML_NODE_HEADER * CandidateNode;
+ AML_NODE_HEADER * PreviousNode;
+
+ if (!IS_AML_NODE_VALID (Node)) {
+ ASSERT (0);
+ return NULL;
+ }
+
+ while (1) {
+
+ if (IS_AML_ROOT_NODE (Node)) {
+ // This is the root node.
+ return NULL;
+ }
+
+ ParentNode = AmlGetParent ((AML_NODE_HEADER*)Node);
+ CandidateNode = AmlGetPreviousSibling (ParentNode, Node);
+
+ if (CandidateNode == NULL) {
+ // Node is the first child of its parent.
+ return ParentNode;
+ } else if (IS_AML_DATA_NODE (CandidateNode)) {
+ // CandidateNode is a data node, thus it has no children.
+ return CandidateNode;
+ } else if (IS_AML_OBJECT_NODE (CandidateNode)) {
+ // Get the previous node in the list of children of ParentNode,
+ // then get the last child of this node.
+ // If this node has children, get its last child, etc.
+ while (1) {
+ PreviousNode = CandidateNode;
+ CandidateNode = AmlGetPreviousSibling (PreviousNode, NULL);
+ if (CandidateNode == NULL) {
+ return PreviousNode;
+ } else if (IS_AML_DATA_NODE (CandidateNode)) {
+ return CandidateNode;
+ }
+ } // while
+
+ } else {
+ ASSERT (0);
+ return NULL;
+ }
+ } // while
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h
new file mode 100644
index 00000000000..4a9208f2fd9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Tree/AmlTreeTraversal.h
@@ -0,0 +1,138 @@
+/** @file
+ AML Tree Traversal.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_TREE_TRAVERSAL_H_
+#define AML_TREE_TRAVERSAL_H_
+
+#include <AmlNodeDefines.h>
+
+/** Get the next sibling node among the children of the input Node.
+
+ This function traverses the FixedArguments followed by the
+ VariableArguments at the same level in the hierarchy.
+
+ Fixed arguments are before variable arguments.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: a, b, c, d, e, f, g, NULL
+
+
+ @param [in] Node Pointer to a root node or an object node.
+ @param [in] ChildNode Get the node after the ChildNode.
+
+ @return The node after the ChildNode among the children of the input Node.
+ - If ChildNode is NULL, return the first available node among
+ the fixed argument list then variable list of arguments;
+ - If ChildNode is the last node of the fixed argument list,
+ return the first argument of the variable list of arguments;
+ - If ChildNode is the last node of the variable list of arguments,
+ return NULL.
+
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetNextSibling (
+ IN CONST AML_NODE_HEADER * Node,
+ IN CONST AML_NODE_HEADER * ChildNode
+ );
+
+/** Get the previous sibling node among the children of the input Node.
+
+ This function traverses the FixedArguments followed by the
+ VariableArguments at the same level in the hierarchy.
+
+ Fixed arguments are before variable arguments.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: g, f, e, d, c, b, a, NULL
+
+ @param [in] Node The node to get the fixed argument from.
+ @param [in] ChildNode Get the node before the ChildNode.
+
+ @return The node before the ChildNode among the children of the input Node.
+ - If ChildNode is NULL, return the last available node among
+ the variable list of arguments then fixed argument list;
+ - If ChildNode is the first node of the variable list of arguments,
+ return the last argument of the fixed argument list;
+ - If ChildNode is the first node of the fixed argument list,
+ return NULL.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetPreviousSibling (
+ IN CONST AML_NODE_HEADER * Node,
+ IN CONST AML_NODE_HEADER * ChildNode
+ );
+
+/** Iterate through the nodes in the same order as the AML bytestream.
+
+ The iteration is similar to a depth-first path.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: a, b, i, c, d, e, h, f, g, NULL
+ Note: The branch i and h will be traversed if it has any children.
+
+ @param [in] Node Pointer to a node.
+
+ @return The next node in the AML bytestream order.
+ Return NULL if Node is the Node corresponding to the last
+ bytecode of the tree.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetNextNode (
+ IN CONST AML_NODE_HEADER * Node
+ );
+
+/** Iterate through the nodes in the reverse order of the AML bytestream.
+
+ The iteration is similar to a depth-first path,
+ but done in a reverse order.
+
+ (Node) /-i # Child of fixed argument b
+ \ /
+ |- [a][b][c][d] # Fixed Arguments
+ |- {(e)->(f)->(g)} # Variable Arguments
+ \
+ \-h # Child of variable argument e
+
+ Traversal Order: g, f, h, e, d, c, i, b, a, NULL
+ Note: The branch i and h will be traversed if it has any children.
+
+ @param [in] Node Pointer to a node.
+
+ @return The previous node in the AML bytestream order.
+ Return NULL if Node is the Node corresponding to the last
+ bytecode of the tree.
+**/
+AML_NODE_HEADER *
+EFIAPI
+AmlGetPreviousNode (
+ IN CONST AML_NODE_HEADER * Node
+ );
+
+#endif // AML_TREE_TRAVERSAL_H_
+
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c
new file mode 100644
index 00000000000..5da5f644cfb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.c
@@ -0,0 +1,906 @@
+/** @file
+ AML Utility.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Utils/AmlUtility.h>
+
+#include <AmlCoreInterface.h>
+#include <Tree/AmlNode.h>
+#include <Tree/AmlTree.h>
+
+/** This function computes and updates the ACPI table checksum.
+
+ @param [in] AcpiTable Pointer to an Acpi table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformChecksum (
+ IN EFI_ACPI_DESCRIPTION_HEADER * AcpiTable
+ )
+{
+ UINT8 * Ptr;
+ UINT8 Sum;
+ UINT32 Size;
+
+ if (AcpiTable == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = (UINT8*)AcpiTable;
+ Size = AcpiTable->Length;
+ Sum = 0;
+
+ // Set the checksum field to 0 first.
+ AcpiTable->Checksum = 0;
+
+ // Compute the checksum.
+ while ((Size--) != 0) {
+ Sum = (UINT8)(Sum + (*Ptr++));
+ }
+
+ // Set the checksum.
+ AcpiTable->Checksum = (UINT8)(0xFF - Sum + 1);
+
+ return EFI_SUCCESS;
+}
+
+/** A callback function that computes the size of a Node and adds it to the
+ Size pointer stored in the Context.
+ Calling this function on the root node will compute the total size of the
+ AML bytestream.
+
+ @param [in] Node Node to compute the size.
+ @param [in, out] Context Pointer holding the computed size.
+ (UINT32 *) Context.
+ @param [in, out] Status Pointer holding:
+ - At entry, the Status returned by the
+ last call to this exact function during
+ the enumeration;
+ - At exit, he returned status of the
+ call to this function.
+ Optional, can be NULL.
+
+ @retval TRUE if the enumeration can continue or has finished without
+ interruption.
+ @retval FALSE if the enumeration needs to stopped or has stopped.
+**/
+STATIC
+BOOLEAN
+EFIAPI
+AmlComputeSizeCallback (
+ IN AML_NODE_HEADER * Node,
+ IN OUT VOID * Context,
+ IN OUT EFI_STATUS * Status OPTIONAL
+ )
+{
+ UINT32 Size;
+ EAML_PARSE_INDEX IndexPtr;
+ CONST AML_OBJECT_NODE * ParentNode;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (Context == NULL)) {
+ ASSERT (0);
+ if (Status != NULL) {
+ *Status = EFI_INVALID_PARAMETER;
+ }
+ return FALSE;
+ }
+
+ // Ignore the second fixed argument of method invocation nodes
+ // as the information stored there (the argument count) is not in the
+ // ACPI specification.
+ ParentNode = (CONST AML_OBJECT_NODE*)AmlGetParent (Node);
+ if (IS_AML_OBJECT_NODE (ParentNode) &&
+ AmlNodeCompareOpCode (ParentNode, AML_METHOD_INVOC_OP, 0) &&
+ AmlIsNodeFixedArgument (Node, &IndexPtr)) {
+ if (IndexPtr == EAmlParseIndexTerm1) {
+ if (Status != NULL) {
+ *Status = EFI_SUCCESS;
+ }
+ return TRUE;
+ }
+ }
+
+ Size = *((UINT32*)Context);
+
+ if (IS_AML_DATA_NODE (Node)) {
+ Size += ((AML_DATA_NODE*)Node)->Size;
+ } else if (IS_AML_OBJECT_NODE (Node) &&
+ !AmlNodeHasAttribute (
+ (CONST AML_OBJECT_NODE*)Node,
+ AML_IS_PSEUDO_OPCODE)) {
+ // Ignore pseudo-opcodes as they are not part of the
+ // ACPI specification.
+
+ Size += (((AML_OBJECT_NODE*)Node)->AmlByteEncoding->OpCode ==
+ AML_EXT_OP) ? 2 : 1;
+
+ // Add the size of the PkgLen.
+ if (AmlNodeHasAttribute (
+ (AML_OBJECT_NODE*)Node,
+ AML_HAS_PKG_LENGTH)) {
+ Size += AmlComputePkgLengthWidth (((AML_OBJECT_NODE*)Node)->PkgLen);
+ }
+ }
+
+ // Check for overflow.
+ // The root node has a null size, thus the strict comparison.
+ if (*((UINT32*)Context) > Size) {
+ ASSERT (0);
+ *Status = EFI_INVALID_PARAMETER;
+ return FALSE;
+ }
+
+ *((UINT32*)Context) = Size;
+
+ if (Status != NULL) {
+ *Status = EFI_SUCCESS;
+ }
+
+ return TRUE;
+}
+
+/** Compute the size of a tree/sub-tree.
+
+ @param [in] Node Node to compute the size.
+ @param [in, out] Size Pointer holding the computed size.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlComputeSize (
+ IN CONST AML_NODE_HEADER * Node,
+ IN OUT UINT32 * Size
+ )
+{
+ EFI_STATUS Status;
+
+ if (!IS_AML_NODE_VALID (Node) ||
+ (Size == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Size = 0;
+
+ AmlEnumTree (
+ (AML_NODE_HEADER*)Node,
+ AmlComputeSizeCallback,
+ (VOID*)Size,
+ &Status
+ );
+
+ return Status;
+}
+
+/** Get the value contained in an integer node.
+
+ @param [in] Node Pointer to an integer node.
+ Must be an object node.
+ @param [out] Value Value contained in the integer node.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlNodeGetIntegerValue (
+ IN AML_OBJECT_NODE * Node,
+ OUT UINT64 * Value
+ )
+{
+ AML_DATA_NODE * DataNode;
+
+ if ((!IsIntegerNode (Node) &&
+ !IsSpecialIntegerNode (Node)) ||
+ (Value == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // For ZeroOp and OneOp, there is no data node.
+ if (IsSpecialIntegerNode (Node)) {
+ if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) {
+ *Value = 0;
+ } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) {
+ *Value = 1;
+ } else {
+ // OnesOp cannot be handled: it represents a maximum value.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ return EFI_SUCCESS;
+ }
+
+ // For integer nodes, the value is in the first fixed argument.
+ DataNode = (AML_DATA_NODE*)Node->FixedArgs[EAmlParseIndexTerm0];
+ if (!IS_AML_DATA_NODE (DataNode) ||
+ (DataNode->DataType != EAmlNodeDataTypeUInt)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (DataNode->Size) {
+ case 1:
+ {
+ *Value = *((UINT8*)(DataNode->Buffer));
+ break;
+ }
+ case 2:
+ {
+ *Value = *((UINT16*)(DataNode->Buffer));
+ break;
+ }
+ case 4:
+ {
+ *Value = *((UINT32*)(DataNode->Buffer));
+ break;
+ }
+ case 8:
+ {
+ *Value = *((UINT64*)(DataNode->Buffer));
+ break;
+ }
+ default:
+ {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ } // switch
+
+ return EFI_SUCCESS;
+}
+
+/** Replace a Zero (AML_ZERO_OP) or One (AML_ONE_OP) object node
+ with a byte integer (AML_BYTE_PREFIX) object node having the same value.
+
+ @param [in] Node Pointer to an integer node.
+ Must be an object node having ZeroOp or OneOp.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlUnwindSpecialInteger (
+ IN AML_OBJECT_NODE * Node
+ )
+{
+ EFI_STATUS Status;
+
+ AML_DATA_NODE * NewDataNode;
+ UINT8 Value;
+ CONST AML_BYTE_ENCODING * ByteEncoding;
+
+ if (!IsSpecialIntegerNode (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Find the value.
+ if (AmlNodeCompareOpCode (Node, AML_ZERO_OP, 0)) {
+ Value = 0;
+ } else if (AmlNodeCompareOpCode (Node, AML_ONE_OP, 0)) {
+ Value = 1;
+ } else {
+ // OnesOp cannot be handled: it represents a maximum value.
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlCreateDataNode (
+ EAmlNodeDataTypeUInt,
+ &Value,
+ sizeof (UINT8),
+ (AML_DATA_NODE**)&NewDataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Change the encoding of the special node to a ByteOp encoding.
+ ByteEncoding = AmlGetByteEncodingByOpCode (AML_BYTE_PREFIX, 0);
+ if (ByteEncoding == NULL) {
+ ASSERT (0);
+ Status = EFI_INVALID_PARAMETER;
+ goto error_handler;
+ }
+
+ // Update the ByteEncoding from ZERO_OP/ONE_OP to AML_BYTE_PREFIX.
+ Node->AmlByteEncoding = ByteEncoding;
+
+ // Add the data node as the first fixed argument of the ByteOp object.
+ Status = AmlSetFixedArgument (
+ (AML_OBJECT_NODE*)Node,
+ EAmlParseIndexTerm0,
+ (AML_NODE_HEADER*)NewDataNode
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ goto error_handler;
+ }
+
+ return Status;
+
+error_handler:
+ AmlDeleteTree ((AML_NODE_HEADER*)NewDataNode);
+ return Status;
+}
+
+/** Set the value contained in an integer node.
+
+ The OpCode is updated accordingly to the new value
+ (e.g.: If the original value was a UINT8 value, then the OpCode
+ would be AML_BYTE_PREFIX. If it the new value is a UINT16
+ value then the OpCode will be updated to AML_WORD_PREFIX).
+
+ @param [in] Node Pointer to an integer node.
+ Must be an object node.
+ @param [in] NewValue New value to write in the integer node.
+ @param [out] ValueWidthDiff Difference in number of bytes used to store
+ the new value.
+ Can be negative.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlNodeSetIntegerValue (
+ IN AML_OBJECT_NODE * Node,
+ IN UINT64 NewValue,
+ OUT INT8 * ValueWidthDiff
+ )
+{
+ EFI_STATUS Status;
+ AML_DATA_NODE * DataNode;
+
+ UINT8 NewOpCode;
+ UINT8 NumberOfBytes;
+
+ if ((!IsIntegerNode (Node) &&
+ !IsSpecialIntegerNode (Node)) ||
+ (ValueWidthDiff == NULL)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ValueWidthDiff = 0;
+ // For ZeroOp and OneOp, there is no data node.
+ // Thus the object node is converted to a byte object node holding 0 or 1.
+ if (IsSpecialIntegerNode (Node)) {
+ switch (NewValue) {
+ case AML_ZERO_OP:
+ Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (AML_ZERO_OP, 0);
+ return EFI_SUCCESS;
+ case AML_ONE_OP:
+ Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (AML_ONE_OP, 0);
+ return EFI_SUCCESS;
+ default:
+ {
+ Status = AmlUnwindSpecialInteger (Node);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ // The AmlUnwindSpecialInteger functions converts a special integer
+ // node to a UInt8/Byte data node. Thus, the size increments by one:
+ // special integer are encoded as one byte (the opcode only) while byte
+ // integers are encoded as two bytes (the opcode + the value).
+ *ValueWidthDiff += sizeof (UINT8);
+ }
+ } // switch
+ } // IsSpecialIntegerNode (Node)
+
+ // For integer nodes, the value is in the first fixed argument.
+ DataNode = (AML_DATA_NODE*)Node->FixedArgs[EAmlParseIndexTerm0];
+ if (!IS_AML_DATA_NODE (DataNode) ||
+ (DataNode->DataType != EAmlNodeDataTypeUInt)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The value can be encoded with a special 0 or 1 OpCode.
+ // The AML_ONES_OP is not handled.
+ if (NewValue <= 1) {
+ NewOpCode = (NewValue == 0) ? AML_ZERO_OP : AML_ONE_OP;
+ Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (NewOpCode, 0);
+
+ // The value is encoded with a AML_ZERO_OP or AML_ONE_OP.
+ // This means there is no need for a DataNode containing the value.
+ // The change in size is equal to the size of the DataNode's buffer.
+ *ValueWidthDiff = -((INT8)DataNode->Size);
+
+ // Detach and free the DataNode containing the integer value.
+ DataNode->NodeHeader.Parent = NULL;
+ Node->FixedArgs[EAmlParseIndexTerm0] = NULL;
+ Status = AmlDeleteNode ((AML_NODE_HEADER*)DataNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ // Check the number of bits needed to represent the value.
+ if (NewValue > MAX_UINT32) {
+ // Value is 64 bits.
+ NewOpCode = AML_QWORD_PREFIX;
+ NumberOfBytes = 8;
+ } else if (NewValue > MAX_UINT16) {
+ // Value is 32 bits.
+ NewOpCode = AML_DWORD_PREFIX;
+ NumberOfBytes = 4;
+ } else if (NewValue > MAX_UINT8) {
+ // Value is 16 bits.
+ NewOpCode = AML_WORD_PREFIX;
+ NumberOfBytes = 2;
+ } else {
+ // Value is 8 bits.
+ NewOpCode = AML_BYTE_PREFIX;
+ NumberOfBytes = 1;
+ }
+
+ *ValueWidthDiff += (INT8)(NumberOfBytes - DataNode->Size);
+
+ // Update the ByteEncoding as it may have changed between [8 .. 64] bits.
+ Node->AmlByteEncoding = AmlGetByteEncodingByOpCode (NewOpCode, 0);
+ if (Node->AmlByteEncoding == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Free the old DataNode buffer and allocate a buffer with the right size
+ // to store the new data.
+ if (*ValueWidthDiff != 0) {
+ FreePool (DataNode->Buffer);
+ DataNode->Buffer = AllocateZeroPool (NumberOfBytes);
+ if (DataNode->Buffer == NULL) {
+ ASSERT (0);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DataNode->Size = NumberOfBytes;
+ }
+
+ // Write the new value.
+ CopyMem (DataNode->Buffer, &NewValue, NumberOfBytes);
+
+ return EFI_SUCCESS;
+}
+
+/** Increment/decrement the value contained in the IntegerNode.
+
+ @param [in] IntegerNode Pointer to an object node containing
+ an integer.
+ @param [in] IsIncrement Choose the operation to do:
+ - TRUE: Increment the Node's size and
+ the Node's count;
+ - FALSE: Decrement the Node's size and
+ the Node's count.
+ @param [in] Diff Value to add/subtract to the integer.
+ @param [out] ValueWidthDiff When modifying the integer, it can be
+ promoted/demoted, e.g. from UINT8 to UINT16.
+ Stores the change in width.
+ Can be negative.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlNodeUpdateIntegerValue (
+ IN AML_OBJECT_NODE * IntegerNode,
+ IN BOOLEAN IsIncrement,
+ IN UINT64 Diff,
+ OUT INT8 * ValueWidthDiff
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Value;
+
+ if (ValueWidthDiff == NULL) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Get the current value.
+ // Checks on the IntegerNode are done in the call.
+ Status = AmlNodeGetIntegerValue (IntegerNode, &Value);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Check for UINT64 over/underflow.
+ if ((IsIncrement && (Value > (MAX_UINT64 - Diff))) ||
+ (!IsIncrement && (Value < Diff))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Compute the new value.
+ if (IsIncrement) {
+ Value += Diff;
+ } else {
+ Value -= Diff;
+ }
+
+ Status = AmlNodeSetIntegerValue (
+ IntegerNode,
+ Value,
+ ValueWidthDiff
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/** Propagate the size information up the tree.
+
+ The length of the ACPI table is updated in the RootNode,
+ but not the checksum.
+
+ @param [in] Node Pointer to a node.
+ Must be a root node or an object node.
+ @param [in] IsIncrement Choose the operation to do:
+ - TRUE: Increment the Node's size and
+ the Node's count;
+ - FALSE: Decrement the Node's size and
+ the Node's count.
+ @param [in] Diff Value to add/subtract to the Node's size.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlPropagateSize (
+ IN AML_NODE_HEADER * Node,
+ IN BOOLEAN IsIncrement,
+ IN UINT32 * Diff
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE * ObjectNode;
+ AML_NODE_HEADER * ParentNode;
+
+ UINT32 Value;
+ UINT32 InitialPkgLenWidth;
+ UINT32 NewPkgLenWidth;
+ UINT32 ReComputedPkgLenWidth;
+ INT8 FieldWidthChange;
+
+ if (!IS_AML_OBJECT_NODE (Node) &&
+ !IS_AML_ROOT_NODE (Node)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IS_AML_OBJECT_NODE (Node)) {
+ ObjectNode = (AML_OBJECT_NODE*)Node;
+
+ // For BufferOp, the buffer size is stored in BufferSize. Therefore,
+ // BufferOp needs special handling to update the BufferSize.
+ // BufferSize must be updated before the PkgLen to accommodate any
+ // increment resulting from the update of the BufferSize.
+ // DefBuffer := BufferOp PkgLength BufferSize ByteList
+ // BufferOp := 0x11
+ // BufferSize := TermArg => Integer
+ if (AmlNodeCompareOpCode (ObjectNode, AML_BUFFER_OP, 0)) {
+ // First fixed argument of BufferOp is an integer (BufferSize)
+ // (can be a BYTE, WORD, DWORD or QWORD).
+ // BufferSize is an object node.
+ Status = AmlNodeUpdateIntegerValue (
+ (AML_OBJECT_NODE*)AmlGetFixedArgument (
+ ObjectNode,
+ EAmlParseIndexTerm0
+ ),
+ IsIncrement,
+ (UINT64)(*Diff),
+ &FieldWidthChange
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // FieldWidthChange is an integer.
+ // It must be positive if IsIncrement is TRUE, negative otherwise.
+ if ((IsIncrement &&
+ (FieldWidthChange < 0)) ||
+ (!IsIncrement &&
+ (FieldWidthChange > 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check for UINT32 overflow.
+ if (*Diff > (MAX_UINT32 - (UINT32)ABS (FieldWidthChange))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update Diff if the field width changed.
+ *Diff = (UINT32)(*Diff + ABS (FieldWidthChange));
+ } // AML_BUFFER_OP node.
+
+ // Update the PgkLen.
+ // Needs to be done at last to reflect the potential field width changes.
+ if (AmlNodeHasAttribute (ObjectNode, AML_HAS_PKG_LENGTH)) {
+ Value = ObjectNode->PkgLen;
+
+ // Subtract the size of the PkgLen encoding. The size of the PkgLen
+ // encoding must be computed after having updated Value.
+ InitialPkgLenWidth = AmlComputePkgLengthWidth (Value);
+ Value -= InitialPkgLenWidth;
+
+ // Check for an over/underflows.
+ // PkgLen is a 28 bit value, cf 20.2.4 Package Length Encoding
+ // i.e. the maximum value is (2^28 - 1) = ((BIT0 << 28) - 1).
+ if ((IsIncrement && ((((BIT0 << 28) - 1) - Value) < *Diff)) ||
+ (!IsIncrement && (Value < *Diff))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the size.
+ if (IsIncrement) {
+ Value += *Diff;
+ } else {
+ Value -= *Diff;
+ }
+
+ // Compute the new PkgLenWidth.
+ NewPkgLenWidth = AmlComputePkgLengthWidth (Value);
+ if (NewPkgLenWidth == 0) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Add it to the Value.
+ Value += NewPkgLenWidth;
+
+ // Check that adding the PkgLenWidth didn't trigger a domino effect,
+ // increasing the encoding width of the PkgLen again.
+ // The PkgLen is encoded on at most 4 bytes. It is possible to increase
+ // the PkgLen width if its encoding is on less than 3 bytes.
+ ReComputedPkgLenWidth = AmlComputePkgLengthWidth (Value);
+ if (ReComputedPkgLenWidth != NewPkgLenWidth) {
+ if ((ReComputedPkgLenWidth != 0) &&
+ (ReComputedPkgLenWidth < 4)) {
+ // No need to recompute the PkgLen since a new threshold cannot
+ // be reached by incrementing the value by one.
+ Value += 1;
+ } else {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ *Diff += (InitialPkgLenWidth > ReComputedPkgLenWidth) ?
+ (InitialPkgLenWidth - ReComputedPkgLenWidth) :
+ (ReComputedPkgLenWidth - InitialPkgLenWidth);
+ ObjectNode->PkgLen = Value;
+ } // PkgLen update.
+
+ // During CodeGeneration, the tree is incomplete and
+ // there is no root node at the top of the tree. Stop
+ // propagating the new size when finding a root node
+ // OR when a NULL parent is found.
+ ParentNode = AmlGetParent ((AML_NODE_HEADER*)Node);
+ if (ParentNode != NULL) {
+ // Propagate the size up the tree.
+ Status = AmlPropagateSize (
+ Node->Parent,
+ IsIncrement,
+ Diff
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ } else if (IS_AML_ROOT_NODE (Node)) {
+ // Update the length field in the SDT header.
+ Value = ((AML_ROOT_NODE*)Node)->SdtHeader->Length;
+
+ // Check for an over/underflows.
+ if ((IsIncrement && (Value > (MAX_UINT32 - *Diff))) ||
+ (!IsIncrement && (Value < *Diff))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the size.
+ if (IsIncrement) {
+ Value += *Diff;
+ } else {
+ Value -= *Diff;
+ }
+
+ ((AML_ROOT_NODE*)Node)->SdtHeader->Length = Value;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Propagate the node count information up the tree.
+
+ @param [in] ObjectNode Pointer to an object node.
+ @param [in] IsIncrement Choose the operation to do:
+ - TRUE: Increment the Node's size and
+ the Node's count;
+ - FALSE: Decrement the Node's size and
+ the Node's count.
+ @param [in] NodeCount Number of nodes added/removed (depends on the
+ value of Operation).
+ @param [out] FieldWidthChange When modifying the integer, it can be
+ promoted/demoted, e.g. from UINT8 to UINT16.
+ Stores the change in width.
+ Can be negative.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+AmlPropagateNodeCount (
+ IN AML_OBJECT_NODE * ObjectNode,
+ IN BOOLEAN IsIncrement,
+ IN UINT8 NodeCount,
+ OUT INT8 * FieldWidthChange
+ )
+{
+ EFI_STATUS Status;
+
+ AML_NODE_HEADER * NodeCountArg;
+ UINT8 CurrNodeCount;
+
+ // Currently there is no use case where (NodeCount > 1).
+ if (!IS_AML_OBJECT_NODE (ObjectNode) ||
+ (FieldWidthChange == NULL) ||
+ (NodeCount > 1)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *FieldWidthChange = 0;
+
+ // Update the number of elements stored in PackageOp and VarPackageOp.
+ // The number of elements is stored as the first fixed argument.
+ // DefPackage := PackageOp PkgLength NumElements PackageElementList
+ // PackageOp := 0x12
+ // DefVarPackage := VarPackageOp PkgLength VarNumElements PackageElementList
+ // VarPackageOp := 0x13
+ // NumElements := ByteData
+ // VarNumElements := TermArg => Integer
+ NodeCountArg = AmlGetFixedArgument (ObjectNode, EAmlParseIndexTerm0);
+ if (AmlNodeCompareOpCode (ObjectNode, AML_PACKAGE_OP, 0)) {
+ // First fixed argument of PackageOp stores the number of elements
+ // in the package. It is an UINT8.
+
+ // Check for over/underflow.
+ CurrNodeCount = *(((AML_DATA_NODE*)NodeCountArg)->Buffer);
+ if ((IsIncrement && (CurrNodeCount == MAX_UINT8)) ||
+ (!IsIncrement && (CurrNodeCount == 0))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the node count in the DataNode.
+ CurrNodeCount = IsIncrement ? (CurrNodeCount + 1) : (CurrNodeCount - 1);
+ *(((AML_DATA_NODE*)NodeCountArg)->Buffer) = CurrNodeCount;
+ } else if (AmlNodeCompareOpCode (ObjectNode, AML_VAR_PACKAGE_OP, 0)) {
+ // First fixed argument of PackageOp stores the number of elements
+ // in the package. It is an integer (can be a BYTE, WORD, DWORD, QWORD).
+ Status = AmlNodeUpdateIntegerValue (
+ (AML_OBJECT_NODE*)NodeCountArg,
+ IsIncrement,
+ NodeCount,
+ FieldWidthChange
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Propagate information up the tree.
+
+ The information can be a new size, a new number of arguments.
+
+ @param [in] Node Pointer to a node.
+ Must be a root node or an object node.
+ @param [in] IsIncrement Choose the operation to do:
+ - TRUE: Increment the Node's size and
+ the Node's count;
+ - FALSE: Decrement the Node's size and
+ the Node's count.
+ @param [in] Diff Value to add/subtract to the Node's size.
+ @param [in] NodeCount Number of nodes added/removed.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlPropagateInformation (
+ IN AML_NODE_HEADER * Node,
+ IN BOOLEAN IsIncrement,
+ IN UINT32 Diff,
+ IN UINT8 NodeCount
+ )
+{
+ EFI_STATUS Status;
+ INT8 FieldWidthChange;
+
+ // Currently there is no use case where (NodeCount > 1).
+ if ((!IS_AML_ROOT_NODE (Node) &&
+ !IS_AML_OBJECT_NODE (Node)) ||
+ (NodeCount > 1)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Propagate the node count first as it may change the number of bytes
+ // needed to store the node count, and then impact FieldWidthChange.
+ if ((NodeCount != 0) &&
+ IS_AML_OBJECT_NODE (Node)) {
+ Status = AmlPropagateNodeCount (
+ (AML_OBJECT_NODE*)Node,
+ IsIncrement,
+ NodeCount,
+ &FieldWidthChange
+ );
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+
+ // Propagate the potential field width change.
+ // Maximum change is between UINT8/UINT64: 8 bytes.
+ if ((ABS (FieldWidthChange) > 8) ||
+ (IsIncrement &&
+ ((FieldWidthChange < 0) ||
+ ((Diff + (UINT8)FieldWidthChange) > MAX_UINT32))) ||
+ (!IsIncrement &&
+ ((FieldWidthChange > 0) ||
+ (Diff < (UINT32)ABS (FieldWidthChange))))) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+ Diff = (UINT32)(Diff + (UINT8)ABS (FieldWidthChange));
+ }
+
+ // Diff can be zero if some data is updated without modifying the data size.
+ if (Diff != 0) {
+ Status = AmlPropagateSize (Node, IsIncrement, &Diff);
+ if (EFI_ERROR (Status)) {
+ ASSERT (0);
+ return Status;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h
new file mode 100644
index 00000000000..ddb764aa585
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/AmlLib/Utils/AmlUtility.h
@@ -0,0 +1,95 @@
+/** @file
+ AML Utility.
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef AML_UTILITY_H_
+#define AML_UTILITY_H_
+
+#include <AmlNodeDefines.h>
+
+/** This function computes and updates the ACPI table checksum.
+
+ @param [in] AcpiTable Pointer to an Acpi table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AcpiPlatformChecksum (
+ IN EFI_ACPI_DESCRIPTION_HEADER * AcpiTable
+ );
+
+/** Compute the size of a tree/sub-tree.
+
+ @param [in] Node Node to compute the size.
+ @param [in, out] Size Pointer holding the computed size.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlComputeSize (
+ IN CONST AML_NODE_HEADER * Node,
+ IN OUT UINT32 * Size
+ );
+
+/** Set the value contained in an integer node.
+
+ The OpCode is updated accordingly to the new value
+ (e.g.: If the original value was a UINT8 value, then the OpCode
+ would be AML_BYTE_PREFIX. If it the new value is a UINT16
+ value then the OpCode will be updated to AML_WORD_PREFIX).
+
+ @param [in] Node Pointer to an integer node.
+ Must be an object node.
+ @param [in] NewValue New value to write in the integer node.
+ @param [out] ValueWidthDiff Difference in number of bytes used to store
+ the new value.
+ Can be negative.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+AmlNodeSetIntegerValue (
+ IN AML_OBJECT_NODE * Node,
+ IN UINT64 NewValue,
+ OUT INT8 * ValueWidthDiff
+ );
+
+/** Propagate information up the tree.
+
+ The information can be a new size, a new number of arguments.
+
+ @param [in] Node Pointer to a node.
+ Must be a root node or an object node.
+ @param [in] IsIncrement Choose the operation to do:
+ - TRUE: Increment the Node's size and
+ the Node's count;
+ - FALSE: Decrement the Node's size and
+ the Node's count.
+ @param [in] Diff Value to add/subtract to the Node's size.
+ @param [in] NodeCount Number of nodes added/removed.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+AmlPropagateInformation (
+ IN AML_NODE_HEADER * Node,
+ IN BOOLEAN IsIncrement,
+ IN UINT32 Diff,
+ IN UINT8 NodeCount
+ );
+
+#endif // AML_UTILITY_H_
+
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.c
new file mode 100644
index 00000000000..ebd8f7916d0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.c
@@ -0,0 +1,536 @@
+/** @file
+ SSDT Serial Port Fixup Library.
+
+ Copyright (c) 2019 - 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Arm Server Base Boot Requirements (SBBR), s4.2.1.8 "SPCR".
+ - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
+**/
+
+#include <IndustryStandard/DebugPort2Table.h>
+#include <Library/AcpiLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/AcpiTable.h>
+
+// Module specific include files.
+#include <AcpiTableGenerator.h>
+#include <ConfigurationManagerObject.h>
+#include <ConfigurationManagerHelper.h>
+#include <Library/AmlLib/AmlLib.h>
+#include <Library/TableHelperLib.h>
+#include <Protocol/ConfigurationManagerProtocol.h>
+
+/** C array containing the compiled AML template.
+ This symbol is defined in the auto generated C file
+ containing the AML bytecode array.
+*/
+extern CHAR8 ssdtserialporttemplate_aml_code[];
+
+/** UART address range length.
+*/
+#define MIN_UART_ADDRESS_LENGTH 0x1000U
+
+/** Validate the Serial Port Information.
+
+ @param [in] SerialPortInfoTable Table of CM_ARM_SERIAL_PORT_INFO.
+ @param [in] SerialPortCount Count of SerialPort in the table.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+ValidateSerialPortInfo (
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfoTable,
+ IN UINT32 SerialPortCount
+ )
+{
+ UINT32 Index;
+ CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo;
+
+ if ((SerialPortInfoTable == NULL) ||
+ (SerialPortCount == 0)) {
+ ASSERT (0);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < SerialPortCount; Index++) {
+ SerialPortInfo = &SerialPortInfoTable[Index];
+ ASSERT (SerialPortInfo != NULL);
+
+ if ((SerialPortInfo == NULL ) ||
+ (SerialPortInfo->BaseAddress == 0)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: UART port base address is invalid. BaseAddress = 0x%llx\n",
+ SerialPortInfo->BaseAddress
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((SerialPortInfo->PortSubtype !=
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART) &&
+ (SerialPortInfo->PortSubtype !=
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X) &&
+ (SerialPortInfo->PortSubtype !=
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART) &&
+ (SerialPortInfo->PortSubtype !=
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_DCC) &&
+ (SerialPortInfo->PortSubtype !=
+ EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: UART port subtype is invalid."
+ " UART Base = 0x%llx, PortSubtype = 0x%x\n",
+ SerialPortInfo->BaseAddress,
+ SerialPortInfo->PortSubtype
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DEBUG ((DEBUG_INFO, "UART Configuration:\n"));
+ DEBUG ((
+ DEBUG_INFO,
+ " UART Base = 0x%llx\n", SerialPortInfo->BaseAddress
+ ));
+ DEBUG ((
+ DEBUG_INFO,
+ " Length = 0x%llx\n",
+ SerialPortInfo->BaseAddressLength
+ ));
+ DEBUG ((DEBUG_INFO, " Clock = %lu\n", SerialPortInfo->Clock));
+ DEBUG ((DEBUG_INFO, " BaudRate = %llu\n", SerialPortInfo->BaudRate));
+ DEBUG ((DEBUG_INFO, " Interrupt = %lu\n", SerialPortInfo->Interrupt));
+ } // for
+
+ return EFI_SUCCESS;
+}
+
+/** Fixup the Serial Port Ids (_UID, _HID, _CID).
+
+ @param [in] RootNodeHandle Pointer to the root of an AML tree.
+ @param [in] Uid UID for the Serial Port.
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
+ structure.
+ Get the Serial Port Information from there.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FixupIds (
+ IN AML_ROOT_NODE_HANDLE RootNodeHandle,
+ IN CONST UINT64 Uid,
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE_HANDLE NameOpIdNode;
+ CONST CHAR8 * HidString;
+ CONST CHAR8 * CidString;
+ CONST CHAR8 * NonBsaHid;
+
+ // Get the _CID and _HID value to write.
+ switch (SerialPortInfo->PortSubtype) {
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_FULL_16550:
+ {
+ // If there is a non-BSA compliant HID, use that.
+ NonBsaHid = (CONST CHAR8*)PcdGetPtr (PcdNonBsaCompliant16550SerialHid);
+ if ((NonBsaHid != NULL) && (AsciiStrLen (NonBsaHid) != 0)) {
+ if (!(IsValidPnpId (NonBsaHid) || IsValidAcpiId (NonBsaHid))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HidString = NonBsaHid;
+ CidString = "";
+ } else {
+ HidString = "PNP0501";
+ CidString = "PNP0500";
+ }
+ break;
+ }
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_PL011_UART:
+ {
+ HidString = "ARMH0011";
+ CidString = "ARMHB000";
+ break;
+ }
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART:
+ case EFI_ACPI_DBG2_PORT_SUBTYPE_SERIAL_ARM_SBSA_GENERIC_UART_2X:
+ {
+ HidString = "ARMH0011";
+ CidString = "";
+ break;
+ }
+ default:
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+ } // switch
+
+ // Get the _UID NameOp object defined by the "Name ()" statement,
+ // and update its value.
+ Status = AmlFindNode (
+ RootNodeHandle,
+ "\\_SB_.COM0._UID",
+ &NameOpIdNode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = AmlNameOpUpdateInteger (NameOpIdNode, (UINT64)Uid);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Get the _HID NameOp object defined by the "Name ()" statement,
+ // and update its value.
+ Status = AmlFindNode (
+ RootNodeHandle,
+ "\\_SB_.COM0._HID",
+ &NameOpIdNode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = AmlNameOpUpdateString (NameOpIdNode, HidString);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Get the _CID NameOp object defined by the "Name ()" statement,
+ // and update its value.
+ Status = AmlFindNode (
+ RootNodeHandle,
+ "\\_SB_.COM0._CID",
+ &NameOpIdNode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // If we have a CID then update a _CID node else delete the node.
+ if (AsciiStrLen (CidString) != 0) {
+ Status = AmlNameOpUpdateString (NameOpIdNode, CidString);
+ } else {
+ // First detach the node from the tree.
+ Status = AmlDetachNode (NameOpIdNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Delete the detached node.
+ Status = AmlDeleteTree (NameOpIdNode);
+ }
+
+ return Status;
+}
+
+/** Fixup the Serial Port _CRS values (BaseAddress, ...).
+
+ @param [in] RootNodeHandle Pointer to the root of an AML tree.
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
+ structure.
+ Get the Serial Port Information from there.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FixupCrs (
+ IN AML_ROOT_NODE_HANDLE RootNodeHandle,
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE_HANDLE NameOpCrsNode;
+ AML_DATA_NODE_HANDLE QWordRdNode;
+ AML_DATA_NODE_HANDLE InterruptRdNode;
+
+ // Get the "_CRS" object defined by the "Name ()" statement.
+ Status = AmlFindNode (
+ RootNodeHandle,
+ "\\_SB_.COM0._CRS",
+ &NameOpCrsNode
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Get the first Rd node in the "_CRS" object.
+ Status = AmlNameOpCrsGetFirstRdNode (NameOpCrsNode, &QWordRdNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (QWordRdNode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the Serial Port base address and length.
+ Status = AmlUpdateRdQWord (
+ QWordRdNode,
+ SerialPortInfo->BaseAddress,
+ ((SerialPortInfo->BaseAddressLength < MIN_UART_ADDRESS_LENGTH) ?
+ MIN_UART_ADDRESS_LENGTH: SerialPortInfo->BaseAddressLength)
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Get the Interrupt node.
+ // It is the second Resource Data element in the NameOpCrsNode's
+ // variable list of arguments.
+ Status = AmlNameOpCrsGetNextRdNode (QWordRdNode, &InterruptRdNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (InterruptRdNode == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Update the interrupt number.
+ return AmlUpdateRdInterrupt (InterruptRdNode, SerialPortInfo->Interrupt);
+}
+
+/** Fixup the Serial Port device name.
+
+ @param [in] RootNodeHandle Pointer to the root of an AML tree.
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
+ structure.
+ Get the Serial Port Information from there.
+ @param [in] Name The Name to give to the Device.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FixupName (
+ IN AML_ROOT_NODE_HANDLE RootNodeHandle,
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
+ IN CONST CHAR8 * Name
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE_HANDLE DeviceNode;
+
+ // Get the COM0 variable defined by the "Device ()" statement.
+ Status = AmlFindNode (RootNodeHandle, "\\_SB_.COM0", &DeviceNode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Update the Device's name.
+ return AmlDeviceOpUpdateName (DeviceNode, (CHAR8*)Name);
+}
+
+/** Fixup the Serial Port Information in the AML tree.
+
+ For each template value:
+ - find the node to update;
+ - update the value.
+
+ @param [in] RootNodeHandle Pointer to the root of the AML tree.
+ @param [in] SerialPortInfo Pointer to a Serial Port Information
+ structure.
+ Get the Serial Port Information from there.
+ @param [in] Name The Name to give to the Device.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ @param [in] Uid UID for the Serial Port.
+ @param [out] Table If success, contains the serialized
+ SSDT table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+FixupSerialPortInfo (
+ IN AML_ROOT_NODE_HANDLE RootNodeHandle,
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
+ IN CONST CHAR8 * Name,
+ IN CONST UINT64 Uid,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (RootNodeHandle != NULL);
+ ASSERT (SerialPortInfo != NULL);
+ ASSERT (Name != NULL);
+ ASSERT (Table != NULL);
+
+ // Fixup the _UID, _HID and _CID values.
+ Status = FixupIds (RootNodeHandle, Uid, SerialPortInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Fixup the _CRS values.
+ Status = FixupCrs (RootNodeHandle, SerialPortInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Fixup the serial-port name.
+ // This MUST be done at the end, otherwise AML paths won't be valid anymore.
+ return FixupName (RootNodeHandle, SerialPortInfo, Name);
+}
+
+/** Free an SSDT table previously created by
+ the BuildSsdtSerialTable function.
+
+ @param [in] Table Pointer to a SSDT table allocated by
+ the BuildSsdtSerialTable function.
+
+ @retval EFI_SUCCESS Success.
+**/
+EFI_STATUS
+EFIAPI
+FreeSsdtSerialPortTable (
+ IN EFI_ACPI_DESCRIPTION_HEADER * Table
+ )
+{
+ ASSERT (Table != NULL);
+ FreePool (Table);
+ return EFI_SUCCESS;
+}
+
+/** Build a SSDT table describing the input serial port.
+
+ The table created by this function must be freed by FreeSsdtSerialTable.
+
+ @param [in] AcpiTableInfo Pointer to the ACPI table information.
+ @param [in] SerialPortInfo Serial port to describe in the SSDT table.
+ @param [in] Name The Name to give to the Device.
+ Must be a NULL-terminated ASL NameString
+ e.g.: "DEV0", "DV15.DEV0", etc.
+ @param [in] Uid UID for the Serial Port.
+ @param [out] Table If success, pointer to the created SSDT table.
+
+ @retval EFI_SUCCESS Table generated successfully.
+ @retval EFI_INVALID_PARAMETER A parameter is invalid.
+ @retval EFI_NOT_FOUND Could not find information.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate memory.
+**/
+EFI_STATUS
+EFIAPI
+BuildSsdtSerialPortTable (
+ IN CONST CM_STD_OBJ_ACPI_TABLE_INFO * AcpiTableInfo,
+ IN CONST CM_ARM_SERIAL_PORT_INFO * SerialPortInfo,
+ IN CONST CHAR8 * Name,
+ IN CONST UINT64 Uid,
+ OUT EFI_ACPI_DESCRIPTION_HEADER ** Table
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ AML_ROOT_NODE_HANDLE RootNodeHandle;
+
+ ASSERT (AcpiTableInfo != NULL);
+ ASSERT (SerialPortInfo != NULL);
+ ASSERT (Name != NULL);
+ ASSERT (Table != NULL);
+
+ // Validate the Serial Port Info.
+ Status = ValidateSerialPortInfo (SerialPortInfo, 1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Parse the SSDT Serial Port Template.
+ Status = AmlParseDefinitionBlock (
+ (EFI_ACPI_DESCRIPTION_HEADER*)ssdtserialporttemplate_aml_code,
+ &RootNodeHandle
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT-FIXUP:"
+ " Failed to parse SSDT Serial Port Template. Status = %r\n",
+ Status
+ ));
+ return Status;
+ }
+
+ // Fixup the template values.
+ Status = FixupSerialPortInfo (
+ RootNodeHandle,
+ SerialPortInfo,
+ Name,
+ Uid,
+ Table
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to fixup SSDT Serial Port Table."
+ " Status = %r\n",
+ Status
+ ));
+ goto exit_handler;
+ }
+
+ // Serialize the tree.
+ Status = AmlSerializeDefinitionBlock (
+ RootNodeHandle,
+ Table
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to Serialize SSDT Table Data."
+ " Status = %r\n",
+ Status
+ ));
+ }
+
+exit_handler:
+ // Cleanup
+ if (RootNodeHandle != NULL) {
+ Status1 = AmlDeleteTree (RootNodeHandle);
+ if (EFI_ERROR (Status1)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "ERROR: SSDT-SERIAL-PORT-FIXUP: Failed to cleanup AML tree."
+ " Status = %r\n",
+ Status1
+ ));
+ // If Status was success but we failed to delete the AML Tree
+ // return Status1 else return the original error code, i.e. Status.
+ if (!EFI_ERROR (Status)) {
+ return Status1;
+ }
+ }
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
new file mode 100644
index 00000000000..dcf961947e0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortFixupLib.inf
@@ -0,0 +1,32 @@
+## @file
+# SSDT Serial Port fixup Library
+#
+# Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = DynamicSsdtSerialPortFixupLib
+ FILE_GUID = AC5978CC-5B62-4466-AD04-23644C2C38C2
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = SsdtSerialPortFixupLib
+
+[Sources]
+ SsdtSerialPortFixupLib.c
+ SsdtSerialPortTemplate.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ DynamicTablesPkg/DynamicTablesPkg.dec
+
+[LibraryClasses]
+ AmlLib
+ BaseLib
+
+[Pcd]
+ gEdkiiDynamicTablesPkgTokenSpaceGuid.PcdNonBsaCompliant16550SerialHid
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortTemplate.asl b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortTemplate.asl
new file mode 100644
index 00000000000..7666e34e19c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/SsdtSerialPortFixupLib/SsdtSerialPortTemplate.asl
@@ -0,0 +1,60 @@
+/** @file
+ SSDT Serial Template
+
+ Copyright (c) 2019 - 2020, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - Arm Server Base Boot Requirements (SBBR), s4.2.1.8 "SPCR".
+
+ @par Glossary:
+ - {template} - Data fixed up using AML Fixup APIs.
+**/
+
+DefinitionBlock ("SsdtSerialPortTemplate.aml", "SSDT", 2, "ARMLTD", "SERIAL", 1) {
+ Scope (_SB) {
+ // UART PL011
+ Device (COM0) { // {template}
+ Name (_UID, 0x0) // {template}
+ Name (_HID, "HID0000") // {template}
+ Name (_CID, "CID0000") // {template}
+
+ Method(_STA) {
+ Return(0xF)
+ }
+
+ Name (_CRS, ResourceTemplate() {
+ QWordMemory (
+ , // ResourceUsage
+ , // Decode
+ , // IsMinFixed
+ , // IsMaxFixed
+ , // Cacheable
+ ReadWrite, // ReadAndWrite
+ 0x0, // AddressGranularity
+ 0xA0000000, // AddressMinimum // {template}
+ 0xAFFFFFFF, // AddressMaximum // {template}
+ 0, // AddressTranslation
+ 0x10000000, // RangeLength // {template}
+ , // ResourceSourceIndex
+ , // ResourceSource
+ , // DescriptorName
+ , // MemoryRangeType
+ // TranslationType
+ ) // QWordMemory
+ Interrupt (
+ ResourceConsumer, // ResourceUsage
+ Level, // EdgeLevel
+ ActiveHigh, // ActiveLevel
+ Exclusive, // Shared
+ , // ResourceSourceIndex
+ , // ResourceSource
+ // DescriptorName
+ ) {
+ 0xA5 // {template}
+ } // Interrupt
+ }) // Name
+ } // Device
+ } // Scope (_SB)
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
index 06ea8aa0c88..8f3fdaa5ff4 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Library/Common/TableHelperLib/TableHelper.c
@@ -1,8 +1,9 @@
/** @file
Table Helper
-Copyright (c) 2017 - 2019, ARM Limited. All rights reserved.
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Protocol/AcpiTable.h>
@@ -244,3 +245,99 @@ FindDuplicateValue (
}
return FALSE;
}
+
+/** Convert a hex number to its ASCII code.
+
+ @param [in] x Hex number to convert.
+ Must be 0 <= x < 16.
+
+ @return The ASCII code corresponding to x.
+**/
+UINT8
+EFIAPI
+AsciiFromHex (
+ IN UINT8 x
+ )
+{
+ if (x < 10) {
+ return (UINT8)(x + '0');
+ }
+
+ if (x < 16) {
+ return (UINT8)(x - 10 + 'A');
+ }
+
+ ASSERT (FALSE);
+ return (UINT8)0;
+}
+
+/** Check if a HID is a valid PNP ID.
+
+ @param [in] Hid The Hid to validate.
+
+ @retval TRUE The Hid is a valid PNP ID.
+ @retval FALSE The Hid is not a valid PNP ID.
+**/
+BOOLEAN
+IsValidPnpId (
+ IN CONST CHAR8 * Hid
+ )
+{
+ UINTN Index;
+
+ if (AsciiStrLen (Hid) != 7) {
+ return FALSE;
+ }
+
+ // A valid PNP ID must be of the form "AAA####"
+ // where A is an uppercase letter and # is a hex digit.
+ for (Index = 0; Index < 3; Index++) {
+ if (!IS_UPPER_CHAR (Hid[Index])) {
+ return FALSE;
+ }
+ }
+
+ for (Index = 3; Index < 7; Index++) {
+ if (!IS_UPPER_HEX (Hid[Index])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/** Check if a HID is a valid ACPI ID.
+
+ @param [in] Hid The Hid to validate.
+
+ @retval TRUE The Hid is a valid ACPI ID.
+ @retval FALSE The Hid is not a valid ACPI ID.
+**/
+BOOLEAN
+IsValidAcpiId (
+ IN CONST CHAR8 * Hid
+ )
+{
+ UINTN Index;
+
+ if (AsciiStrLen (Hid) != 8) {
+ return FALSE;
+ }
+
+ // A valid ACPI ID must be of the form "NNNN####"
+ // where N is an uppercase letter or a digit ('0'-'9')
+ // and # is a hex digit.
+ for (Index = 0; Index < 4; Index++) {
+ if (!(IS_UPPER_CHAR (Hid[Index]) || IS_DIGIT (Hid[Index]))) {
+ return FALSE;
+ }
+ }
+
+ for (Index = 4; Index < 8; Index++) {
+ if (!IS_UPPER_HEX (Hid[Index])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Readme.md b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Readme.md
index 05a1ac4a8e4..e927a210d14 100644
--- a/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Readme.md
+++ b/src/VBox/Devices/EFI/Firmware/DynamicTablesPkg/Readme.md
@@ -1,5 +1,4 @@
-Dynamic Tables Framework
-------------------------
+# Dynamic Tables Framework
Dynamic Tables Framework provides mechanisms to reduce the amount
of effort required in porting firmware to new platforms. The aim is
@@ -10,8 +9,8 @@ be generated from the system construction. This initial release
does not fully implement that - the configuration is held in local
UEFI modules.
-Feature Summary
----------------
+# Feature Summary
+
The dynamic tables framework is designed to generate standardised
firmware tables that describe the hardware information at
run-time. A goal of standardised firmware is to have a common
@@ -58,8 +57,105 @@ The framework currently supports the following table generators for ARM:
* SSDT - Secondary System Description Table. This is essentially
a RAW table generator.
-Roadmap
--------
+## Dynamic AML
+
+ACPI Definition block (e.g. DSDT or SSDT) tables are used to describe system
+devices along with other control and power management information. These tables
+are written using ACPI Source Language (ASL). The ASL code is compiled using an
+ASL compiler (e.g. Intel iASL compiler) to generate ACPI Machine Language (AML)
+bytecode.
+
+Since, definition blocks are represented using AML grammar, run-time generation
+of definition blocks is complex. Dynamic AML is a feature of Dynamic Tables
+framework that provides a solution for dynamic generation of ACPI Definition
+block tables.
+
+Dynamic AML introduces the following techniques:
+* AML Fixup
+* AML Codegen
+* AML Fixup + Codegen
+
+### AML Fixup
+AML fixup is a technique that involves compiling an ASL template file to
+generate AML bytecode. This template AML bytecode can be parsed at run-time
+and a fixup code can update the required fields in the AML template.
+
+To simplify AML Fixup, the Dynamic Tables Framework provides an *AmlLib*
+library with a rich set of APIs that can be used to fixup the AML code.
+
+### AML Codegen
+AML Codegen employs generating small segments of AML code. The *AmlLib*
+library provides AML Codegen APIs that generate the AML code segments.
+
+ Example: The following table depicts the AML Codegen APIs and the
+ corresponding ASL code that would be generated.
+
+ | AML Codegen API | ASL Code |
+ |--------------------------------|--------------------------------|
+ | AmlCodeGenDefinitionBlock ( | DefinitionBlock ( |
+ | .., | ... |
+ | &RootNode); | ) { |
+ | AmlCodeGenScope ( | Scope (_SB) { |
+ | "\_SB", | |
+ | RootNode, | |
+ | &ScopeNode); | |
+ | AmlCodeGenDevice ( | Device (CPU0) { |
+ | "CPU0", | |
+ | ScopeNode, | |
+ | &CpuNode); | |
+ | AmlCodeGenNameString ( | Name (_HID, "ACPI0007") |
+ | "_HID", | |
+ | "ACPI0007", | |
+ | CpuNode, | |
+ | &HidNode); | |
+ | AmlCodeGenNameInteger ( | Name (_UID, Zero) |
+ | "_UID", | |
+ | 0, | |
+ | CpuNode, | |
+ | &UidNode); | |
+ | | } // Device |
+ | | } // Scope |
+ | | } // DefinitionBlock |
+
+### AML Fixup + Codegen
+A combination of AML Fixup and AML Codegen could be used for generating
+Definition Blocks. For example the AML Fixup could be used to fixup certain
+parts of the AML template while the AML Codegen APIs could be used to inserted
+small fragments of AML code in the AML template.
+
+### AmlLib Library
+Since, AML bytecode represents complex AML grammar, an **AmlLib** library is
+introduced to assist parsing and traversing of the AML bytecode at run-time.
+
+The AmlLib library parses a definition block and represents it as an AML
+tree. This tree representation is based on the AML grammar defined by the
+ACPI 6.3 specification, section - 20 'ACPI Machine Language (AML)
+Specification'.
+
+AML objects, methods and data are represented as tree nodes. Since the AML
+data is represented as tree nodes, it is possible to traverse the tree, locate
+a node and modify the node data. The tree can then be serialized to a buffer
+(that represents the definition block). This definition block containing
+the fixed up AML code can then be installed as an ACPI table (DSDT/SSDT).
+
+AmlLib provides a rich API to operate on AML data. For example it provides
+APIs to update a device's name, the value of a "_UID" object, and the memory
+and interrupt number stored in a "_CRS" node.
+
+Although the AmlLib performs checks to a reasonable extent while modifying a
+definition block, these checks may not cover all aspects due to the complexity
+of the ASL/AML language. It is therefore recommended to review any operation
+performed, and validate the generated output.
+
+ Example: The serialized AML code could be validated by
+ - Saving the generated AML to a file and comparing with
+ a reference output.
+ or
+ - Disassemble the generated AML using the iASL compiler
+ and verifying the output.
+
+# Roadmap
+
The current implementation of the Configuration Manager populates the
platform information statically as a C structure. Further enhancements
to introduce runtime loading of platform information from a platform
@@ -68,29 +164,13 @@ information file is planned.
Also support for generating SMBIOS tables is planned and will be added
subsequently.
-Related Modules
----------------
-
-### ACPICA iASL compiler
-The RAW table generator, used to process the DSDT/SSDT files depends on
-the iASL compiler to convert the DSDT/SSDT ASL files to a C array containing
-the hex AML code. The "-tc" option of the iASL compiler has been enhanced to
-support generation of an AML hex file (C header) with a unique symbol name
-so that it is suitable for inclusion from a C source file.
-
-Related Links
---------------
-
-<https://github.com/acpica/acpica.git>
+# Supported Platforms
-
-Supported Platforms
--------------------
1. Juno
2. FVP Models
-Build Instructions
-------------------
+# Build Instructions
+
1. Set path for the iASL compiler with support for generating a C header
file as output.
@@ -118,22 +198,84 @@ or
>build -a AARCH64 -p Platform\ARM\VExpressPkg\ArmVExpress-FVP-AArch64.dsc
-t GCC5 **-D DYNAMIC_TABLES_FRAMEWORK**
-Prerequisites
--------------
-ACPICA iASL compiler with the enhanced "-tc" option to support generation of
-AML hex (C header) files with unique symbol names.
+# Prerequisites
+
+Ensure that the latest ACPICA iASL compiler is used for building *Dynamic Tables Framework*.
+*Dynamic Tables Framework* has been tested using the following iASL compiler version:
+[Version 20200717](https://www.acpica.org/node/183), dated 17 July, 2020.
+
+
+#Running CI builds locally
+
+The TianoCore EDKII project has introduced Core CI infrastructure using TianoCore EDKII Tools PIP modules:
+
+ - *[edk2-pytool-library](https://pypi.org/project/edk2-pytool-library)*
+
+ - *[edk2-pytool-extensions](https://pypi.org/project/edk2-pytool-extensions)*
+
+
+The instructions to setup the CI environment are in *'edk2\\.pytool\\Readme.md'*
+
+## Building DynamicTablesPkg with Pytools
+
+1. [Optional] Create a Python Virtual Environment - generally once per workspace
-A patch *'[iASL: Enhance the -tc option (create AML hex file in C)](https://github.com/acpica/acpica/commit/f9a88a4c1cd020b6a5475d63b29626852a0b5f37)'*, dated 16 March 2018 (2018-03-16),
-to enable this support has been integrated to the ACPICA source repository.
+ ```
+ python -m venv <name of virtual environment>
-Ensure that the iASL compiler used for building *Dynamic Tables Framework* has this feature enabled.
+ e.g. python -m venv edk2-ci
+ ```
-This feature was made available in the *ACPICA Compiler update
-[Version 20180508](https://www.acpica.org/node/156)*, dated 8 May 2018 (2018-05-08).
+2. [Optional] Activate Virtual Environment - each time new shell/command window is opened
-Documentation
--------------
+ ```
+ <name of virtual environment>/Scripts/activate
+
+ e.g. On a windows host PC run:
+ edk2-ci\Scripts\activate.bat
+ ```
+3. Install Pytools - generally once per virtual env or whenever pip-requirements.txt changes
+
+ ```
+ pip install --upgrade -r pip-requirements.txt
+ ```
+
+4. Initialize & Update Submodules - only when submodules updated
+
+ ```
+ stuart_setup -c .pytool/CISettings.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
+
+ e.g. stuart_setup -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5
+ ```
+
+5. Initialize & Update Dependencies - only as needed when ext_deps change
+
+ ```
+ stuart_update -c .pytool/CISettings.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
+
+ e.g. stuart_update -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5
+ ```
+
+6. Compile the basetools if necessary - only when basetools C source files change
+
+ ```
+ python BaseTools/Edk2ToolsBuild.py -t <ToolChainTag>
+ ```
+
+7. Compile DynamicTablesPkg
+
+ ```
+ stuart_build-c .pytool/CISettings.py TOOL_CHAIN_TAG=<TOOL_CHAIN_TAG> -a <TARGET_ARCH>
+
+ e.g. stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=GCC5 -p DynamicTablesPkg -a AARCH64 --verbose
+ ```
+
+ - use `stuart_build -c .pytool/CISettings.py -h` option to see help on additional options.
+
+
+# Documentation
Refer to the following presentation from *UEFI Plugfest Seattle 2018*:
-[Dynamic Tables Framework: A Step Towards Automatic Generation of Advanced Configuration and Power Interface (ACPI) & System Management BIOS (SMBIOS) Tables – Sami Mujawar (Arm).](http://www.uefi.org/sites/default/files/resources/Arm_Dynamic%20Tables%20Framework%20A%20Step%20Towards%20Automatic%20Generation%20of%20Advanced%20Configuration%20and%20Power%20Interface%20%28ACPI%29%20%26%20System%20Management%20BIOS%20%28SMBIOS%29%20Tables%20_0.pdf)
+[Dynamic Tables Framework: A Step Towards Automatic Generation of Advanced Configuration and Power Interface (ACPI) & System Management BIOS (SMBIOS) Tables](http://www.uefi.org/sites/default/files/resources/Arm_Dynamic%20Tables%20Framework%20A%20Step%20Towards%20Automatic%20Generation%20of%20Advanced%20Configuration%20and%20Power%20Interface%20%28ACPI%29%20%26%20System%20Management%20BIOS%20%28SMBIOS%29%20Tables%20_0.pdf)
+
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c
index cfcd14bc3fc..48605463d93 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.c
@@ -1,14 +1,7 @@
/** @file
Copyright (c) 2019, Linaro, Ltd. All rights reserved.<BR>
-
- This program and the accompanying materials are licensed and made available
- under the terms and conditions of the BSD License which accompanies this
- distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf
index d3fed6e567c..12ab8a803f7 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Drivers/NonCoherentIoMmuDxe/NonCoherentIoMmuDxe.inf
@@ -1,15 +1,7 @@
#/** @file
#
# Copyright (c) 2019, Linaro, Ltd. All rights reserved.<BR>
-#
-# This program and the accompanying materials are licensed and made available
-# under the terms and conditions of the BSD License which accompanies this
-# distribution. The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR
-# IMPLIED.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
#
#**/
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/EmbeddedPkg.dsc b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/EmbeddedPkg.dsc
index 8a64000cd32..0a095028b66 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/EmbeddedPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/EmbeddedPkg.dsc
@@ -2,7 +2,7 @@
# Embedded Package
#
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2012-2015, ARM Ltd. All rights reserved.<BR>
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
#
@@ -40,6 +40,9 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses.common]
# DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
@@ -103,6 +106,8 @@
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DtPlatformDtbLoaderLib|EmbeddedPkg/Library/DxeDtPlatformDtbLoaderLibDefault/DxeDtPlatformDtbLoaderLibDefault.inf
+ TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
+
[LibraryClasses.common.DXE_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/Library/TimeBaseLib.h b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/Library/TimeBaseLib.h
index 08804d1de90..d160db89d6d 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/Library/TimeBaseLib.h
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/Library/TimeBaseLib.h
@@ -2,6 +2,7 @@
*
* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
* Copyright (c) 2016-2019, Linaro Limited. All rights reserved.
+* Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
@@ -12,6 +13,38 @@
#include <Uefi/UefiBaseType.h>
+//
+// Convenience macros to obtain a build date
+//
+// These macros should work for any compiler that follows ISO/IEC 9899,
+// in which case __DATE__ is defined as a "Mmm dd yyyy" 11 chars string,
+// but add an explicit filter for compilers that have been validated.
+//
+#if (defined(__GNUC__) || defined(_MSC_VER) || defined(__clang__))
+#define TIME_BUILD_YEAR (__DATE__[7] == '?' ? 1900 \
+ : (((__DATE__[7] - '0') * 1000 ) \
+ + (__DATE__[8] - '0') * 100 \
+ + (__DATE__[9] - '0') * 10 \
+ + __DATE__[10] - '0'))
+#define TIME_BUILD_MONTH ( __DATE__ [2] == '?' ? 1 \
+ : __DATE__ [2] == 'n' ? ( \
+ __DATE__ [1] == 'a' ? 1 : 6) \
+ : __DATE__ [2] == 'b' ? 2 \
+ : __DATE__ [2] == 'r' ? ( \
+ __DATE__ [0] == 'M' ? 3 : 4) \
+ : __DATE__ [2] == 'y' ? 5 \
+ : __DATE__ [2] == 'l' ? 7 \
+ : __DATE__ [2] == 'g' ? 8 \
+ : __DATE__ [2] == 'p' ? 9 \
+ : __DATE__ [2] == 't' ? 10 \
+ : __DATE__ [2] == 'v' ? 11 \
+ : 12)
+#define TIME_BUILD_DAY ( __DATE__[4] == '?' ? 1 \
+ : ((__DATE__[4] == ' ' ? 0 : \
+ ((__DATE__[4] - '0') * 10)) \
+ + __DATE__[5] - '0'))
+#endif
+
// Define EPOCH (1970-JANUARY-01) in the Julian Date representation
#define EPOCH_JULIAN_DATE 2440588
@@ -19,21 +52,82 @@
#define SEC_PER_MIN ((UINTN) 60)
#define SEC_PER_HOUR ((UINTN) 3600)
#define SEC_PER_DAY ((UINTN) 86400)
-#define SEC_PER_MONTH ((UINTN) 2,592,000)
-#define SEC_PER_YEAR ((UINTN) 31,536,000)
+/**
+ Check if it is a leap year.
+
+ @param Time The UEFI time to be checked.
+
+ @retval TRUE It is a leap year.
+ @retval FALSE It is NOT a leap year.
+
+**/
BOOLEAN
EFIAPI
IsLeapYear (
IN EFI_TIME *Time
);
+/**
+ Check if the day in the UEFI time is valid.
+
+ @param Time The UEFI time to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
BOOLEAN
EFIAPI
IsDayValid (
IN EFI_TIME *Time
);
+/**
+ Check if the time zone is valid.
+ Valid values are between -1440 and 1440 or 2047 (EFI_UNSPECIFIED_TIMEZONE).
+
+ @param TimeZone The time zone to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
+BOOLEAN
+EFIAPI
+IsValidTimeZone (
+ IN INT16 TimeZone
+ );
+
+/**
+ Check if the daylight is valid.
+ Valid values are:
+ 0 : Time is not affected.
+ 1 : Time is affected, and has not been adjusted for daylight savings.
+ 3 : Time is affected, and has been adjusted for daylight savings.
+ All other values are invalid.
+
+ @param Daylight The daylight to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
+BOOLEAN
+EFIAPI
+IsValidDaylight (
+ IN INT8 Daylight
+ );
+
+/**
+ Check if the UEFI time is valid.
+
+ @param Time The UEFI time to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
BOOLEAN
EFIAPI
IsTimeValid (
@@ -41,8 +135,12 @@ IsTimeValid (
);
/**
- Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
- **/
+ Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME.
+
+ @param EpochSeconds Epoch seconds.
+ @param Time The time converted to UEFI format.
+
+**/
VOID
EFIAPI
EpochToEfiTime (
@@ -51,17 +149,27 @@ EpochToEfiTime (
);
/**
- Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC)
- **/
-UINT32
+ Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC).
+
+ @param Time The UEFI time to be converted.
+
+ @return Number of seconds.
+
+**/
+UINTN
EFIAPI
EfiTimeToEpoch (
IN EFI_TIME *Time
);
/**
- returns Day of the week [0-6] 0=Sunday
- **/
+ Get the day of the week from the UEFI time.
+
+ @param Time The UEFI time to be calculated.
+
+ @return The day of the week: Sunday=0, Monday=1, ... Saturday=6
+
+**/
UINTN
EfiTimeToWday (
IN EFI_TIME *Time
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/libfdt_env.h b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/libfdt_env.h
index 1ad2304717d..863e54e9b12 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/libfdt_env.h
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Include/libfdt_env.h
@@ -76,4 +76,8 @@ static inline size_t strnlen (const char* str, size_t strsz ) {
return AsciiStrnLenS (str, strsz);
}
+static inline size_t strncmp (const char* str1, const char* str2, size_t strsz ) {
+ return AsciiStrnCmp (str1, str2, strsz);
+}
+
#endif /* _LIBFDT_ENV_H */
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c
index 21c54ce47ec..444884c93c3 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/AndroidBootImgLib/AndroidBootImgLib.c
@@ -97,7 +97,7 @@ AndroidBootImgGetKernelInfo (
ASSERT (IS_VALID_ANDROID_PAGE_SIZE (Header->PageSize));
*KernelSize = Header->KernelSize;
- *Kernel = BootImg + Header->PageSize;
+ *Kernel = (VOID *)((UINTN)BootImg + Header->PageSize);
return EFI_SUCCESS;
}
@@ -341,7 +341,7 @@ AndroidBootImgUpdateFdt (
Status = AndroidBootImgSetProperty64 (UpdatedFdtBase, ChosenNode,
"linux,initrd-end",
- (UINTN)(RamdiskData + RamdiskSize));
+ (UINTN)RamdiskData + RamdiskSize);
if (EFI_ERROR (Status)) {
goto Fdt_Exit;
}
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c
index 7db3821d6de..bd9cab9f2a6 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/NonCoherentDmaLib/NonCoherentDmaLib.c
@@ -225,8 +225,7 @@ DmaMap (
}
if (Map->Operation == MapOperationBusMasterRead) {
- CopyMem (Map->BufferAddress, (VOID *)(UINTN)Map->HostAddress,
- *NumberOfBytes);
+ CopyMem (Map->BufferAddress, (VOID *)(UINTN)HostAddress, *NumberOfBytes);
}
mCpu->FlushDataCache (mCpu, (UINTN)Map->BufferAddress, AllocSize,
EfiCpuFlushTypeWriteBack);
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
index c49eefe0ada..b9103a93830 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiHobLib/PrePiHobLib.inf
@@ -12,7 +12,7 @@
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PrePiHobLib
- FILE_GUID = 1F3A3278-82EB-4C0D-86F1-5BCDA5846CB2
+ FILE_GUID = AEF7D85A-6A91-4ACD-9A28-193DEFB325FB
MODULE_TYPE = BASE
VERSION_STRING = 1.0
LIBRARY_CLASS = HobLib
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiMemoryAllocationLib/MemoryAllocationLib.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiMemoryAllocationLib/MemoryAllocationLib.c
index 6aedc1f2316..939516d730e 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiMemoryAllocationLib/MemoryAllocationLib.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/PrePiMemoryAllocationLib/MemoryAllocationLib.c
@@ -184,7 +184,9 @@ AllocatePool (
return 0;
} else {
- Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL, (UINT16)(sizeof (EFI_HOB_TYPE_MEMORY_POOL) + AllocationSize));
+ Hob = (EFI_HOB_MEMORY_POOL *)CreateHob (EFI_HOB_TYPE_MEMORY_POOL,
+ (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) +
+ AllocationSize));
return (VOID *)(Hob + 1);
}
}
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c
index 15076f37a38..2a3962c4c08 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.c
@@ -2,6 +2,7 @@
*
* Copyright (c) 2016, Hisilicon Limited. All rights reserved.
* Copyright (c) 2016-2019, Linaro Limited. All rights reserved.
+* Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
@@ -13,8 +14,12 @@
#include <Library/TimeBaseLib.h>
/**
- Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME
- **/
+ Converts Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC) to EFI_TIME.
+
+ @param EpochSeconds Epoch seconds.
+ @param Time The time converted to UEFI format.
+
+**/
VOID
EFIAPI
EpochToEfiTime (
@@ -71,8 +76,13 @@ EpochToEfiTime (
}
/**
- Calculate Epoch days
- **/
+ Calculate Epoch days.
+
+ @param Time The UEFI time to be calculated.
+
+ @return Number of days.
+
+**/
UINTN
EFIAPI
EfiGetEpochDays (
@@ -96,17 +106,23 @@ EfiGetEpochDays (
return EpochDays;
}
+
/**
- Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC)
- **/
-UINT32
+ Converts EFI_TIME to Epoch seconds (elapsed since 1970 JANUARY 01, 00:00:00 UTC).
+
+ @param Time The UEFI time to be converted.
+
+ @return Number of seconds.
+
+**/
+UINTN
EFIAPI
EfiTimeToEpoch (
IN EFI_TIME *Time
)
{
- UINT32 EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
- UINT32 EpochSeconds;
+ UINTN EpochDays; // Number of days elapsed since EPOCH_JULIAN_DAY
+ UINTN EpochSeconds;
EpochDays = EfiGetEpochDays (Time);
@@ -116,8 +132,13 @@ EfiTimeToEpoch (
}
/**
- returns Day of the week [0-6] 0=Sunday
- **/
+ Get the day of the week from the UEFI time.
+
+ @param Time The UEFI time to be calculated.
+
+ @return The day of the week: Sunday=0, Monday=1, ... Saturday=6
+
+**/
UINTN
EfiTimeToWday (
IN EFI_TIME *Time
@@ -132,6 +153,15 @@ EfiTimeToWday (
return (EpochDays + 4) % 7;
}
+/**
+ Check if it is a leap year.
+
+ @param Time The UEFI time to be checked.
+
+ @retval TRUE It is a leap year.
+ @retval FALSE It is NOT a leap year.
+
+**/
BOOLEAN
EFIAPI
IsLeapYear (
@@ -153,6 +183,15 @@ IsLeapYear (
}
}
+/**
+ Check if the day in the UEFI time is valid.
+
+ @param Time The UEFI time to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
BOOLEAN
EFIAPI
IsDayValid (
@@ -171,25 +210,78 @@ IsDayValid (
return TRUE;
}
+/**
+ Check if the time zone is valid.
+ Valid values are between -1440 and 1440 or 2047 (EFI_UNSPECIFIED_TIMEZONE).
+
+ @param TimeZone The time zone to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
+BOOLEAN
+EFIAPI
+IsValidTimeZone (
+ IN INT16 TimeZone
+ )
+{
+ return TimeZone == EFI_UNSPECIFIED_TIMEZONE ||
+ (TimeZone >= -1440 && TimeZone <= 1440);
+}
+
+/**
+ Check if the daylight is valid.
+ Valid values are:
+ 0 : Time is not affected.
+ 1 : Time is affected, and has not been adjusted for daylight savings.
+ 3 : Time is affected, and has been adjusted for daylight savings.
+ All other values are invalid.
+
+ @param Daylight The daylight to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
+BOOLEAN
+EFIAPI
+IsValidDaylight (
+ IN INT8 Daylight
+ )
+{
+ return Daylight == 0 ||
+ Daylight == EFI_TIME_ADJUST_DAYLIGHT ||
+ Daylight == (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT);
+}
+
+/**
+ Check if the UEFI time is valid.
+
+ @param Time The UEFI time to be checked.
+
+ @retval TRUE Valid.
+ @retval FALSE Invalid.
+
+**/
BOOLEAN
EFIAPI
-IsTimeValid(
+IsTimeValid (
IN EFI_TIME *Time
)
{
// Check the input parameters are within the range specified by UEFI
- if ((Time->Year < 2000) ||
- (Time->Year > 2099) ||
- (Time->Month < 1 ) ||
- (Time->Month > 12 ) ||
- (!IsDayValid (Time) ) ||
- (Time->Hour > 23 ) ||
- (Time->Minute > 59 ) ||
- (Time->Second > 59 ) ||
- (Time->Nanosecond > 999999999) ||
- (!((Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE) || ((Time->TimeZone >= -1440) && (Time->TimeZone <= 1440)))) ||
- (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT)))
- ) {
+ if ((Time->Year < 2000) ||
+ (Time->Year > 2099) ||
+ (Time->Month < 1 ) ||
+ (Time->Month > 12 ) ||
+ (!IsDayValid (Time) ) ||
+ (Time->Hour > 23 ) ||
+ (Time->Minute > 59 ) ||
+ (Time->Second > 59 ) ||
+ (Time->Nanosecond > 999999999) ||
+ (!IsValidTimeZone(Time->TimeZone)) ||
+ (!IsValidDaylight(Time->Daylight))) {
return FALSE;
}
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
index 641f0862949..c93bf4081ff 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Library/VirtualRealTimeClockLib/VirtualRealTimeClockLib.c
@@ -92,6 +92,14 @@ LibGetTime (
"LibGetTime: %s non volatile variable was not found - Using compilation time epoch.\n",
mEpochVariableName
));
+
+ EfiSetVariable (
+ (CHAR16 *)mEpochVariableName,
+ &gEfiCallerIdGuid,
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof (EpochSeconds),
+ &EpochSeconds
+ );
}
Counter = GetPerformanceCounter ();
EpochSeconds += DivU64x64Remainder (Counter, Freq, &Remainder);
@@ -202,14 +210,14 @@ LibGetTime (
// Because we use the performance counter, we can fill the Nanosecond attribute
// provided that the remainder doesn't overflow 64-bit during multiplication.
if (Remainder <= 18446744073U) {
- Time->Nanosecond = MultU64x64 (Remainder, 1000000000U) / Freq;
+ Time->Nanosecond = (UINT32)(MultU64x64 (Remainder, 1000000000U) / Freq);
} else {
DEBUG ((DEBUG_WARN, "LibGetTime: Nanosecond value not set (64-bit overflow).\n"));
}
if (Capabilities) {
Capabilities->Accuracy = 0;
- Capabilities->Resolution = Freq;
+ Capabilities->Resolution = 1;
Capabilities->SetsToZero = FALSE;
}
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c
index 35289b052bf..5081d6126af 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClock.c
@@ -3,6 +3,7 @@
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
+ Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -11,6 +12,7 @@
#include <PiDxe.h>
#include <Library/DebugLib.h>
#include <Library/RealTimeClockLib.h>
+#include <Library/TimeBaseLib.h>
#include <Library/UefiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeLib.h>
@@ -31,92 +33,6 @@ typedef struct {
STATIC CONST CHAR16 mTimeSettingsVariableName[] = L"RtcTimeSettings";
STATIC NON_VOLATILE_TIME_SETTINGS mTimeSettings;
-STATIC
-BOOLEAN
-IsValidTimeZone (
- IN INT16 TimeZone
- )
-{
- return TimeZone == EFI_UNSPECIFIED_TIMEZONE ||
- (TimeZone >= -1440 && TimeZone <= 1440);
-}
-
-STATIC
-BOOLEAN
-IsValidDaylight (
- IN INT8 Daylight
- )
-{
- return Daylight == 0 ||
- Daylight == EFI_TIME_ADJUST_DAYLIGHT ||
- Daylight == (EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT);
-}
-
-STATIC
-BOOLEAN
-EFIAPI
-IsLeapYear (
- IN EFI_TIME *Time
- )
-{
- if (Time->Year % 4 == 0) {
- if (Time->Year % 100 == 0) {
- if (Time->Year % 400 == 0) {
- return TRUE;
- } else {
- return FALSE;
- }
- } else {
- return TRUE;
- }
- } else {
- return FALSE;
- }
-}
-
-STATIC CONST INTN mDayOfMonth[12] = {
- 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-STATIC
-BOOLEAN
-EFIAPI
-IsDayValid (
- IN EFI_TIME *Time
- )
-{
- if (Time->Day < 1 ||
- Time->Day > mDayOfMonth[Time->Month - 1] ||
- (Time->Month == 2 && !IsLeapYear (Time) && Time->Day > 28)) {
- return FALSE;
- }
- return TRUE;
-}
-
-STATIC
-BOOLEAN
-EFIAPI
-IsTimeValid(
- IN EFI_TIME *Time
- )
-{
- // Check the input parameters are within the range specified by UEFI
- if (Time->Year < 1900 ||
- Time->Year > 9999 ||
- Time->Month < 1 ||
- Time->Month > 12 ||
- !IsDayValid (Time) ||
- Time->Hour > 23 ||
- Time->Minute > 59 ||
- Time->Second > 59 ||
- Time->Nanosecond > 999999999 ||
- !IsValidTimeZone (Time->TimeZone) ||
- !IsValidDaylight (Time->Daylight)) {
- return FALSE;
- }
- return TRUE;
-}
-
/**
Returns the current time and date information, and the time-keeping capabilities
of the hardware platform.
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
index c0eca4c590f..2f3a8234092 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf
@@ -3,6 +3,7 @@
#
# Copyright (c) 2006 - 2007, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
+# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -28,6 +29,7 @@
[LibraryClasses]
DebugLib
RealTimeClockLib
+ TimeBaseLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeLib
@@ -36,5 +38,5 @@
gEfiRealTimeClockArchProtocolGuid
[Depex]
- TRUE
+ gEfiVariableArchProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/Diagnostics.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
index 15e2e4b3170..7a9b37ad964 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
@@ -1,7 +1,7 @@
/** @file
Diagnostics Protocol implementation for the MMC DXE driver
- Copyright (c) 2011-2014, ARM Limited. All rights reserved.
+ Copyright (c) 2011-2020, ARM Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -56,7 +56,7 @@ GenerateRandomBuffer (
UINT64* Buffer64 = (UINT64*)Buffer;
for (i = 0; i < (BufferSize >> 3); i++) {
- *Buffer64 = i | (~i << 32);
+ *Buffer64 = i | LShiftU64 (~i, 32);
Buffer64++;
}
}
@@ -227,7 +227,11 @@ MmcDriverDiagnosticsRunDiagnostics (
// LBA=10 Size=BlockSize
DiagnosticLog (L"MMC Driver Diagnostics - Test: Any Block\n");
- Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);
+ Status = MmcReadWriteDataTest (
+ MmcHostInstance,
+ RShiftU64 (MmcHostInstance->BlockIo.Media->LastBlock, 1),
+ MmcHostInstance->BlockIo.Media->BlockSize
+ );
// LBA=LastBlock Size=BlockSize
DiagnosticLog (L"MMC Driver Diagnostics - Test: Last Block\n");
diff --git a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
index ac854b6f5ea..d9f97acbadc 100644
--- a/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
+++ b/src/VBox/Devices/EFI/Firmware/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c
@@ -1,6 +1,6 @@
/** @file
*
-* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
+* Copyright (c) 2011-2020, ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
@@ -149,7 +149,7 @@ MmcTransferBlock (
if (MmcHostInstance->CardInfo.OCRData.AccessMode & SD_CARD_CAPACITY) {
CmdArg = Lba;
} else {
- CmdArg = Lba * This->Media->BlockSize;
+ CmdArg = MultU64x32 (Lba, This->Media->BlockSize);
}
} else {
//Set command argument based on the card access mode (Byte mode or Block mode)
@@ -157,7 +157,7 @@ MmcTransferBlock (
MMC_OCR_ACCESS_SECTOR) {
CmdArg = Lba;
} else {
- CmdArg = Lba * This->Media->BlockSize;
+ CmdArg = MultU64x32 (Lba, This->Media->BlockSize);
}
}
@@ -242,6 +242,8 @@ MmcIoBlocks (
UINTN BytesRemainingToBeTransfered;
UINTN BlockCount;
UINTN ConsumeSize;
+ UINT32 MaxBlock;
+ UINTN RemainingBlock;
BlockCount = 1;
MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
@@ -262,8 +264,18 @@ MmcIoBlocks (
return EFI_NO_MEDIA;
}
+ // Reading 0 Byte is valid
+ if (BufferSize == 0) {
+ return EFI_SUCCESS;
+ }
+
+ // The buffer size must be an exact multiple of the block size
+ if ((BufferSize % This->Media->BlockSize) != 0) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
if (MMC_HOST_HAS_ISMULTIBLOCK(MmcHost) && MmcHost->IsMultiBlock(MmcHost)) {
- BlockCount = (BufferSize + This->Media->BlockSize - 1) / This->Media->BlockSize;
+ BlockCount = BufferSize / This->Media->BlockSize;
}
// All blocks must be within the device
@@ -275,24 +287,23 @@ MmcIoBlocks (
return EFI_WRITE_PROTECTED;
}
- // Reading 0 Byte is valid
- if (BufferSize == 0) {
- return EFI_SUCCESS;
- }
-
- // The buffer size must be an exact multiple of the block size
- if ((BufferSize % This->Media->BlockSize) != 0) {
- return EFI_BAD_BUFFER_SIZE;
- }
-
// Check the alignment
if ((This->Media->IoAlign > 2) && (((UINTN)Buffer & (This->Media->IoAlign - 1)) != 0)) {
return EFI_INVALID_PARAMETER;
}
+ // Max block number in single cmd is 65535 blocks.
+ MaxBlock = 0xFFFF;
+ RemainingBlock = BlockCount;
BytesRemainingToBeTransfered = BufferSize;
while (BytesRemainingToBeTransfered > 0) {
+ if (RemainingBlock <= MaxBlock) {
+ BlockCount = RemainingBlock;
+ } else {
+ BlockCount = MaxBlock;
+ }
+
// Check if the Card is in Ready status
CmdArg = MmcHostInstance->CardInfo.RCA << 16;
Response[0] = 0;
@@ -338,6 +349,7 @@ MmcIoBlocks (
DEBUG ((EFI_D_ERROR, "%a(): Failed to transfer block and Status:%r\n", __func__, Status));
}
+ RemainingBlock -= BlockCount;
BytesRemainingToBeTransfered -= ConsumeSize;
if (BytesRemainingToBeTransfered > 0) {
Lba += BlockCount;
diff --git a/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.ci.yaml
index 030904f4e79..7dc1829bc6e 100644
--- a/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.ci.yaml
@@ -2,9 +2,24 @@
# CI configuration for FatPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
"CompilerPlugin": {
"DscPath": "FatPkg.dsc"
},
diff --git a/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.dsc b/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.dsc
index 26af1aef39f..5cdfdaabb57 100644
--- a/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/FatPkg/FatPkg.dsc
@@ -3,7 +3,7 @@
#
# This Platform file is used to generate the Binary Fat Drivers
# for EDK II Prime release.
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -27,6 +27,8 @@
RVCT:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
#
# Entry Point Libraries
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
index 7f9c363a037..9c4b058e006 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
@@ -1,7 +1,7 @@
## @file
# Sec Core for FSP
#
-# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -29,7 +29,6 @@
[Sources.IA32]
Ia32/Stack.nasm
- Ia32/InitializeFpu.nasm
Ia32/FspApiEntryM.nasm
Ia32/FspApiEntryCommon.nasm
Ia32/FspHelper.nasm
@@ -41,6 +40,7 @@
[Packages]
MdePkg/MdePkg.dec
IntelFsp2Pkg/IntelFsp2Pkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
[LibraryClasses]
BaseMemoryLib
@@ -51,6 +51,7 @@
FspSwitchStackLib
FspCommonLib
FspSecPlatformLib
+ UefiCpuLib
[Pcd]
gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase ## CONSUMES
@@ -58,6 +59,7 @@
gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize ## CONSUMES
gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage ## CONSUMES
gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported ## CONSUMES
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspPrivateTemporaryRamSize ## CONSUMES
[Ppis]
gEfiTemporaryRamSupportPpiGuid ## PRODUCES
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
index 3efbf2c68e5..ab3e16f929b 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
@@ -25,7 +25,6 @@
[Sources.IA32]
Ia32/Stack.nasm
- Ia32/InitializeFpu.nasm
Ia32/FspApiEntryT.nasm
Ia32/FspHelper.nasm
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
index cfff33a1c66..c831a147556 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/FspApiEntryT.nasm
@@ -1,7 +1,7 @@
;; @file
; Provide FSP API entry points.
;
-; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;;
@@ -78,6 +78,23 @@ struc LoadMicrocodeParams
.size:
endstruc
+struc LoadMicrocodeParamsFsp22
+ ; FSP_UPD_HEADER {
+ .FspUpdHeaderSignature: resd 2
+ .FspUpdHeaderRevision: resb 1
+ .FspUpdHeaderReserved: resb 23
+ ; }
+ ; FSPT_ARCH_UPD{
+ .FsptArchUpd: resd 8
+ ; }
+ ; FSPT_CORE_UPD {
+ .MicrocodeCodeAddr: resd 1
+ .MicrocodeCodeSize: resd 1
+ .CodeRegionBase: resd 1
+ .CodeRegionSize: resd 1
+ ; }
+ .size:
+endstruc
;
; Define SSE macros
@@ -169,6 +186,11 @@ ASM_PFX(LoadMicrocodeDefault):
; skip loading Microcode if the MicrocodeCodeSize is zero
; and report error if size is less than 2k
+ ; first check UPD header revision
+ cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
+ jae Fsp22UpdHeader
+
+ ; UPD structure is compliant with FSP spec 2.0/2.1
mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
cmp eax, 0
jz Exit2
@@ -178,6 +200,19 @@ ASM_PFX(LoadMicrocodeDefault):
mov esi, dword [esp + LoadMicrocodeParams.MicrocodeCodeAddr]
cmp esi, 0
jnz CheckMainHeader
+ jmp ParamError
+
+Fsp22UpdHeader:
+ ; UPD structure is compliant with FSP spec 2.2
+ mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
+ cmp eax, 0
+ jz Exit2
+ cmp eax, 0800h
+ jl ParamError
+
+ mov esi, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
+ cmp esi, 0
+ jnz CheckMainHeader
ParamError:
mov eax, 080000002h
@@ -272,10 +307,11 @@ AdvanceFixedSize:
add esi, dword 1024
CheckAddress:
- ; Is valid Microcode start point ?
- cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
- jz Done
+ ; Check UPD header revision
+ cmp byte [esp + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
+ jae Fsp22UpdHeader1
+ ; UPD structure is compliant with FSP spec 2.0/2.1
; Is automatic size detection ?
mov eax, dword [esp + LoadMicrocodeParams.MicrocodeCodeSize]
cmp eax, 0ffffffffh
@@ -287,7 +323,24 @@ CheckAddress:
jae Done ;Jif address is outside of microcode region
jmp CheckMainHeader
+Fsp22UpdHeader1:
+ ; UPD structure is compliant with FSP spec 2.2
+ ; Is automatic size detection ?
+ mov eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeSize]
+ cmp eax, 0ffffffffh
+ jz LoadMicrocodeDefault4
+
+ ; Address >= microcode region address + microcode region size?
+ add eax, dword [esp + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr]
+ cmp esi, eax
+ jae Done ;Jif address is outside of microcode region
+ jmp CheckMainHeader
+
LoadMicrocodeDefault4:
+ ; Is valid Microcode start point ?
+ cmp dword [esi + MicrocodeHdr.MicrocodeHdrVersion], 0ffffffffh
+ jz Done
+
LoadCheck:
; Get the revision of the current microcode update loaded
mov ecx, MSR_IA32_BIOS_SIGN_ID
@@ -349,11 +402,26 @@ ASM_PFX(EstablishStackFsp):
push DATA_LEN_OF_MCUD ; Size of the data region
push 4455434Dh ; Signature of the data region 'MCUD'
- push dword [edx + 2Ch] ; Code size sizeof(FSPT_UPD_COMMON) + 12
- push dword [edx + 28h] ; Code base sizeof(FSPT_UPD_COMMON) + 8
- push dword [edx + 24h] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
- push dword [edx + 20h] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
+ ; check UPD structure revision (edx + 8)
+ cmp byte [edx + LoadMicrocodeParamsFsp22.FspUpdHeaderRevision], 2
+ jae Fsp22UpdHeader2
+
+ ; UPD structure is compliant with FSP spec 2.0/2.1
+ push dword [edx + LoadMicrocodeParams.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
+ push dword [edx + LoadMicrocodeParams.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
+ push dword [edx + LoadMicrocodeParams.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
+ push dword [edx + LoadMicrocodeParams.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
+ jmp ContinueAfterUpdPush
+
+Fsp22UpdHeader2:
+ ; UPD structure is compliant with FSP spec 2.2
+ push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionSize] ; Code size sizeof(FSPT_UPD_COMMON) + 12
+ push dword [edx + LoadMicrocodeParamsFsp22.CodeRegionBase] ; Code base sizeof(FSPT_UPD_COMMON) + 8
+ push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeSize] ; Microcode size sizeof(FSPT_UPD_COMMON) + 4
+ push dword [edx + LoadMicrocodeParamsFsp22.MicrocodeCodeAddr] ; Microcode base sizeof(FSPT_UPD_COMMON) + 0
+
+ContinueAfterUpdPush:
;
; Save API entry/exit timestamp into stack
;
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm
deleted file mode 100644
index a723b08e464..00000000000
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/Ia32/InitializeFpu.nasm
+++ /dev/null
@@ -1,72 +0,0 @@
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Abstract:
-;
-;------------------------------------------------------------------------------
-
-
-SECTION .data
-;
-; Float control word initial value:
-; all exceptions masked, double-precision, round-to-nearest
-;
-ASM_PFX(mFpuControlWord):
- dw 0x027F
-;
-; Multimedia-extensions control word:
-; all exceptions masked, round-to-nearest, flush to zero for masked underflow
-;
-ASM_PFX(mMmxControlWord):
- dd 0x01F80
-
-SECTION .text
-
-;
-; Initializes floating point units for requirement of UEFI specification.
-;
-; This function initializes floating-point control word to 0x027F (all exceptions
-; masked,double-precision, round-to-nearest) and multimedia-extensions control word
-; (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
-; for masked underflow).
-;
-
-global ASM_PFX(InitializeFloatingPointUnits)
-ASM_PFX(InitializeFloatingPointUnits):
-
-
- push ebx
-
- ;
- ; Initialize floating point units
- ;
- finit
- fldcw [ASM_PFX(mFpuControlWord)]
-
- ;
- ; Use CpuId instruction (CPUID.01H:EDX.SSE[bit 25] = 1) to test
- ; whether the processor supports SSE instruction.
- ;
- mov eax, 1
- cpuid
- bt edx, 25
- jnc Done
-
- ;
- ; Set OSFXSR bit 9 in CR4
- ;
- mov eax, cr4
- or eax, BIT9
- mov cr4, eax
-
- ;
- ; The processor should support SSE instruction and we can use
- ; ldmxcsr instruction
- ;
- ldmxcsr [ASM_PFX(mMmxControlWord)]
-Done:
- pop ebx
-
- ret
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c
index 144bece1d22..1d102fca13b 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.c
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -150,15 +150,18 @@ SecStartup (
SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
SecCoreData.BootFirmwareVolumeSize = (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *)BootFirmwareVolume)->FvLength;
- SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
+ //
+ // Support FSP reserved temporary memory from the whole temporary memory provided by bootloader.
+ // FSP reserved temporary memory will not be given to PeiCore.
+ //
+ SecCoreData.TemporaryRamBase = (UINT8 *)(UINTN) TempRamBase + PcdGet32 (PcdFspPrivateTemporaryRamSize);
+ SecCoreData.TemporaryRamSize = SizeOfRam - PcdGet32 (PcdFspPrivateTemporaryRamSize);
if (PcdGet8 (PcdFspHeapSizePercentage) == 0) {
- SecCoreData.TemporaryRamSize = SizeOfRam; // stack size that is going to be copied to the permanent memory
SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize;
SecCoreData.StackBase = (VOID *)GetFspEntryStack(); // Share the same boot loader stack
SecCoreData.StackSize = 0;
} else {
- SecCoreData.TemporaryRamSize = SizeOfRam;
SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize * PcdGet8 (PcdFspHeapSizePercentage) / 100;
SecCoreData.StackBase = (VOID*)(UINTN)((UINTN)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize);
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h
index ddcba76e314..1487b846139 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/FspSecCore/SecMain.h
@@ -21,6 +21,7 @@
#include <Library/SerialPortLib.h>
#include <Library/FspSwitchStackLib.h>
#include <Library/FspCommonLib.h>
+#include <Library/UefiCpuLib.h>
#include <FspEas.h>
typedef VOID (*PEI_CORE_ENTRY) ( \
@@ -80,20 +81,6 @@ SecTemporaryRamSupport (
IN UINTN CopySize
);
-/**
- Initializes floating point units for requirement of UEFI specification.
-
- This function initializes floating-point control word to 0x027F (all exceptions
- masked,double-precision, round-to-nearest) and multimedia-extensions control word
- (if supported) to 0x1F80 (all exceptions masked, round-to-nearest, flush to zero
- for masked underflow).
-
-**/
-VOID
-EFIAPI
-InitializeFloatingPointUnits (
- VOID
- );
/**
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h
index 7c710901485..eb9ce861245 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Include/FspEas/FspApi.h
@@ -99,13 +99,36 @@ typedef struct {
///
UINT64 Signature;
///
- /// Revision of the Data structure. For FSP v2.0 value is 1.
+ /// Revision of the Data structure.
+ /// For FSP spec 2.0/2.1 value is 1.
+ /// For FSP spec 2.2 value is 2.
///
UINT8 Revision;
UINT8 Reserved[23];
} FSP_UPD_HEADER;
///
+/// FSPT_ARCH_UPD Configuration.
+///
+typedef struct {
+ ///
+ /// Revision Revision of the structure is 1 for this version of the specification.
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ ///
+ /// Length Length of the structure in bytes. The current value for this field is 32.
+ ///
+ UINT32 Length;
+ ///
+ /// FspDebugHandler Optional debug handler for the bootloader to receive debug messages
+ /// occurring during FSP execution.
+ ///
+ FSP_DEBUG_HANDLER FspDebugHandler;
+ UINT8 Reserved1[20];
+} FSPT_ARCH_UPD;
+
+///
/// FSPM_ARCH_UPD Configuration.
///
typedef struct {
@@ -146,6 +169,32 @@ typedef struct {
UINT8 Reserved1[4];
} FSPM_ARCH_UPD;
+typedef struct {
+ ///
+ /// Revision Revision of the structure is 1 for this version of the specification.
+ ///
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ ///
+ /// Length Length of the structure in bytes. The current value for this field is 32.
+ ///
+ UINT32 Length;
+ ///
+ /// FspEventHandler Optional event handler for the bootloader to be informed of events
+ /// occurring during FSP execution.
+ ///
+ FSP_EVENT_HANDLER FspEventHandler;
+ ///
+ /// A FSP binary may optionally implement multi-phase silicon initialization,
+ /// This is only supported if the FspMultiPhaseSiInitEntryOffset field in FSP_INFO_HEADER
+ /// is non-zero.
+ /// To enable multi-phase silicon initialization, the bootloader must set
+ /// EnableMultiPhaseSiliconInit to a non-zero value.
+ ///
+ UINT8 EnableMultiPhaseSiliconInit;
+ UINT8 Reserved1[19];
+} FSPS_ARCH_UPD;
+
///
/// FSPT_UPD_COMMON Configuration.
///
@@ -157,6 +206,21 @@ typedef struct {
} FSPT_UPD_COMMON;
///
+/// FSPT_UPD_COMMON Configuration for FSP spec. 2.2 and above.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+
+ ///
+ /// FSPT_ARCH_UPD Configuration.
+ ///
+ FSPT_ARCH_UPD FsptArchUpd;
+} FSPT_UPD_COMMON_FSP22;
+
+///
/// FSPM_UPD_COMMON Configuration.
///
typedef struct {
@@ -181,6 +245,21 @@ typedef struct {
} FSPS_UPD_COMMON;
///
+/// FSPS_UPD_COMMON Configuration for FSP spec. 2.2 and above.
+///
+typedef struct {
+ ///
+ /// FSP_UPD_HEADER Configuration.
+ ///
+ FSP_UPD_HEADER FspUpdHeader;
+
+ ///
+ /// FSPS_ARCH_UPD Configuration.
+ ///
+ FSPS_ARCH_UPD FspsArchUpd;
+} FSPS_UPD_COMMON_FSP22;
+
+///
/// Enumeration of FSP_INIT_PHASE for NOTIFY_PHASE.
///
typedef enum {
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec
index 3e3f9fb456c..d49f8227615 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dec
@@ -1,7 +1,7 @@
## @file
# Provides driver and definitions to build fsp in EDKII bios.
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -98,6 +98,11 @@
# Maximal Interrupt supported in IDT table.
#
gIntelFsp2PkgTokenSpaceGuid.PcdFspMaxInterruptSupported | 34| UINT8|0x10000005
+ #
+ # Allows FSP-M to reserve a section of Temporary RAM for implementation specific use.
+ # Reduces the amount of memory available for the PeiCore heap.
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspPrivateTemporaryRamSize |0x00000000|UINT32|0x10000006
[PcdsFixedAtBuild,PcdsDynamic,PcdsDynamicEx]
gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedMemoryLength |0x00100000|UINT32|0x46530000
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc
index 152971115ab..74af2bfba84 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/IntelFsp2Pkg.dsc
@@ -1,7 +1,7 @@
## @file
# Provides driver and definitions to build fsp.
#
-# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -16,6 +16,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
@@ -25,6 +27,7 @@
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
@@ -65,6 +68,7 @@
IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf
IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf
IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf
+ IntelFsp2Pkg/FspSecCore/Fsp22SecCoreS.inf
IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
[PcdsFixedAtBuild.common]
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py
new file mode 100644
index 00000000000..b3f2a3e5d1d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/FspDscBsf2Yaml.py
@@ -0,0 +1,884 @@
+#!/usr/bin/env python
+## @ FspDscBsf2Yaml.py
+# This script convert DSC or BSF format file into YAML format
+#
+# Copyright(c) 2021, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+import os
+import re
+import sys
+from datetime import date
+from collections import OrderedDict
+from functools import reduce
+
+from GenCfgOpt import CGenCfgOpt
+
+__copyright_tmp__ = """## @file
+#
+# YAML CFGDATA %s File.
+#
+# Copyright(c) %4d, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+"""
+
+__copyright_dsc__ = """## @file
+#
+# Copyright (c) %04d, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[PcdsDynamicVpd.Upd]
+ #
+ # Global definitions in BSF
+ # !BSF BLOCK:{NAME:"FSP UPD Configuration", VER:"0.1"}
+ #
+
+"""
+
+
+def Bytes2Val(Bytes):
+ return reduce(lambda x, y: (x << 8) | y, Bytes[::-1])
+
+
+def Str2Bytes(Value, Blen):
+ Result = bytearray(Value[1:-1], 'utf-8') # Excluding quotes
+ if len(Result) < Blen:
+ Result.extend(b'\x00' * (Blen - len(Result)))
+ return Result
+
+
+class CFspBsf2Dsc:
+
+ def __init__(self, bsf_file):
+ self.cfg_list = CFspBsf2Dsc.parse_bsf(bsf_file)
+
+ def get_dsc_lines(self):
+ return CFspBsf2Dsc.generate_dsc(self.cfg_list)
+
+ def save_dsc(self, dsc_file):
+ return CFspBsf2Dsc.generate_dsc(self.cfg_list, dsc_file)
+
+ @staticmethod
+ def parse_bsf(bsf_file):
+
+ fd = open(bsf_file, 'r')
+ bsf_txt = fd.read()
+ fd.close()
+
+ find_list = []
+ regex = re.compile(r'\s+Find\s+"(.*?)"(.*?)^\s+\$(.*?)\s+', re.S | re.MULTILINE)
+ for match in regex.finditer(bsf_txt):
+ find = match.group(1)
+ name = match.group(3)
+ if not name.endswith('_Revision'):
+ raise Exception("Unexpected CFG item following 'Find' !")
+ find_list.append((name, find))
+
+ idx = 0
+ count = 0
+ prefix = ''
+ chk_dict = {}
+ cfg_list = []
+ cfg_temp = {'find': '', 'cname': '', 'length': 0, 'value': '0', 'type': 'Reserved',
+ 'embed': '', 'page': '', 'option': '', 'instance': 0}
+ regex = re.compile(r'^\s+(\$(.*?)|Skip)\s+(\d+)\s+bytes(\s+\$_DEFAULT_\s+=\s+(.+?))?$',
+ re.S | re.MULTILINE)
+
+ for match in regex.finditer(bsf_txt):
+ dlen = int(match.group(3))
+ if match.group(1) == 'Skip':
+ key = 'gPlatformFspPkgTokenSpaceGuid_BsfSkip%d' % idx
+ val = ', '.join(['%02X' % ord(i) for i in '\x00' * dlen])
+ idx += 1
+ option = '$SKIP'
+ else:
+ key = match.group(2)
+ val = match.group(5)
+ option = ''
+
+ cfg_item = dict(cfg_temp)
+ finds = [i for i in find_list if i[0] == key]
+ if len(finds) > 0:
+ if count >= 1:
+ # Append a dummy one
+ cfg_item['cname'] = 'Dummy'
+ cfg_list.append(dict(cfg_item))
+ cfg_list[-1]['embed'] = '%s:TAG_%03X:END' % (prefix, ord(prefix[-1]))
+ prefix = finds[0][1]
+ cfg_item['embed'] = '%s:TAG_%03X:START' % (prefix, ord(prefix[-1]))
+ cfg_item['find'] = prefix
+ cfg_item['cname'] = 'Signature'
+ cfg_item['length'] = len(finds[0][1])
+ str2byte = Str2Bytes("'" + finds[0][1] + "'", len(finds[0][1]))
+ cfg_item['value'] = '0x%X' % Bytes2Val(str2byte)
+ cfg_list.append(dict(cfg_item))
+ cfg_item = dict(cfg_temp)
+ find_list.pop(0)
+ count = 0
+
+ cfg_item['cname'] = key
+ cfg_item['length'] = dlen
+ cfg_item['value'] = val
+ cfg_item['option'] = option
+
+ if key not in chk_dict.keys():
+ chk_dict[key] = 0
+ else:
+ chk_dict[key] += 1
+ cfg_item['instance'] = chk_dict[key]
+
+ cfg_list.append(cfg_item)
+ count += 1
+
+ if prefix:
+ cfg_item = dict(cfg_temp)
+ cfg_item['cname'] = 'Dummy'
+ cfg_item['embed'] = '%s:%03X:END' % (prefix, ord(prefix[-1]))
+ cfg_list.append(cfg_item)
+
+ option_dict = {}
+ selreg = re.compile(r'\s+Selection\s*(.+?)\s*,\s*"(.*?)"$', re.S | re.MULTILINE)
+ regex = re.compile(r'^List\s&(.+?)$(.+?)^EndList$', re.S | re.MULTILINE)
+ for match in regex.finditer(bsf_txt):
+ key = match.group(1)
+ option_dict[key] = []
+ for select in selreg.finditer(match.group(2)):
+ option_dict[key].append((int(select.group(1), 0), select.group(2)))
+
+ chk_dict = {}
+ pagereg = re.compile(r'^Page\s"(.*?)"$(.+?)^EndPage$', re.S | re.MULTILINE)
+ for match in pagereg.finditer(bsf_txt):
+ page = match.group(1)
+ for line in match.group(2).splitlines():
+ match = re.match(r'\s+(Combo|EditNum)\s\$(.+?),\s"(.*?)",\s(.+?),$', line)
+ if match:
+ cname = match.group(2)
+ if cname not in chk_dict.keys():
+ chk_dict[cname] = 0
+ else:
+ chk_dict[cname] += 1
+ instance = chk_dict[cname]
+ cfg_idxs = [i for i, j in enumerate(cfg_list) if j['cname'] == cname and j['instance'] == instance]
+ if len(cfg_idxs) != 1:
+ raise Exception("Multiple CFG item '%s' found !" % cname)
+ cfg_item = cfg_list[cfg_idxs[0]]
+ cfg_item['page'] = page
+ cfg_item['type'] = match.group(1)
+ cfg_item['prompt'] = match.group(3)
+ cfg_item['range'] = None
+ if cfg_item['type'] == 'Combo':
+ cfg_item['option'] = option_dict[match.group(4)[1:]]
+ elif cfg_item['type'] == 'EditNum':
+ cfg_item['option'] = match.group(4)
+ match = re.match(r'\s+ Help\s"(.*?)"$', line)
+ if match:
+ cfg_item['help'] = match.group(1)
+
+ match = re.match(r'\s+"Valid\srange:\s(.*)"$', line)
+ if match:
+ parts = match.group(1).split()
+ cfg_item['option'] = (
+ (int(parts[0], 0), int(parts[2], 0), cfg_item['option']))
+
+ return cfg_list
+
+ @staticmethod
+ def generate_dsc(option_list, dsc_file=None):
+ dsc_lines = []
+ header = '%s' % (__copyright_dsc__ % date.today().year)
+ dsc_lines.extend(header.splitlines())
+
+ pages = []
+ for cfg_item in option_list:
+ if cfg_item['page'] and (cfg_item['page'] not in pages):
+ pages.append(cfg_item['page'])
+
+ page_id = 0
+ for page in pages:
+ dsc_lines.append(' # !BSF PAGES:{PG%02X::"%s"}' % (page_id, page))
+ page_id += 1
+ dsc_lines.append('')
+
+ last_page = ''
+ for option in option_list:
+ dsc_lines.append('')
+ default = option['value']
+ pos = option['cname'].find('_')
+ name = option['cname'][pos + 1:]
+
+ if option['find']:
+ dsc_lines.append(' # !BSF FIND:{%s}' % option['find'])
+ dsc_lines.append('')
+
+ if option['instance'] > 0:
+ name = name + '_%s' % option['instance']
+
+ if option['embed']:
+ dsc_lines.append(' # !HDR EMBED:{%s}' % option['embed'])
+
+ if option['type'] == 'Reserved':
+ dsc_lines.append(' # !BSF NAME:{Reserved} TYPE:{Reserved}')
+ if option['option'] == '$SKIP':
+ dsc_lines.append(' # !BSF OPTION:{$SKIP}')
+ else:
+ prompt = option['prompt']
+
+ if last_page != option['page']:
+ last_page = option['page']
+ dsc_lines.append(' # !BSF PAGE:{PG%02X}' % (pages.index(option['page'])))
+
+ if option['type'] == 'Combo':
+ dsc_lines.append(' # !BSF NAME:{%s} TYPE:{%s}' %
+ (prompt, option['type']))
+ ops = []
+ for val, text in option['option']:
+ ops.append('0x%x:%s' % (val, text))
+ dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))
+ elif option['type'] == 'EditNum':
+ cfg_len = option['length']
+ if ',' in default and cfg_len > 8:
+ dsc_lines.append(' # !BSF NAME:{%s} TYPE:{Table}' % (prompt))
+ if cfg_len > 16:
+ cfg_len = 16
+ ops = []
+ for i in range(cfg_len):
+ ops.append('%X:1:HEX' % i)
+ dsc_lines.append(' # !BSF OPTION:{%s}' % (', '.join(ops)))
+ else:
+ dsc_lines.append(
+ ' # !BSF NAME:{%s} TYPE:{%s, %s,(0x%X, 0x%X)}' %
+ (prompt, option['type'], option['option'][2],
+ option['option'][0], option['option'][1]))
+ dsc_lines.append(' # !BSF HELP:{%s}' % option['help'])
+
+ if ',' in default:
+ default = '{%s}' % default
+ dsc_lines.append(' gCfgData.%-30s | * | 0x%04X | %s' %
+ (name, option['length'], default))
+
+ if dsc_file:
+ fd = open(dsc_file, 'w')
+ fd.write('\n'.join(dsc_lines))
+ fd.close()
+
+ return dsc_lines
+
+
+class CFspDsc2Yaml():
+
+ def __init__(self):
+ self._Hdr_key_list = ['EMBED', 'STRUCT']
+ self._Bsf_key_list = ['NAME', 'HELP', 'TYPE', 'PAGE', 'PAGES', 'OPTION',
+ 'CONDITION', 'ORDER', 'MARKER', 'SUBT', 'FIELD', 'FIND']
+ self.gen_cfg_data = None
+ self.cfg_reg_exp = re.compile(r"^([_a-zA-Z0-9$\(\)]+)\s*\|\s*(0x[0-9A-F]+|\*)\s*\|"
+ + r"\s*(\d+|0x[0-9a-fA-F]+)\s*\|\s*(.+)")
+ self.bsf_reg_exp = re.compile(r"(%s):{(.+?)}(?:$|\s+)" % '|'.join(self._Bsf_key_list))
+ self.hdr_reg_exp = re.compile(r"(%s):{(.+?)}" % '|'.join(self._Hdr_key_list))
+ self.prefix = ''
+ self.unused_idx = 0
+ self.offset = 0
+ self.base_offset = 0
+
+ def load_config_data_from_dsc(self, file_name):
+ """
+ Load and parse a DSC CFGDATA file.
+ """
+ gen_cfg_data = CGenCfgOpt('FSP')
+ if file_name.endswith('.dsc'):
+ # if gen_cfg_data.ParseDscFileYaml(file_name, '') != 0:
+ if gen_cfg_data.ParseDscFile(file_name, '') != 0:
+ raise Exception('DSC file parsing error !')
+ if gen_cfg_data.CreateVarDict() != 0:
+ raise Exception('DSC variable creation error !')
+ else:
+ raise Exception('Unsupported file "%s" !' % file_name)
+ self.gen_cfg_data = gen_cfg_data
+
+ def print_dsc_line(self):
+ """
+ Debug function to print all DSC lines.
+ """
+ for line in self.gen_cfg_data._DscLines:
+ print(line)
+
+ def format_value(self, field, text, indent=''):
+ """
+ Format a CFGDATA item into YAML format.
+ """
+ if(not text.startswith('!expand')) and (': ' in text):
+ tgt = ':' if field == 'option' else '- '
+ text = text.replace(': ', tgt)
+ lines = text.splitlines()
+ if len(lines) == 1 and field != 'help':
+ return text
+ else:
+ return '>\n ' + '\n '.join([indent + i.lstrip() for i in lines])
+
+ def reformat_pages(self, val):
+ # Convert XXX:YYY into XXX::YYY format for page definition
+ parts = val.split(',')
+ if len(parts) <= 1:
+ return val
+
+ new_val = []
+ for each in parts:
+ nodes = each.split(':')
+ if len(nodes) == 2:
+ each = '%s::%s' % (nodes[0], nodes[1])
+ new_val.append(each)
+ ret = ','.join(new_val)
+ return ret
+
+ def reformat_struct_value(self, utype, val):
+ # Convert DSC UINT16/32/64 array into new format by
+ # adding prefix 0:0[WDQ] to provide hint to the array format
+ if utype in ['UINT16', 'UINT32', 'UINT64']:
+ if val and val[0] == '{' and val[-1] == '}':
+ if utype == 'UINT16':
+ unit = 'W'
+ elif utype == 'UINT32':
+ unit = 'D'
+ else:
+ unit = 'Q'
+ val = '{ 0:0%s, %s }' % (unit, val[1:-1])
+ return val
+
+ def process_config(self, cfg):
+ if 'page' in cfg:
+ cfg['page'] = self.reformat_pages(cfg['page'])
+
+ if 'struct' in cfg:
+ cfg['value'] = self.reformat_struct_value(cfg['struct'], cfg['value'])
+
+ def parse_dsc_line(self, dsc_line, config_dict, init_dict, include):
+ """
+ Parse a line in DSC and update the config dictionary accordingly.
+ """
+ init_dict.clear()
+ match = re.match(r'g(CfgData|\w+FspPkgTokenSpaceGuid)\.(.+)', dsc_line)
+ if match:
+ match = self.cfg_reg_exp.match(match.group(2))
+ if not match:
+ return False
+ config_dict['cname'] = self.prefix + match.group(1)
+ value = match.group(4).strip()
+ length = match.group(3).strip()
+ config_dict['length'] = length
+ config_dict['value'] = value
+ if match.group(2) == '*':
+ self.offset += int(length, 0)
+ else:
+ org_offset = int(match.group(2), 0)
+ if org_offset == 0:
+ self.base_offset = self.offset
+ offset = org_offset + self.base_offset
+ if self.offset != offset:
+ if offset > self.offset:
+ init_dict['padding'] = offset - self.offset
+ self.offset = offset + int(length, 0)
+ return True
+
+ match = re.match(r"^\s*#\s+!([<>])\s+include\s+(.+)", dsc_line)
+ if match and len(config_dict) == 0:
+ # !include should not be inside a config field
+ # if so, do not convert include into YAML
+ init_dict = dict(config_dict)
+ config_dict.clear()
+ config_dict['cname'] = '$ACTION'
+ if match.group(1) == '<':
+ config_dict['include'] = match.group(2)
+ else:
+ config_dict['include'] = ''
+ return True
+
+ match = re.match(r"^\s*#\s+(!BSF|!HDR)\s+(.+)", dsc_line)
+ if not match:
+ return False
+
+ remaining = match.group(2)
+ if match.group(1) == '!BSF':
+ result = self.bsf_reg_exp.findall(remaining)
+ if not result:
+ return False
+
+ for each in result:
+ key = each[0].lower()
+ val = each[1]
+ if key == 'field':
+ name = each[1]
+ if ':' not in name:
+ raise Exception('Incorrect bit field format !')
+ parts = name.split(':')
+ config_dict['length'] = parts[1]
+ config_dict['cname'] = '@' + parts[0]
+ return True
+ elif key in ['pages', 'page', 'find']:
+ init_dict = dict(config_dict)
+ config_dict.clear()
+ config_dict['cname'] = '$ACTION'
+ if key == 'find':
+ config_dict['find'] = val
+ else:
+ config_dict['page'] = val
+ return True
+ elif key == 'subt':
+ config_dict.clear()
+ parts = each[1].split(':')
+ tmp_name = parts[0][:-5]
+ if tmp_name == 'CFGHDR':
+ cfg_tag = '_$FFF_'
+ sval = '!expand { %s_TMPL : [ ' % tmp_name + '%s, %s, ' % (parts[1], cfg_tag) \
+ + ', '.join(parts[2:]) + ' ] }'
+ else:
+ sval = '!expand { %s_TMPL : [ ' % tmp_name + ', '.join(parts[1:]) + ' ] }'
+ config_dict.clear()
+ config_dict['cname'] = tmp_name
+ config_dict['expand'] = sval
+ return True
+ else:
+ if key in ['name', 'help', 'option'] and val.startswith('+'):
+ val = config_dict[key] + '\n' + val[1:]
+ if val.strip() == '':
+ val = "''"
+ config_dict[key] = val
+
+ else:
+ match = self.hdr_reg_exp.match(remaining)
+ if not match:
+ return False
+ key = match.group(1)
+ remaining = match.group(2)
+ if key == 'EMBED':
+ parts = remaining.split(':')
+ names = parts[0].split(',')
+ if parts[-1] == 'END':
+ prefix = '>'
+ else:
+ prefix = '<'
+ skip = False
+ if parts[1].startswith('TAG_'):
+ tag_txt = '%s:%s' % (names[0], parts[1])
+ else:
+ tag_txt = names[0]
+ if parts[2] in ['START', 'END']:
+ if names[0] == 'PCIE_RP_PIN_CTRL[]':
+ skip = True
+ else:
+ tag_txt = '%s:%s' % (names[0], parts[1])
+ if not skip:
+ config_dict.clear()
+ config_dict['cname'] = prefix + tag_txt
+ return True
+
+ if key == 'STRUCT':
+ text = remaining.strip()
+ config_dict[key.lower()] = text
+
+ return False
+
+ def process_template_lines(self, lines):
+ """
+ Process a line in DSC template section.
+ """
+ template_name = ''
+ bsf_temp_dict = OrderedDict()
+ temp_file_dict = OrderedDict()
+ include_file = ['.']
+
+ for line in lines:
+ match = re.match(r"^\s*#\s+!([<>])\s+include\s+(.+)", line)
+ if match:
+ if match.group(1) == '<':
+ include_file.append(match.group(2))
+ else:
+ include_file.pop()
+
+ match = re.match(r"^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", line)
+ if match:
+ if match.group(3) == 'START' and not template_name:
+ template_name = match.group(2).strip()
+ temp_file_dict[template_name] = list(include_file)
+ bsf_temp_dict[template_name] = []
+ if match.group(3) == 'END' and (template_name == match.group(2).strip()) \
+ and template_name:
+ template_name = ''
+ else:
+ if template_name:
+ bsf_temp_dict[template_name].append(line)
+ return bsf_temp_dict, temp_file_dict
+
+ def process_option_lines(self, lines):
+ """
+ Process a line in DSC config section.
+ """
+ cfgs = []
+ struct_end = False
+ config_dict = dict()
+ init_dict = dict()
+ include = ['']
+ for line in lines:
+ ret = self.parse_dsc_line(line, config_dict, init_dict, include)
+ if ret:
+ if 'padding' in init_dict:
+ num = init_dict['padding']
+ init_dict.clear()
+ padding_dict = {}
+ cfgs.append(padding_dict)
+ padding_dict['cname'] = 'UnusedUpdSpace%d' % self.unused_idx
+ padding_dict['length'] = '0x%x' % num
+ padding_dict['value'] = '{ 0 }'
+ self.unused_idx += 1
+
+ if cfgs and cfgs[-1]['cname'][0] != '@' and config_dict['cname'][0] == '@':
+ # it is a bit field, mark the previous one as virtual
+ cname = cfgs[-1]['cname']
+ new_cfg = dict(cfgs[-1])
+ new_cfg['cname'] = '@$STRUCT'
+ cfgs[-1].clear()
+ cfgs[-1]['cname'] = cname
+ cfgs.append(new_cfg)
+
+ if cfgs and cfgs[-1]['cname'] == 'CFGHDR' and config_dict['cname'][0] == '<':
+ # swap CfgHeader and the CFG_DATA order
+ if ':' in config_dict['cname']:
+ # replace the real TAG for CFG_DATA
+ cfgs[-1]['expand'] = cfgs[-1]['expand'].replace(
+ '_$FFF_', '0x%s' %
+ config_dict['cname'].split(':')[1][4:])
+ cfgs.insert(-1, config_dict)
+ else:
+ self.process_config(config_dict)
+ if struct_end:
+ struct_end = False
+ cfgs.insert(-1, config_dict)
+ else:
+ cfgs.append(config_dict)
+ if config_dict['cname'][0] == '>':
+ struct_end = True
+
+ config_dict = dict(init_dict)
+ return cfgs
+
+ def variable_fixup(self, each):
+ """
+ Fix up some variable definitions for SBL.
+ """
+ key = each
+ val = self.gen_cfg_data._MacroDict[each]
+ return key, val
+
+ def template_fixup(self, tmp_name, tmp_list):
+ """
+ Fix up some special config templates for SBL
+ """
+ return
+
+ def config_fixup(self, cfg_list):
+ """
+ Fix up some special config items for SBL.
+ """
+
+ # Insert FSPT_UPD/FSPM_UPD/FSPS_UPD tag so as to create C strcture
+ idxs = []
+ for idx, cfg in enumerate(cfg_list):
+ if cfg['cname'].startswith('<FSP_UPD_HEADER'):
+ idxs.append(idx)
+
+ if len(idxs) != 3:
+ return
+
+ # Handle insert backwards so that the index does not change in the loop
+ fsp_comp = 'SMT'
+ idx_comp = 0
+ for idx in idxs[::-1]:
+ # Add current FSP?_UPD start tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '<FSP%s_UPD' % fsp_comp[idx_comp]
+ cfg_list.insert(idx, cfgfig_dict)
+ if idx_comp < 2:
+ # Add previous FSP?_UPD end tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[idx_comp + 1]
+ cfg_list.insert(idx, cfgfig_dict)
+ idx_comp += 1
+
+ # Add final FSPS_UPD end tag
+ cfgfig_dict = {}
+ cfgfig_dict['cname'] = '>FSP%s_UPD' % fsp_comp[0]
+ cfg_list.append(cfgfig_dict)
+
+ return
+
+ def get_section_range(self, section_name):
+ """
+ Extract line number range from config file for a given section name.
+ """
+ start = -1
+ end = -1
+ for idx, line in enumerate(self.gen_cfg_data._DscLines):
+ if start < 0 and line.startswith('[%s]' % section_name):
+ start = idx
+ elif start >= 0 and line.startswith('['):
+ end = idx
+ break
+ if start == -1:
+ start = 0
+ if end == -1:
+ end = len(self.gen_cfg_data._DscLines)
+ return start, end
+
+ def normalize_file_name(self, file, is_temp=False):
+ """
+ Normalize file name convention so that it is consistent.
+ """
+ if file.endswith('.dsc'):
+ file = file[:-4] + '.yaml'
+ dir_name = os.path.dirname(file)
+ base_name = os.path.basename(file)
+ if is_temp:
+ if 'Template_' not in file:
+ base_name = base_name.replace('Template', 'Template_')
+ else:
+ if 'CfgData_' not in file:
+ base_name = base_name.replace('CfgData', 'CfgData_')
+ if dir_name:
+ path = dir_name + '/' + base_name
+ else:
+ path = base_name
+ return path
+
+ def output_variable(self):
+ """
+ Output variable block into a line list.
+ """
+ lines = []
+ for each in self.gen_cfg_data._MacroDict:
+ key, value = self.variable_fixup(each)
+ lines.append('%-30s : %s' % (key, value))
+ return lines
+
+ def output_template(self):
+ """
+ Output template block into a line list.
+ """
+ self.offset = 0
+ self.base_offset = 0
+ start, end = self.get_section_range('PcdsDynamicVpd.Tmp')
+ bsf_temp_dict, temp_file_dict = self.process_template_lines(self.gen_cfg_data._DscLines[start:end])
+ template_dict = dict()
+ lines = []
+ file_lines = {}
+ last_file = '.'
+ file_lines[last_file] = []
+
+ for tmp_name in temp_file_dict:
+ temp_file_dict[tmp_name][-1] = self.normalize_file_name(temp_file_dict[tmp_name][-1], True)
+ if len(temp_file_dict[tmp_name]) > 1:
+ temp_file_dict[tmp_name][-2] = self.normalize_file_name(temp_file_dict[tmp_name][-2], True)
+
+ for tmp_name in bsf_temp_dict:
+ file = temp_file_dict[tmp_name][-1]
+ if last_file != file and len(temp_file_dict[tmp_name]) > 1:
+ inc_file = temp_file_dict[tmp_name][-2]
+ file_lines[inc_file].extend(['', '- !include %s' % temp_file_dict[tmp_name][-1], ''])
+ last_file = file
+ if file not in file_lines:
+ file_lines[file] = []
+ lines = file_lines[file]
+ text = bsf_temp_dict[tmp_name]
+ tmp_list = self.process_option_lines(text)
+ self.template_fixup(tmp_name, tmp_list)
+ template_dict[tmp_name] = tmp_list
+ lines.append('%s: >' % tmp_name)
+ lines.extend(self.output_dict(tmp_list, False)['.'])
+ lines.append('\n')
+ return file_lines
+
+ def output_config(self):
+ """
+ Output config block into a line list.
+ """
+ self.offset = 0
+ self.base_offset = 0
+ start, end = self.get_section_range('PcdsDynamicVpd.Upd')
+ cfgs = self.process_option_lines(self.gen_cfg_data._DscLines[start:end])
+ self.config_fixup(cfgs)
+ file_lines = self.output_dict(cfgs, True)
+ return file_lines
+
+ def output_dict(self, cfgs, is_configs):
+ """
+ Output one config item into a line list.
+ """
+ file_lines = {}
+ level = 0
+ file = '.'
+ for each in cfgs:
+ if 'length' in each and int(each['length'], 0) == 0:
+ continue
+
+ if 'include' in each:
+ if each['include']:
+ each['include'] = self.normalize_file_name(each['include'])
+ file_lines[file].extend(['', '- !include %s' % each['include'], ''])
+ file = each['include']
+ else:
+ file = '.'
+ continue
+
+ if file not in file_lines:
+ file_lines[file] = []
+
+ lines = file_lines[file]
+ name = each['cname']
+
+ prefix = name[0]
+ if prefix == '<':
+ level += 1
+
+ padding = ' ' * level
+ if prefix not in '<>@':
+ padding += ' '
+ else:
+ name = name[1:]
+ if prefix == '@':
+ padding += ' '
+
+ if ':' in name:
+ parts = name.split(':')
+ name = parts[0]
+
+ padding = padding[2:] if is_configs else padding
+
+ if prefix != '>':
+ if 'expand' in each:
+ lines.append('%s- %s' % (padding, each['expand']))
+ else:
+ lines.append('%s- %-12s :' % (padding, name))
+
+ for field in each:
+ if field in ['cname', 'expand', 'include']:
+ continue
+ value_str = self.format_value(field, each[field], padding + ' ' * 16)
+ full_line = ' %s %-12s : %s' % (padding, field, value_str)
+ lines.extend(full_line.splitlines())
+
+ if prefix == '>':
+ level -= 1
+ if level == 0:
+ lines.append('')
+
+ return file_lines
+
+
+def bsf_to_dsc(bsf_file, dsc_file):
+ fsp_dsc = CFspBsf2Dsc(bsf_file)
+ dsc_lines = fsp_dsc.get_dsc_lines()
+ fd = open(dsc_file, 'w')
+ fd.write('\n'.join(dsc_lines))
+ fd.close()
+ return
+
+
+def dsc_to_yaml(dsc_file, yaml_file):
+ dsc2yaml = CFspDsc2Yaml()
+ dsc2yaml.load_config_data_from_dsc(dsc_file)
+
+ cfgs = {}
+ for cfg in ['Template', 'Option']:
+ if cfg == 'Template':
+ file_lines = dsc2yaml.output_template()
+ else:
+ file_lines = dsc2yaml.output_config()
+ for file in file_lines:
+ lines = file_lines[file]
+ if file == '.':
+ cfgs[cfg] = lines
+ else:
+ if('/' in file or '\\' in file):
+ continue
+ file = os.path.basename(file)
+ fo = open(os.path.join(file), 'w')
+ fo.write(__copyright_tmp__ % (cfg, date.today().year) + '\n\n')
+ for line in lines:
+ fo.write(line + '\n')
+ fo.close()
+
+ variables = dsc2yaml.output_variable()
+ fo = open(yaml_file, 'w')
+ fo.write(__copyright_tmp__ % ('Default', date.today().year))
+ if len(variables) > 0:
+ fo.write('\n\nvariable:\n')
+ for line in variables:
+ fo.write(' ' + line + '\n')
+
+ fo.write('\n\ntemplate:\n')
+ for line in cfgs['Template']:
+ if line != '':
+ fo.write(' ' + line + '\n')
+
+ fo.write('\n\nconfigs:\n')
+ for line in cfgs['Option']:
+ if line != '':
+ fo.write(' ' + line + '\n')
+
+ fo.close()
+
+
+def get_fsp_name_from_path(bsf_file):
+ name = ''
+ parts = bsf_file.split(os.sep)
+ for part in parts:
+ if part.endswith('FspBinPkg'):
+ name = part[:-9]
+ break
+ if not name:
+ raise Exception('Could not get FSP name from file path!')
+ return name
+
+
+def usage():
+ print('\n'.join([
+ "FspDscBsf2Yaml Version 0.10",
+ "Usage:",
+ " FspDscBsf2Yaml BsfFile|DscFile YamlFile"
+ ]))
+
+
+def main():
+ #
+ # Parse the options and args
+ #
+ argc = len(sys.argv)
+ if argc < 3:
+ usage()
+ return 1
+
+ bsf_file = sys.argv[1]
+ yaml_file = sys.argv[2]
+ if os.path.isdir(yaml_file):
+ yaml_file = os.path.join(yaml_file, get_fsp_name_from_path(bsf_file) + '.yaml')
+
+ if bsf_file.endswith('.dsc'):
+ dsc_file = bsf_file
+ bsf_file = ''
+ else:
+ dsc_file = os.path.splitext(yaml_file)[0] + '.dsc'
+ bsf_to_dsc(bsf_file, dsc_file)
+
+ dsc_to_yaml(dsc_file, yaml_file)
+
+ print("'%s' was created successfully!" % yaml_file)
+
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py
index 85b65d4a345..34484c16bba 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/GenCfgOpt.py
@@ -1,6 +1,6 @@
## @ GenCfgOpt.py
#
-# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -283,10 +283,10 @@ class CLogicalExpression:
return Result
class CGenCfgOpt:
- def __init__(self):
+ def __init__(self, Mode = ''):
self.Debug = False
self.Error = ''
-
+ self.Mode = Mode
self._GlobalDataDef = """
GlobalDataDef
SKUID = 0, "DEFAULT"
@@ -300,19 +300,22 @@ List &EN_DIS
EndList
"""
-
- self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE','OPTION','ORDER']
+ self._BsfKeyList = ['FIND','NAME','HELP','TYPE','PAGE', 'PAGES', 'BLOCK', 'OPTION','CONDITION','ORDER', 'MARKER', 'SUBT']
self._HdrKeyList = ['HEADER','STRUCT', 'EMBED', 'COMMENT']
self._BuidinOption = {'$EN_DIS' : 'EN_DIS'}
self._MacroDict = {}
+ self._VarDict = {}
self._PcdsDict = {}
self._CfgBlkDict = {}
self._CfgPageDict = {}
+ self._BsfTempDict = {}
self._CfgItemList = []
+ self._DscLines = []
self._DscFile = ''
- self._FvDir = ''
+
self._MapVer = 0
+ self._DscTime = 0
def ParseMacros (self, MacroDefStr):
# ['-DABC=1', '-D', 'CFG_DEBUG=1', '-D', 'CFG_OUTDIR=Build']
@@ -350,7 +353,7 @@ EndList
print ("INFO : Eval Ifdef [%s] : %s" % (Macro, Result))
return Result
- def ExpandMacros (self, Input):
+ def ExpandMacros (self, Input, Preserve = False):
Line = Input
Match = re.findall("\$\(\w+\)", Input)
if Match:
@@ -361,7 +364,8 @@ EndList
else:
if self.Debug:
print ("WARN : %s is not defined" % Each)
- Line = Line.replace(Each, Each[2:-1])
+ if not Preserve:
+ Line = Line.replace(Each, Each[2:-1])
return Line
def ExpandPcds (self, Input):
@@ -385,6 +389,70 @@ EndList
print ("INFO : Eval Express [%s] : %s" % (Expr, Result))
return Result
+ def ValueToByteArray (self, ValueStr, Length):
+ Match = re.match("\{\s*FILE:(.+)\}", ValueStr)
+ if Match:
+ FileList = Match.group(1).split(',')
+ Result = bytearray()
+ for File in FileList:
+ File = File.strip()
+ BinPath = os.path.join(os.path.dirname(self._DscFile), File)
+ Result.extend(bytearray(open(BinPath, 'rb').read()))
+ else:
+ try:
+ Result = bytearray(self.ValueToList(ValueStr, Length))
+ except ValueError as e:
+ raise Exception ("Bytes in '%s' must be in range 0~255 !" % ValueStr)
+ if len(Result) < Length:
+ Result.extend(b'\x00' * (Length - len(Result)))
+ elif len(Result) > Length:
+ raise Exception ("Value '%s' is too big to fit into %d bytes !" % (ValueStr, Length))
+
+ return Result[:Length]
+
+ def ValueToList (self, ValueStr, Length):
+ if ValueStr[0] == '{':
+ Result = []
+ BinList = ValueStr[1:-1].split(',')
+ InBitField = False
+ LastInBitField = False
+ Value = 0
+ BitLen = 0
+ for Element in BinList:
+ InBitField = False
+ Each = Element.strip()
+ if len(Each) == 0:
+ pass
+ else:
+ if Each[0] in ['"', "'"]:
+ Result.extend(list(bytearray(Each[1:-1], 'utf-8')))
+ elif ':' in Each:
+ Match = re.match("(.+):(\d+)b", Each)
+ if Match is None:
+ raise Exception("Invald value list format '%s' !" % Each)
+ InBitField = True
+ CurrentBitLen = int(Match.group(2))
+ CurrentValue = ((self.EvaluateExpress(Match.group(1)) & (1<<CurrentBitLen) - 1)) << BitLen
+ else:
+ Result.append(self.EvaluateExpress(Each.strip()))
+ if InBitField:
+ Value += CurrentValue
+ BitLen += CurrentBitLen
+ if LastInBitField and ((not InBitField) or (Element == BinList[-1])):
+ if BitLen % 8 != 0:
+ raise Exception("Invald bit field length!")
+ Result.extend(Val2Bytes(Value, BitLen // 8))
+ Value = 0
+ BitLen = 0
+ LastInBitField = InBitField
+ elif ValueStr.startswith("'") and ValueStr.endswith("'"):
+ Result = Str2Bytes (ValueStr, Length)
+ elif ValueStr.startswith('"') and ValueStr.endswith('"'):
+ Result = Str2Bytes (ValueStr, Length)
+ else:
+ Result = Val2Bytes (self.EvaluateExpress(ValueStr), Length)
+ return Result
+
def FormatListValue(self, ConfigDict):
Struct = ConfigDict['struct']
if Struct not in ['UINT8','UINT16','UINT32','UINT64']:
@@ -423,25 +491,53 @@ EndList
self._DscFile = DscFile
self._FvDir = FvDir
+ self._DscLines = []
+ self._BsfTempDict = {}
+
+ # Initial DSC time is parent DSC time.
+ self._DscTime = os.path.getmtime(DscFile)
+
+ CfgDict = {}
+
IsDefSect = False
IsPcdSect = False
IsUpdSect = False
IsVpdSect = False
+ IsTmpSect = False
+
+ TemplateName = ''
IfStack = []
ElifStack = []
Error = 0
ConfigDict = {}
- DscFd = open(DscFile, "r")
- DscLines = DscFd.readlines()
- DscFd.close()
+
+ if type(DscFile) is list:
+ # it is DSC lines already
+ DscLines = DscFile
+ self._DscFile = '.'
+ else:
+ DscFd = open(DscFile, "r")
+ DscLines = DscFd.readlines()
+ DscFd.close()
+ self._DscFile = DscFile
+
+ SkipLines = 0
MaxAlign = 32 #Default align to 32, but if there are 64 bit unit, align to 64
SizeAlign = 0 #record the struct max align
Base = 0 #Starting offset of sub-structure.
+
while len(DscLines):
DscLine = DscLines.pop(0).strip()
+ if SkipLines == 0:
+ self._DscLines.append (DscLine)
+ else:
+ SkipLines = SkipLines - 1
+ if len(DscLine) == 0:
+ continue
+
Handle = False
Match = re.match("^\[(.+)\]", DscLine)
if Match is not None:
@@ -449,11 +545,15 @@ EndList
IsPcdSect = False
IsVpdSect = False
IsUpdSect = False
- if Match.group(1).lower() == "Defines".lower():
+ IsTmpSect = False
+ SectionName = Match.group(1).lower()
+ if SectionName == "Defines".lower():
IsDefSect = True
- if (Match.group(1).lower() == "PcdsFeatureFlag".lower() or Match.group(1).lower() == "PcdsFixedAtBuild".lower()):
+ if (SectionName == "PcdsFeatureFlag".lower() or SectionName == "PcdsFixedAtBuild".lower()):
IsPcdSect = True
- elif Match.group(1).lower() == "PcdsDynamicVpd.Upd".lower():
+ elif SectionName == "PcdsDynamicVpd.Tmp".lower():
+ IsTmpSect = True
+ elif SectionName == "PcdsDynamicVpd.Upd".lower():
ConfigDict = {}
ConfigDict['header'] = 'ON'
ConfigDict['region'] = 'UPD'
@@ -461,84 +561,98 @@ EndList
ConfigDict['page'] = ''
ConfigDict['name'] = ''
ConfigDict['find'] = ''
+ ConfigDict['marker'] = ''
ConfigDict['struct'] = ''
ConfigDict['embed'] = ''
ConfigDict['comment'] = ''
ConfigDict['subreg'] = []
+ ConfigDict['condition'] = ''
+ ConfigDict['option'] = ''
IsUpdSect = True
Offset = 0
else:
- if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect:
- if re.match("^!else($|\s+#.+)", DscLine):
+ if IsDefSect or IsPcdSect or IsUpdSect or IsVpdSect or IsTmpSect:
+
+ Match = False if DscLine[0] != '!' else True
+ if Match:
+ Match = re.match("^!(else|endif|ifdef|ifndef|if|elseif|include)\s*(.+)?$", DscLine.split("#")[0])
+ Keyword = Match.group(1) if Match else ''
+ Remaining = Match.group(2) if Match else ''
+ Remaining = '' if Remaining is None else Remaining.strip()
+
+ if Keyword in ['if', 'elseif', 'ifdef', 'ifndef', 'include'] and not Remaining:
+ raise Exception ("ERROR: Expression is expected after '!if' or !elseif' for line '%s'" % DscLine)
+
+ if Keyword == 'else':
if IfStack:
IfStack[-1] = not IfStack[-1]
else:
- print("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
- raise SystemExit
- elif re.match("^!endif($|\s+#.+)", DscLine):
+ raise Exception ("ERROR: No paired '!if' found for '!else' for line '%s'" % DscLine)
+ elif Keyword == 'endif':
if IfStack:
IfStack.pop()
Level = ElifStack.pop()
if Level > 0:
del IfStack[-Level:]
else:
- print("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
- raise SystemExit
- else:
- Result = False
- Match = re.match("!(ifdef|ifndef)\s+(.+)", DscLine)
- if Match:
- Result = self.EvaulateIfdef (Match.group(2))
- if Match.group(1) == 'ifndef':
- Result = not Result
- IfStack.append(Result)
+ raise Exception ("ERROR: No paired '!if' found for '!endif' for line '%s'" % DscLine)
+ elif Keyword == 'ifdef' or Keyword == 'ifndef':
+ Result = self.EvaulateIfdef (Remaining)
+ if Keyword == 'ifndef':
+ Result = not Result
+ IfStack.append(Result)
+ ElifStack.append(0)
+ elif Keyword == 'if' or Keyword == 'elseif':
+ Result = self.EvaluateExpress(Remaining)
+ if Keyword == "if":
ElifStack.append(0)
+ IfStack.append(Result)
+ else: #elseif
+ if IfStack:
+ IfStack[-1] = not IfStack[-1]
+ IfStack.append(Result)
+ ElifStack[-1] = ElifStack[-1] + 1
+ else:
+ raise Exception ("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
+ else:
+ if IfStack:
+ Handle = reduce(lambda x,y: x and y, IfStack)
else:
- Match = re.match("!(if|elseif)\s+(.+)", DscLine.split("#")[0])
+ Handle = True
+ if Handle:
+ Match = re.match("!include\s+(.+)", DscLine)
if Match:
- Result = self.EvaluateExpress(Match.group(2))
- if Match.group(1) == "if":
- ElifStack.append(0)
- IfStack.append(Result)
- else: #elseif
- if IfStack:
- IfStack[-1] = not IfStack[-1]
- IfStack.append(Result)
- ElifStack[-1] = ElifStack[-1] + 1
- else:
- print("ERROR: No paired '!if' found for '!elif' for line '%s'" % DscLine)
- raise SystemExit
- else:
- if IfStack:
- Handle = reduce(lambda x,y: x and y, IfStack)
+ IncludeFilePath = Match.group(1)
+ IncludeFilePath = self.ExpandMacros(IncludeFilePath)
+ PackagesPath = os.getenv("PACKAGES_PATH")
+ if PackagesPath:
+ for PackagePath in PackagesPath.split(os.pathsep):
+ IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))
+ if os.path.exists(IncludeFilePathAbs):
+ IncludeDsc = open(IncludeFilePathAbs, "r")
+ break
else:
- Handle = True
- if Handle:
- Match = re.match("!include\s+(.+)", DscLine)
- if Match:
- IncludeFilePath = Match.group(1)
- IncludeFilePath = self.ExpandMacros(IncludeFilePath)
- PackagesPath = os.getenv("PACKAGES_PATH")
- if PackagesPath:
- for PackagePath in PackagesPath.split(os.pathsep):
- IncludeFilePathAbs = os.path.join(os.path.normpath(PackagePath), os.path.normpath(IncludeFilePath))
- if os.path.exists(IncludeFilePathAbs):
- IncludeDsc = open(IncludeFilePathAbs, "r")
- break
- else:
- IncludeDsc = open(IncludeFilePath, "r")
- if IncludeDsc == None:
- print("ERROR: Cannot open file '%s'" % IncludeFilePath)
- raise SystemExit
- NewDscLines = IncludeDsc.readlines()
- IncludeDsc.close()
- DscLines = NewDscLines + DscLines
- Offset = 0
- else:
- if DscLine.startswith('!'):
- print("ERROR: Unrecognized directive for line '%s'" % DscLine)
- raise SystemExit
+ IncludeDsc = open(IncludeFilePath, "r")
+ if IncludeDsc == None:
+ print("ERROR: Cannot open file '%s'" % IncludeFilePath)
+ raise SystemExit
+
+ # Update DscTime when newer DSC time found.
+ CurrentDscTime = os.path.getmtime(os.path.realpath(IncludeDsc.name))
+ if CurrentDscTime > self._DscTime:
+ self._DscTime = CurrentDscTime
+
+ NewDscLines = IncludeDsc.readlines()
+ IncludeDsc.close()
+ DscLines = NewDscLines + DscLines
+ del self._DscLines[-1]
+ Offset = 0
+ else:
+ if DscLine.startswith('!'):
+ print("ERROR: Unrecognized directive for line '%s'" % DscLine)
+ raise SystemExit
if not Handle:
+ del self._DscLines[-1]
continue
if IsDefSect:
@@ -546,11 +660,11 @@ EndList
#DEFINE FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
#DEFINE FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
#DEFINE FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
- Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*([-.\w]+)", DscLine)
+ Match = re.match("^\s*(?:DEFINE\s+)*(\w+)\s*=\s*(.+)", DscLine)
if Match:
- self._MacroDict[Match.group(1)] = Match.group(2)
+ self._MacroDict[Match.group(1)] = self.ExpandMacros(Match.group(2))
if self.Debug:
- print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), Match.group(2)))
+ print ("INFO : DEFINE %s = [ %s ]" % (Match.group(1), self.ExpandMacros(Match.group(2))))
elif IsPcdSect:
#gSiPkgTokenSpaceGuid.PcdTxtEnable|FALSE
#gSiPkgTokenSpaceGuid.PcdOverclockEnable|TRUE
@@ -565,6 +679,23 @@ EndList
if Match:
self._PcdsDict[Match.group(1)] = Match.group(2)
i += 1
+
+ elif IsTmpSect:
+ # !BSF DEFT:{GPIO_TMPL:START}
+ Match = re.match("^\s*#\s+(!BSF)\s+DEFT:{(.+?):(START|END)}", DscLine)
+ if Match:
+ if Match.group(3) == 'START' and not TemplateName:
+ TemplateName = Match.group(2).strip()
+ self._BsfTempDict[TemplateName] = []
+ if Match.group(3) == 'END' and (TemplateName == Match.group(2).strip()) and TemplateName:
+ TemplateName = ''
+ else:
+ if TemplateName:
+ Match = re.match("^!include\s*(.+)?$", DscLine)
+ if Match:
+ continue
+ self._BsfTempDict[TemplateName].append(DscLine)
+
else:
Match = re.match("^\s*#\s+(!BSF|@Bsf|!HDR)\s+(.+)", DscLine)
if Match:
@@ -577,7 +708,8 @@ EndList
for Page in PageList:
Page = Page.strip()
Match = re.match("(\w+):\"(.+)\"", Page)
- self._CfgPageDict[Match.group(1)] = Match.group(2)
+ if Match != None:
+ self._CfgPageDict[Match.group(1)] = Match.group(2)
Match = re.match("(?:^|.+\s+)BLOCK:{NAME:\"(.+)\"\s*,\s*VER:\"(.+)\"\s*}", Remaining)
if Match:
@@ -620,9 +752,9 @@ EndList
Match = re.match("^\s*#\s*@ValidRange\s*(.+)\s*\|\s*(.+)\s*-\s*(.+)\s*", DscLine)
if Match:
if "0x" in Match.group(2) or "0x" in Match.group(3):
- ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
+ ConfigDict['type'] = "EditNum, HEX, (%s,%s)" % (Match.group(2), Match.group(3))
else:
- ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
+ ConfigDict['type'] = "EditNum, DEC, (%s,%s)" % (Match.group(2), Match.group(3))
Match = re.match("^\s*##\s+(.+)", DscLine)
if Match:
@@ -738,6 +870,7 @@ EndList
ConfigDict['struct'] = ''
ConfigDict['embed'] = ''
ConfigDict['comment'] = ''
+ ConfigDict['marker'] = ''
ConfigDict['order'] = -1
ConfigDict['subreg'] = []
ConfigDict['option'] = ''
@@ -776,9 +909,8 @@ EndList
bitsvalue = bitsvalue[::-1]
bitslen = len(bitsvalue)
if start > bitslen or end > bitslen:
- print ("Invalid bits offset [%d,%d] for %s" % (start, end, subitem['name']))
- raise SystemExit
- return hex(int(bitsvalue[start:end][::-1], 2))
+ raise Exception ("Invalid bits offset [%d,%d] %d for %s" % (start, end, bitslen, subitem['name']))
+ return '0x%X' % (int(bitsvalue[start:end][::-1], 2))
def UpdateSubRegionDefaultValue (self):
Error = 0
@@ -810,6 +942,16 @@ EndList
SubItem['value'] = valuestr
return Error
+ def NoDscFileChange (self, OutPutFile):
+ NoFileChange = True
+ if not os.path.exists(OutPutFile):
+ NoFileChange = False
+ else:
+ OutputTime = os.path.getmtime(OutPutFile)
+ if self._DscTime > OutputTime:
+ NoFileChange = False
+ return NoFileChange
+
def CreateSplitUpdTxt (self, UpdTxtFile):
GuidList = ['FSP_T_UPD_TOOL_GUID','FSP_M_UPD_TOOL_GUID','FSP_S_UPD_TOOL_GUID']
SignatureList = ['0x545F', '0x4D5F','0x535F'] # _T, _M, and _S signature for FSPT, FSPM, FSPS
@@ -823,16 +965,7 @@ EndList
if UpdTxtFile == '':
UpdTxtFile = os.path.join(FvDir, self._MacroDict[GuidList[Index]] + '.txt')
- ReCreate = False
- if not os.path.exists(UpdTxtFile):
- ReCreate = True
- else:
- DscTime = os.path.getmtime(self._DscFile)
- TxtTime = os.path.getmtime(UpdTxtFile)
- if DscTime > TxtTime:
- ReCreate = True
-
- if not ReCreate:
+ if (self.NoDscFileChange (UpdTxtFile)):
# DSC has not been modified yet
# So don't have to re-generate other files
self.Error = 'No DSC file change, skip to create UPD TXT file'
@@ -877,63 +1010,142 @@ EndList
TxtFd.close()
return 0
- def ProcessMultilines (self, String, MaxCharLength):
- Multilines = ''
- StringLength = len(String)
- CurrentStringStart = 0
- StringOffset = 0
- BreakLineDict = []
- if len(String) <= MaxCharLength:
- while (StringOffset < StringLength):
- if StringOffset >= 1:
- if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
- BreakLineDict.append (StringOffset + 1)
- StringOffset += 1
- if BreakLineDict != []:
- for Each in BreakLineDict:
- Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
- CurrentStringStart = Each
- if StringLength - CurrentStringStart > 0:
- Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ def CreateVarDict (self):
+ Error = 0
+ self._VarDict = {}
+ if len(self._CfgItemList) > 0:
+ Item = self._CfgItemList[-1]
+ self._VarDict['_LENGTH_'] = '%d' % (Item['offset'] + Item['length'])
+ for Item in self._CfgItemList:
+ Embed = Item['embed']
+ Match = re.match("^(\w+):(\w+):(START|END)", Embed)
+ if Match:
+ StructName = Match.group(1)
+ VarName = '_%s_%s_' % (Match.group(3), StructName)
+ if Match.group(3) == 'END':
+ self._VarDict[VarName] = Item['offset'] + Item['length']
+ self._VarDict['_LENGTH_%s_' % StructName] = \
+ self._VarDict['_END_%s_' % StructName] - self._VarDict['_START_%s_' % StructName]
+ if Match.group(2).startswith('TAG_'):
+ if (self.Mode != 'FSP') and (self._VarDict['_LENGTH_%s_' % StructName] % 4):
+ raise Exception("Size of structure '%s' is %d, not DWORD aligned !" % (StructName, self._VarDict['_LENGTH_%s_' % StructName]))
+ self._VarDict['_TAG_%s_' % StructName] = int (Match.group(2)[4:], 16) & 0xFFF
else:
- Multilines = " %s\n" % String
+ self._VarDict[VarName] = Item['offset']
+ if Item['marker']:
+ self._VarDict['_OFFSET_%s_' % Item['marker'].strip()] = Item['offset']
+ return Error
+
+ def UpdateBsfBitUnit (self, Item):
+ BitTotal = 0
+ BitOffset = 0
+ StartIdx = 0
+ Unit = None
+ UnitDec = {1:'BYTE', 2:'WORD', 4:'DWORD', 8:'QWORD'}
+ for Idx, SubItem in enumerate(Item['subreg']):
+ if Unit is None:
+ Unit = SubItem['bitunit']
+ BitLength = SubItem['bitlength']
+ BitTotal += BitLength
+ BitOffset += BitLength
+
+ if BitOffset > 64 or BitOffset > Unit * 8:
+ break
+
+ if BitOffset == Unit * 8:
+ for SubIdx in range (StartIdx, Idx + 1):
+ Item['subreg'][SubIdx]['bitunit'] = Unit
+ BitOffset = 0
+ StartIdx = Idx + 1
+ Unit = None
+
+ if BitOffset > 0:
+ raise Exception ("Bit fields cannot fit into %s for '%s.%s' !" % (UnitDec[Unit], Item['cname'], SubItem['cname']))
+
+ ExpectedTotal = Item['length'] * 8
+ if Item['length'] * 8 != BitTotal:
+ raise Exception ("Bit fields total length (%d) does not match length (%d) of '%s' !" % (BitTotal, ExpectedTotal, Item['cname']))
+
+ def UpdateDefaultValue (self):
+ Error = 0
+ for Idx, Item in enumerate(self._CfgItemList):
+ if len(Item['subreg']) == 0:
+ Value = Item['value']
+ if (len(Value) > 0) and (Value[0] == '{' or Value[0] == "'" or Value[0] == '"'):
+ # {XXX} or 'XXX' strings
+ self.FormatListValue(self._CfgItemList[Idx])
+ else:
+ Match = re.match("(0x[0-9a-fA-F]+|[0-9]+)", Value)
+ if not Match:
+ NumValue = self.EvaluateExpress (Value)
+ Item['value'] = '0x%X' % NumValue
+ else:
+ ValArray = self.ValueToByteArray (Item['value'], Item['length'])
+ for SubItem in Item['subreg']:
+ SubItem['value'] = self.GetBsfBitFields(SubItem, ValArray)
+ self.UpdateBsfBitUnit (Item)
+ return Error
+
+ def ProcessMultilines (self, String, MaxCharLength):
+ Multilines = ''
+ StringLength = len(String)
+ CurrentStringStart = 0
+ StringOffset = 0
+ BreakLineDict = []
+ if len(String) <= MaxCharLength:
+ while (StringOffset < StringLength):
+ if StringOffset >= 1:
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
+ BreakLineDict.append (StringOffset + 1)
+ StringOffset += 1
+ if BreakLineDict != []:
+ for Each in BreakLineDict:
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
+ CurrentStringStart = Each
+ if StringLength - CurrentStringStart > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
else:
- NewLineStart = 0
- NewLineCount = 0
- FoundSpaceChar = False
- while (StringOffset < StringLength):
- if StringOffset >= 1:
- if NewLineCount >= MaxCharLength - 1:
- if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
- BreakLineDict.append (NewLineStart + NewLineCount)
- NewLineStart = NewLineStart + NewLineCount
- NewLineCount = 0
- FoundSpaceChar = True
- elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
- BreakLineDict.append (0)
- if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
- BreakLineDict.append (StringOffset + 1)
- NewLineStart = StringOffset + 1
+ Multilines = " %s\n" % String
+ else:
+ NewLineStart = 0
+ NewLineCount = 0
+ FoundSpaceChar = False
+ while (StringOffset < StringLength):
+ if StringOffset >= 1:
+ if NewLineCount >= MaxCharLength - 1:
+ if String[StringOffset] == ' ' and StringLength - StringOffset > 10:
+ BreakLineDict.append (NewLineStart + NewLineCount)
+ NewLineStart = NewLineStart + NewLineCount
NewLineCount = 0
- StringOffset += 1
- NewLineCount += 1
- if BreakLineDict != []:
- BreakLineDict.sort ()
- for Each in BreakLineDict:
- if Each > 0:
- Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
- CurrentStringStart = Each
- if StringLength - CurrentStringStart > 0:
- Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
- return Multilines
-
- def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option):
+ FoundSpaceChar = True
+ elif StringOffset == StringLength - 1 and FoundSpaceChar == False:
+ BreakLineDict.append (0)
+ if String[StringOffset - 1] == '\\' and String[StringOffset] == 'n':
+ BreakLineDict.append (StringOffset + 1)
+ NewLineStart = StringOffset + 1
+ NewLineCount = 0
+ StringOffset += 1
+ NewLineCount += 1
+ if BreakLineDict != []:
+ BreakLineDict.sort ()
+ for Each in BreakLineDict:
+ if Each > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:Each].lstrip()
+ CurrentStringStart = Each
+ if StringLength - CurrentStringStart > 0:
+ Multilines += " %s\n" % String[CurrentStringStart:].lstrip()
+ return Multilines
+
+ def CreateField (self, Item, Name, Length, Offset, Struct, BsfName, Help, Option, BitsLength = None):
PosName = 28
PosComment = 30
NameLine=''
HelpLine=''
OptionLine=''
+ if Length == 0 and Name == 'Dummy':
+ return '\n'
+
IsArray = False
if Length in [1,2,4,8]:
Type = "UINT%d" % (Length * 8)
@@ -981,7 +1193,12 @@ EndList
else:
OffsetStr = '0x%04X' % Offset
- return "\n/** Offset %s%s%s%s**/\n %s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name,)
+ if BitsLength is None:
+ BitsLength = ''
+ else:
+ BitsLength = ' : %d' % BitsLength
+
+ return "\n/** Offset %s%s%s%s**/\n %s%s%s%s;\n" % (OffsetStr, NameLine, HelpLine, OptionLine, Type, ' ' * Space1, Name, BitsLength)
def PostProcessBody (self, TextBody):
NewTextBody = []
@@ -1056,7 +1273,11 @@ EndList
HeaderFile = os.path.join(FvDir, HeaderFileName)
# Check if header needs to be recreated
- ReCreate = False
+ if (self.NoDscFileChange (HeaderFile)):
+ # DSC has not been modified yet
+ # So don't have to re-generate other files
+ self.Error = 'No DSC file change, skip to create UPD header file'
+ return 256
TxtBody = []
for Item in self._CfgItemList:
@@ -1082,6 +1303,7 @@ EndList
UpdStructure = ['FSPT_UPD', 'FSPM_UPD', 'FSPS_UPD']
for Item in self._CfgItemList:
if Item["cname"] == 'Signature' and Item["value"][0:6] in UpdSignature:
+ Item["offset"] = 0 # re-initialize offset to 0 when new UPD structure starting
UpdOffsetTable.append (Item["offset"])
for UpdIdx in range(len(UpdOffsetTable)):
@@ -1175,8 +1397,9 @@ EndList
UpdRegionCheck = ['FSPT', 'FSPM', 'FSPS'] # FSPX_UPD_REGION
UpdConfigCheck = ['FSP_T', 'FSP_M', 'FSP_S'] # FSP_X_CONFIG, FSP_X_TEST_CONFIG, FSP_X_RESTRICTED_CONFIG
UpdSignatureCheck = ['FSPT_UPD_SIGNATURE', 'FSPM_UPD_SIGNATURE', 'FSPS_UPD_SIGNATURE']
- ExcludedSpecificUpd = 'FSPM_ARCH_UPD'
+ ExcludedSpecificUpd = ['FSPT_ARCH_UPD', 'FSPM_ARCH_UPD', 'FSPS_ARCH_UPD']
+ IncLines = []
if InputHeaderFile != '':
if not os.path.exists(InputHeaderFile):
self.Error = "Input header file '%s' does not exist" % InputHeaderFile
@@ -1229,7 +1452,7 @@ EndList
if Match:
StartIndex = Index - 1
Match = re.match("}\s([_A-Z0-9]+);", Line)
- if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd not in Match.group(1)):
+ if Match and (UpdRegionCheck[item] in Match.group(1) or UpdConfigCheck[item] in Match.group(1)) and (ExcludedSpecificUpd[item] not in Match.group(1)):
EndIndex = Index
StructStart.append(StartIndex)
StructEnd.append(EndIndex)
@@ -1381,6 +1604,12 @@ EndList
self.Error = "BSF output file '%s' is invalid" % BsfFile
return 1
+ if (self.NoDscFileChange (BsfFile)):
+ # DSC has not been modified yet
+ # So don't have to re-generate other files
+ self.Error = 'No DSC file change, skip to create UPD BSF file'
+ return 256
+
Error = 0
OptionDict = {}
BsfFd = open(BsfFile, "w")
@@ -1466,7 +1695,7 @@ EndList
def Usage():
- print ("GenCfgOpt Version 0.54")
+ print ("GenCfgOpt Version 0.56")
print ("Usage:")
print (" GenCfgOpt UPDTXT PlatformDscFile BuildFvDir [-D Macros]")
print (" GenCfgOpt HEADER PlatformDscFile BuildFvDir InputHFile [-D Macros]")
@@ -1528,13 +1757,25 @@ def Main():
print ("ERROR: %s !" % (GenCfgOpt.Error))
return Ret
elif sys.argv[1] == "HEADER":
- if GenCfgOpt.CreateHeaderFile(OutFile) != 0:
- print ("ERROR: %s !" % GenCfgOpt.Error)
- return 8
+ Ret = GenCfgOpt.CreateHeaderFile(OutFile)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print ("INFO: %s !" % (GenCfgOpt.Error))
+ else :
+ print ("ERROR: %s !" % (GenCfgOpt.Error))
+ return 8
+ return Ret
elif sys.argv[1] == "GENBSF":
- if GenCfgOpt.GenerateBsfFile(OutFile) != 0:
- print ("ERROR: %s !" % GenCfgOpt.Error)
- return 9
+ Ret = GenCfgOpt.GenerateBsfFile(OutFile)
+ if Ret != 0:
+ # No change is detected
+ if Ret == 256:
+ print ("INFO: %s !" % (GenCfgOpt.Error))
+ else :
+ print ("ERROR: %s !" % (GenCfgOpt.Error))
+ return 9
+ return Ret
else:
if argc < 5:
Usage()
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py
index 3f82a3992d6..adec12eaab7 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/PatchFv.py
@@ -163,7 +163,7 @@ class Symbols:
# If the fvDir is not a directory, then raise an exception
#
if not os.path.isdir(fvDir):
- raise Exception ("'%s' is not a valid directory!" % FvDir)
+ raise Exception ("'%s' is not a valid directory!" % fvDir)
#
# If the Guid.xref is not existing in fvDir, then raise an exception
@@ -361,9 +361,11 @@ class Symbols:
foundModHdr = False
while (rptLine != "" ):
if rptLine[0] != ' ':
- #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958)
- #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178)
- match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine)
+ #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958,Type=PE)
+ match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+),\s*Type=\w+\)", rptLine)
+ if match is None:
+ #DxeIpl (Fixed Flash Address, BaseAddress=0x00fffb4310, EntryPoint=0x00fffb4958)
+ match = re.match("([_a-zA-Z0-9\-]+)\s\(.+BaseAddress=(0x[0-9a-fA-F]+),\s+EntryPoint=(0x[0-9a-fA-F]+)\)", rptLine)
if match is not None:
foundModHdr = True
modName = match.group(1)
@@ -371,6 +373,7 @@ class Symbols:
modName = self.dictGuidNameXref[modName.upper()]
self.dictModBase['%s:BASE' % modName] = int (match.group(2), 16)
self.dictModBase['%s:ENTRY' % modName] = int (match.group(3), 16)
+ #(GUID=86D70125-BAA3-4296-A62F-602BEBBB9081 .textbaseaddress=0x00fffb4398 .databaseaddress=0x00fffb4178)
match = re.match("\(GUID=([A-Z0-9\-]+)\s+\.textbaseaddress=(0x[0-9a-fA-F]+)\s+\.databaseaddress=(0x[0-9a-fA-F]+)\)", rptLine)
if match is not None:
if foundModHdr:
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py
index e23cb675548..fe90f90bedb 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/SplitFspBin.py
@@ -677,8 +677,12 @@ class PeTeImage:
else:
offset = self.Offset + self.DosHdr.e_lfanew
offset += EFI_IMAGE_NT_HEADERS32.OptionalHeader.offset
- offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
- size = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
+ if self.PeHdr.OptionalHeader.PePlusOptHdr.Magic == 0x20b: # PE32+ image
+ offset += EFI_IMAGE_OPTIONAL_HEADER32_PLUS.ImageBase.offset
+ size = EFI_IMAGE_OPTIONAL_HEADER32_PLUS.ImageBase.size
+ else:
+ offset += EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.offset
+ size = EFI_IMAGE_OPTIONAL_HEADER32.ImageBase.size
value = Bytes2Val(fdbin[offset:offset+size]) + delta
fdbin[offset:offset+size] = Val2Bytes(value, size)
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h
new file mode 100644
index 00000000000..cfc89e4860b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspUpd.h
@@ -0,0 +1,16 @@
+#ifndef __FSPUPD_H__
+#define __FSPUPD_H__
+
+#include <FspEas.h>
+
+#pragma pack(1)
+
+#define FSPT_UPD_SIGNATURE 0x545F4450554D4551 /* 'QEMUPD_T' */
+
+#define FSPM_UPD_SIGNATURE 0x4D5F4450554D4551 /* 'QEMUPD_M' */
+
+#define FSPS_UPD_SIGNATURE 0x535F4450554D4551 /* 'QEMUPD_S' */
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h
new file mode 100644
index 00000000000..b88c9be0f92
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspmUpd.h
@@ -0,0 +1,75 @@
+#ifndef __FSPMUPD_H__
+#define __FSPMUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp M Configuration
+**/
+typedef struct {
+
+/** Offset 0x00C8 - Debug Serial Port Base address
+ Debug serial port base address. This option will be used only when the 'Serial Port
+ Debug Device' option is set to 'External Device'. 0x00000000(Default).
+**/
+ UINT32 SerialDebugPortAddress;
+
+/** Offset 0x00CC - Debug Serial Port Type
+ 16550 compatible debug serial port resource type. NONE means no serial port support.
+ 0x02:MMIO(Default).
+ 0:NONE, 1:I/O, 2:MMIO
+**/
+ UINT8 SerialDebugPortType;
+
+/** Offset 0x00CD - Serial Port Debug Device
+ Select active serial port device for debug.For SOC UART devices,'Debug Serial Port
+ Base' options will be ignored. 0x02:SOC UART2(Default).
+ 0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device
+**/
+ UINT8 SerialDebugPortDevice;
+
+/** Offset 0x00CE - Debug Serial Port Stride Size
+ Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).
+ 0:1, 2:4
+**/
+ UINT8 SerialDebugPortStrideSize;
+
+/** Offset 0x00CF
+**/
+ UINT8 UnusedUpdSpace2[1];
+
+/** Offset 0x00D0
+**/
+ UINT8 ReservedFspmUpd[4];
+} FSP_M_CONFIG;
+
+/** Fsp M UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x00A8
+**/
+ FSPM_ARCH_UPD FspmArchUpd;
+
+/** Offset 0x00C8
+**/
+ FSP_M_CONFIG FspmConfig;
+
+/** Offset 0x00D4
+**/
+ UINT8 UnusedUpdSpace3[2];
+
+/** Offset 0x00D6
+**/
+ UINT16 UpdTerminator;
+} FSPM_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h
new file mode 100644
index 00000000000..e859d8274db
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFspsUpd.h
@@ -0,0 +1,69 @@
+#ifndef __FSPSUPD_H__
+#define __FSPSUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp S Configuration
+**/
+typedef struct {
+
+/** Offset 0x0118 - BMP Logo Data Size
+ BMP logo data buffer size. 0x00000000(Default).
+**/
+ UINT32 LogoSize;
+
+/** Offset 0x011C - BMP Logo Data Pointer
+ BMP logo data pointer to a BMP format buffer. 0x00000000(Default).
+**/
+ UINT32 LogoPtr;
+
+/** Offset 0x0120 - Graphics Configuration Data Pointer
+ Graphics configuration data used for initialization. 0x00000000(Default).
+**/
+ UINT32 GraphicsConfigPtr;
+
+/** Offset 0x0124 - PCI GFX Temporary MMIO Base
+ PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).
+**/
+ UINT32 PciTempResourceBase;
+
+/** Offset 0x0128
+**/
+ UINT8 UnusedUpdSpace1[3];
+
+/** Offset 0x012B
+**/
+ UINT8 ReservedFspsUpd;
+} FSP_S_CONFIG;
+
+/** Fsp S UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x00F8
+**/
+ FSPS_ARCH_UPD FspsArchUpd;
+
+/** Offset 0x0118
+**/
+ FSP_S_CONFIG FspsConfig;
+
+/** Offset 0x012C
+**/
+ UINT8 UnusedUpdSpace2[2];
+
+/** Offset 0x012E
+**/
+ UINT16 UpdTerminator;
+} FSPS_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h
new file mode 100644
index 00000000000..979ac324fa6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedFsptUpd.h
@@ -0,0 +1,87 @@
+#ifndef __FSPTUPD_H__
+#define __FSPTUPD_H__
+
+#include <FspUpd.h>
+
+#pragma pack(1)
+
+
+/** Fsp T Common UPD
+**/
+typedef struct {
+
+/** Offset 0x0040
+**/
+ UINT8 Revision;
+
+/** Offset 0x0041
+**/
+ UINT8 Reserved[3];
+
+/** Offset 0x0044
+**/
+ UINT32 MicrocodeRegionBase;
+
+/** Offset 0x0048
+**/
+ UINT32 MicrocodeRegionLength;
+
+/** Offset 0x004C
+**/
+ UINT32 CodeRegionBase;
+
+/** Offset 0x0050
+**/
+ UINT32 CodeRegionLength;
+
+/** Offset 0x0054
+**/
+ UINT8 Reserved1[12];
+} FSPT_COMMON_UPD;
+
+/** Fsp T Configuration
+**/
+typedef struct {
+
+/** Offset 0x0060 - Chicken bytes to test Hex config
+ This option shows how to present option for 4 bytes data
+**/
+ UINT32 ChickenBytes;
+
+/** Offset 0x0064
+**/
+ UINT8 ReservedFsptUpd1[28];
+} FSP_T_CONFIG;
+
+/** Fsp T UPD Configuration
+**/
+typedef struct {
+
+/** Offset 0x0000
+**/
+ FSP_UPD_HEADER FspUpdHeader;
+
+/** Offset 0x0020
+**/
+ FSPT_ARCH_UPD FsptArchUpd;
+
+/** Offset 0x0040
+**/
+ FSPT_COMMON_UPD FsptCommonUpd;
+
+/** Offset 0x0060
+**/
+ FSP_T_CONFIG FsptConfig;
+
+/** Offset 0x0080
+**/
+ UINT8 UnusedUpdSpace0[6];
+
+/** Offset 0x0086
+**/
+ UINT16 UpdTerminator;
+} FSPT_UPD;
+
+#pragma pack()
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
new file mode 100644
index 00000000000..c4a041dcd52
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.bsf
@@ -0,0 +1,88 @@
+GlobalDataDef
+ SKUID = 0, "DEFAULT"
+EndGlobalData
+
+
+StructDef
+
+ Find "QEMUPD_T"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 87 bytes
+ $gQemuFspPkgTokenSpaceGuid_ChickenBytes 4 bytes $_DEFAULT_ = 0x00000000
+
+ Find "QEMUPD_M"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 35 bytes
+ $gQemuFspPkgTokenSpaceGuid_StackBase 4 bytes $_DEFAULT_ = 0x00070000
+ $gQemuFspPkgTokenSpaceGuid_StackSize 4 bytes $_DEFAULT_ = 0x00010000
+ $gQemuFspPkgTokenSpaceGuid_BootLoaderTolumSize 4 bytes $_DEFAULT_ = 0x00000000
+ $gPlatformFspPkgTokenSpaceGuid_Bootmode 4 bytes $_DEFAULT_ = 0x00000000
+ Skip 8 bytes
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortAddress 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortType 1 bytes $_DEFAULT_ = 0x02
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice 1 bytes $_DEFAULT_ = 0x02
+ $gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize 1 bytes $_DEFAULT_ = 0x02
+
+ Find "QEMUPD_S"
+ $gQemuFspPkgTokenSpaceGuid_Revision 1 bytes $_DEFAULT_ = 0x01
+ Skip 55 bytes
+ $gQemuFspPkgTokenSpaceGuid_LogoSize 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_LogoPtr 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_GraphicsConfigPtr 4 bytes $_DEFAULT_ = 0x00000000
+ $gQemuFspPkgTokenSpaceGuid_PciTempResourceBase 4 bytes $_DEFAULT_ = 0x80000000
+
+EndStruct
+
+
+List &EN_DIS
+ Selection 0x1 , "Enabled"
+ Selection 0x0 , "Disabled"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortType
+ Selection 0 , "NONE"
+ Selection 1 , "I/O"
+ Selection 2 , "MMIO"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice
+ Selection 0 , "SOC UART0"
+ Selection 1 , "SOC UART1"
+ Selection 2 , "SOC UART2"
+ Selection 3 , "External Device"
+EndList
+
+List &gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize
+ Selection 0 , "1"
+ Selection 2 , "4"
+EndList
+
+BeginInfoBlock
+ PPVer "0.1"
+ Description "QEMU Platform"
+EndInfoBlock
+
+Page "FSP T"
+ EditNum $gQemuFspPkgTokenSpaceGuid_ChickenBytes, "Chicken bytes to test Hex config", HEX,
+ Help "This option shows how to present option for 4 bytes data"
+ "Valid range: 0x00000000 ~ 0xFFFFFFFF"
+EndPage
+
+Page "FSP MemoryInit Settings"
+ EditNum $gQemuFspPkgTokenSpaceGuid_SerialDebugPortAddress, "Debug Serial Port Base address", HEX,
+ Help "Debug serial port base address. This option will be used only when the 'Serial Port Debug Device' option is set to 'External Device'. 0x00000000(Default)."
+ "Valid range: 0x00000000 ~ 0xFFFFFFFF"
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortType, "Debug Serial Port Type", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortType,
+ Help "16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default)."
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice, "Serial Port Debug Device", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortDevice,
+ Help "Select active serial port device for debug.For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default)."
+ Combo $gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize, "Debug Serial Port Stride Size", &gQemuFspPkgTokenSpaceGuid_SerialDebugPortStrideSize,
+ Help "Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default)."
+EndPage
+
+Page "FSP SiliconInit Settings"
+ EditNum $gQemuFspPkgTokenSpaceGuid_PciTempResourceBase, "PCI GFX Temporary MMIO Base", HEX,
+ Help "PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default)."
+ "Valid range: 0x80000000 ~ 0xDFFFFFFF"
+EndPage
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml
new file mode 100644
index 00000000000..db0513f93f4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/ExpectedOutput.yaml
@@ -0,0 +1,267 @@
+variable:
+ PLATFORM_NAME : QemuFspPkg
+ PLATFORM_GUID : 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ PLATFORM_VERSION : 0.1
+ DSC_SPECIFICATION : 0x00010005
+ OUTPUT_DIRECTORY : Build/QemuFspPkg
+ SUPPORTED_ARCHITECTURES : IA32|X64
+ BUILD_TARGETS : DEBUG|RELEASE
+ SKUID_IDENTIFIER : DEFAULT
+ FLASH_DEFINITION : QemuFspPkg/QemuFspPkg.fdf
+ FSP_T_UPD_TOOL_GUID : 34686CA3-34F9-4901-B82A-BA630F0714C6
+ FSP_V_UPD_TOOL_GUID : 4E2F4725-734A-4399-BAF5-B4E16348EB2F
+ FSP_M_UPD_TOOL_GUID : 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ FSP_S_UPD_TOOL_GUID : CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ FSP_T_UPD_FFS_GUID : 70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA
+ FSP_V_UPD_FFS_GUID : 0197EF5E-2FFC-4089-8E55-F70400B18146
+ FSP_M_UPD_FFS_GUID : D5B86AEA-6AF7-40D4-8014-982301BC3D89
+ FSP_S_UPD_FFS_GUID : E3CD9B18-998C-4F76-B65E-98B154E5446F
+ FSP_PACKAGE : QemuFspPkg
+ FSP_IMAGE_ID : 0x245053464D455124 # $QEMFSP$
+ FSP_IMAGE_REV : 0x00001010
+ CAR_BASE_ADDRESS : 0x00000000
+ CAR_REGION_SIZE : 0x00080000
+ CAR_BLD_REGION_SIZE : 0x00070000
+ CAR_FSP_REGION_SIZE : 0x00010000
+ FSP_ARCH : X64
+
+
+template:
+
+
+configs:
+ - $ACTION :
+ page : TMP::"FSP T", MEM::"FSP MemoryInit Settings", SIL::"FSP SiliconInit Settings"
+ - $ACTION :
+ find : QEMUPD_T
+ - FSPT_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x545F4450554D4551
+ - Revision :
+ name : FsptUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPT_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - Length :
+ length : 0x04
+ value : 0x00000020
+ - FspDebugHandler :
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x14
+ value : {0x00}
+ - FSPT_COMMON_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - MicrocodeRegionBase :
+ length : 0x04
+ value : 0x00000000
+ - MicrocodeRegionLength :
+ length : 0x04
+ value : 0x00000000
+ - CodeRegionBase :
+ length : 0x04
+ value : 0x00000000
+ - CodeRegionLength :
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x0C
+ value : {0x00}
+ - FSP_T_CONFIG :
+ - $ACTION :
+ page : TMP
+ - ChickenBytes :
+ name : Chicken bytes to test Hex config
+ type : EditNum, HEX, (0x00000000,0xFFFFFFFF)
+ help : >
+ This option shows how to present option for 4 bytes data
+ length : 0x04
+ value : 0x00000000
+ - ReservedFsptUpd1 :
+ length : 0x1C
+ value : {0x00}
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
+ - $ACTION :
+ find : QEMUPD_M
+ - FSPM_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x4D5F4450554D4551
+ - Revision :
+ name : FspmUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPM_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - NvsBufferPtr :
+ struct : VOID*
+ length : 0x04
+ value : 0x00000000
+ - StackBase :
+ struct : VOID*
+ name : StackBase
+ help : >
+ Stack base for FSP use. Default- 0xFEF16000
+ length : 0x04
+ value : $(CAR_BLD_REGION_SIZE)
+ - StackSize :
+ name : StackSize
+ help : >
+ To pass the stack size for FSP use. Bootloader can programmatically get the FSP requested StackSize by using the defaults in the FSP-M component. This is the minimum stack size expected by this revision of FSP. Default- 0x2A000
+ length : 0x04
+ value : $(CAR_FSP_REGION_SIZE)
+ - BootLoaderTolumSize :
+ name : BootLoaderTolumSize
+ help : >
+ To pass Bootloader Tolum size.
+ length : 0x04
+ value : 0x00000000
+ - Bootmode :
+ name : Bootmode
+ help : >
+ To maintain Bootmode details.
+ length : 0x04
+ value : 0x00000000
+ - Reserved1 :
+ length : 0x08
+ value : {0x00}
+ - FSP_M_CONFIG :
+ - $ACTION :
+ page : MEM
+ - SerialDebugPortAddress :
+ name : Debug Serial Port Base address
+ type : EditNum, HEX, (0x00000000,0xFFFFFFFF)
+ help : >
+ Debug serial port base address. This option will be used only when the 'Serial Port Debug Device'
+ option is set to 'External Device'. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - SerialDebugPortType :
+ name : Debug Serial Port Type
+ type : Combo
+ option : 0:NONE, 1:I/O, 2:MMIO
+ help : >
+ 16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default).
+ length : 0x01
+ value : 0x02
+ - SerialDebugPortDevice :
+ name : Serial Port Debug Device
+ type : Combo
+ option : 0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device
+ help : >
+ Select active serial port device for debug.
+ For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default).
+ length : 0x01
+ value : 0x02
+ - SerialDebugPortStrideSize :
+ name : Debug Serial Port Stride Size
+ type : Combo
+ option : 0:1, 2:4
+ help : >
+ Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).
+ length : 0x01
+ value : 0x02
+ - ReservedFspmUpd :
+ length : 0x04
+ value : {0x00}
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
+ - $ACTION :
+ find : QEMUPD_S
+ - FSPS_UPD :
+ - FSP_UPD_HEADER :
+ - Signature :
+ length : 0x08
+ value : 0x535F4450554D4551
+ - Revision :
+ name : FspsUpdRevision
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x17
+ value : {0x00}
+ - FSPS_ARCH_UPD :
+ - Revision :
+ length : 0x01
+ value : 0x01
+ - Reserved :
+ length : 0x03
+ value : {0x00}
+ - Length :
+ length : 0x04
+ value : 0x00000020
+ - FspEventHandler :
+ length : 0x04
+ value : 0x00000000
+ - EnableMultiPhaseSiliconInit :
+ length : 0x01
+ value : 0x00
+ - Reserved1 :
+ length : 0x13
+ value : {0x00}
+ - FSP_S_CONFIG :
+ - $ACTION :
+ page : SIL
+ - LogoSize :
+ name : BMP Logo Data Size
+ type : Reserved
+ help : >
+ BMP logo data buffer size. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - LogoPtr :
+ name : BMP Logo Data Pointer
+ type : Reserved
+ help : >
+ BMP logo data pointer to a BMP format buffer. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - GraphicsConfigPtr :
+ name : Graphics Configuration Data Pointer
+ type : Reserved
+ help : >
+ Graphics configuration data used for initialization. 0x00000000(Default).
+ length : 0x04
+ value : 0x00000000
+ - PciTempResourceBase :
+ name : PCI GFX Temporary MMIO Base
+ type : EditNum, HEX, (0x80000000,0xDFFFFFFF)
+ help : >
+ PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).
+ length : 0x04
+ value : 0x80000000
+ - ReservedFspsUpd :
+ length : 0x01
+ value : 0x00
+ - UpdTerminator :
+ length : 0x02
+ value : 0x55AA
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
new file mode 100644
index 00000000000..25d517838b4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/QemuFspPkg.dsc
@@ -0,0 +1,471 @@
+## @file
+# FSP DSC build file for QEMU platform
+#
+# Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = QemuFspPkg
+ PLATFORM_GUID = 1BEDB57A-7904-406e-8486-C89FC7FB39EE
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/QemuFspPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = QemuFspPkg/QemuFspPkg.fdf
+
+ #
+ # UPD tool definition
+ #
+ FSP_T_UPD_TOOL_GUID = 34686CA3-34F9-4901-B82A-BA630F0714C6
+ FSP_V_UPD_TOOL_GUID = 4E2F4725-734A-4399-BAF5-B4E16348EB2F
+ FSP_M_UPD_TOOL_GUID = 39A250DB-E465-4DD1-A2AC-E2BD3C0E2385
+ FSP_S_UPD_TOOL_GUID = CAE3605B-5B34-4C85-B3D7-27D54273C40F
+ FSP_T_UPD_FFS_GUID = 70BCF6A5-FFB1-47D8-B1AE-EFE5508E23EA
+ FSP_V_UPD_FFS_GUID = 0197EF5E-2FFC-4089-8E55-F70400B18146
+ FSP_M_UPD_FFS_GUID = D5B86AEA-6AF7-40D4-8014-982301BC3D89
+ FSP_S_UPD_FFS_GUID = E3CD9B18-998C-4F76-B65E-98B154E5446F
+
+ #
+ # Set platform specific package/folder name, same as passed from PREBUILD script.
+ # PLATFORM_PACKAGE would be the same as PLATFORM_NAME as well as package build folder
+ # DEFINE only takes effect at R9 DSC and FDF.
+ #
+ DEFINE FSP_PACKAGE = QemuFspPkg
+ DEFINE FSP_IMAGE_ID = 0x245053464D455124 # $QEMFSP$
+ DEFINE FSP_IMAGE_REV = 0x00001010
+
+ DEFINE CAR_BASE_ADDRESS = 0x00000000
+ DEFINE CAR_REGION_SIZE = 0x00080000
+ DEFINE CAR_BLD_REGION_SIZE = 0x00070000
+ DEFINE CAR_FSP_REGION_SIZE = 0x00010000
+
+ DEFINE FSP_ARCH = X64
+
+################################################################################
+#
+# SKU Identification section - list of all SKU IDs supported by this
+# Platform.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT # The entry: 0|DEFAULT is reserved and always required.
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ CacheLib|IntelFsp2Pkg/Library/BaseCacheLib/BaseCacheLib.inf
+ CacheAsRamLib|IntelFsp2Pkg/Library/BaseCacheAsRamLibNull/BaseCacheAsRamLibNull.inf
+ FspSwitchStackLib|IntelFsp2Pkg/Library/BaseFspSwitchStackLib/BaseFspSwitchStackLib.inf
+ FspCommonLib|IntelFsp2Pkg/Library/BaseFspCommonLib/BaseFspCommonLib.inf
+ FspPlatformLib|IntelFsp2Pkg/Library/BaseFspPlatformLib/BaseFspPlatformLib.inf
+ PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+!if $(TARGET) == DEBUG
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+ SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
+!else
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
+!endif
+
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot | TRUE
+ gQemuFspPkgTokenSpaceGuid.PcdFspHeaderRevision | 0x03
+ gQemuFspPkgTokenSpaceGuid.PcdFspImageIdString | $(FSP_IMAGE_ID)
+ gQemuFspPkgTokenSpaceGuid.PcdFspImageRevision | $(FSP_IMAGE_REV)
+ #
+ # FSP CAR Usages (BL RAM | FSP RAM | FSP CODE)
+ #
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamBase | $(CAR_BASE_ADDRESS)
+ gIntelFsp2PkgTokenSpaceGuid.PcdTemporaryRamSize | $(CAR_REGION_SIZE)
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspTemporaryRamSize | $(CAR_FSP_REGION_SIZE)
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedBufferSize | 0x0100
+
+ # This defines how much space will be used for heap in FSP temporary memory
+ # x % of FSP temporary memory will be used for heap
+ # (100 - x) % of FSP temporary memory will be used for stack
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspHeapSizePercentage | 65
+
+ # This is a platform specific global pointer used by FSP
+ gIntelFsp2PkgTokenSpaceGuid.PcdGlobalDataPointerAddress | 0xFED00148
+ gIntelFsp2PkgTokenSpaceGuid.PcdFspReservedMemoryLength | 0x00100000
+
+!if $(TARGET) == RELEASE
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel | 0x00000000
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdFixedDebugPrintErrorLevel | 0x80000047
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0x27
+!endif
+
+[PcdsPatchableInModule]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress | 0xE0000000
+ #
+ # This entry will be patched during the build process
+ #
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress | 0x12345678
+
+!if $(TARGET) == RELEASE
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0x80000047
+!endif
+
+[PcdsDynamicVpd.Upd]
+ #
+ # This section is not used by the normal build process
+ # However, FSP will use dedicated tool to handle it and generate a
+ # VPD similar binary block (User Configuration Data). This block will
+ # be accessed through a generated data structure directly rather than
+ # PCD services. This is for size consideration.
+ # Format:
+ # gQemuFspPkgTokenSpaceGuid.Updxxxxxxxxxxxxn | OFFSET | LENGTH | VALUE
+ # Only simple data type is supported
+ #
+
+ #
+ # Comments with !BSF will be used to generate BSF file
+ # Comments with !HDR will be used to generate H header file
+ #
+
+ # Global definitions in BSF
+ # !BSF PAGES:{TMP:"FSP T", MEM:"FSP MemoryInit Settings", SIL:"FSP SiliconInit Settings"}
+ # !BSF BLOCK:{NAME:"QEMU Platform", VER:"0.1"}
+
+ # !BSF FIND:{QEMUPD_T}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FsptUpdSignature: {QEMUPD_T}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x545F4450554D4551
+ # !BSF NAME:{FsptUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPT_ARCH_UPD:FSPT_ARCH_UPD}
+ # !HDR EMBED:{FSPT_ARCH_UPD:FsptArchUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+ gQemuFspPkgTokenSpaceGuid.Length | * | 0x04 | 0x00000020
+ gQemuFspPkgTokenSpaceGuid.FspDebugHandler | * | 0x04 | 0x00000000
+ # !HDR EMBED:{FSPT_ARCH_UPD:FsptArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x14 | {0x00}
+
+ # !HDR COMMENT:{FSPT_COMMON_UPD:Fsp T Common UPD}
+ # !HDR EMBED:{FSPT_COMMON_UPD:FsptCommonUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+
+ # Base address of the microcode region.
+ gQemuFspPkgTokenSpaceGuid.MicrocodeRegionBase | * | 0x04 | 0x00000000
+
+ # Length of the microcode region.
+ gQemuFspPkgTokenSpaceGuid.MicrocodeRegionLength | * | 0x04 | 0x00000000
+
+ # Base address of the cacheable flash region.
+ gQemuFspPkgTokenSpaceGuid.CodeRegionBase | * | 0x04 | 0x00000000
+
+ # Length of the cacheable flash region.
+ gQemuFspPkgTokenSpaceGuid.CodeRegionLength | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSPT_COMMON_UPD:FsptCommonUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x0C | {0x00}
+
+ # !HDR COMMENT:{FSP_T_CONFIG:Fsp T Configuration}
+ # !HDR EMBED:{FSP_T_CONFIG:FsptConfig:START}
+ # !BSF PAGE:{TMP}
+ # !BSF NAME:{Chicken bytes to test Hex config}
+ # !BSF TYPE:{EditNum, HEX, (0x00000000,0xFFFFFFFF)}
+ # !BSF HELP:{This option shows how to present option for 4 bytes data}
+ gQemuFspPkgTokenSpaceGuid.ChickenBytes | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSP_T_CONFIG:FsptConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFsptUpd1 | * | 0x1C | {0x00}
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+ ################################################################################
+ #
+ # UPDs consumed in FspMemoryInit Api
+ #
+ ################################################################################
+ # !BSF FIND:{QEMUPD_M}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FspmUpdSignature: {QEMUPD_M}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x4D5F4450554D4551
+ # !BSF NAME:{FspmUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPM_ARCH_UPD:Fsp M Architectural UPD}
+ # !HDR EMBED:{FSPM_ARCH_UPD:FspmArchUpd:START}
+
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+
+ # !HDR STRUCT:{VOID*}
+ gQemuFspPkgTokenSpaceGuid.NvsBufferPtr | * | 0x04 | 0x00000000
+
+ # !HDR STRUCT:{VOID*}
+ # !BSF NAME:{StackBase}
+ # !BSF HELP:{Stack base for FSP use. Default: 0xFEF16000}
+ gQemuFspPkgTokenSpaceGuid.StackBase | * | 0x04 | $(CAR_BLD_REGION_SIZE)
+
+ # !BSF NAME:{StackSize}
+ # !BSF HELP:{To pass the stack size for FSP use. Bootloader can programmatically get the FSP requested StackSize by using the defaults in the FSP-M component. This is the minimum stack size expected by this revision of FSP. Default: 0x2A000}
+ gQemuFspPkgTokenSpaceGuid.StackSize | * | 0x04 | $(CAR_FSP_REGION_SIZE)
+
+ # !BSF NAME:{BootLoaderTolumSize}
+ # !BSF HELP:{To pass Bootloader Tolum size.}
+ gQemuFspPkgTokenSpaceGuid.BootLoaderTolumSize | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Bootmode}
+ # !BSF HELP:{To maintain Bootmode details.}
+ gPlatformFspPkgTokenSpaceGuid.Bootmode | * | 0x04 | 0x00000000
+
+ # !HDR EMBED:{FSPM_ARCH_UPD:FspmArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x08 | {0x00}
+
+ # !HDR COMMENT:{FSP_M_CONFIG:Fsp M Configuration}
+ # !HDR EMBED:{FSP_M_CONFIG:FspmConfig:START}
+ # !BSF PAGE:{MEM}
+ # !BSF NAME:{Debug Serial Port Base address}
+ # !BSF TYPE:{EditNum, HEX, (0x00000000,0xFFFFFFFF)}
+ # !BSF HELP:{Debug serial port base address. This option will be used only when the 'Serial Port Debug Device'}
+ # !BSF HELP:{+ option is set to 'External Device'. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortAddress | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Debug Serial Port Type} TYPE:{Combo}
+ # !BSF OPTION:{0:NONE, 1:I/O, 2:MMIO}
+ # !BSF HELP:{16550 compatible debug serial port resource type. NONE means no serial port support. 0x02:MMIO(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortType | * | 0x01 | 0x02
+
+ # !BSF NAME:{Serial Port Debug Device} TYPE:{Combo}
+ # !BSF OPTION:{0:SOC UART0, 1:SOC UART1, 2:SOC UART2, 3:External Device}
+ # !BSF HELP:{Select active serial port device for debug.}
+ # !BSF HELP:{+For SOC UART devices,'Debug Serial Port Base' options will be ignored. 0x02:SOC UART2(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortDevice | * | 0x01 | 0x02
+
+ # !BSF NAME:{Debug Serial Port Stride Size} TYPE:{Combo}
+ # !BSF OPTION:{0:1, 2:4}
+ # !BSF HELP:{Debug serial port register map stride size in bytes. 0x00:1, 0x02:4(Default).}
+ gQemuFspPkgTokenSpaceGuid.SerialDebugPortStrideSize | * | 0x01 | 0x02
+
+
+ # !HDR EMBED:{FSP_M_CONFIG:FspmConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFspmUpd | * | 0x04 | {0x00}
+
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+ ################################################################################
+ #
+ # UPDs consumed in FspSiliconInit Api
+ #
+ ################################################################################
+ # !BSF FIND:{QEMUPD_S}
+ # !HDR COMMENT:{FSP_UPD_HEADER:FSP UPD Header}
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:START}
+ # FspsUpdSignature: {QEMUPD_S}
+ gQemuFspPkgTokenSpaceGuid.Signature | * | 0x08 | 0x535F4450554D4551
+ # !BSF NAME:{FspsUpdRevision}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ # !HDR EMBED:{FSP_UPD_HEADER:FspUpdHeader:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x17 | {0x00}
+
+ # !HDR COMMENT:{FSPS_ARCH_UPD:FSPS_ARCH_UPD}
+ # !HDR EMBED:{FSPS_ARCH_UPD:FspsArchUpd:START}
+ gQemuFspPkgTokenSpaceGuid.Revision | * | 0x01 | 0x01
+ gQemuFspPkgTokenSpaceGuid.Reserved | * | 0x03 | {0x00}
+ gQemuFspPkgTokenSpaceGuid.Length | * | 0x04 | 0x00000020
+ gQemuFspPkgTokenSpaceGuid.FspEventHandler | * | 0x04 | 0x00000000
+ gQemuFspPkgTokenSpaceGuid.EnableMultiPhaseSiliconInit | * | 0x01 | 0x00
+ # !HDR EMBED:{FSPS_ARCH_UPD:FspsArchUpd:END}
+ gQemuFspPkgTokenSpaceGuid.Reserved1 | * | 0x13 | {0x00}
+
+ # !HDR COMMENT:{FSP_S_CONFIG:Fsp S Configuration}
+ # !HDR EMBED:{FSP_S_CONFIG:FspsConfig:START}
+ # !BSF PAGE:{SIL}
+
+ # !BSF NAME:{BMP Logo Data Size}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{BMP logo data buffer size. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.LogoSize | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{BMP Logo Data Pointer}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{BMP logo data pointer to a BMP format buffer. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.LogoPtr | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{Graphics Configuration Data Pointer}
+ # !BSF TYPE:{Reserved}
+ # !BSF HELP:{Graphics configuration data used for initialization. 0x00000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.GraphicsConfigPtr | * | 0x04 | 0x00000000
+
+ # !BSF NAME:{PCI GFX Temporary MMIO Base}
+ # !BSF TYPE:{EditNum, HEX, (0x80000000,0xDFFFFFFF)}
+ # !BSF HELP:{PCI Temporary PCI GFX Base used before full PCI enumeration. 0x80000000(Default).}
+ gQemuFspPkgTokenSpaceGuid.PciTempResourceBase | * | 0x04 | 0x80000000
+
+ # !HDR EMBED:{FSP_S_CONFIG:FspsConfig:END}
+ gQemuFspPkgTokenSpaceGuid.ReservedFspsUpd | * | 0x01 | 0x00
+
+ # Note please keep "UpdTerminator" at the end of each UPD region.
+ # The tool will use this field to determine the actual end of the UPD data
+ # structure.
+ gQemuFspPkgTokenSpaceGuid.UpdTerminator | * | 0x02 | 0x55AA
+
+###################################################################################################
+#
+# Components Section - list of the modules and components that will be processed by compilation
+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.
+#
+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed
+# into firmware volume images. This section is just a list of modules to compile from
+# source into UEFI-compliant binaries.
+# It is the FDF file that contains information on combining binary files into firmware
+# volume images, whose concept is beyond UEFI and is described in PI specification.
+# Binary modules do not need to be listed in this section, as they should be
+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),
+# Logo (Logo.bmp), and etc.
+# There may also be modules listed in this section that are not required in the FDF file,
+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be
+# generated for it, but the binary will not be put into any firmware volume.
+#
+###################################################################################################
+[Components.IA32]
+ #
+ # FSP Binary Components
+ #
+ $(FSP_PACKAGE)/FspHeader/FspHeader.inf
+
+ #
+ # SEC
+ #
+ IntelFsp2Pkg/FspSecCore/FspSecCoreT.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecTLib.inf
+ }
+
+[Components.$(FSP_ARCH)]
+ IntelFsp2Pkg/FspSecCore/FspSecCoreV.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecVLib.inf
+ }
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreM.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecMLib.inf
+ }
+
+ IntelFsp2Pkg/FspSecCore/FspSecCoreS.inf {
+ <LibraryClasses>
+ FspSecPlatformLib|$(FSP_PACKAGE)/Library/PlatformSecLib/Vtf0PlatformSecSLib.inf
+ }
+
+ #
+ # PEI Core
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+
+ #
+ # PCD
+ #
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ $(FSP_PACKAGE)/FspvInit/FspvInit.inf
+ $(FSP_PACKAGE)/FspmInit/FspmInit.inf
+ $(FSP_PACKAGE)/FspsInit/FspsInit.inf
+ $(FSP_PACKAGE)/QemuVideo/QemuVideo.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+ <LibraryClasses>
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
+ }
+ IntelFsp2Pkg/FspNotifyPhase/FspNotifyPhasePeim.inf
+
+###################################################################################################
+#
+# BuildOptions Section - Define the module specific tool chain flags that should be used as
+# the default flags for a module. These flags are appended to any
+# standard flags that are defined by the build process. They can be
+# applied for any modules or only those modules with the specific
+# module style (EDK or EDKII) specified in [Components] section.
+#
+###################################################################################################
+[BuildOptions]
+# Append build options for EDK and EDKII drivers (= is Append, == is Replace)
+ # Enable link-time optimization when building with GCC49
+ *_GCC49_IA32_CC_FLAGS = -flto
+ *_GCC49_IA32_DLINK_FLAGS = -flto
+ *_GCC5_IA32_CC_FLAGS = -fno-pic
+ *_GCC5_IA32_DLINK_FLAGS = -no-pie
+ *_GCC5_IA32_ASLCC_FLAGS = -fno-pic
+ *_GCC5_IA32_ASLDLINK_FLAGS = -no-pie
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py
new file mode 100644
index 00000000000..a71073ba6d5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py
@@ -0,0 +1,96 @@
+# @file
+# Split a file into two pieces at the request offset.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+# Import Modules
+import unittest
+import tempfile
+import os
+import shutil
+import struct as st
+import filecmp
+
+import os, sys
+currentdir = os.path.dirname(os.path.realpath(__file__))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+import FspDscBsf2Yaml
+
+YamlHeaderLineLength = 10
+HdrFileHeaderLineLength = 32
+BsfFileHeaderLineLength = 19
+
+def GenFileWithoutHdr(inputfile, numLineToStrip):
+ yaml_file = open(inputfile, "r")
+ lines = yaml_file.readlines()
+ yaml_file.close()
+ del lines[:numLineToStrip]
+
+ noHdrOutputFileName = "no-header-" + inputfile
+ stripped_file = open(noHdrOutputFileName, "w")
+ for line in lines:
+ stripped_file.write(line)
+ stripped_file.close()
+ return noHdrOutputFileName
+
+class TestFspScripts(unittest.TestCase):
+ def test_generateFspHeader_fromDsc(self):
+ # Generate HEADER
+ cmd = '{} {} HEADER {} {} {}'.format(
+ 'python',
+ '..\GenCfgOpt.py',
+ 'QemuFspPkg.dsc',
+ '.',
+ "")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("FspUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspUpd.h'))
+
+ def test_generateFspsHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FspsUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspsUpd.h'))
+
+ def test_generateFsptHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FsptUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFsptUpd.h'))
+
+ def test_generateFspmHeader_fromDsc(self):
+ noHdrOutputFileName = GenFileWithoutHdr("FspmUpd.h", HdrFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedFspmUpd.h'))
+
+ def test_generateBsf_fromDsc(self):
+ # Generate BSF
+ cmd = '{} {} GENBSF {} {} {}'.format(
+ 'python',
+ '..\GenCfgOpt.py',
+ 'QemuFspPkg.dsc',
+ '.',
+ "Output.bsf")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("Output.bsf", BsfFileHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedOutput.bsf'))
+
+ def test_generateYaml_fromDsc(self):
+ # Generate YAML
+ cmd = '{} {} {} {}'.format(
+ 'python',
+ '..\FspDscBsf2Yaml.py',
+ 'QemuFspPkg.dsc',
+ "Output.yaml")
+ os.system(cmd)
+ noHdrOutputFileName = GenFileWithoutHdr("Output.yaml", YamlHeaderLineLength)
+ self.assertTrue(filecmp.cmp(noHdrOutputFileName,
+ 'ExpectedOutput.yaml'))
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md
new file mode 100644
index 00000000000..e739ffc25e2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/UserManuals/FspDscBsf2YamlUserManual.md
@@ -0,0 +1,39 @@
+#Name
+**FspDscBsf2Yaml.py** The python script that generates YAML file for
+the Boot Settings from an EDK II Platform Description (**DSC**) file
+or from a Boot Settings File (**BSF**). It is created to help
+transitioning FSP Updateable Product Data (**UPD**) file format to
+new standardized YAML format so that it can be configured through
+open source tools.
+
+#Synopsis
+```
+FspDscBsf2Yaml DscFile|BsfFile YamlFile
+```
+
+#Description
+**FspDscBsf2Yaml.py** is a script that generates configuration options from an
+**EDK II Platform Description (DSC)** file or **a Boot Settings File (BSF)** file.
+
+It generates a **YAML file** that can be used by the **Config Editor** to provide
+a graphical user interface for manipulating settings in the UPD regions.
+
+The following sections explain the usage of this script.
+
+## 1. FspDscBsf2Yaml.py DscFile YamlFile
+
+The **DscFile** option is an input DSC file.
+
+The **YamlFile** option is an output YAML file.
+
+The script takes the FSP DSC file consisting BSF syntax and generates a YAML
+output file describing the boot settings.
+
+## 2. FspDscBsf2Yaml.py BsfFile YamlFile
+
+The **BsfFile** option is an input BSF file.
+
+The **YamlFile** option is an output YAML file.
+
+The script generates a YAML output file from a BSF file. The BSF file
+can be generated using GenCfgOpt tool.
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
index b1998aaa998..43f2f656a91 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.c
@@ -3,7 +3,7 @@
register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
notify to call FspSiliconInit API.
- Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -25,11 +25,14 @@
#include <Library/FspWrapperPlatformLib.h>
#include <Library/FspWrapperHobProcessLib.h>
#include <Library/FspWrapperApiLib.h>
+#include <Library/FspMeasurementLib.h>
#include <Ppi/FspSiliconInitDone.h>
#include <Ppi/EndOfPeiPhase.h>
#include <Ppi/MemoryDiscovered.h>
#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/Tcg.h>
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
#include <Library/FspWrapperApiTestLib.h>
#include <FspEas.h>
#include <FspStatusCode.h>
@@ -147,7 +150,21 @@ FspmWrapperInit (
VOID
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
+ EFI_PEI_PPI_DESCRIPTOR *MeasurementExcludedPpiList;
+
+ MeasurementExcludedFvPpi = AllocatePool (sizeof(*MeasurementExcludedFvPpi));
+ ASSERT(MeasurementExcludedFvPpi != NULL);
+ MeasurementExcludedFvPpi->Count = 1;
+ MeasurementExcludedFvPpi->Fv[0].FvBase = PcdGet32 (PcdFspmBaseAddress);
+ MeasurementExcludedFvPpi->Fv[0].FvLength = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFspmBaseAddress))->FvLength;
+
+ MeasurementExcludedPpiList = AllocatePool (sizeof(*MeasurementExcludedPpiList));
+ ASSERT(MeasurementExcludedPpiList != NULL);
+ MeasurementExcludedPpiList->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ MeasurementExcludedPpiList->Guid = &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid;
+ MeasurementExcludedPpiList->Ppi = MeasurementExcludedFvPpi;
Status = EFI_SUCCESS;
@@ -155,6 +172,9 @@ FspmWrapperInit (
Status = PeiFspMemoryInit ();
ASSERT_EFI_ERROR (Status);
} else {
+ Status = PeiServicesInstallPpi (MeasurementExcludedPpiList);
+ ASSERT_EFI_ERROR (Status);
+
PeiServicesInstallFvInfoPpi (
NULL,
(VOID *)(UINTN) PcdGet32 (PcdFspmBaseAddress),
@@ -168,6 +188,67 @@ FspmWrapperInit (
}
/**
+ This function is called after TCG installed PPI.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TcgPpiNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mTcgPpiNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiTcgPpiGuid,
+ TcgPpiNotify
+};
+
+/**
+ This function is called after TCG installed PPI.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TcgPpiNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ )
+{
+ UINT32 FspMeasureMask;
+
+ DEBUG ((DEBUG_INFO, "TcgPpiNotify FSPM\n"));
+
+ FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);
+
+ if ((FspMeasureMask & FSP_MEASURE_FSPT) != 0) {
+ MeasureFspFirmwareBlob (0, "FSPT", PcdGet32(PcdFsptBaseAddress),
+ (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFsptBaseAddress))->FvLength);
+ }
+
+ if ((FspMeasureMask & FSP_MEASURE_FSPM) != 0) {
+ MeasureFspFirmwareBlob (0, "FSPM", PcdGet32(PcdFspmBaseAddress),
+ (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFspmBaseAddress))->FvLength);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
This is the entrypoint of PEIM
@param[in] FileHandle Handle of the file being invoked.
@@ -182,8 +263,13 @@ FspmWrapperPeimEntryPoint (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
+ EFI_STATUS Status;
+
DEBUG((DEBUG_INFO, "FspmWrapperPeimEntryPoint\n"));
+ Status = PeiServicesNotifyPpi (&mTcgPpiNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
+
FspmWrapperInit ();
return EFI_SUCCESS;
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
index e8211f0d805..c1bd297e7d2 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
@@ -6,7 +6,7 @@
# register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
# notify to call FspSiliconInit API.
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -44,17 +44,22 @@
TimerLib
FspWrapperApiLib
FspWrapperApiTestLib
+ FspMeasurementLib
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
+ SecurityPkg/SecurityPkg.dec
IntelFsp2Pkg/IntelFsp2Pkg.dec
IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
[Pcd]
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress ## CONSUMES
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmUpdDataAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFsptBaseAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig ## CONSUMES
[Sources]
FspmWrapperPeim.c
@@ -63,5 +68,9 @@
gFspHobGuid ## PRODUCES ## HOB
gFspApiPerformanceGuid ## SOMETIMES_CONSUMES ## GUID
+[Ppis]
+ gEdkiiTcgPpiGuid ## NOTIFY
+ gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid ## PRODUCES
+
[Depex]
gEfiPeiMasterBootModePpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
index 4bec2977eed..aa5b7f77c7f 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.c
@@ -3,7 +3,7 @@
register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
notify to call FspSiliconInit API.
- Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -24,12 +24,15 @@
#include <Library/TimerLib.h>
#include <Library/PerformanceLib.h>
#include <Library/FspWrapperApiLib.h>
+#include <Library/FspMeasurementLib.h>
#include <Ppi/FspSiliconInitDone.h>
#include <Ppi/EndOfPeiPhase.h>
#include <Ppi/MemoryDiscovered.h>
#include <Ppi/TemporaryRamDone.h>
#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/Tcg.h>
+#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
#include <Library/FspWrapperApiTestLib.h>
#include <FspEas.h>
#include <FspStatusCode.h>
@@ -379,7 +382,25 @@ FspsWrapperInitDispatchMode (
VOID
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_PEI_FIRMWARE_VOLUME_INFO_MEASUREMENT_EXCLUDED_PPI *MeasurementExcludedFvPpi;
+ EFI_PEI_PPI_DESCRIPTOR *MeasurementExcludedPpiList;
+
+ MeasurementExcludedFvPpi = AllocatePool (sizeof(*MeasurementExcludedFvPpi));
+ ASSERT(MeasurementExcludedFvPpi != NULL);
+ MeasurementExcludedFvPpi->Count = 1;
+ MeasurementExcludedFvPpi->Fv[0].FvBase = PcdGet32 (PcdFspsBaseAddress);
+ MeasurementExcludedFvPpi->Fv[0].FvLength = ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFspsBaseAddress))->FvLength;
+
+ MeasurementExcludedPpiList = AllocatePool (sizeof(*MeasurementExcludedPpiList));
+ ASSERT(MeasurementExcludedPpiList != NULL);
+ MeasurementExcludedPpiList->Flags = EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST;
+ MeasurementExcludedPpiList->Guid = &gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid;
+ MeasurementExcludedPpiList->Ppi = MeasurementExcludedFvPpi;
+
+ Status = PeiServicesInstallPpi (MeasurementExcludedPpiList);
+ ASSERT_EFI_ERROR (Status);
+
//
// FSP-S Wrapper running in Dispatch mode and reports FSP-S FV to PEI dispatcher.
//
@@ -399,6 +420,62 @@ FspsWrapperInitDispatchMode (
}
/**
+ This function is called after TCG installed PPI.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TcgPpiNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ );
+
+EFI_PEI_NOTIFY_DESCRIPTOR mTcgPpiNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiTcgPpiGuid,
+ TcgPpiNotify
+};
+
+/**
+ This function is called after TCG installed PPI.
+
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
+
+ @retval EFI_STATUS Always return EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+TcgPpiNotify (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
+ )
+{
+ UINT32 FspMeasureMask;
+
+ DEBUG ((DEBUG_INFO, "TcgPpiNotify FSPS\n"));
+
+ FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);
+
+ if ((FspMeasureMask & FSP_MEASURE_FSPS) != 0) {
+ MeasureFspFirmwareBlob (0, "FSPS", PcdGet32(PcdFspsBaseAddress),
+ (UINT32)((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) PcdGet32 (PcdFspsBaseAddress))->FvLength);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
This is the entrypoint of PEIM.
@param[in] FileHandle Handle of the file being invoked.
@@ -413,8 +490,13 @@ FspsWrapperPeimEntryPoint (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
+ EFI_STATUS Status;
+
DEBUG ((DEBUG_INFO, "FspsWrapperPeimEntryPoint\n"));
+ Status = PeiServicesNotifyPpi (&mTcgPpiNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
+
if (PcdGet8 (PcdFspModeSelection) == 1) {
FspsWrapperInitApiMode ();
} else {
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
index ab41bf27620..933c1936db3 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
@@ -6,7 +6,7 @@
# register TemporaryRamDonePpi to call TempRamExit API, and register MemoryDiscoveredPpi
# notify to call FspSiliconInit API.
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -44,24 +44,30 @@
PerformanceLib
FspWrapperApiLib
FspWrapperApiTestLib
+ FspMeasurementLib
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
+ SecurityPkg/SecurityPkg.dec
IntelFsp2Pkg/IntelFsp2Pkg.dec
IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
[Ppis]
- gTopOfTemporaryRamPpiGuid ## PRODUCES
- gFspSiliconInitDonePpiGuid ## PRODUCES
- gEfiEndOfPeiSignalPpiGuid ## PRODUCES
- gEfiTemporaryRamDonePpiGuid ## PRODUCES
- gEfiPeiMemoryDiscoveredPpiGuid ## NOTIFY
+ gTopOfTemporaryRamPpiGuid ## PRODUCES
+ gFspSiliconInitDonePpiGuid ## PRODUCES
+ gEfiEndOfPeiSignalPpiGuid ## PRODUCES
+ gEfiTemporaryRamDonePpiGuid ## PRODUCES
+ gEfiPeiMemoryDiscoveredPpiGuid ## NOTIFY
+ gEdkiiTcgPpiGuid ## NOTIFY
+ gEfiPeiFirmwareVolumeInfoMeasurementExcludedPpiGuid ## PRODUCES
[Pcd]
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress ## CONSUMES
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress ## CONSUMES
- gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspsBaseAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspsUpdDataAddress ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig ## CONSUMES
[Guids]
gFspHobGuid ## CONSUMES ## HOB
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h
new file mode 100644
index 00000000000..a96d9554f1b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Include/Library/FspMeasurementLib.h
@@ -0,0 +1,39 @@
+/** @file
+ This library is used by FSP modules to measure data to TPM.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FSP_MEASUREMENT_LIB_H_
+#define _FSP_MEASUREMENT_LIB_H_
+
+#define FSP_MEASURE_FSP BIT0
+#define FSP_MEASURE_FSPT BIT1
+#define FSP_MEASURE_FSPM BIT2
+#define FSP_MEASURE_FSPS BIT3
+#define FSP_MEASURE_FSPUPD BIT31
+
+/**
+ Measure a FSP FirmwareBlob.
+
+ @param[in] PcrIndex PCR Index.
+ @param[in] Description Description for this FirmwareBlob.
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+*/
+EFI_STATUS
+EFIAPI
+MeasureFspFirmwareBlob (
+ IN UINT32 PcrIndex,
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
+ IN UINT64 FirmwareBlobLength
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
index a1a208f55b3..b0eaf0fb59c 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
@@ -1,7 +1,7 @@
## @file
# Provides drivers and definitions to support fsp in EDKII bios.
#
-# Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -26,6 +26,8 @@
## @libraryclass Provide FSP platform related function.
FspWrapperPlatformLib|Include/Library/FspWrapperPlatformLib.h
+ ## @libraryclass Provide FSP TPM measurement related function.
+ FspMeasurementLib|Include/Library/FspMeasurementLib.h
[Guids]
#
# GUID defined in package
@@ -92,6 +94,23 @@
#
gIntelFsp2WrapperTokenSpaceGuid.PcdFspModeSelection|0x00000001|UINT8|0x4000000A
+ ## This PCD decides how FSP is measured
+ # 1) The BootGuard ACM may already measured the FSP component, such as FSPT/FSPM.
+ # We need a flag (PCD) to indicate if there is need to do such FSP measurement or NOT.
+ # 2) The FSP binary includes FSP code and FSP UPD region. The UPD region is considered
+ # as configuration block, and it may be updated by OEM by design.
+ # This flag (PCD) is to indicate if we need isolate the the UPD region from the FSP code region.
+ # BIT0: Need measure FSP. (for FSP1.x) - reserved in FSP2.
+ # BIT1: Need measure FSPT. (for FSP 2.x)
+ # BIT2: Need measure FSPM. (for FSP 2.x)
+ # BIT3: Need measure FSPS. (for FSP 2.x)
+ # BIT4~30: reserved.
+ # BIT31: Need isolate UPD region measurement.
+ #0: measure FSP[T|M|S] as one binary in one record (PCR0).
+ #1: measure FSP UPD region in one record (PCR1), the FSP code without UPD in another record (PCR0).
+ #
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig|0x00000000|UINT32|0x4000000B
+
[PcdsFixedAtBuild, PcdsPatchableInModule,PcdsDynamic,PcdsDynamicEx]
#
## These are the base address of FSP-M/S
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
index cdfb66cf27a..0c7f35546b2 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dsc
@@ -1,7 +1,7 @@
## @file
# Provides drivers and definitions to support fsp in EDKII bios.
#
-# Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -16,6 +16,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
@@ -45,18 +47,25 @@
# FSP Wrapper Lib
FspWrapperApiLib|IntelFsp2WrapperPkg/Library/BaseFspWrapperApiLib/BaseFspWrapperApiLib.inf
FspWrapperApiTestLib|IntelFsp2WrapperPkg/Library/BaseFspWrapperApiTestLibNull/BaseFspWrapperApiTestLibNull.inf
+ FspMeasurementLib|IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
# FSP platform sample
FspWrapperPlatformLib|IntelFsp2WrapperPkg/Library/BaseFspWrapperPlatformLibSample/BaseFspWrapperPlatformLibSample.inf
PlatformSecLib|IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
FspWrapperHobProcessLib|IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
+ Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+
[LibraryClasses.common.PEIM,LibraryClasses.common.PEI_CORE]
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ TpmMeasurementLib|SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf
+ TcgEventLogRecordLib|SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf
+ HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
[LibraryClasses.common.DXE_DRIVER]
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
@@ -73,6 +82,7 @@
IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecFspWrapperPlatformSecLibSample.inf
IntelFsp2WrapperPkg/Library/PeiFspWrapperHobProcessLibSample/PeiFspWrapperHobProcessLibSample.inf
IntelFsp2WrapperPkg/Library/PeiFspWrapperApiTestLib/PeiFspWrapperApiTestLib.inf
+ IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
IntelFsp2WrapperPkg/FspmWrapperPeim/FspmWrapperPeim.inf
IntelFsp2WrapperPkg/FspsWrapperPeim/FspsWrapperPeim.inf
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
new file mode 100644
index 00000000000..47bb8d33d5a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/BaseFspMeasurementLib.inf
@@ -0,0 +1,54 @@
+## @file
+# Provides FSP measurement functions.
+#
+# This library provides MeasureFspFirmwareBlob() to measure FSP binary.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FspMeasurementLib
+ FILE_GUID = 890B12B4-56CC-453E-B062-4597FC6D3D8C
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = FspMeasurementLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FspMeasurementLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ IntelFsp2Pkg/IntelFsp2Pkg.dec
+ IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ PcdLib
+ PeiServicesLib
+ PeiServicesTablePointerLib
+ FspWrapperApiLib
+ TcgEventLogRecordLib
+ HashLib
+
+[Ppis]
+ gEdkiiTcgPpiGuid ## CONSUMES
+
+[Pcd]
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspMeasurementConfig ## CONSUMES
+ gIntelFsp2WrapperTokenSpaceGuid.PcdFspmBaseAddress ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c
new file mode 100644
index 00000000000..251ffbfa8c6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/BaseFspMeasurementLib/FspMeasurementLib.c
@@ -0,0 +1,248 @@
+/** @file
+ This library is used by FSP modules to measure data to TPM.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Uefi.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/DebugLib.h>
+#include <Library/FspWrapperApiLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <Library/FspMeasurementLib.h>
+#include <Library/TcgEventLogRecordLib.h>
+#include <Library/HashLib.h>
+
+#include <Ppi/Tcg.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+/**
+ Tpm measure and log data, and extend the measurement result into a specific PCR.
+
+ @param[in] PcrIndex PCR Index.
+ @param[in] EventType Event type.
+ @param[in] EventLog Measurement event log.
+ @param[in] LogLen Event log length in bytes.
+ @param[in] HashData The start of the data buffer to be hashed, extended.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
+ @param[in] Flags Bitmap providing additional information.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+TpmMeasureAndLogDataWithFlags (
+ IN UINT32 PcrIndex,
+ IN UINT32 EventType,
+ IN VOID *EventLog,
+ IN UINT32 LogLen,
+ IN VOID *HashData,
+ IN UINT64 HashDataLen,
+ IN UINT64 Flags
+ )
+{
+ EFI_STATUS Status;
+ EDKII_TCG_PPI *TcgPpi;
+ TCG_PCR_EVENT_HDR TcgEventHdr;
+
+ Status = PeiServicesLocatePpi(
+ &gEdkiiTcgPpiGuid,
+ 0,
+ NULL,
+ (VOID**)&TcgPpi
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ TcgEventHdr.PCRIndex = PcrIndex;
+ TcgEventHdr.EventType = EventType;
+ TcgEventHdr.EventSize = LogLen;
+
+ Status = TcgPpi->HashLogExtendEvent (
+ TcgPpi,
+ Flags,
+ HashData,
+ (UINTN)HashDataLen,
+ &TcgEventHdr,
+ EventLog
+ );
+ return Status;
+}
+
+/**
+ Measure a FSP FirmwareBlob.
+
+ @param[in] Description Description for this FirmwareBlob.
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.
+ @param[in] CfgRegionOffset Configuration region offset in bytes.
+ @param[in] CfgRegionSize Configuration region in bytes.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+MeasureFspFirmwareBlobWithCfg (
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
+ IN UINT64 FirmwareBlobLength,
+ IN UINT32 CfgRegionOffset,
+ IN UINT32 CfgRegionSize
+ )
+{
+ EFI_PLATFORM_FIRMWARE_BLOB FvBlob, UpdBlob;
+ PLATFORM_FIRMWARE_BLOB2_STRUCT FvBlob2, UpdBlob2;
+ VOID *FvName;
+ UINT32 FvEventType;
+ VOID *FvEventLog, *UpdEventLog;
+ UINT32 FvEventLogSize, UpdEventLogSize;
+ EFI_STATUS Status;
+ HASH_HANDLE HashHandle;
+ UINT8 *HashBase;
+ UINTN HashSize;
+ TPML_DIGEST_VALUES DigestList;
+
+ FvName = TpmMeasurementGetFvName (FirmwareBlobBase, FirmwareBlobLength);
+
+ if (((Description != NULL) || (FvName != NULL)) &&
+ (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) {
+ if (Description != NULL) {
+ AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "%a", Description);
+ AsciiSPrint((CHAR8*)UpdBlob2.BlobDescription, sizeof(UpdBlob2.BlobDescription), "%aUDP", Description);
+ } else {
+ AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);
+ AsciiSPrint((CHAR8*)UpdBlob2.BlobDescription, sizeof(UpdBlob2.BlobDescription), "(%g)UDP", FvName);
+ }
+
+ FvBlob2.BlobDescriptionSize = sizeof(FvBlob2.BlobDescription);
+ FvBlob2.BlobBase = FirmwareBlobBase;
+ FvBlob2.BlobLength = FirmwareBlobLength;
+ FvEventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
+ FvEventLog = &FvBlob2;
+ FvEventLogSize = sizeof(FvBlob2);
+
+ UpdBlob2.BlobDescriptionSize = sizeof(UpdBlob2.BlobDescription);
+ UpdBlob2.BlobBase = CfgRegionOffset;
+ UpdBlob2.BlobLength = CfgRegionSize;
+ UpdEventLog = &UpdBlob2;
+ UpdEventLogSize = sizeof(UpdBlob2);
+ } else {
+ FvBlob.BlobBase = FirmwareBlobBase;
+ FvBlob.BlobLength = FirmwareBlobLength;
+ FvEventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
+ FvEventLog = &FvBlob;
+ FvEventLogSize = sizeof(FvBlob);
+
+ UpdBlob.BlobBase = CfgRegionOffset;
+ UpdBlob.BlobLength = CfgRegionSize;
+ UpdEventLog = &UpdBlob;
+ UpdEventLogSize = sizeof(UpdBlob);
+ }
+
+ /** Initialize a SHA hash context. **/
+ Status = HashStart (&HashHandle);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "HashStart failed - %r\n", Status));
+ return Status;
+ }
+
+ /** Hash FSP binary before UDP **/
+ HashBase = (UINT8 *) (UINTN) FirmwareBlobBase;
+ HashSize = (UINTN) CfgRegionOffset;
+ Status = HashUpdate (HashHandle, HashBase, HashSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));
+ return Status;
+ }
+
+ /** Hash FSP binary after UDP **/
+ HashBase = (UINT8 *) (UINTN) FirmwareBlobBase + CfgRegionOffset + CfgRegionSize;
+ HashSize = (UINTN)(FirmwareBlobLength - CfgRegionOffset - CfgRegionSize);
+ Status = HashUpdate (HashHandle, HashBase, HashSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "HashUpdate failed - %r\n", Status));
+ return Status;
+ }
+
+ /** Finalize the SHA hash. **/
+ Status = HashCompleteAndExtend (HashHandle, 0, NULL, 0, &DigestList);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "HashCompleteAndExtend failed - %r\n", Status));
+ return Status;
+ }
+
+ Status = TpmMeasureAndLogDataWithFlags (
+ 0,
+ FvEventType,
+ FvEventLog,
+ FvEventLogSize,
+ (UINT8 *) &DigestList,
+ (UINTN) sizeof(DigestList),
+ EDKII_TCG_PRE_HASH_LOG_ONLY
+ );
+
+ Status = TpmMeasureAndLogData (
+ 1,
+ EV_PLATFORM_CONFIG_FLAGS,
+ UpdEventLog,
+ UpdEventLogSize,
+ (UINT8 *) (UINTN) FirmwareBlobBase + CfgRegionOffset,
+ CfgRegionSize
+ );
+
+ return Status;
+}
+
+/**
+ Measure a FSP FirmwareBlob.
+
+ @param[in] PcrIndex PCR Index.
+ @param[in] Description Description for this FirmwareBlob.
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+MeasureFspFirmwareBlob (
+ IN UINT32 PcrIndex,
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
+ IN UINT64 FirmwareBlobLength
+ )
+{
+ UINT32 FspMeasureMask;
+ FSP_INFO_HEADER *FspHeaderPtr;
+
+ FspMeasureMask = PcdGet32 (PcdFspMeasurementConfig);
+ if ((FspMeasureMask & FSP_MEASURE_FSPUPD) != 0) {
+ FspHeaderPtr = (FSP_INFO_HEADER *) FspFindFspHeader (FirmwareBlobBase);
+ if (FspHeaderPtr != NULL) {
+ return MeasureFspFirmwareBlobWithCfg(Description, FirmwareBlobBase, FirmwareBlobLength,
+ FspHeaderPtr->CfgRegionOffset, FspHeaderPtr->CfgRegionSize);
+ }
+ }
+
+ return MeasureFirmwareBlob (PcrIndex, Description, FirmwareBlobBase, FirmwareBlobLength);
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
index bd9730bf430..6f1f6ddf690 100644
--- a/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
+++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2WrapperPkg/Library/SecFspWrapperPlatformSecLibSample/SecRamInitData.c
@@ -1,7 +1,7 @@
/** @file
Sample to provide TempRamInitParams data.
- Copyright (c) 2014 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -18,17 +18,39 @@ typedef struct {
typedef struct {
FSP_UPD_HEADER FspUpdHeader;
+ //
+ // If platform does not support FSP spec 2.2 remove FSPT_ARCH_UPD structure.
+ //
+ FSPT_ARCH_UPD FsptArchUpd;
FSPT_CORE_UPD FsptCoreUpd;
} FSPT_UPD_CORE_DATA;
GLOBAL_REMOVE_IF_UNREFERENCED CONST FSPT_UPD_CORE_DATA FsptUpdDataPtr = {
{
0x4450555F54505346,
- 0x00,
+ //
+ // UPD header revision must be equal or greater than 2 when the structure is compliant with FSP spec 2.2.
+ //
+ 0x02,
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}
},
+ //
+ // If platform does not support FSP spec 2.2 remove FSPT_ARCH_UPD structure.
+ //
+ {
+ 0x01,
+ {
+ 0x00, 0x00, 0x00
+ },
+ 0x00000020,
+ 0x00000000,
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ }
+ },
{
((UINT32)FixedPcdGet64 (PcdCpuMicrocodePatchAddress) + FixedPcdGet32 (PcdFlashMicrocodeOffset)),
((UINT32)FixedPcdGet64 (PcdCpuMicrocodePatchRegionSize) - FixedPcdGet32 (PcdFlashMicrocodeOffset)),
diff --git a/src/VBox/Devices/EFI/Firmware/Maintainers.txt b/src/VBox/Devices/EFI/Firmware/Maintainers.txt
index d17731f74c3..9861e88c8aa 100644
--- a/src/VBox/Devices/EFI/Firmware/Maintainers.txt
+++ b/src/VBox/Devices/EFI/Firmware/Maintainers.txt
@@ -80,7 +80,7 @@ W: https://github.com/tianocore/tianocore.github.io/wiki/Security
EDK II Releases:
----------------
W: https://github.com/tianocore/tianocore.github.io/wiki/EDK-II-Release-Planning
-M: Liming Gao <liming.gao@intel.com>
+M: Liming Gao <gaoliming@byosoft.com.cn>
UEFI Shell Binaries (ShellBinPkg.zip) from EDK II Releases:
-----------------------------------------------------------
@@ -88,7 +88,7 @@ W: https://github.com/tianocore/edk2/releases/
M: Ray Ni <ray.ni@intel.com> (Ia32/X64)
M: Zhichao Gao <zhichao.gao@intel.com> (Ia32/X64)
M: Leif Lindholm <leif@nuviainc.com> (ARM/AArch64)
-M: Ard Biesheuvel <ard.biesheuvel@arm.com> (ARM/AArch64)
+M: Ard Biesheuvel <ardb+tianocore@kernel.org> (ARM/AArch64)
EDK II Architectures:
---------------------
@@ -96,7 +96,12 @@ ARM, AARCH64
F: */AArch64/
F: */Arm/
M: Leif Lindholm <leif@nuviainc.com>
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
+
+RISCV64
+F: */RiscV64/
+M: Abner Chang <abner.chang@hpe.com>
+R: Daniel Schaefer <daniel.schaefer@hpe.com>
EDK II Continuous Integration:
------------------------------
@@ -105,12 +110,12 @@ F: .azurepipelines/
M: Sean Brogan <sean.brogan@microsoft.com>
M: Bret Barkelew <Bret.Barkelew@microsoft.com>
R: Michael D Kinney <michael.d.kinney@intel.com>
-R: Liming Gao <liming.gao@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
.mergify/
F: .mergify/
M: Michael D Kinney <michael.d.kinney@intel.com>
-M: Liming Gao <liming.gao@intel.com>
+M: Liming Gao <gaoliming@byosoft.com.cn>
R: Sean Brogan <sean.brogan@microsoft.com>
R: Bret Barkelew <Bret.Barkelew@microsoft.com>
@@ -119,7 +124,7 @@ F: .pytool/
M: Sean Brogan <sean.brogan@microsoft.com>
M: Bret Barkelew <Bret.Barkelew@microsoft.com>
R: Michael D Kinney <michael.d.kinney@intel.com>
-R: Liming Gao <liming.gao@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
EDK II Packages:
----------------
@@ -127,19 +132,19 @@ ArmPkg
F: ArmPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/ArmPkg
M: Leif Lindholm <leif@nuviainc.com>
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
ArmPlatformPkg
F: ArmPlatformPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/ArmPlatformPkg
M: Leif Lindholm <leif@nuviainc.com>
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
ArmVirtPkg
F: ArmVirtPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/ArmVirtPkg
M: Laszlo Ersek <lersek@redhat.com>
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
R: Leif Lindholm <leif@nuviainc.com>
ArmVirtPkg: modules used on Xen
@@ -152,17 +157,30 @@ F: ArmVirtPkg/XenPlatformHasAcpiDtDxe/
F: ArmVirtPkg/XenioFdtDxe/
R: Julien Grall <julien@xen.org>
+ArmVirtPkg: Kvmtool emulated platform support
+F: ArmVirtPkg/ArmVirtKvmTool.*
+F: ArmVirtPkg/KvmtoolPlatformDxe/
+F: ArmVirtPkg/Library/Fdt16550SerialPortHookLib/
+F: ArmVirtPkg/Library/KvmtoolPlatformPeiLib/
+F: ArmVirtPkg/Library/KvmtoolRtcFdtClientLib/
+F: ArmVirtPkg/Library/KvmtoolVirtMemInfoLib/
+F: ArmVirtPkg/Library/NorFlashKvmtoolLib/
+R: Sami Mujawar <sami.mujawar@arm.com>
+
BaseTools
F: BaseTools/
W: https://github.com/tianocore/tianocore.github.io/wiki/BaseTools
M: Bob Feng <bob.c.feng@intel.com>
-M: Liming Gao <liming.gao@intel.com>
+M: Liming Gao <gaoliming@byosoft.com.cn>
+R: Yuwei Chen <yuwei.chen@intel.com>
CryptoPkg
F: CryptoPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/CryptoPkg
+M: Jiewen Yao <jiewen.yao@intel.com>
M: Jian J Wang <jian.j.wang@intel.com>
R: Xiaoyu Lu <xiaoyux.lu@intel.com>
+R: Guomin Jiang <guomin.jiang@intel.com>
DynamicTablesPkg
F: DynamicTablesPkg/
@@ -174,12 +192,11 @@ EmbeddedPkg
F: EmbeddedPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/EmbeddedPkg
M: Leif Lindholm <leif@nuviainc.com>
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
EmulatorPkg
F: EmulatorPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/EmulatorPkg
-M: Jordan Justen <jordan.l.justen@intel.com>
M: Andrew Fish <afish@apple.com>
M: Ray Ni <ray.ni@intel.com>
S: Maintained
@@ -194,8 +211,10 @@ T: git - https://github.com/tianocore/edk2-FatPkg.git
FmpDevicePkg
F: FmpDevicePkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/FmpDevicePkg
-M: Liming Gao <liming.gao@intel.com>
+M: Liming Gao <gaoliming@byosoft.com.cn>
M: Michael D Kinney <michael.d.kinney@intel.com>
+R: Guomin Jiang <guomin.jiang@intel.com>
+R: Wei6 Xu <wei6.xu@intel.com>
IntelFsp2Pkg
F: IntelFsp2Pkg/
@@ -221,9 +240,9 @@ MdeModulePkg: ACPI modules
F: MdeModulePkg/Include/*Acpi*.h
F: MdeModulePkg/Universal/Acpi/
R: Dandan Bi <dandan.bi@intel.com>
-R: Liming Gao <liming.gao@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
-MdeModulePkg: ACPI S3 modules
+MdeModulePkg: ACPI modules related to S3
F: MdeModulePkg/*LockBox*/
F: MdeModulePkg/Include/*BootScript*.h
F: MdeModulePkg/Include/*LockBox*.h
@@ -265,7 +284,6 @@ F: MdeModulePkg/*StatusCode*/
F: MdeModulePkg/Application/DumpDynPcd/
F: MdeModulePkg/Core/Dxe/
F: MdeModulePkg/Core/DxeIplPeim/
-F: MdeModulePkg/Core/Pei/
F: MdeModulePkg/Core/RuntimeDxe/
F: MdeModulePkg/Include/*Mem*.h
F: MdeModulePkg/Include/*Pcd*.h
@@ -284,18 +302,16 @@ F: MdeModulePkg/Universal/PCD/
F: MdeModulePkg/Universal/PlatformDriOverrideDxe/
F: MdeModulePkg/Universal/SecurityStubDxe/SecurityStub.c
R: Dandan Bi <dandan.bi@intel.com>
-R: Liming Gao <liming.gao@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
MdeModulePkg: Device and Peripheral modules
F: MdeModulePkg/*PciHostBridge*/
-F: MdeModulePkg/*Serial*/
F: MdeModulePkg/Bus/
F: MdeModulePkg/Include/*Ata*.h
F: MdeModulePkg/Include/*IoMmu*.h
F: MdeModulePkg/Include/*NonDiscoverableDevice*.h
F: MdeModulePkg/Include/*NvmExpress*.h
F: MdeModulePkg/Include/*SdMmc*.h
-F: MdeModulePkg/Include/*SerialPort*.h
F: MdeModulePkg/Include/*Ufs*.h
F: MdeModulePkg/Include/*Usb*.h
F: MdeModulePkg/Include/Guid/RecoveryDevice.h
@@ -304,11 +320,16 @@ F: MdeModulePkg/Include/Library/PciHostBridgeLib.h
F: MdeModulePkg/Include/Ppi/StorageSecurityCommand.h
F: MdeModulePkg/Include/Protocol/Ps2Policy.h
F: MdeModulePkg/Library/NonDiscoverableDeviceRegistrationLib/
-F: MdeModulePkg/Universal/Disk/
F: MdeModulePkg/Universal/PcatSingleSegmentPciCfg2Pei/
R: Hao A Wu <hao.a.wu@intel.com>
R: Ray Ni <ray.ni@intel.com>
+MdeModulePkg: Disk modules
+F: MdeModulePkg/Universal/Disk/
+R: Hao A Wu <hao.a.wu@intel.com>
+R: Ray Ni <ray.ni@intel.com>
+R: Zhichao Gao <zhichao.gao@intel.com>
+
MdeModulePkg: Firmware Update modules
F: MdeModulePkg/*Capsule*/
F: MdeModulePkg/Include/*Capsule*.h
@@ -320,7 +341,8 @@ F: MdeModulePkg/Library/DisplayUpdateProgressLib*/
F: MdeModulePkg/Library/FmpAuthenticationLibNull/
F: MdeModulePkg/Universal/Esrt*/
R: Hao A Wu <hao.a.wu@intel.com>
-R: Liming Gao <liming.gao@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
+R: Guomin Jiang <guomin.jiang@intel.com>
MdeModulePkg: HII and UI modules
F: MdeModulePkg/*FileExplorer*/
@@ -347,16 +369,32 @@ F: MdeModulePkg/Include/*Smm*.h
R: Eric Dong <eric.dong@intel.com>
R: Ray Ni <ray.ni@intel.com>
+MdeModulePkg: Pei Core
+F: MdeModulePkg/Core/Pei/
+R: Dandan Bi <dandan.bi@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
+R: Debkumar De <debkumar.de@intel.com>
+R: Harry Han <harry.han@intel.com>
+R: Catharine West <catharine.west@intel.com>
+
MdeModulePkg: Reset modules
F: MdeModulePkg/*Reset*/
F: MdeModulePkg/Include/*Reset*.h
R: Zhichao Gao <zhichao.gao@intel.com>
R: Ray Ni <ray.ni@intel.com>
+MdeModulePkg: Serial modules
+F: MdeModulePkg/*Serial*/
+F: MdeModulePkg/Include/*SerialPort*.h
+R: Hao A Wu <hao.a.wu@intel.com>
+R: Ray Ni <ray.ni@intel.com>
+R: Zhichao Gao <zhichao.gao@intel.com>
+
MdeModulePkg: SMBIOS modules
F: MdeModulePkg/Universal/Smbios*/
R: Dandan Bi <dandan.bi@intel.com>
R: Star Zeng <star.zeng@intel.com>
+R: Zhichao Gao <zhichao.gao@intel.com>
MdeModulePkg: UEFI Variable modules
F: MdeModulePkg/*Var*/
@@ -366,13 +404,14 @@ F: MdeModulePkg/Include/Guid/SystemNvDataGuid.h
F: MdeModulePkg/Include/Protocol/SwapAddressRange.h
F: MdeModulePkg/Universal/FaultTolerantWrite*/
R: Hao A Wu <hao.a.wu@intel.com>
-R: Liming Gao <liming.gao@intel.com>
+R: Liming Gao <gaoliming@byosoft.com.cn>
MdePkg
F: MdePkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/MdePkg
M: Michael D Kinney <michael.d.kinney@intel.com>
-M: Liming Gao <liming.gao@intel.com>
+M: Liming Gao <gaoliming@byosoft.com.cn>
+R: Zhiguang Liu <zhiguang.liu@intel.com>
NetworkPkg
F: NetworkPkg/
@@ -384,11 +423,66 @@ R: Siyuan Fu <siyuan.fu@intel.com>
OvmfPkg
F: OvmfPkg/
W: http://www.tianocore.org/ovmf/
-M: Jordan Justen <jordan.l.justen@intel.com>
M: Laszlo Ersek <lersek@redhat.com>
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
+R: Jordan Justen <jordan.l.justen@intel.com>
S: Maintained
+OvmfPkg: bhyve-related modules
+F: OvmfPkg/Bhyve/
+F: OvmfPkg/Include/IndustryStandard/Bhyve.h
+F: OvmfPkg/Include/Library/BhyveFwCtlLib.h
+F: OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.c
+F: OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
+F: OvmfPkg/Library/BhyveFwCtlLib/
+F: OvmfPkg/Library/PlatformBootManagerLibBhyve/
+F: OvmfPkg/Library/ResetSystemLib/BaseResetShutdownBhyve.c
+F: OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf
+R: Rebecca Cran <rebecca@bsdio.com>
+R: Peter Grehan <grehan@freebsd.org>
+
+OvmfPkg: CSM modules
+F: OvmfPkg/Csm/
+R: David Woodhouse <dwmw2@infradead.org>
+
+OvmfPkg: Confidential Computing
+F: OvmfPkg/AmdSev/
+F: OvmfPkg/AmdSevDxe/
+F: OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
+F: OvmfPkg/Include/Library/MemEncryptSevLib.h
+F: OvmfPkg/IoMmuDxe/AmdSevIoMmu.*
+F: OvmfPkg/Library/BaseMemEncryptSevLib/
+F: OvmfPkg/Library/PlatformBootManagerLibGrub/
+F: OvmfPkg/Library/VmgExitLib/
+F: OvmfPkg/PlatformPei/AmdSev.c
+F: OvmfPkg/ResetVector/
+F: OvmfPkg/Sec/
+R: Brijesh Singh <brijesh.singh@amd.com>
+R: Erdem Aktas <erdemaktas@google.com>
+R: James Bottomley <jejb@linux.ibm.com>
+R: Jiewen Yao <jiewen.yao@intel.com>
+R: Min Xu <min.m.xu@intel.com>
+R: Tom Lendacky <thomas.lendacky@amd.com>
+
+OvmfPkg: LsiScsi driver
+F: OvmfPkg/LsiScsiDxe/
+R: Gary Lin <glin@suse.com>
+
+OvmfPkg: MptScsi and PVSCSI driver
+F: OvmfPkg/MptScsiDxe/
+F: OvmfPkg/PvScsiDxe/
+R: Liran Alon <liran.alon@oracle.com>
+R: Nikita Leshenko <nikita.leshchenko@oracle.com>
+
+OvmfPkg: TCG- and TPM2-related modules
+F: OvmfPkg/Include/IndustryStandard/QemuTpm.h
+F: OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
+F: OvmfPkg/Library/Tcg2PhysicalPresenceLib*/
+F: OvmfPkg/PlatformPei/ClearCache.c
+F: OvmfPkg/Tcg/
+R: Marc-André Lureau <marcandre.lureau@redhat.com>
+R: Stefan Berger <stefanb@linux.ibm.com>
+
OvmfPkg: Xen-related modules
F: OvmfPkg/AcpiPlatformDxe/Xen.c
F: OvmfPkg/Include/Guid/XenBusRootDevice.h
@@ -422,36 +516,32 @@ F: OvmfPkg/XenTimerDxe/
R: Anthony Perard <anthony.perard@citrix.com>
R: Julien Grall <julien@xen.org>
-OvmfPkg: TCG- and TPM2-related modules
-F: OvmfPkg/Include/IndustryStandard/QemuTpm.h
-F: OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
-F: OvmfPkg/Library/Tcg2PhysicalPresenceLib*/
-F: OvmfPkg/PlatformPei/ClearCache.c
-F: OvmfPkg/Tcg/
-R: Marc-André Lureau <marcandre.lureau@redhat.com>
-R: Stefan Berger <stefanb@linux.ibm.com>
-
-OvmfPkg: CSM modules
-F: OvmfPkg/Csm/
-R: David Woodhouse <dwmw2@infradead.org>
-
-OvmfPkg: MptScsi and PVSCSI driver
-F: OvmfPkg/MptScsiDxe/
-F: OvmfPkg/PvScsiDxe/
-R: Liran Alon <liran.alon@oracle.com>
-R: Nikita Leshenko <nikita.leshchenko@oracle.com>
-
PcAtChipsetPkg
F: PcAtChipsetPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/PcAtChipsetPkg
M: Ray Ni <ray.ni@intel.com>
+RedfishPkg: Redfish related modules
+F: RedfishPkg/
+M: Abner Chang <abner.chang@hpe.com>
+R: Nickle Wang <nickle.wang@hpe.com>
+
SecurityPkg
F: SecurityPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/SecurityPkg
M: Jiewen Yao <jiewen.yao@intel.com>
M: Jian J Wang <jian.j.wang@intel.com>
-R: Chao Zhang <chao.b.zhang@intel.com>
+
+SecurityPkg: Secure boot related modules
+F: SecurityPkg/Library/DxeImageVerificationLib/
+F: SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/
+F: SecurityPkg/Library/AuthVariableLib/
+R: Min Xu <min.m.xu@intel.com>
+
+SecurityPkg: Tcg related modules
+F: SecurityPkg/Tcg/
+R: Qi Zhang <qi1.zhang@intel.com>
+R: Rahul Kumar <rahul1.kumar@intel.com>
ShellPkg
F: ShellPkg/
@@ -462,20 +552,34 @@ M: Zhichao Gao <zhichao.gao@intel.com>
SignedCapsulePkg
F: SignedCapsulePkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/SignedCapsulePkg
-M: Jiewen Yao <jiewen.yao@intel.com>
-M: Chao Zhang <chao.b.zhang@intel.com>
+M: Jian J Wang <jian.j.wang@intel.com>
SourceLevelDebugPkg
F: SourceLevelDebugPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/SourceLevelDebugPkg
M: Hao A Wu <hao.a.wu@intel.com>
+StandaloneMmPkg
+F: StandaloneMmPkg/
+M: Ard Biesheuvel <ardb+tianocore@kernel.org>
+M: Sami Mujawar <sami.mujawar@arm.com>
+M: Jiewen Yao <jiewen.yao@intel.com>
+R: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
+
UefiCpuPkg
F: UefiCpuPkg/
W: https://github.com/tianocore/tianocore.github.io/wiki/UefiCpuPkg
M: Eric Dong <eric.dong@intel.com>
M: Ray Ni <ray.ni@intel.com>
R: Laszlo Ersek <lersek@redhat.com>
+R: Rahul Kumar <rahul1.kumar@intel.com>
+
+UefiCpuPkg: Sec related modules
+F: UefiCpuPkg/SecCore/
+F: UefiCpuPkg/ResetVector/
+R: Debkumar De <debkumar.de@intel.com>
+R: Harry Han <harry.han@intel.com>
+R: Catharine West <catharine.west@intel.com>
UefiPayloadPkg
F: UefiPayloadPkg/
@@ -491,10 +595,3 @@ M: Michael D Kinney <michael.d.kinney@intel.com>
R: Sean Brogan <sean.brogan@microsoft.com>
R: Bret Barkelew <Bret.Barkelew@microsoft.com>
S: Maintained
-
-StandaloneMmPkg
-F: StandaloneMmPkg/
-M: Ard Biesheuvel <ard.biesheuvel@arm.com>
-M: Sami Mujawar <sami.mujawar@arm.com>
-M: Jiewen Yao <jiewen.yao@intel.com>
-R: Supreeth Venkatesh <supreeth.venkatesh@arm.com>
diff --git a/src/VBox/Devices/EFI/Firmware/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/Makefile.kmk
index 451cb843192..16c08075a84 100644
--- a/src/VBox/Devices/EFI/Firmware/Makefile.kmk
+++ b/src/VBox/Devices/EFI/Firmware/Makefile.kmk
@@ -49,12 +49,14 @@ VBOX_EFI_BLDPROGS := $(filter-out $(VBOX_EFI_BLDPROGS),$(BLDPROGS)) VBoxEfiBldPy
# Binary wrappers for python scripts.
#
VBOX_EFI_PYTHON_WRAPPERS = \
+ AmlToC \
BPDG \
build \
Ecc \
GenFds \
GenPatchPcdTable \
PatchPcdValue \
+ Split \
Trim \
TargetTool \
UPT
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
index 99d37c137bc..da74e046a25 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenu.c
@@ -451,20 +451,10 @@ BootMenuSelectItem (
}
//
- // Print want to select item
- //
- FirstItem = BootMenuData->ScrollBarControl.FirstItem;
- gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);
- String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);
- PrintCol = StartCol + 1;
- PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;
- PrintStringAt (PrintCol, PrintRow, String);
- FreePool (String);
-
- //
// if Want Select and selected item isn't the same and doesn't re-draw selectable
// items, clear select item
//
+ FirstItem = BootMenuData->ScrollBarControl.FirstItem;
if (WantSelectItem != BootMenuData->SelectItem && !RePaintItems) {
gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE);
String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[BootMenuData->SelectItem], NULL);
@@ -474,6 +464,16 @@ BootMenuSelectItem (
FreePool (String);
}
+ //
+ // Print want to select item
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLACK);
+ String = HiiGetString (gStringPackHandle, BootMenuData->PtrTokens[WantSelectItem], NULL);
+ PrintCol = StartCol + 1;
+ PrintRow = StartRow + TITLE_TOKEN_COUNT + 2 + WantSelectItem - FirstItem;
+ PrintStringAt (PrintCol, PrintRow, String);
+ FreePool (String);
+
gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute);
BootMenuData->SelectItem = WantSelectItem;
return EFI_SUCCESS;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
index 6016bf53d94..b1cf39ca263 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Application/CapsuleApp/CapsuleOnDisk.c
@@ -795,7 +795,7 @@ ProcessCapsuleOnDisk (
Status = GetUpdateFileSystem (Map, &BootNext, &Fs, &UpdateBootNext);
if (EFI_ERROR (Status)) {
- Print (L"CapsuleApp: cannot find a valid file system on boot devies. Status = %r\n", Status);
+ Print (L"CapsuleApp: cannot find a valid file system on boot devices. Status = %r\n", Status);
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
index eaaa16f4049..385d90eb8ec 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.c
@@ -1,7 +1,7 @@
/** @file
The file for AHCI mode of ATA host controller.
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -248,32 +248,23 @@ AhciWaitMemSet (
/**
Check the memory status to the test value.
- @param[in] Address The memory address to test.
- @param[in] MaskValue The mask value of memory.
- @param[in] TestValue The test value of memory.
- @param[in, out] Task Optional. Pointer to the ATA_NONBLOCK_TASK used by
- non-blocking mode. If NULL, then just try once.
+ @param[in] Address The memory address to test.
+ @param[in] MaskValue The mask value of memory.
+ @param[in] TestValue The test value of memory.
- @retval EFI_NOTREADY The memory is not set.
- @retval EFI_TIMEOUT The memory setting retry times out.
+ @retval EFI_NOT_READY The memory is not set.
@retval EFI_SUCCESS The memory is correct set.
-
**/
EFI_STATUS
EFIAPI
AhciCheckMemSet (
IN UINTN Address,
IN UINT32 MaskValue,
- IN UINT32 TestValue,
- IN OUT ATA_NONBLOCK_TASK *Task
+ IN UINT32 TestValue
)
{
UINT32 Value;
- if (Task != NULL) {
- Task->RetryTimes--;
- }
-
Value = *(volatile UINT32 *) Address;
Value &= MaskValue;
@@ -281,11 +272,7 @@ AhciCheckMemSet (
return EFI_SUCCESS;
}
- if ((Task != NULL) && !Task->InfiniteWait && (Task->RetryTimes == 0)) {
- return EFI_TIMEOUT;
- } else {
- return EFI_NOT_READY;
- }
+ return EFI_NOT_READY;
}
@@ -357,7 +344,7 @@ AhciDumpPortStatus (
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
- Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
+ Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H);
if (!EFI_ERROR (Status)) {
//
// If D2H FIS is received, update StatusBlock with its content.
@@ -622,6 +609,292 @@ AhciBuildCommandFis (
}
/**
+ Wait until SATA device reports it is ready for operation.
+
+ @param[in] PciIo Pointer to AHCI controller PciIo.
+ @param[in] Port SATA port index on which to reset.
+
+ @retval EFI_SUCCESS Device ready for operation.
+ @retval EFI_TIMEOUT Device failed to get ready within required period.
+**/
+EFI_STATUS
+AhciWaitDeviceReady (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Port
+ )
+{
+ UINT32 PhyDetectDelay;
+ UINT32 Data;
+ UINT32 Offset;
+
+ //
+ // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
+ // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
+ //
+ PhyDetectDelay = 16 * 1000;
+ do {
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
+ if (AhciReadReg(PciIo, Offset) != 0) {
+ AhciWriteReg (PciIo, Offset, AhciReadReg(PciIo, Offset));
+ }
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+
+ Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;
+ if (Data == 0) {
+ break;
+ }
+
+ MicroSecondDelay (1000);
+ PhyDetectDelay--;
+ } while (PhyDetectDelay > 0);
+
+ if (PhyDetectDelay == 0) {
+ DEBUG ((DEBUG_ERROR, "Port %d Device not ready (TFD=0x%X)\n", Port, Data));
+ return EFI_TIMEOUT;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+
+/**
+ Reset the SATA port. Algorithm follows AHCI spec 1.3.1 section 10.4.2
+
+ @param[in] PciIo Pointer to AHCI controller PciIo.
+ @param[in] Port SATA port index on which to reset.
+
+ @retval EFI_SUCCESS Port reset.
+ @retval Others Failed to reset the port.
+**/
+EFI_STATUS
+AhciResetPort (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Port
+ )
+{
+ UINT32 Offset;
+ EFI_STATUS Status;
+
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SCTL;
+ AhciOrReg (PciIo, Offset, EFI_AHCI_PORT_SCTL_DET_INIT);
+ //
+ // SW is required to keep DET set to 0x1 at least for 1 milisecond to ensure that
+ // at least one COMRESET signal is sent.
+ //
+ MicroSecondDelay(1000);
+ AhciAndReg (PciIo, Offset, ~(UINT32)EFI_AHCI_PORT_SSTS_DET_MASK);
+
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SSTS;
+ Status = AhciWaitMmioSet (PciIo, Offset, EFI_AHCI_PORT_SSTS_DET_MASK, EFI_AHCI_PORT_SSTS_DET_PCE, ATA_ATAPI_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return AhciWaitDeviceReady (PciIo, Port);
+}
+
+/**
+ Recovers the SATA port from error condition.
+ This function implements algorithm described in
+ AHCI spec 1.3.1 section 6.2.2
+
+ @param[in] PciIo Pointer to AHCI controller PciIo.
+ @param[in] Port SATA port index on which to check.
+
+ @retval EFI_SUCCESS Port recovered.
+ @retval Others Failed to recover port.
+**/
+EFI_STATUS
+AhciRecoverPortError (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Port
+ )
+{
+ UINT32 Offset;
+ UINT32 PortInterrupt;
+ UINT32 PortTfd;
+ EFI_STATUS Status;
+
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
+ PortInterrupt = AhciReadReg (PciIo, Offset);
+ if ((PortInterrupt & EFI_AHCI_PORT_IS_FATAL_ERROR_MASK) == 0) {
+ //
+ // No fatal error detected. Exit with success as port should still be operational.
+ // No need to clear IS as it will be cleared when the next command starts.
+ //
+ return EFI_SUCCESS;
+ }
+
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_CMD;
+ AhciAndReg (PciIo, Offset, ~(UINT32)EFI_AHCI_PORT_CMD_ST);
+
+ Status = AhciWaitMmioSet (PciIo, Offset, EFI_AHCI_PORT_CMD_CR, 0, ATA_ATAPI_TIMEOUT);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Ahci port %d is in hung state, aborting recovery\n", Port));
+ return Status;
+ }
+
+ //
+ // If TFD.BSY or TFD.DRQ is still set it means that drive is hung and software has
+ // to reset it before sending any additional commands.
+ //
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+ PortTfd = AhciReadReg (PciIo, Offset);
+ if ((PortTfd & (EFI_AHCI_PORT_TFD_BSY | EFI_AHCI_PORT_TFD_DRQ)) != 0) {
+ Status = AhciResetPort (PciIo, Port);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to reset the port %d\n", Port));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Checks if specified FIS has been received.
+
+ @param[in] PciIo Pointer to AHCI controller PciIo.
+ @param[in] Port SATA port index on which to check.
+ @param[in] FisType FIS type for which to check.
+
+ @retval EFI_SUCCESS FIS received.
+ @retval EFI_NOT_READY FIS not received yet.
+ @retval EFI_DEVICE_ERROR AHCI controller reported an error on port.
+**/
+EFI_STATUS
+AhciCheckFisReceived (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Port,
+ IN SATA_FIS_TYPE FisType
+ )
+{
+ UINT32 Offset;
+ UINT32 PortInterrupt;
+ UINT32 PortTfd;
+
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_IS;
+ PortInterrupt = AhciReadReg (PciIo, Offset);
+ if ((PortInterrupt & EFI_AHCI_PORT_IS_ERROR_MASK) != 0) {
+ DEBUG ((DEBUG_ERROR, "AHCI: Error interrupt reported PxIS: %X\n", PortInterrupt));
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // For PIO setup FIS - According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
+ // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
+ // after the transaction is finished successfully.
+ // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
+ // By this way, we can know if there is a real error happened.
+ //
+ if (((FisType == SataFisD2H) && ((PortInterrupt & EFI_AHCI_PORT_IS_DHRS) != 0)) ||
+ ((FisType == SataFisPioSetup) && (PortInterrupt & (EFI_AHCI_PORT_IS_PSS | EFI_AHCI_PORT_IS_DHRS)) != 0) ||
+ ((FisType == SataFisDmaSetup) && (PortInterrupt & (EFI_AHCI_PORT_IS_DSS | EFI_AHCI_PORT_IS_DHRS)) != 0)) {
+ Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
+ PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
+ if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
+ return EFI_DEVICE_ERROR;
+ } else {
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_READY;
+}
+
+/**
+ Waits until specified FIS has been received.
+
+ @param[in] PciIo Pointer to AHCI controller PciIo.
+ @param[in] Port SATA port index on which to check.
+ @param[in] Timeout Time after which function should stop polling.
+ @param[in] FisType FIS type for which to check.
+
+ @retval EFI_SUCCESS FIS received.
+ @retval EFI_TIMEOUT FIS failed to arrive within a specified time period.
+ @retval EFI_DEVICE_ERROR AHCI controller reported an error on port.
+**/
+EFI_STATUS
+AhciWaitUntilFisReceived (
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN UINT8 Port,
+ IN UINT64 Timeout,
+ IN SATA_FIS_TYPE FisType
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN InfiniteWait;
+ UINT64 Delay;
+
+ Delay = DivU64x32 (Timeout, 1000) + 1;
+ if (Timeout == 0) {
+ InfiniteWait = TRUE;
+ } else {
+ InfiniteWait = FALSE;
+ }
+
+ do {
+ Status = AhciCheckFisReceived (PciIo, Port, FisType);
+ if (Status != EFI_NOT_READY) {
+ return Status;
+ }
+ //
+ // Stall for 100 microseconds.
+ //
+ MicroSecondDelay (100);
+ Delay--;
+ } while (InfiniteWait || (Delay > 0));
+
+ return EFI_TIMEOUT;
+}
+
+/**
+ Prints contents of the ATA command block into the debug port.
+
+ @param[in] AtaCommandBlock AtaCommandBlock to print.
+ @param[in] DebugLevel Debug level on which to print.
+**/
+VOID
+AhciPrintCommandBlock (
+ IN EFI_ATA_COMMAND_BLOCK *AtaCommandBlock,
+ IN UINT32 DebugLevel
+ )
+{
+ DEBUG ((DebugLevel, "ATA COMMAND BLOCK:\n"));
+ DEBUG ((DebugLevel, "AtaCommand: %d\n", AtaCommandBlock->AtaCommand));
+ DEBUG ((DebugLevel, "AtaFeatures: %X\n", AtaCommandBlock->AtaFeatures));
+ DEBUG ((DebugLevel, "AtaSectorNumber: %d\n", AtaCommandBlock->AtaSectorNumber));
+ DEBUG ((DebugLevel, "AtaCylinderLow: %X\n", AtaCommandBlock->AtaCylinderHigh));
+ DEBUG ((DebugLevel, "AtaCylinderHigh: %X\n", AtaCommandBlock->AtaCylinderHigh));
+ DEBUG ((DebugLevel, "AtaDeviceHead: %d\n", AtaCommandBlock->AtaDeviceHead));
+ DEBUG ((DebugLevel, "AtaSectorNumberExp: %d\n", AtaCommandBlock->AtaSectorNumberExp));
+ DEBUG ((DebugLevel, "AtaCylinderLowExp: %X\n", AtaCommandBlock->AtaCylinderLowExp));
+ DEBUG ((DebugLevel, "AtaCylinderHighExp: %X\n", AtaCommandBlock->AtaCylinderHighExp));
+ DEBUG ((DebugLevel, "AtaFeaturesExp: %X\n", AtaCommandBlock->AtaFeaturesExp));
+ DEBUG ((DebugLevel, "AtaSectorCount: %d\n", AtaCommandBlock->AtaSectorCount));
+ DEBUG ((DebugLevel, "AtaSectorCountExp: %d\n", AtaCommandBlock->AtaSectorCountExp));
+}
+
+/**
+ Prints contents of the ATA status block into the debug port.
+
+ @param[in] AtaStatusBlock AtaStatusBlock to print.
+ @param[in] DebugLevel Debug level on which to print.
+**/
+VOID
+AhciPrintStatusBlock (
+ IN EFI_ATA_STATUS_BLOCK *AtaStatusBlock,
+ IN UINT32 DebugLevel
+ )
+{
+ //
+ // Only print status and error since we have all of the rest printed as
+ // a part of command block print.
+ //
+ DEBUG ((DebugLevel, "ATA STATUS BLOCK:\n"));
+ DEBUG ((DebugLevel, "AtaStatus: %d\n", AtaStatusBlock->AtaStatus));
+ DEBUG ((DebugLevel, "AtaError: %d\n", AtaStatusBlock->AtaError));
+}
+
+/**
Start a PIO data transfer on specific port.
@param[in] PciIo The PCI IO protocol instance.
@@ -665,26 +938,14 @@ AhciPioTransfer (
)
{
EFI_STATUS Status;
- UINTN FisBaseAddr;
- UINTN Offset;
EFI_PHYSICAL_ADDRESS PhyAddr;
VOID *Map;
UINTN MapLength;
EFI_PCI_IO_PROTOCOL_OPERATION Flag;
- UINT64 Delay;
EFI_AHCI_COMMAND_FIS CFis;
EFI_AHCI_COMMAND_LIST CmdList;
- UINT32 PortTfd;
UINT32 PrdCount;
- BOOLEAN InfiniteWait;
- BOOLEAN PioFisReceived;
- BOOLEAN D2hFisReceived;
-
- if (Timeout == 0) {
- InfiniteWait = TRUE;
- } else {
- InfiniteWait = FALSE;
- }
+ UINT32 Retry;
if (Read) {
Flag = EfiPciIoOperationBusMasterWrite;
@@ -719,114 +980,58 @@ AhciPioTransfer (
CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
CmdList.AhciCmdW = Read ? 0 : 1;
- AhciBuildCommand (
- PciIo,
- AhciRegisters,
- Port,
- PortMultiplier,
- &CFis,
- &CmdList,
- AtapiCommand,
- AtapiCommandLength,
- 0,
- (VOID *)(UINTN)PhyAddr,
- DataCount
- );
-
- Status = AhciStartCommand (
- PciIo,
- Port,
- 0,
- Timeout
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- //
- // Check the status and wait the driver sending data
- //
- FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
-
- if (Read && (AtapiCommand == 0)) {
- //
- // Wait device sends the PIO setup fis before data transfer
- //
- Status = EFI_TIMEOUT;
- Delay = DivU64x32 (Timeout, 1000) + 1;
- do {
- PioFisReceived = FALSE;
- D2hFisReceived = FALSE;
- Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
- Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, NULL);
- if (!EFI_ERROR (Status)) {
- PioFisReceived = TRUE;
- }
- //
- // According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
- // But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
- // after the transaction is finished successfully.
- // To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
- // By this way, we can know if there is a real error happened.
- //
- Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
- Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
- if (!EFI_ERROR (Status)) {
- D2hFisReceived = TRUE;
- }
+ for (Retry = 0; Retry < AHCI_COMMAND_RETRIES; Retry++) {
+ AhciBuildCommand (
+ PciIo,
+ AhciRegisters,
+ Port,
+ PortMultiplier,
+ &CFis,
+ &CmdList,
+ AtapiCommand,
+ AtapiCommandLength,
+ 0,
+ (VOID *)(UINTN)PhyAddr,
+ DataCount
+ );
- if (PioFisReceived || D2hFisReceived) {
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
- PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
- //
- // PxTFD will be updated if there is a D2H or SetupFIS received.
- //
- if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
- Status = EFI_DEVICE_ERROR;
- break;
- }
+ DEBUG ((DEBUG_VERBOSE, "Starting command for PIO transfer:\n"));
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
+ Status = AhciStartCommand (
+ PciIo,
+ Port,
+ 0,
+ Timeout
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ if (Read && (AtapiCommand == 0)) {
+ Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisPioSetup);
+ if (Status == EFI_SUCCESS) {
PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
if (PrdCount == DataCount) {
Status = EFI_SUCCESS;
- break;
+ } else {
+ Status = EFI_DEVICE_ERROR;
}
}
-
- //
- // Stall for 100 microseconds.
- //
- MicroSecondDelay(100);
-
- Delay--;
- if (Delay == 0) {
- Status = EFI_TIMEOUT;
- }
- } while (InfiniteWait || (Delay > 0));
- } else {
- //
- // Wait for D2H Fis is received
- //
- Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
- Status = AhciWaitMemSet (
- Offset,
- EFI_AHCI_FIS_TYPE_MASK,
- EFI_AHCI_FIS_REGISTER_D2H,
- Timeout
- );
-
- if (EFI_ERROR (Status)) {
- goto Exit;
+ } else {
+ Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisD2H);
}
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
- PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
- if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
- Status = EFI_DEVICE_ERROR;
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "PIO command failed at retry %d\n", Retry));
+ Status = AhciRecoverPortError (PciIo, Port);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ break;
}
}
-Exit:
AhciStopCommand (
PciIo,
Port,
@@ -846,6 +1051,18 @@ Exit:
AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "Failed to execute command for PIO transfer:\n"));
+ //
+ // Repeat command block here to make sure it is printed on
+ // device error debug level.
+ //
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_ERROR);
+ AhciPrintStatusBlock (AtaStatusBlock, DEBUG_ERROR);
+ } else {
+ AhciPrintStatusBlock (AtaStatusBlock, DEBUG_VERBOSE);
+ }
+
return Status;
}
@@ -893,18 +1110,15 @@ AhciDmaTransfer (
)
{
EFI_STATUS Status;
- UINTN Offset;
EFI_PHYSICAL_ADDRESS PhyAddr;
VOID *Map;
UINTN MapLength;
EFI_PCI_IO_PROTOCOL_OPERATION Flag;
EFI_AHCI_COMMAND_FIS CFis;
EFI_AHCI_COMMAND_LIST CmdList;
- UINTN FisBaseAddr;
- UINT32 PortTfd;
-
EFI_PCI_IO_PROTOCOL *PciIo;
EFI_TPL OldTpl;
+ UINT32 Retry;
Map = NULL;
PciIo = Instance->PciIo;
@@ -914,36 +1128,21 @@ AhciDmaTransfer (
}
//
- // Before starting the Blocking BlockIO operation, push to finish all non-blocking
- // BlockIO tasks.
- // Delay 100us to simulate the blocking time out checking.
+ // Set Status to suppress incorrect compiler/analyzer warnings
//
- OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
- while ((Task == NULL) && (!IsListEmpty (&Instance->NonBlockingTaskList))) {
- AsyncNonBlockingTransferRoutine (NULL, Instance);
- //
- // Stall for 100us.
- //
- MicroSecondDelay (100);
- }
- gBS->RestoreTPL (OldTpl);
+ Status = EFI_SUCCESS;
- if ((Task == NULL) || ((Task != NULL) && (!Task->IsStart))) {
- //
- // Mark the Task to indicate that it has been started.
- //
- if (Task != NULL) {
- Task->IsStart = TRUE;
- }
+ //
+ // DMA buffer allocation. Needs to be done only once for both sync and async
+ // DMA transfers irrespective of number of retries.
+ //
+ if ((Task == NULL) || ((Task != NULL) && (Task->Map == NULL))) {
if (Read) {
Flag = EfiPciIoOperationBusMasterWrite;
} else {
Flag = EfiPciIoOperationBusMasterRead;
}
- //
- // Construct command list and command table with pci bus address.
- //
MapLength = DataCount;
Status = PciIo->Map (
PciIo,
@@ -957,80 +1156,127 @@ AhciDmaTransfer (
if (EFI_ERROR (Status) || (DataCount != MapLength)) {
return EFI_BAD_BUFFER_SIZE;
}
-
if (Task != NULL) {
Task->Map = Map;
}
- //
- // Package read needed
- //
+ }
+
+ if (Task == NULL || (Task != NULL && !Task->IsStart)) {
AhciBuildCommandFis (&CFis, AtaCommandBlock);
ZeroMem (&CmdList, sizeof (EFI_AHCI_COMMAND_LIST));
CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
CmdList.AhciCmdW = Read ? 0 : 1;
-
- AhciBuildCommand (
- PciIo,
- AhciRegisters,
- Port,
- PortMultiplier,
- &CFis,
- &CmdList,
- AtapiCommand,
- AtapiCommandLength,
- 0,
- (VOID *)(UINTN)PhyAddr,
- DataCount
- );
-
- Status = AhciStartCommand (
- PciIo,
- Port,
- 0,
- Timeout
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
}
- //
- // Wait for command complete
- //
- FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
- Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
- if (Task != NULL) {
+ if (Task == NULL) {
//
- // For Non-blocking
+ // Before starting the Blocking BlockIO operation, push to finish all non-blocking
+ // BlockIO tasks.
+ // Delay 100us to simulate the blocking time out checking.
//
- Status = AhciCheckMemSet (
- Offset,
- EFI_AHCI_FIS_TYPE_MASK,
- EFI_AHCI_FIS_REGISTER_D2H,
- Task
- );
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ while (!IsListEmpty (&Instance->NonBlockingTaskList)) {
+ AsyncNonBlockingTransferRoutine (NULL, Instance);
+ //
+ // Stall for 100us.
+ //
+ MicroSecondDelay (100);
+ }
+ gBS->RestoreTPL (OldTpl);
+ for (Retry = 0; Retry < AHCI_COMMAND_RETRIES; Retry++) {
+ AhciBuildCommand (
+ PciIo,
+ AhciRegisters,
+ Port,
+ PortMultiplier,
+ &CFis,
+ &CmdList,
+ AtapiCommand,
+ AtapiCommandLength,
+ 0,
+ (VOID *)(UINTN)PhyAddr,
+ DataCount
+ );
+
+ DEBUG ((DEBUG_VERBOSE, "Starting command for sync DMA transfer:\n"));
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
+ Status = AhciStartCommand (
+ PciIo,
+ Port,
+ 0,
+ Timeout
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisD2H);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "DMA command failed at retry: %d\n", Retry));
+ Status = AhciRecoverPortError (PciIo, Port);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
} else {
- Status = AhciWaitMemSet (
- Offset,
- EFI_AHCI_FIS_TYPE_MASK,
- EFI_AHCI_FIS_REGISTER_D2H,
- Timeout
- );
- }
+ if (!Task->IsStart) {
+ AhciBuildCommand (
+ PciIo,
+ AhciRegisters,
+ Port,
+ PortMultiplier,
+ &CFis,
+ &CmdList,
+ AtapiCommand,
+ AtapiCommandLength,
+ 0,
+ (VOID *)(UINTN)PhyAddr,
+ DataCount
+ );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
+ DEBUG ((DEBUG_VERBOSE, "Starting command for async DMA transfer:\n"));
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
+ Status = AhciStartCommand (
+ PciIo,
+ Port,
+ 0,
+ Timeout
+ );
+ if (!EFI_ERROR (Status)) {
+ Task->IsStart = TRUE;
+ }
+ }
+ if (Task->IsStart) {
+ Status = AhciCheckFisReceived (PciIo, Port, SataFisD2H);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "DMA command failed at retry: %d\n", Task->RetryTimes));
+ Status = AhciRecoverPortError (PciIo, Port);
+ //
+ // If recovery passed mark the Task as not started and change the status
+ // to EFI_NOT_READY. This will make the higher level call this function again
+ // and on next call the command will be re-issued due to IsStart being FALSE.
+ // This also makes the next condition decrement the RetryTimes.
+ //
+ if (Status == EFI_SUCCESS) {
+ Task->IsStart = FALSE;
+ Status = EFI_NOT_READY;
+ }
+ }
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
- PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
- if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
- Status = EFI_DEVICE_ERROR;
+ if (Status == EFI_NOT_READY) {
+ if (!Task->InfiniteWait && Task->RetryTimes == 0) {
+ Status = EFI_TIMEOUT;
+ } else {
+ Task->RetryTimes--;
+ }
+ }
+ }
}
-Exit:
//
// For Blocking mode, the command should be stopped, the Fis should be disabled
// and the PciIo should be unmapped.
@@ -1064,6 +1310,19 @@ Exit:
}
AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
+
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "Failed to execute command for DMA transfer:\n"));
+ //
+ // Repeat command block here to make sure it is printed on
+ // device error debug level.
+ //
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_ERROR);
+ AhciPrintStatusBlock (AtaStatusBlock, DEBUG_ERROR);
+ } else {
+ AhciPrintStatusBlock (AtaStatusBlock, DEBUG_VERBOSE);
+ }
+
return Status;
}
@@ -1105,11 +1364,9 @@ AhciNonDataTransfer (
)
{
EFI_STATUS Status;
- UINTN FisBaseAddr;
- UINTN Offset;
- UINT32 PortTfd;
EFI_AHCI_COMMAND_FIS CFis;
EFI_AHCI_COMMAND_LIST CmdList;
+ UINT32 Retry;
//
// Package read needed
@@ -1120,53 +1377,45 @@ AhciNonDataTransfer (
CmdList.AhciCmdCfl = EFI_AHCI_FIS_REGISTER_H2D_LENGTH / 4;
- AhciBuildCommand (
- PciIo,
- AhciRegisters,
- Port,
- PortMultiplier,
- &CFis,
- &CmdList,
- AtapiCommand,
- AtapiCommandLength,
- 0,
- NULL,
- 0
- );
-
- Status = AhciStartCommand (
- PciIo,
- Port,
- 0,
- Timeout
- );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
-
- //
- // Wait device sends the Response Fis
- //
- FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
- Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
- Status = AhciWaitMemSet (
- Offset,
- EFI_AHCI_FIS_TYPE_MASK,
- EFI_AHCI_FIS_REGISTER_D2H,
- Timeout
- );
+ for (Retry = 0; Retry < AHCI_COMMAND_RETRIES; Retry++) {
+ AhciBuildCommand (
+ PciIo,
+ AhciRegisters,
+ Port,
+ PortMultiplier,
+ &CFis,
+ &CmdList,
+ AtapiCommand,
+ AtapiCommandLength,
+ 0,
+ NULL,
+ 0
+ );
- if (EFI_ERROR (Status)) {
- goto Exit;
- }
+ DEBUG ((DEBUG_VERBOSE, "Starting command for non data transfer:\n"));
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_VERBOSE);
+ Status = AhciStartCommand (
+ PciIo,
+ Port,
+ 0,
+ Timeout
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
- PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
- if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
- Status = EFI_DEVICE_ERROR;
+ Status = AhciWaitUntilFisReceived (PciIo, Port, Timeout, SataFisD2H);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "Non data transfer failed at retry %d\n", Retry));
+ Status = AhciRecoverPortError (PciIo, Port);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ } else {
+ break;
+ }
}
-Exit:
AhciStopCommand (
PciIo,
Port,
@@ -1181,6 +1430,18 @@ Exit:
AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "Failed to execute command for non data transfer:\n"));
+ //
+ // Repeat command block here to make sure it is printed on
+ // device error debug level.
+ //
+ AhciPrintCommandBlock (AtaCommandBlock, DEBUG_ERROR);
+ AhciPrintStatusBlock (AtaStatusBlock, DEBUG_ERROR);
+ } else {
+ AhciPrintStatusBlock (AtaStatusBlock, DEBUG_VERBOSE);
+ }
+
return Status;
}
@@ -2629,29 +2890,8 @@ AhciModeInitialization (
continue;
}
- //
- // According to SATA1.0a spec section 5.2, we need to wait for PxTFD.BSY and PxTFD.DRQ
- // and PxTFD.ERR to be zero. The maximum wait time is 16s which is defined at ATA spec.
- //
- PhyDetectDelay = 16 * 1000;
- do {
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_SERR;
- if (AhciReadReg(PciIo, Offset) != 0) {
- AhciWriteReg (PciIo, Offset, AhciReadReg(PciIo, Offset));
- }
- Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
-
- Data = AhciReadReg (PciIo, Offset) & EFI_AHCI_PORT_TFD_MASK;
- if (Data == 0) {
- break;
- }
-
- MicroSecondDelay (1000);
- PhyDetectDelay--;
- } while (PhyDetectDelay > 0);
-
- if (PhyDetectDelay == 0) {
- DEBUG ((EFI_D_ERROR, "Port %d Device presence detected but phy not ready (TFD=0x%X)\n", Port, Data));
+ Status = AhciWaitDeviceReady (PciIo, Port);
+ if (EFI_ERROR (Status)) {
continue;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h
index 37fccf6249c..f4c44bb2a38 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AhciMode.h
@@ -1,7 +1,7 @@
/** @file
Header file for AHCI mode of ATA host controller.
- Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -96,7 +96,7 @@ typedef union {
#define EFI_AHCI_PORT_IS 0x0010
#define EFI_AHCI_PORT_IS_DHRS BIT0
#define EFI_AHCI_PORT_IS_PSS BIT1
-#define EFI_AHCI_PORT_IS_SSS BIT2
+#define EFI_AHCI_PORT_IS_DSS BIT2
#define EFI_AHCI_PORT_IS_SDBS BIT3
#define EFI_AHCI_PORT_IS_UFS BIT4
#define EFI_AHCI_PORT_IS_DPS BIT5
@@ -113,6 +113,8 @@ typedef union {
#define EFI_AHCI_PORT_IS_CPDS BIT31
#define EFI_AHCI_PORT_IS_CLEAR 0xFFFFFFFF
#define EFI_AHCI_PORT_IS_FIS_CLEAR 0x0000000F
+#define EFI_AHCI_PORT_IS_ERROR_MASK (EFI_AHCI_PORT_IS_INFS | EFI_AHCI_PORT_IS_IFS | EFI_AHCI_PORT_IS_HBDS | EFI_AHCI_PORT_IS_HBFS | EFI_AHCI_PORT_IS_TFES)
+#define EFI_AHCI_PORT_IS_FATAL_ERROR_MASK (EFI_AHCI_PORT_IS_IFS | EFI_AHCI_PORT_IS_HBDS | EFI_AHCI_PORT_IS_HBFS | EFI_AHCI_PORT_IS_TFES)
#define EFI_AHCI_PORT_IE 0x0014
#define EFI_AHCI_PORT_CMD 0x0018
@@ -121,9 +123,11 @@ typedef union {
#define EFI_AHCI_PORT_CMD_SUD BIT1
#define EFI_AHCI_PORT_CMD_POD BIT2
#define EFI_AHCI_PORT_CMD_CLO BIT3
-#define EFI_AHCI_PORT_CMD_CR BIT15
#define EFI_AHCI_PORT_CMD_FRE BIT4
+#define EFI_AHCI_PORT_CMD_CCS_MASK (BIT8 | BIT9 | BIT10 | BIT11 | BIT12)
+#define EFI_AHCI_PORT_CMD_CCS_SHIFT 8
#define EFI_AHCI_PORT_CMD_FR BIT14
+#define EFI_AHCI_PORT_CMD_CR BIT15
#define EFI_AHCI_PORT_CMD_MASK ~(EFI_AHCI_PORT_CMD_ST | EFI_AHCI_PORT_CMD_FRE | EFI_AHCI_PORT_CMD_COL)
#define EFI_AHCI_PORT_CMD_PMA BIT17
#define EFI_AHCI_PORT_CMD_HPCP BIT18
@@ -188,6 +192,8 @@ typedef union {
#define AHCI_PORT_DEVSLP_DITO_MASK 0x01FF8000
#define AHCI_PORT_DEVSLP_DM_MASK 0x1E000000
+#define AHCI_COMMAND_RETRIES 5
+
#pragma pack(1)
//
// Command List structure includes total 32 entries.
@@ -240,6 +246,12 @@ typedef struct {
UINT8 AhciCFisRsvd5[44];
} EFI_AHCI_COMMAND_FIS;
+typedef enum {
+ SataFisD2H = 0,
+ SataFisPioSetup,
+ SataFisDmaSetup
+} SATA_FIS_TYPE;
+
//
// ACMD: ATAPI command (12 or 16 bytes)
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.uni
index f34c68c18bc..ec9cdddc874 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.uni
@@ -1,7 +1,7 @@
// /** @file
// PCI Incompatible device support module template.
//
-// Installs EFI PCI Incompatible Device Support protocol and includes one incompatile
+// Installs EFI PCI Incompatible Device Support protocol and includes one incompatible
// pci devices list template.
//
// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
index 6d38aa52e76..d92004481ee 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
@@ -1,7 +1,7 @@
## @file
# PCI Incompatible device support module template.
#
-# Installs EFI PCI Incompatible Device Support protocol and includes one incompatile
+# Installs EFI PCI Incompatible Device Support protocol and includes one incompatible
# pci devices list template.
#
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
index 2bd9305ec36..0d2bf0c87cc 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceIo.c
@@ -856,6 +856,10 @@ CoherentPciIoAllocateBuffer (
return EFI_UNSUPPORTED;
}
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
if ((MemoryType != EfiBootServicesData) &&
(MemoryType != EfiRuntimeServicesData)) {
return EFI_INVALID_PARAMETER;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
index 67af88d723a..967933e278b 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBus.h
@@ -1,7 +1,7 @@
/** @file
Header files and data structures needed by PCI Bus module.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -280,6 +280,8 @@ struct _PCI_IO_DEVICE {
// This field is used to support this case.
//
UINT16 BridgeIoAlignment;
+ UINT32 ResizableBarOffset;
+ UINT32 ResizableBarNumber;
};
#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
index b3cd04e2224..9d999f973b5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
@@ -2,7 +2,7 @@
# The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
# Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -106,6 +106,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdAriSupport ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMrIovSupport ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport ## CONSUMES
[UserExtensions.TianoCore."ExtraFiles"]
PciBusDxeExtra.uni
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
index 7ffb829c8a2..15bd182bed1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.c
@@ -1,7 +1,7 @@
/** @file
PCI emumeration support functions implementation for PCI Bus module.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -1168,12 +1168,7 @@ ProcessOptionRomLight (
ProcessOptionRomLight (Temp);
}
- PciRomGetImageMapping (Temp);
-
- //
- // The OpRom has already been processed in the first round
- //
- Temp->AllOpRomProcessed = TRUE;
+ Temp->AllOpRomProcessed = PciRomGetImageMapping (Temp);
CurrentLink = CurrentLink->ForwardLink;
}
@@ -1686,6 +1681,7 @@ PciIovParseVfBar (
);
if (EFI_ERROR (Status)) {
+ PciIoDevice->VfPciBar[BarIndex].BarType = PciBarTypeUnknown;
return Offset + 4;
}
@@ -2426,6 +2422,31 @@ CreatePciIoDevice (
}
}
+ PciIoDevice->ResizableBarOffset = 0;
+ if (PcdGetBool (PcdPcieResizableBarSupport)) {
+ Status = LocatePciExpressCapabilityRegBlock (
+ PciIoDevice,
+ PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID,
+ &PciIoDevice->ResizableBarOffset,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
+ UINT32 Offset;
+ Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
+ + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY),
+ PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ Offset,
+ sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL),
+ &ResizableBarControl
+ );
+ PciIoDevice->ResizableBarNumber = ResizableBarControl.Bits.ResizableBarNumber;
+ PciProgramResizableBar (PciIoDevice, PciResizableBarMax);
+ }
+ }
+
//
// Initialize the reserved resource list
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
index b2dbb5f563b..1d39c5171d3 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumeratorSupport.h
@@ -1,7 +1,7 @@
/** @file
PCI enumeration support functions declaration for PCI Bus module.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -467,4 +467,14 @@ DumpPpbPaddingResource (
IN PCI_BAR_TYPE ResourceType
);
+/**
+ Dump the PCI BAR information.
+
+ @param PciIoDevice PCI IO instance.
+**/
+VOID
+DumpPciBars (
+ IN PCI_IO_DEVICE *PciIoDevice
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
index 3c4a65f8eb0..2b761007406 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.c
@@ -1,7 +1,7 @@
/** @file
Internal library implementation for PCI Bus module.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -378,6 +378,60 @@ DumpResourceMap (
}
/**
+ Adjust the Devices' BAR size to minimum value if it support Resizeable BAR capability.
+
+ @param RootBridgeDev Pointer to instance of PCI_IO_DEVICE..
+
+ @return TRUE if BAR size is adjusted.
+
+**/
+BOOLEAN
+AdjustPciDeviceBarSize (
+ IN PCI_IO_DEVICE *RootBridgeDev
+ )
+{
+ PCI_IO_DEVICE *PciIoDevice;
+ LIST_ENTRY *CurrentLink;
+ BOOLEAN Adjusted;
+ UINTN Offset;
+ UINTN BarIndex;
+
+ Adjusted = FALSE;
+ CurrentLink = RootBridgeDev->ChildList.ForwardLink;
+
+ while (CurrentLink != NULL && CurrentLink != &RootBridgeDev->ChildList) {
+ PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
+
+ if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
+ if (AdjustPciDeviceBarSize (PciIoDevice)) {
+ Adjusted = TRUE;
+ }
+ } else {
+ if (PciIoDevice->ResizableBarOffset != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n",
+ PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber
+ ));
+ PciProgramResizableBar (PciIoDevice, PciResizableBarMin);
+ //
+ // Start to parse the bars
+ //
+ for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
+ Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
+ }
+ Adjusted = TRUE;
+ DEBUG_CODE (DumpPciBars (PciIoDevice););
+ }
+ }
+
+ CurrentLink = CurrentLink->ForwardLink;
+ }
+
+ return Adjusted;
+}
+
+/**
Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
@param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
@@ -422,6 +476,10 @@ PciHostBridgeResourceAllocator (
PCI_RESOURCE_NODE PMem64Pool;
EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData;
EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
+ BOOLEAN ResizableBarNeedAdjust;
+ BOOLEAN ResizableBarAdjusted;
+
+ ResizableBarNeedAdjust = PcdGetBool (PcdPcieResizableBarSupport);
//
// It may try several times if the resource allocation fails
@@ -703,19 +761,30 @@ PciHostBridgeResourceAllocator (
sizeof (AllocFailExtendedData)
);
- Status = PciHostBridgeAdjustAllocation (
- &IoPool,
- &Mem32Pool,
- &PMem32Pool,
- &Mem64Pool,
- &PMem64Pool,
- IoResStatus,
- Mem32ResStatus,
- PMem32ResStatus,
- Mem64ResStatus,
- PMem64ResStatus
- );
-
+ //
+ // When resource conflict happens, adjust the BAR size first.
+ // Only when adjusting BAR size doesn't help or BAR size cannot be adjusted,
+ // reject the device who requests largest resource that causes conflict.
+ //
+ ResizableBarAdjusted = FALSE;
+ if (ResizableBarNeedAdjust) {
+ ResizableBarAdjusted = AdjustPciDeviceBarSize (RootBridgeDev);
+ ResizableBarNeedAdjust = FALSE;
+ }
+ if (!ResizableBarAdjusted) {
+ Status = PciHostBridgeAdjustAllocation (
+ &IoPool,
+ &Mem32Pool,
+ &PMem32Pool,
+ &Mem64Pool,
+ &PMem64Pool,
+ IoResStatus,
+ Mem32ResStatus,
+ PMem32ResStatus,
+ Mem64ResStatus,
+ PMem64ResStatus
+ );
+ }
//
// Destroy all the resource tree
//
@@ -1651,3 +1720,90 @@ PciHostBridgeEnumerator (
return EFI_SUCCESS;
}
+
+/**
+ This function is used to program the Resizable BAR Register.
+
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.
+ @param ResizableBarOp PciResizableBarMax: Set BAR to max size
+ PciResizableBarMin: set BAR to min size.
+
+ @retval EFI_SUCCESS Successfully enumerated the host bridge.
+ @retval other Some error occurred when enumerating the host bridge.
+
+**/
+EFI_STATUS
+PciProgramResizableBar (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Capabilities;
+ UINT32 Index;
+ UINT32 Offset;
+ INTN Bit;
+ UINTN ResizableBarNumber;
+ EFI_STATUS Status;
+ PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Entries[PCI_MAX_BAR];
+
+ ASSERT (PciIoDevice->ResizableBarOffset != 0);
+
+ DEBUG ((DEBUG_INFO, " Programs Resizable BAR register, offset: 0x%08x, number: %d\n",
+ PciIoDevice->ResizableBarOffset, PciIoDevice->ResizableBarNumber));
+
+ ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);
+ PciIo = &PciIoDevice->PciIo;
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),
+ sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
+ (VOID *)(&Entries)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ for (Index = 0; Index < ResizableBarNumber; Index++) {
+
+ //
+ // When the bit of Capabilities Set, indicates that the Function supports
+ // operating with the BAR sized to (2^Bit) MB.
+ // Example:
+ // Bit 0 is set: supports operating with the BAR sized to 1 MB
+ // Bit 1 is set: supports operating with the BAR sized to 2 MB
+ // Bit n is set: supports operating with the BAR sized to (2^n) MB
+ //
+ Capabilities = LShiftU64(Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)
+ | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;
+
+ if (ResizableBarOp == PciResizableBarMax) {
+ Bit = HighBitSet64(Capabilities);
+ } else {
+ ASSERT (ResizableBarOp == PciResizableBarMin);
+ Bit = LowBitSet64(Capabilities);
+ }
+
+ ASSERT (Bit >= 0);
+
+ Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
+ + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)
+ + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);
+
+ Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32) Bit;
+ DEBUG ((
+ DEBUG_INFO,
+ " Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",
+ OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),
+ Capabilities, LShiftU64 (SIZE_1MB, Bit)
+ ));
+ PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint32,
+ Offset,
+ 1,
+ &Entries[Index].ResizableBarControl.Uint32
+ );
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
index b943cf0fd47..70ab07a8c37 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciBusDxe/PciLib.h
@@ -1,7 +1,7 @@
/** @file
Internal library declaration for PCI Bus module.
-Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -24,6 +24,10 @@ typedef struct {
UINT8 *AllocRes;
} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD;
+typedef enum {
+ PciResizableBarMin = 0x00,
+ PciResizableBarMax = 0xFF
+} PCI_RESIZABLE_BAR_OPERATION;
/**
Retrieve the PCI Card device BAR information via PciIo interface.
@@ -156,4 +160,20 @@ PciHostBridgeEnumerator (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
);
+/**
+ This function is used to program the Resizable BAR Register.
+
+ @param PciIoDevice A pointer to the PCI_IO_DEVICE.
+ @param ResizableBarOp PciResizableBarMax: Set BAR to max size
+ PciResizableBarMin: set BAR to min size.
+
+ @retval EFI_SUCCESS Successfully enumerated the host bridge.
+ @retval other Some error occurred when enumerating the host bridge.
+
+**/
+EFI_STATUS
+PciProgramResizableBar (
+ IN PCI_IO_DEVICE *PciIoDevice,
+ IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp
+ );
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c
index bc8422b5509..6782d27d7a3 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/PciSioSerialDxe/SerialIo.c
@@ -1,7 +1,7 @@
/** @file
SerialIo implementation for PCI or SIO UARTs.
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -436,6 +436,68 @@ SerialReceiveTransmit (
return EFI_SUCCESS;
}
+/**
+ Flush the serial hardware transmit FIFO, holding register, and shift register.
+
+ @param SerialDevice The device to flush.
+
+ @retval EFI_SUCCESS The transmit FIFO is completely flushed.
+ @retval EFI_TIMEOUT A timeout occured waiting for the transmit FIFO to flush.
+**/
+EFI_STATUS
+SerialFlushTransmitFifo (
+ SERIAL_DEV *SerialDevice
+ )
+{
+ SERIAL_PORT_LSR Lsr;
+ UINTN Timeout;
+ UINTN Elapsed;
+
+ //
+ // If this is the first time the UART is being configured, then the current
+ // UART settings are not known, so compute a timeout to wait for the Tx FIFO
+ // assuming the worst case current settings.
+ //
+ // Timeout = (Max Bits per Char) * (Max Pending Chars) / (Slowest Baud Rate)
+ // Max Bits per Char = Start bit + 8 data bits + parity + 2 stop bits = 12
+ // Max Pending Chars = Largest Tx FIFO + hold + shift = 64 + 1 + 1 = 66
+ // Slowest Reasonable Baud Rate = 300 baud
+ // Timeout = 12 * 66 / 300 = 2.64 seconds = 2,640,000 uS
+ //
+ Timeout = 2640000;
+
+ //
+ // Use the largest of the computed timeout, the default timeout, and the
+ // currently set timeout.
+ //
+ Timeout = MAX (Timeout, SERIAL_PORT_DEFAULT_TIMEOUT);
+ Timeout = MAX (Timeout, SerialDevice->SerialMode.Timeout);
+
+ //
+ // Wait for the shortest time possible for the serial port to be ready making
+ // sure the transmit FIFO, holding register, and shift register are all
+ // empty. The actual wait time is expected to be very small because the
+ // number characters currently in the FIFO should be small when a
+ // configuration change is requested.
+ //
+ // NOTE: Do not use any DEBUG() or REPORT_STATUS_CODE() or any other calls
+ // in the rest of this function that may send additional characters to this
+ // UART device invalidating the flush operation.
+ //
+ Elapsed = 0;
+ Lsr.Data = READ_LSR (SerialDevice);
+ while (Lsr.Bits.Temt == 0 || Lsr.Bits.Thre == 0) {
+ if (Elapsed >= Timeout) {
+ return EFI_TIMEOUT;
+ }
+ gBS->Stall (TIMEOUT_STALL_INTERVAL);
+ Elapsed += TIMEOUT_STALL_INTERVAL;
+ Lsr.Data = READ_LSR (SerialDevice);
+ }
+
+ return EFI_SUCCESS;
+}
+
//
// Interface Functions
//
@@ -477,6 +539,15 @@ SerialReset (
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
//
+ // Wait for all data to be transmitted before changing the UART configuration.
+ //
+ // NOTE: Do not use any DEBUG() or REPORT_STATUS_CODE() or any other calls
+ // that may send additional characters to this UART device until the UART
+ // configuration change is complete.
+ //
+ SerialFlushTransmitFifo (SerialDevice);
+
+ //
// Make sure DLAB is 0.
//
Lcr.Data = READ_LCR (SerialDevice);
@@ -655,6 +726,15 @@ SerialSetAttributes (
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
//
+ // Wait for all data to be transmitted before changing the UART configuration.
+ //
+ // NOTE: Do not use any DEBUG() or REPORT_STATUS_CODE() or any other calls
+ // that may send additional characters to this UART device until the UART
+ // configuration change is complete.
+ //
+ SerialFlushTransmitFifo (SerialDevice);
+
+ //
// Put serial port on Divisor Latch Mode
//
Lcr.Data = READ_LCR (SerialDevice);
@@ -826,6 +906,15 @@ SerialSetControl (
Tpl = gBS->RaiseTPL (TPL_NOTIFY);
+ //
+ // Wait for all data to be transmitted before changing the UART configuration.
+ //
+ // NOTE: Do not use any DEBUG() or REPORT_STATUS_CODE() or any other calls
+ // that may send additional characters to this UART device until the UART
+ // configuration change is complete.
+ //
+ SerialFlushTransmitFifo (SerialDevice);
+
Mcr.Data = READ_MCR (SerialDevice);
Mcr.Bits.DtrC = 0;
Mcr.Bits.Rts = 0;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
index 7b30afb4167..10b22a9ab30 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/UhciDxe/UhciSched.c
@@ -513,7 +513,7 @@ UhciCheckTdStatus (
// terminate the transfer
//
if (!IsLow && (TdHw->ShortPacket == 1) && (Len < Td->DataLen)) {
- DEBUG ((EFI_D_VERBOSE, "UhciCheckTdStatus: short packet read occured\n"));
+ DEBUG ((DEBUG_VERBOSE, "UhciCheckTdStatus: short packet read occurred\n"));
Finished = TRUE;
goto ON_EXIT;
@@ -590,7 +590,7 @@ UhciExecuteTransfer (
Finished = UhciCheckTdStatus (Uhc, Td, IsLow, QhResult);
//
- // Transfer is OK or some error occured (TD inactive)
+ // Transfer is OK or some error occurred (TD inactive)
//
if (Finished) {
break;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
index b28bb062c90..3ca74df1004 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -423,14 +423,15 @@ XhcClearOpRegBit (
Wait the operation register's bit as specified by Bit
to become set (or clear).
- @param Xhc The XHCI Instance.
- @param Offset The offset of the operation register.
- @param Bit The bit of the register to wait for.
- @param WaitToSet Wait the bit to set or clear.
- @param Timeout The time to wait before abort (in millisecond, ms).
+ @param Xhc The XHCI Instance.
+ @param Offset The offset of the operation register.
+ @param Bit The bit of the register to wait for.
+ @param WaitToSet Wait the bit to set or clear.
+ @param Timeout The time to wait before abort (in millisecond, ms).
- @retval EFI_SUCCESS The bit successfully changed by host controller.
- @retval EFI_TIMEOUT The time out occurred.
+ @retval EFI_SUCCESS The bit successfully changed by host controller.
+ @retval EFI_TIMEOUT The time out occurred.
+ @retval EFI_OUT_OF_RESOURCES Memory for the timer event could not be allocated.
**/
EFI_STATUS
@@ -442,20 +443,52 @@ XhcWaitOpRegBit (
IN UINT32 Timeout
)
{
- UINT32 Index;
- UINT64 Loop;
+ EFI_STATUS Status;
+ EFI_EVENT TimeoutEvent;
+
+ TimeoutEvent = NULL;
+
+ if (Timeout == 0) {
+ return EFI_TIMEOUT;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &TimeoutEvent
+ );
+
+ if (EFI_ERROR(Status)) {
+ goto DONE;
+ }
- Loop = Timeout * XHC_1_MILLISECOND;
+ Status = gBS->SetTimer (TimeoutEvent,
+ TimerRelative,
+ EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
- for (Index = 0; Index < Loop; Index++) {
+ if (EFI_ERROR(Status)) {
+ goto DONE;
+ }
+
+ do {
if (XHC_REG_BIT_IS_SET (Xhc, Offset, Bit) == WaitToSet) {
- return EFI_SUCCESS;
+ Status = EFI_SUCCESS;
+ goto DONE;
}
gBS->Stall (XHC_1_MICROSECOND);
+ } while (EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
+
+ Status = EFI_TIMEOUT;
+
+DONE:
+ if (TimeoutEvent != NULL) {
+ gBS->CloseEvent (TimeoutEvent);
}
- return EFI_TIMEOUT;
+ return Status;
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index 4be309e9f7b..9e3cb42b28a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -2,7 +2,7 @@
XHCI transfer scheduling routines.
-Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -1254,14 +1254,15 @@ EXIT:
/**
Execute the transfer by polling the URB. This is a synchronous operation.
- @param Xhc The XHCI Instance.
- @param CmdTransfer The executed URB is for cmd transfer or not.
- @param Urb The URB to execute.
- @param Timeout The time to wait before abort, in millisecond.
+ @param Xhc The XHCI Instance.
+ @param CmdTransfer The executed URB is for cmd transfer or not.
+ @param Urb The URB to execute.
+ @param Timeout The time to wait before abort, in millisecond.
- @return EFI_DEVICE_ERROR The transfer failed due to transfer error.
- @return EFI_TIMEOUT The transfer failed due to time out.
- @return EFI_SUCCESS The transfer finished OK.
+ @return EFI_DEVICE_ERROR The transfer failed due to transfer error.
+ @return EFI_TIMEOUT The transfer failed due to time out.
+ @return EFI_SUCCESS The transfer finished OK.
+ @retval EFI_OUT_OF_RESOURCES Memory for the timer event could not be allocated.
**/
EFI_STATUS
@@ -1273,11 +1274,16 @@ XhcExecTransfer (
)
{
EFI_STATUS Status;
- UINTN Index;
- UINT64 Loop;
UINT8 SlotId;
UINT8 Dci;
BOOLEAN Finished;
+ EFI_EVENT TimeoutEvent;
+ BOOLEAN IndefiniteTimeout;
+
+ Status = EFI_SUCCESS;
+ Finished = FALSE;
+ TimeoutEvent = NULL;
+ IndefiniteTimeout = FALSE;
if (CmdTransfer) {
SlotId = 0;
@@ -1291,29 +1297,56 @@ XhcExecTransfer (
ASSERT (Dci < 32);
}
- Status = EFI_SUCCESS;
- Loop = Timeout * XHC_1_MILLISECOND;
if (Timeout == 0) {
- Loop = 0xFFFFFFFF;
+ IndefiniteTimeout = TRUE;
+ goto RINGDOORBELL;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &TimeoutEvent
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto DONE;
}
+ Status = gBS->SetTimer (TimeoutEvent,
+ TimerRelative,
+ EFI_TIMER_PERIOD_MILLISECONDS(Timeout));
+
+ if (EFI_ERROR (Status)) {
+ goto DONE;
+ }
+
+RINGDOORBELL:
XhcRingDoorBell (Xhc, SlotId, Dci);
- for (Index = 0; Index < Loop; Index++) {
+ do {
Finished = XhcCheckUrbResult (Xhc, Urb);
if (Finished) {
break;
}
gBS->Stall (XHC_1_MICROSECOND);
- }
+ } while (IndefiniteTimeout || EFI_ERROR(gBS->CheckEvent (TimeoutEvent)));
- if (Index == Loop) {
+DONE:
+ if (EFI_ERROR(Status)) {
+ Urb->Result = EFI_USB_ERR_NOTEXECUTE;
+ } else if (!Finished) {
Urb->Result = EFI_USB_ERR_TIMEOUT;
Status = EFI_TIMEOUT;
} else if (Urb->Result != EFI_USB_NOERROR) {
Status = EFI_DEVICE_ERROR;
}
+ if (TimeoutEvent != NULL) {
+ gBS->CloseEvent (TimeoutEvent);
+ }
+
return Status;
}
@@ -1684,9 +1717,11 @@ XhcPollPortStatusChange (
EFI_STATUS Status;
UINT8 Speed;
UINT8 SlotId;
+ UINT8 Retries;
USB_DEV_ROUTE RouteChart;
Status = EFI_SUCCESS;
+ Retries = XHC_INIT_DEVICE_SLOT_RETRIES;
if ((PortState->PortChangeStatus & (USB_PORT_STAT_C_CONNECTION | USB_PORT_STAT_C_ENABLE | USB_PORT_STAT_C_OVERCURRENT | USB_PORT_STAT_C_RESET)) == 0) {
return EFI_SUCCESS;
@@ -1728,17 +1763,29 @@ XhcPollPortStatusChange (
} else if ((PortState->PortStatus & USB_PORT_STAT_SUPER_SPEED) != 0) {
Speed = EFI_USB_SPEED_SUPER;
}
- //
- // Execute Enable_Slot cmd for attached device, initialize device context and assign device address.
- //
- SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);
- if ((SlotId == 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != 0)) {
- if (Xhc->HcCParams.Data.Csz == 0) {
- Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);
- } else {
- Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed);
+
+ do {
+ //
+ // Execute Enable_Slot cmd for attached device, initialize device context and assign device address.
+ //
+ SlotId = XhcRouteStringToSlotId (Xhc, RouteChart);
+ if ((SlotId == 0) && ((PortState->PortChangeStatus & USB_PORT_STAT_C_RESET) != 0)) {
+ if (Xhc->HcCParams.Data.Csz == 0) {
+ Status = XhcInitializeDeviceSlot (Xhc, ParentRouteChart, Port, RouteChart, Speed);
+ } else {
+ Status = XhcInitializeDeviceSlot64 (Xhc, ParentRouteChart, Port, RouteChart, Speed);
+ }
}
- }
+
+ //
+ // According to the xHCI specification (section 4.6.5), "a USB Transaction
+ // Error Completion Code for an Address Device Command may be due to a Stall
+ // response from a device. Software should issue a Disable Slot Command for
+ // the Device Slot then an Enable Slot Command to recover from this error."
+ // Therefore, retry the device slot initialization if it fails due to a
+ // device error.
+ //
+ } while ((Status == EFI_DEVICE_ERROR) && (Retries-- != 0));
}
return Status;
@@ -2246,6 +2293,9 @@ XhcInitializeDeviceSlot (
DeviceAddress = (UINT8) ((DEVICE_CONTEXT *) OutputContext)->Slot.DeviceAddress;
DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
+ } else {
+ DEBUG ((DEBUG_INFO, " Address %d assigned unsuccessfully\n"));
+ XhcDisableSlotCmd (Xhc, SlotId);
}
return Status;
@@ -2456,7 +2506,11 @@ XhcInitializeDeviceSlot64 (
DeviceAddress = (UINT8) ((DEVICE_CONTEXT_64 *) OutputContext)->Slot.DeviceAddress;
DEBUG ((EFI_D_INFO, " Address %d assigned successfully\n", DeviceAddress));
Xhc->UsbDevContext[SlotId].XhciDevAddr = DeviceAddress;
+ } else {
+ DEBUG ((DEBUG_INFO, " Address %d assigned unsuccessfully\n"));
+ XhcDisableSlotCmd64 (Xhc, SlotId);
}
+
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
index eaf153c646e..54348838e11 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
@@ -11,6 +11,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define _EFI_XHCI_SCHED_H_
#define XHC_URB_SIG SIGNATURE_32 ('U', 'S', 'B', 'R')
+#define XHC_INIT_DEVICE_SLOT_RETRIES 1
//
// Transfer types, used in URB to identify the transfer type
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
index 807e4939430..d56dcc784ac 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.c
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -749,7 +749,7 @@ UfsFinishDeviceInitialization (
{
EFI_STATUS Status;
UINT8 DeviceInitStatus;
- UINT8 Timeout;
+ UINT32 Timeout;
DeviceInitStatus = 0xFF;
@@ -761,7 +761,10 @@ UfsFinishDeviceInitialization (
return Status;
}
- Timeout = 5;
+ //
+ // There are cards that can take upto 600ms to clear fDeviceInit flag.
+ //
+ Timeout = UFS_INIT_COMPLETION_TIMEOUT;
do {
Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
if (EFI_ERROR (Status)) {
@@ -771,7 +774,13 @@ UfsFinishDeviceInitialization (
Timeout--;
} while (DeviceInitStatus != 0 && Timeout != 0);
- return EFI_SUCCESS;
+ if (Timeout == 0) {
+ DEBUG ((DEBUG_ERROR, "UfsFinishDeviceInitialization DeviceInitStatus=%x EFI_TIMEOUT \n", DeviceInitStatus));
+ return EFI_TIMEOUT;
+ } else {
+ DEBUG ((DEBUG_INFO, "UfsFinishDeviceInitialization Timeout left=%x EFI_SUCCESS \n", Timeout));
+ return EFI_SUCCESS;
+ }
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
index 01ef641cd66..b86ddabbd59 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThru.h
@@ -1,6 +1,6 @@
/** @file
- Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -40,6 +40,7 @@
//
#define UFS_MAX_LUNS 12
#define UFS_WLUN_PREFIX 0xC1
+#define UFS_INIT_COMPLETION_TIMEOUT 600000
typedef struct {
UINT8 Lun[UFS_MAX_LUNS];
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain.inf
index ae77900c86b..f74bb468c3c 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain.inf
@@ -185,6 +185,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPoolType ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth ## CONSUMES
# [Hob]
# RESOURCE_DESCRIPTOR ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
index f0284b5505b..29697a24204 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/DxeMain/DxeMain.c
@@ -299,6 +299,14 @@ DxeMain (
PERF_CROSSMODULE_BEGIN ("DXE");
//
+ // Log MemoryBaseAddress and MemoryLength again (from
+ // CoreInitializeMemoryServices()), now that library constructors have
+ // executed.
+ //
+ DEBUG ((DEBUG_INFO, "%a: MemoryBaseAddress=0x%Lx MemoryLength=0x%Lx\n",
+ __FUNCTION__, MemoryBaseAddress, MemoryLength));
+
+ //
// Report DXE Core image information to the PE/COFF Extra Action Library
//
ZeroMem (&ImageContext, sizeof (ImageContext));
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVol.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVol.c
index e84a0eefdc4..8856d380e21 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVol.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVol.c
@@ -572,7 +572,7 @@ Done:
EFI_FIRMWARE_VOLUME2_PROTOCOL on the same handle. This is the function where
the actual initialization of the EFI_FIRMWARE_VOLUME2_PROTOCOL is done.
- @param Event The event that occured
+ @param Event The event that occurred
@param Context For EFI compatiblity. Not used.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
index e725e1cf414..e4f838444e0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/FwVol/FwVolRead.c
@@ -1,7 +1,7 @@
/** @file
Implements functions to read firmware file
-Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -143,9 +143,9 @@ FvGetNextFile (
return EFI_ACCESS_DENIED;
}
- if (*FileType > EFI_FV_FILETYPE_SMM_CORE) {
+ if (*FileType > EFI_FV_FILETYPE_MM_CORE_STANDALONE) {
//
- // File type needs to be in 0 - 0x0D
+ // File type needs to be in 0 - 0x0F
//
return EFI_NOT_FOUND;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
index ddd97e247bb..7eb3f33107e 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
@@ -35,13 +35,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT)
-#define EXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \
- EFI_MEMORY_WT | EFI_MEMORY_WB | \
- EFI_MEMORY_WP | EFI_MEMORY_UCE)
-
-#define NONEXCLUSIVE_MEMORY_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | \
- EFI_MEMORY_RO)
-
//
// Module Variables
//
@@ -665,7 +658,7 @@ ConverToCpuArchAttributes (
{
UINT64 CpuArchAttributes;
- CpuArchAttributes = Attributes & NONEXCLUSIVE_MEMORY_ATTRIBUTES;
+ CpuArchAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK;
if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) {
CpuArchAttributes |= EFI_MEMORY_UC;
@@ -951,7 +944,7 @@ CoreConvertSpace (
// Keep original CPU arch attributes when caller just calls
// SetMemorySpaceAttributes() with none CPU arch attributes (for example, RUNTIME).
//
- Attributes |= (Entry->Attributes & (EXCLUSIVE_MEMORY_ATTRIBUTES | NONEXCLUSIVE_MEMORY_ATTRIBUTES));
+ Attributes |= (Entry->Attributes & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
}
Entry->Attributes = Attributes;
break;
@@ -2105,6 +2098,60 @@ CalculateTotalMemoryBinSizeNeeded (
}
/**
+ Find the largest region in the specified region that is not covered by an existing memory allocation
+
+ @param BaseAddress On input start of the region to check.
+ On output start of the largest free region.
+ @param Length On input size of region to check.
+ On output size of the largest free region.
+ @param MemoryHob Hob pointer for the first memory allocation pointer to check
+**/
+VOID
+FindLargestFreeRegion (
+ IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress,
+ IN OUT UINT64 *Length,
+ IN EFI_HOB_MEMORY_ALLOCATION *MemoryHob
+ )
+{
+ EFI_PHYSICAL_ADDRESS TopAddress;
+ EFI_PHYSICAL_ADDRESS AllocatedTop;
+ EFI_PHYSICAL_ADDRESS LowerBase;
+ UINT64 LowerSize;
+ EFI_PHYSICAL_ADDRESS UpperBase;
+ UINT64 UpperSize;
+
+ TopAddress = *BaseAddress + *Length;
+ while (MemoryHob != NULL) {
+ AllocatedTop = MemoryHob->AllocDescriptor.MemoryBaseAddress + MemoryHob->AllocDescriptor.MemoryLength;
+
+ if ((MemoryHob->AllocDescriptor.MemoryBaseAddress >= *BaseAddress) &&
+ (AllocatedTop <= TopAddress)) {
+ LowerBase = *BaseAddress;
+ LowerSize = MemoryHob->AllocDescriptor.MemoryBaseAddress - *BaseAddress;
+ UpperBase = AllocatedTop;
+ UpperSize = TopAddress - AllocatedTop;
+
+ if (LowerSize != 0) {
+ FindLargestFreeRegion (&LowerBase, &LowerSize, (EFI_HOB_MEMORY_ALLOCATION *) GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (MemoryHob)));
+ }
+ if (UpperSize != 0) {
+ FindLargestFreeRegion (&UpperBase, &UpperSize, (EFI_HOB_MEMORY_ALLOCATION *) GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (MemoryHob)));
+ }
+
+ if (UpperSize >= LowerSize) {
+ *Length = UpperSize;
+ *BaseAddress = UpperBase;
+ } else {
+ *Length = LowerSize;
+ *BaseAddress = LowerBase;
+ }
+ return;
+ }
+ MemoryHob = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (MemoryHob));
+ }
+}
+
+/**
External function. Initializes memory services based on the memory
descriptor HOBs. This function is responsible for priming the memory
map, so memory allocations and resource allocations can be made.
@@ -2242,6 +2289,7 @@ CoreInitializeMemoryServices (
Attributes = PhitResourceHob->ResourceAttribute;
BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop);
Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress);
+ FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
if (Length < MinimalMemorySizeNeeded) {
//
// If that range is not large enough to intialize the DXE Core, then
@@ -2249,6 +2297,7 @@ CoreInitializeMemoryServices (
//
BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom);
Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress);
+ //This region is required to have no memory allocation inside it, skip check for entries in HOB List
if (Length < MinimalMemorySizeNeeded) {
//
// If that range is not large enough to intialize the DXE Core, then
@@ -2256,6 +2305,7 @@ CoreInitializeMemoryServices (
//
BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress));
+ FindLargestFreeRegion (&BaseAddress, &Length, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
}
}
break;
@@ -2319,6 +2369,7 @@ CoreInitializeMemoryServices (
//
TestedMemoryBaseAddress = PageAlignAddress (ResourceHob->PhysicalStart);
TestedMemoryLength = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - TestedMemoryBaseAddress);
+ FindLargestFreeRegion (&TestedMemoryBaseAddress, &TestedMemoryLength, (EFI_HOB_MEMORY_ALLOCATION *)GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION));
if (TestedMemoryLength < MinimalMemorySizeNeeded) {
continue;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Image/Image.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Image/Image.c
index 3f7d270166b..f0b41aa8342 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Image/Image.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Image/Image.c
@@ -470,7 +470,7 @@ GetPeCoffImageFixLoadingAssignedAddress(
if (ValueInSectionHeader != 0) {
//
// When the feature is configured as load module at fixed absolute address, the ImageAddress field of ImageContext
- // hold the spcified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
+ // hold the specified address. If the feature is configured as load module at fixed offset, ImageAddress hold an offset
// relative to top address
//
if ((INT64)PcdGet64(PcdLoadModuleAtFixAddressEnable) < 0) {
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Mem/Page.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Mem/Page.c
index a94c62574fc..d5bbbb162dc 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -1857,8 +1857,7 @@ CoreGetMemoryMap (
MemoryMap->VirtualStart = 0;
MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
MemoryMap->Attribute = (MergeGcdMapEntry.Attributes & ~EFI_MEMORY_PORT_IO) |
- (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
- EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB));
+ (MergeGcdMapEntry.Capabilities & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeReserved) {
MemoryMap->Type = EfiReservedMemoryType;
@@ -1892,8 +1891,7 @@ CoreGetMemoryMap (
MemoryMap->VirtualStart = 0;
MemoryMap->NumberOfPages = RShiftU64 ((MergeGcdMapEntry.EndAddress - MergeGcdMapEntry.BaseAddress + 1), EFI_PAGE_SHIFT);
MemoryMap->Attribute = MergeGcdMapEntry.Attributes | EFI_MEMORY_NV |
- (MergeGcdMapEntry.Capabilities & (EFI_MEMORY_RP | EFI_MEMORY_WP | EFI_MEMORY_XP | EFI_MEMORY_RO |
- EFI_MEMORY_UC | EFI_MEMORY_UCE | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB));
+ (MergeGcdMapEntry.Capabilities & (EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK));
MemoryMap->Type = EfiPersistentMemory;
//
@@ -1926,17 +1924,16 @@ CoreGetMemoryMap (
// set attributes and change memory paging attribute accordingly.
// But current EFI_MEMORY_DESCRIPTOR.Attribute is assigned by
// value from Capabilities in GCD memory map. This might cause
- // boot problems. Clearing all paging related capabilities can
- // workaround it. Following code is supposed to be removed once
- // the usage of EFI_MEMORY_DESCRIPTOR.Attribute is clarified in
- // UEFI spec and adopted by both EDK-II Core and all supported
- // OSs.
+ // boot problems. Clearing all page-access permission related
+ // capabilities can workaround it. Following code is supposed to
+ // be removed once the usage of EFI_MEMORY_DESCRIPTOR.Attribute
+ // is clarified in UEFI spec and adopted by both EDK-II Core and
+ // all supported OSs.
//
MemoryMapEnd = MemoryMap;
MemoryMap = MemoryMapStart;
while (MemoryMap < MemoryMapEnd) {
- MemoryMap->Attribute &= ~(UINT64)(EFI_MEMORY_RP | EFI_MEMORY_RO |
- EFI_MEMORY_XP);
+ MemoryMap->Attribute &= ~(UINT64)EFI_MEMORY_ACCESS_MASK;
MemoryMap = NEXT_MEMORY_DESCRIPTOR (MemoryMap, Size);
}
MergeMemoryMap (MemoryMapStart, &BufferSize, Size);
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
index aaaf3040e5d..a611602aa82 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/Misc/MemoryProtection.c
@@ -42,9 +42,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "DxeMain.h"
#include "Mem/HeapGuard.h"
-#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)
-#define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)
-
//
// Image type definitions
//
@@ -221,7 +218,7 @@ SetUefiImageMemoryAttributes (
Status = CoreGetMemorySpaceDescriptor(BaseAddress, &Descriptor);
ASSERT_EFI_ERROR(Status);
- FinalAttributes = (Descriptor.Attributes & CACHE_ATTRIBUTE_MASK) | (Attributes & MEMORY_ATTRIBUTE_MASK);
+ FinalAttributes = (Descriptor.Attributes & EFI_CACHE_ATTRIBUTE_MASK) | (Attributes & EFI_MEMORY_ATTRIBUTE_MASK);
DEBUG ((DEBUG_INFO, "SetUefiImageMemoryAttributes - 0x%016lx - 0x%016lx (0x%016lx)\n", BaseAddress, Length, FinalAttributes));
@@ -924,7 +921,7 @@ InitializeDxeNxMemoryProtectionPolicy (
(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) {
Attributes = GetPermissionAttributeForMemoryType (EfiConventionalMemory) |
- (Entry->Attributes & CACHE_ATTRIBUTE_MASK);
+ (Entry->Attributes & EFI_CACHE_ATTRIBUTE_MASK);
DEBUG ((DEBUG_INFO,
"Untested GCD memory space region: - 0x%016lx - 0x%016lx (0x%016lx)\n",
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
index 4fb846c2135..52f153c0d75 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c
@@ -952,9 +952,12 @@ CreateChildNode (
search.
@param SearchType Indicates the type of section to search for.
@param SectionInstance Indicates which instance of section to find.
- This is an in/out parameter to deal with
- recursions.
+ This is an in/out parameter and it is 1-based,
+ to deal with recursions.
@param SectionDefinitionGuid Guid of section definition
+ @param Depth Nesting depth of encapsulation sections.
+ Callers different from FindChildNode() are
+ responsible for passing in a zero Depth.
@param FoundChild Output indicating the child node that is found.
@param FoundStream Output indicating which section stream the child
was found in. If this stream was generated as a
@@ -968,6 +971,9 @@ CreateChildNode (
@retval EFI_NOT_FOUND Requested child node does not exist.
@retval EFI_PROTOCOL_ERROR a required GUIDED section extraction protocol
does not exist
+ @retval EFI_ABORTED Recursion aborted because Depth has been
+ greater than or equal to
+ PcdFwVolDxeMaxEncapsulationDepth.
**/
EFI_STATUS
@@ -976,6 +982,7 @@ FindChildNode (
IN EFI_SECTION_TYPE SearchType,
IN OUT UINTN *SectionInstance,
IN EFI_GUID *SectionDefinitionGuid,
+ IN UINT32 Depth,
OUT CORE_SECTION_CHILD_NODE **FoundChild,
OUT CORE_SECTION_STREAM_NODE **FoundStream,
OUT UINT32 *AuthenticationStatus
@@ -988,6 +995,12 @@ FindChildNode (
EFI_STATUS ErrorStatus;
EFI_STATUS Status;
+ ASSERT (*SectionInstance > 0);
+
+ if (Depth >= PcdGet32 (PcdFwVolDxeMaxEncapsulationDepth)) {
+ return EFI_ABORTED;
+ }
+
CurrentChildNode = NULL;
ErrorStatus = EFI_NOT_FOUND;
@@ -1037,6 +1050,11 @@ FindChildNode (
}
}
+ //
+ // Type mismatch, or we haven't found the desired instance yet.
+ //
+ ASSERT (*SectionInstance > 0);
+
if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) {
//
// If the current node is an encapsulating node, recurse into it...
@@ -1046,20 +1064,33 @@ FindChildNode (
SearchType,
SectionInstance,
SectionDefinitionGuid,
+ Depth + 1,
&RecursedChildNode,
&RecursedFoundStream,
AuthenticationStatus
);
- //
- // If the status is not EFI_SUCCESS, just save the error code and continue
- // to find the request child node in the rest stream.
- //
if (*SectionInstance == 0) {
+ //
+ // The recursive FindChildNode() call decreased (*SectionInstance) to
+ // zero.
+ //
ASSERT_EFI_ERROR (Status);
*FoundChild = RecursedChildNode;
*FoundStream = RecursedFoundStream;
return EFI_SUCCESS;
} else {
+ if (Status == EFI_ABORTED) {
+ //
+ // If the recursive call was aborted due to nesting depth, stop
+ // looking for the requested child node. The skipped subtree could
+ // throw off the instance counting.
+ //
+ return Status;
+ }
+ //
+ // Save the error code and continue to find the requested child node in
+ // the rest of the stream.
+ //
ErrorStatus = Status;
}
} else if ((CurrentChildNode->Type == EFI_SECTION_GUID_DEFINED) && (SearchType != EFI_SECTION_GUID_DEFINED)) {
@@ -1261,11 +1292,20 @@ GetSection (
*SectionType,
&Instance,
SectionDefinitionGuid,
+ 0, // encapsulation depth
&ChildNode,
&ChildStreamNode,
&ExtractedAuthenticationStatus
);
if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ DEBUG ((DEBUG_ERROR, "%a: recursion aborted due to nesting depth\n",
+ __FUNCTION__));
+ //
+ // Map "aborted" to "not found".
+ //
+ Status = EFI_NOT_FOUND;
+ }
goto GetSection_Done;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
index 9fbd28d7c19..f7bdccacff0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
@@ -115,6 +115,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES
[Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64]
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
index a13fa7b214d..2e4aa41b6ac 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
@@ -123,7 +123,7 @@ Create4GPageTablesIa32Pae (
//
// Need to split this 2M page that covers stack range.
//
- Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
+ Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, 0, 0);
} else {
//
// Fill in the Page Directory entries
@@ -282,7 +282,7 @@ HandOffToDxeCore (
//
// Create page table and save PageMapLevel4 to CR3
//
- PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE);
+ PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE, 0, 0);
//
// End of PEI phase signal
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
index fcf547a067f..2056725d25f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
@@ -35,6 +35,8 @@ HandOffToDxeCore (
UINT32 Index;
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;
+ VOID *GhcbBase;
+ UINTN GhcbSize;
//
// Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
@@ -81,12 +83,19 @@ HandOffToDxeCore (
TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+ //
+ // Get the address and size of the GHCB pages
+ //
+ GhcbBase = (VOID *) PcdGet64 (PcdGhcbBase);
+ GhcbSize = PcdGet64 (PcdGhcbSize);
+
PageTables = 0;
if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
//
// Create page table and save PageMapLevel4 to CR3
//
- PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE);
+ PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) GhcbBase, GhcbSize);
} else {
//
// Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
index 677691b6046..7ce43e03f42 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
@@ -181,6 +181,8 @@ EnableExecuteDisableBit (
@param Size Size of the given physical memory.
@param StackBase Base address of stack.
@param StackSize Size of stack.
+ @param GhcbBase Base address of GHCB pages.
+ @param GhcbSize Size of GHCB area.
@retval TRUE Page table should be split.
@retval FALSE Page table should not be split.
@@ -190,7 +192,9 @@ ToSplitPageTable (
IN EFI_PHYSICAL_ADDRESS Address,
IN UINTN Size,
IN EFI_PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
)
{
if (IsNullDetectionEnabled () && Address == 0) {
@@ -209,6 +213,12 @@ ToSplitPageTable (
}
}
+ if (GhcbBase != 0) {
+ if ((Address < GhcbBase + GhcbSize) && ((Address + Size) > GhcbBase)) {
+ return TRUE;
+ }
+ }
+
return FALSE;
}
/**
@@ -322,6 +332,8 @@ AllocatePageTableMemory (
@param[in, out] PageEntry2M Pointer to 2M page entry.
@param[in] StackBase Stack base address.
@param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
**/
VOID
@@ -329,7 +341,9 @@ Split2MPageTo4K (
IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
IN OUT UINT64 *PageEntry2M,
IN EFI_PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
)
{
EFI_PHYSICAL_ADDRESS PhysicalAddress4K;
@@ -355,7 +369,20 @@ Split2MPageTo4K (
//
// Fill in the Page Table entries
//
- PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
+ PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K;
+
+ //
+ // The GHCB range consists of two pages per CPU, the GHCB and a
+ // per-CPU variable page. The GHCB page needs to be mapped as an
+ // unencrypted page while the per-CPU variable page needs to be
+ // mapped encrypted. These pages alternate in assignment.
+ //
+ if ((GhcbBase == 0)
+ || (PhysicalAddress4K < GhcbBase)
+ || (PhysicalAddress4K >= GhcbBase + GhcbSize)
+ || (((PhysicalAddress4K - GhcbBase) & SIZE_4KB) != 0)) {
+ PageTableEntry->Uint64 |= AddressEncMask;
+ }
PageTableEntry->Bits.ReadWrite = 1;
if ((IsNullDetectionEnabled () && PhysicalAddress4K == 0) ||
@@ -383,6 +410,8 @@ Split2MPageTo4K (
@param[in, out] PageEntry1G Pointer to 1G page entry.
@param[in] StackBase Stack base address.
@param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
**/
VOID
@@ -390,7 +419,9 @@ Split1GPageTo2M (
IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
IN OUT UINT64 *PageEntry1G,
IN EFI_PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
)
{
EFI_PHYSICAL_ADDRESS PhysicalAddress2M;
@@ -413,11 +444,11 @@ Split1GPageTo2M (
PhysicalAddress2M = PhysicalAddress;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
- if (ToSplitPageTable (PhysicalAddress2M, SIZE_2MB, StackBase, StackSize)) {
+ if (ToSplitPageTable (PhysicalAddress2M, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) {
//
// Need to split this 2M page that covers NULL or stack range.
//
- Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
+ Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize);
} else {
//
// Fill in the Page Directory entries
@@ -616,6 +647,8 @@ EnablePageTableProtection (
@param[in] StackBase Stack base address.
@param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB base address.
+ @param[in] GhcbSize GHCB size.
@return The address of 4 level page map.
@@ -623,7 +656,9 @@ EnablePageTableProtection (
UINTN
CreateIdentityMappingPageTables (
IN EFI_PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
)
{
UINT32 RegEax;
@@ -809,8 +844,8 @@ CreateIdentityMappingPageTables (
PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
- if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSize)) {
- Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);
+ if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSize, GhcbBase, GhcbSize)) {
+ Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize, GhcbBase, GhcbSize);
} else {
//
// Fill in the Page Directory entries
@@ -840,11 +875,11 @@ CreateIdentityMappingPageTables (
PageDirectoryPointerEntry->Bits.Present = 1;
for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
- if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackSize)) {
+ if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) {
//
// Need to split this 2M page that covers NULL or stack range.
//
- Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);
+ Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize);
} else {
//
// Fill in the Page Directory entries
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
index 4238c469212..0fbbc906db8 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
@@ -201,6 +201,8 @@ EnableExecuteDisableBit (
@param[in, out] PageEntry2M Pointer to 2M page entry.
@param[in] StackBase Stack base address.
@param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
**/
VOID
@@ -208,7 +210,9 @@ Split2MPageTo4K (
IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
IN OUT UINT64 *PageEntry2M,
IN EFI_PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
);
/**
@@ -217,6 +221,8 @@ Split2MPageTo4K (
@param[in] StackBase Stack base address.
@param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
@return The address of 4 level page map.
@@ -224,7 +230,9 @@ Split2MPageTo4K (
UINTN
CreateIdentityMappingPageTables (
IN EFI_PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbkSize
);
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
index 36632aee146..3a49c8a502f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Dispatcher/Dispatcher.c
@@ -953,6 +953,437 @@ PeiCheckAndSwitchStack (
}
/**
+ Migrate a PEIM from temporary RAM to permanent memory.
+
+ @param PeimFileHandle Pointer to the FFS file header of the image.
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
+
+ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *Pe32Data;
+ VOID *ImageAddress;
+ CHAR8 *AsciiString;
+ UINTN Index;
+
+ Status = EFI_SUCCESS;
+
+ FileHeader = (EFI_FFS_FILE_HEADER *) FileHandle;
+ ASSERT (!IS_FFS_FILE2 (FileHeader));
+
+ ImageAddress = NULL;
+ PeiGetPe32Data (MigratedFileHandle, &ImageAddress);
+ if (ImageAddress != NULL) {
+ DEBUG_CODE_BEGIN ();
+ AsciiString = PeCoffLoaderGetPdbPointer (ImageAddress);
+ for (Index = 0; AsciiString[Index] != 0; Index++) {
+ if (AsciiString[Index] == '\\' || AsciiString[Index] == '/') {
+ AsciiString = AsciiString + Index + 1;
+ Index = 0;
+ } else if (AsciiString[Index] == '.') {
+ AsciiString[Index] = 0;
+ }
+ }
+ DEBUG ((DEBUG_INFO, "%a", AsciiString));
+ DEBUG_CODE_END ();
+
+ Pe32Data = (VOID *) ((UINTN) ImageAddress - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
+ Status = LoadAndRelocatePeCoffImageInPlace (Pe32Data, ImageAddress);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
+/**
+ Migrate Status Code Callback function pointers inside an FV from temporary memory to permanent memory.
+
+ @param OrgFvHandle Address of FV handle in temporary memory.
+ @param FvHandle Address of FV handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertStatusCodeCallbacks (
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ UINTN *NumberOfEntries;
+ UINTN *CallbackEntry;
+ UINTN Index;
+
+ Hob.Raw = GetFirstGuidHob (&gStatusCodeCallbackGuid);
+ while (Hob.Raw != NULL) {
+ NumberOfEntries = GET_GUID_HOB_DATA (Hob);
+ CallbackEntry = NumberOfEntries + 1;
+ for (Index = 0; Index < *NumberOfEntries; Index++) {
+ if (((VOID *) CallbackEntry[Index]) != NULL) {
+ if ((CallbackEntry[Index] >= OrgFvHandle) && (CallbackEntry[Index] < (OrgFvHandle + FvSize))) {
+ DEBUG ((
+ DEBUG_INFO,
+ "Migrating CallbackEntry[%Lu] from 0x%0*Lx to ",
+ (UINT64)Index,
+ (sizeof CallbackEntry[Index]) * 2,
+ (UINT64)CallbackEntry[Index]
+ ));
+ if (OrgFvHandle > FvHandle) {
+ CallbackEntry[Index] = CallbackEntry[Index] - (OrgFvHandle - FvHandle);
+ } else {
+ CallbackEntry[Index] = CallbackEntry[Index] + (FvHandle - OrgFvHandle);
+ }
+ DEBUG ((
+ DEBUG_INFO,
+ "0x%0*Lx\n",
+ (sizeof CallbackEntry[Index]) * 2,
+ (UINT64)CallbackEntry[Index]
+ ));
+ }
+ }
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gStatusCodeCallbackGuid, Hob.Raw);
+ }
+}
+
+/**
+ Migrates SEC modules in the given firmware volume.
+
+ Migrating SECURITY_CORE files requires special treatment since they are not tracked for PEI dispatch.
+
+ This functioun should be called after the FV has been copied to its post-memory location and the PEI Core FV list has
+ been updated.
+
+ @param Private Pointer to the PeiCore's private data structure.
+ @param FvIndex The firmware volume index to migrate.
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.
+
+ @retval EFI_SUCCESS SEC modules were migrated successfully
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+ @retval EFI_NOT_FOUND Can't find valid FFS header.
+
+**/
+EFI_STATUS
+EFIAPI
+MigrateSecModulesInFv (
+ IN PEI_CORE_INSTANCE *Private,
+ IN UINTN FvIndex,
+ IN UINTN OrgFvHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS FindFileStatus;
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+ UINT32 SectionAuthenticationStatus;
+ UINT32 FileSize;
+ VOID *OrgPe32SectionData;
+ VOID *Pe32SectionData;
+ EFI_FFS_FILE_HEADER *FfsFileHeader;
+ EFI_COMMON_SECTION_HEADER *Section;
+ BOOLEAN IsFfs3Fv;
+ UINTN SectionInstance;
+
+ if (Private == NULL || FvIndex >= Private->FvCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ do {
+ FindFileStatus = PeiFfsFindNextFile (
+ GetPeiServicesTablePointer (),
+ EFI_FV_FILETYPE_SECURITY_CORE,
+ Private->Fv[FvIndex].FvHandle,
+ &MigratedFileHandle
+ );
+ if (!EFI_ERROR (FindFileStatus ) && MigratedFileHandle != NULL) {
+ FileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) MigratedFileHandle - (UINTN) Private->Fv[FvIndex].FvHandle + OrgFvHandle);
+ FfsFileHeader = (EFI_FFS_FILE_HEADER *) MigratedFileHandle;
+
+ DEBUG ((DEBUG_VERBOSE, " Migrating SEC_CORE MigratedFileHandle at 0x%x.\n", (UINTN) MigratedFileHandle));
+ DEBUG ((DEBUG_VERBOSE, " FileHandle at 0x%x.\n", (UINTN) FileHandle));
+
+ IsFfs3Fv = CompareGuid (&Private->Fv[FvIndex].FvHeader->FileSystemGuid, &gEfiFirmwareFileSystem3Guid);
+ if (IS_FFS_FILE2 (FfsFileHeader)) {
+ ASSERT (FFS_FILE2_SIZE (FfsFileHeader) > 0x00FFFFFF);
+ if (!IsFfs3Fv) {
+ DEBUG ((DEBUG_ERROR, "It is a FFS3 formatted file: %g in a non-FFS3 formatted FV.\n", &FfsFileHeader->Name));
+ return EFI_NOT_FOUND;
+ }
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER2));
+ FileSize = FFS_FILE2_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER2);
+ } else {
+ Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER));
+ FileSize = FFS_FILE_SIZE (FfsFileHeader) - sizeof (EFI_FFS_FILE_HEADER);
+ }
+
+ SectionInstance = 1;
+ SectionAuthenticationStatus = 0;
+ Status = ProcessSection (
+ GetPeiServicesTablePointer (),
+ EFI_SECTION_PE32,
+ &SectionInstance,
+ Section,
+ FileSize,
+ &Pe32SectionData,
+ &SectionAuthenticationStatus,
+ IsFfs3Fv
+ );
+
+ if (!EFI_ERROR (Status)) {
+ OrgPe32SectionData = (VOID *) ((UINTN) Pe32SectionData - (UINTN) MigratedFileHandle + (UINTN) FileHandle);
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in migrated file at 0x%x.\n", (UINTN) Pe32SectionData));
+ DEBUG ((DEBUG_VERBOSE, " PE32 section in original file at 0x%x.\n", (UINTN) OrgPe32SectionData));
+ Status = LoadAndRelocatePeCoffImageInPlace (OrgPe32SectionData, Pe32SectionData);
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+ } while (!EFI_ERROR (FindFileStatus));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Migrates PEIMs in the given firmware volume.
+
+ @param Private Pointer to the PeiCore's private data structure.
+ @param FvIndex The firmware volume index to migrate.
+ @param OrgFvHandle The handle to the firmware volume in temporary memory.
+ @param FvHandle The handle to the firmware volume in permanent memory.
+
+ @retval EFI_SUCCESS The PEIMs in the FV were migrated successfully
+ @retval EFI_INVALID_PARAMETER The Private pointer is NULL or FvCount is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeimsInFv (
+ IN PEI_CORE_INSTANCE *Private,
+ IN UINTN FvIndex,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ )
+{
+ EFI_STATUS Status;
+ volatile UINTN FileIndex;
+ EFI_PEI_FILE_HANDLE MigratedFileHandle;
+ EFI_PEI_FILE_HANDLE FileHandle;
+
+ if (Private == NULL || FvIndex >= Private->FvCount) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Private->Fv[FvIndex].ScanFv) {
+ for (FileIndex = 0; FileIndex < Private->Fv[FvIndex].PeimCount; FileIndex++) {
+ if (Private->Fv[FvIndex].FvFileHandles[FileIndex] != NULL) {
+ FileHandle = Private->Fv[FvIndex].FvFileHandles[FileIndex];
+
+ MigratedFileHandle = (EFI_PEI_FILE_HANDLE) ((UINTN) FileHandle - OrgFvHandle + FvHandle);
+
+ DEBUG ((DEBUG_VERBOSE, " Migrating FileHandle %2d ", FileIndex));
+ Status = MigratePeim (FileHandle, MigratedFileHandle);
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ Private->Fv[FvIndex].FvFileHandles[FileIndex] = MigratedFileHandle;
+ if (FvIndex == Private->CurrentPeimFvCount) {
+ Private->CurrentFvFileHandles[FileIndex] = MigratedFileHandle;
+ }
+ }
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Migrate FVs out of temporary RAM before the cache is flushed.
+
+ @param Private PeiCore's private data structure
+ @param SecCoreData Points to a data structure containing information about the PEI core's operating
+ environment, such as the size and location of temporary RAM, the stack location and
+ the BFV location.
+
+ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
+
+**/
+EFI_STATUS
+EFIAPI
+EvacuateTempRam (
+ IN PEI_CORE_INSTANCE *Private,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ )
+{
+ EFI_STATUS Status;
+ volatile UINTN FvIndex;
+ volatile UINTN FvChildIndex;
+ UINTN ChildFvOffset;
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *ChildFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *RawDataFvHeader;
+ EFI_FIRMWARE_VOLUME_HEADER *MigratedChildFvHeader;
+
+ PEI_CORE_FV_HANDLE PeiCoreFvHandle;
+ EFI_PEI_CORE_FV_LOCATION_PPI *PeiCoreFvLocationPpi;
+ EDKII_MIGRATED_FV_INFO MigratedFvInfo;
+
+ ASSERT (Private->PeiMemoryInstalled);
+
+ DEBUG ((DEBUG_VERBOSE, "Beginning evacuation of content in temporary RAM.\n"));
+
+ //
+ // Migrate PPI Pointers of PEI_CORE from temporary memory to newly loaded PEI_CORE in permanent memory.
+ //
+ Status = PeiLocatePpi ((CONST EFI_PEI_SERVICES **) &Private->Ps, &gEfiPeiCoreFvLocationPpiGuid, 0, NULL, (VOID **) &PeiCoreFvLocationPpi);
+ if (!EFI_ERROR (Status) && (PeiCoreFvLocationPpi->PeiCoreFvLocation != NULL)) {
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) PeiCoreFvLocationPpi->PeiCoreFvLocation;
+ } else {
+ PeiCoreFvHandle.FvHandle = (EFI_PEI_FV_HANDLE) SecCoreData->BootFirmwareVolumeBase;
+ }
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ if (Private->Fv[FvIndex].FvHandle == PeiCoreFvHandle.FvHandle) {
+ CopyMem (&PeiCoreFvHandle, &Private->Fv[FvIndex], sizeof (PEI_CORE_FV_HANDLE));
+ break;
+ }
+ }
+ Status = EFI_SUCCESS;
+
+ ConvertPeiCorePpiPointers (Private, &PeiCoreFvHandle);
+
+ for (FvIndex = 0; FvIndex < Private->FvCount; FvIndex++) {
+ FvHeader = Private->Fv[FvIndex].FvHeader;
+ ASSERT (FvHeader != NULL);
+ ASSERT (FvIndex < Private->FvCount);
+
+ DEBUG ((DEBUG_VERBOSE, "FV[%02d] at 0x%x.\n", FvIndex, (UINTN) FvHeader));
+ if (
+ !(
+ ((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader >= Private->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader + (FvHeader->FvLength - 1)) < Private->FreePhysicalMemoryTop)
+ )
+ ) {
+ //
+ // Allocate page to save the rebased PEIMs, the PEIMs will get dispatched later.
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
+ (EFI_PHYSICAL_ADDRESS *) &MigratedFvHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Allocate pool to save the raw PEIMs, which is used to keep consistent context across
+ // multiple boot and PCR0 will keep the same no matter if the address of allocated page is changed.
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES ((UINTN) FvHeader->FvLength),
+ (EFI_PHYSICAL_ADDRESS *) &RawDataFvHeader
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " Migrating FV[%d] from 0x%08X to 0x%08X\n",
+ FvIndex,
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader
+ ));
+
+ //
+ // Copy the context to the rebased pages and raw pages, and create hob to save the
+ // information. The MigratedFvInfo HOB will never be produced when
+ // PcdMigrateTemporaryRamFirmwareVolumes is FALSE, because the PCD control the
+ // feature.
+ //
+ CopyMem (MigratedFvHeader, FvHeader, (UINTN) FvHeader->FvLength);
+ CopyMem (RawDataFvHeader, MigratedFvHeader, (UINTN) FvHeader->FvLength);
+ MigratedFvInfo.FvOrgBase = (UINT32) (UINTN) FvHeader;
+ MigratedFvInfo.FvNewBase = (UINT32) (UINTN) MigratedFvHeader;
+ MigratedFvInfo.FvDataBase = (UINT32) (UINTN) RawDataFvHeader;
+ MigratedFvInfo.FvLength = (UINT32) (UINTN) FvHeader->FvLength;
+ BuildGuidDataHob (&gEdkiiMigratedFvInfoGuid, &MigratedFvInfo, sizeof (MigratedFvInfo));
+
+ //
+ // Migrate any children for this FV now
+ //
+ for (FvChildIndex = FvIndex; FvChildIndex < Private->FvCount; FvChildIndex++) {
+ ChildFvHeader = Private->Fv[FvChildIndex].FvHeader;
+ if (
+ ((UINTN) ChildFvHeader > (UINTN) FvHeader) &&
+ (((UINTN) ChildFvHeader + ChildFvHeader->FvLength) < ((UINTN) FvHeader) + FvHeader->FvLength)
+ ) {
+ DEBUG ((DEBUG_VERBOSE, " Child FV[%02d] is being migrated.\n", FvChildIndex));
+ ChildFvOffset = (UINTN) ChildFvHeader - (UINTN) FvHeader;
+ DEBUG ((DEBUG_VERBOSE, " Child FV offset = 0x%x.\n", ChildFvOffset));
+ MigratedChildFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) MigratedFvHeader + ChildFvOffset);
+ Private->Fv[FvChildIndex].FvHeader = MigratedChildFvHeader;
+ Private->Fv[FvChildIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedChildFvHeader;
+ DEBUG ((DEBUG_VERBOSE, " Child migrated FV header at 0x%x.\n", (UINTN) MigratedChildFvHeader));
+
+ Status = MigratePeimsInFv (Private, FvChildIndex, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);
+ ASSERT_EFI_ERROR (Status);
+
+ ConvertPpiPointersFv (
+ Private,
+ (UINTN) ChildFvHeader,
+ (UINTN) MigratedChildFvHeader,
+ (UINTN) ChildFvHeader->FvLength - 1
+ );
+
+ ConvertStatusCodeCallbacks (
+ (UINTN) ChildFvHeader,
+ (UINTN) MigratedChildFvHeader,
+ (UINTN) ChildFvHeader->FvLength - 1
+ );
+
+ ConvertFvHob (Private, (UINTN) ChildFvHeader, (UINTN) MigratedChildFvHeader);
+ }
+ }
+ Private->Fv[FvIndex].FvHeader = MigratedFvHeader;
+ Private->Fv[FvIndex].FvHandle = (EFI_PEI_FV_HANDLE) MigratedFvHeader;
+
+ Status = MigratePeimsInFv (Private, FvIndex, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
+ ASSERT_EFI_ERROR (Status);
+
+ ConvertPpiPointersFv (
+ Private,
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader,
+ (UINTN) FvHeader->FvLength - 1
+ );
+
+ ConvertStatusCodeCallbacks (
+ (UINTN) FvHeader,
+ (UINTN) MigratedFvHeader,
+ (UINTN) FvHeader->FvLength - 1
+ );
+
+ ConvertFvHob (Private, (UINTN) FvHeader, (UINTN) MigratedFvHeader);
+ }
+ }
+
+ RemoveFvHobsInTemporaryMemory (Private);
+
+ return Status;
+}
+
+/**
Conduct PEIM dispatch.
@param SecCoreData Points to a data structure containing information about the PEI core's operating
@@ -988,7 +1419,11 @@ PeiDispatcher (
PeimFileHandle = NULL;
EntryPoint = 0;
- if ((Private->PeiMemoryInstalled) && (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
+ if ((Private->PeiMemoryInstalled) &&
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
+ PcdGetBool (PcdShadowPeimOnS3Boot))
+ ) {
//
// Once real memory is available, shadow the RegisterForShadow modules. And meanwhile
// update the modules' status from PEIM_STATE_REGISTER_FOR_SHADOW to PEIM_STATE_DONE.
@@ -1187,13 +1622,17 @@ PeiDispatcher (
PeiCheckAndSwitchStack (SecCoreData, Private);
if ((Private->PeiMemoryInstalled) && (Private->Fv[FvCount].PeimState[PeimCount] == PEIM_STATE_REGISTER_FOR_SHADOW) && \
- (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME || PcdGetBool (PcdShadowPeimOnS3Boot))) {
+ (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) ||
+ PcdGetBool (PcdShadowPeimOnS3Boot))
+ ) {
//
// If memory is available we shadow images by default for performance reasons.
// We call the entry point a 2nd time so the module knows it's shadowed.
//
//PERF_START (PeiServices, L"PEIM", PeimFileHandle, 0);
- if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot)) {
+ if ((Private->HobList.HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME) && !PcdGetBool (PcdShadowPeimOnBoot) &&
+ !PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
//
// Load PEIM into Memory for Register for shadow PEIM.
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Image/Image.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Image/Image.c
index 651ba121b75..ed5f1bbe494 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Image/Image.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Image/Image.c
@@ -328,8 +328,11 @@ LoadAndRelocatePeCoffImage (
//
// When Image has no reloc section, it can't be relocated into memory.
//
- if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {
+ if (ImageContext.RelocationsStripped && (Private->PeiMemoryInstalled) &&
+ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
+ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
+ ) {
DEBUG ((EFI_D_INFO|EFI_D_LOAD, "The image at 0x%08x without reloc section can't be loaded into memory\n", (UINTN) Pe32Data));
}
@@ -343,8 +346,11 @@ LoadAndRelocatePeCoffImage (
// On normal boot, PcdShadowPeimOnBoot decides whether load PEIM or PeiCore into memory.
// On S3 boot, PcdShadowPeimOnS3Boot decides whether load PEIM or PeiCore into memory.
//
- if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) && ((!IsPeiModule) ||
- (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) || (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))) {
+ if ((!ImageContext.RelocationsStripped) && (Private->PeiMemoryInstalled) &&
+ ((!IsPeiModule) || PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (!IsS3Boot && (PcdGetBool (PcdShadowPeimOnBoot) || IsRegisterForShadow)) ||
+ (IsS3Boot && PcdGetBool (PcdShadowPeimOnS3Boot)))
+ ) {
//
// Allocate more buffer to avoid buffer overflow.
//
@@ -445,6 +451,122 @@ LoadAndRelocatePeCoffImage (
}
/**
+ Loads and relocates a PE/COFF image in place.
+
+ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
+ @param ImageAddress The base address of the relocated PE/COFF image
+
+ @retval EFI_SUCCESS The file was loaded and relocated.
+ @retval Others The file not be loaded and error occurred.
+
+**/
+EFI_STATUS
+LoadAndRelocatePeCoffImageInPlace (
+ IN VOID *Pe32Data,
+ IN VOID *ImageAddress
+ )
+{
+ EFI_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+ ImageContext.Handle = Pe32Data;
+ ImageContext.ImageRead = PeiImageRead;
+
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ ImageContext.ImageAddress = (PHYSICAL_ADDRESS)(UINTN) ImageAddress;
+
+ //
+ // Load the image in place
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Relocate the image in place
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Flush the instruction cache so the image data is written before we execute it
+ //
+ if (ImageContext.ImageAddress != (EFI_PHYSICAL_ADDRESS)(UINTN) Pe32Data) {
+ InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize);
+ }
+
+ return Status;
+}
+
+/**
+ Find the PE32 Data for an FFS file.
+
+ @param FileHandle Pointer to the FFS file header of the image.
+ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
+
+ @retval EFI_SUCCESS Image is successfully loaded.
+ @retval EFI_NOT_FOUND Fail to locate PE32 Data.
+
+**/
+EFI_STATUS
+PeiGetPe32Data (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT VOID **Pe32Data
+ )
+{
+ EFI_STATUS Status;
+ EFI_SECTION_TYPE SearchType1;
+ EFI_SECTION_TYPE SearchType2;
+ UINT32 AuthenticationState;
+
+ *Pe32Data = NULL;
+
+ if (FeaturePcdGet (PcdPeiCoreImageLoaderSearchTeSectionFirst)) {
+ SearchType1 = EFI_SECTION_TE;
+ SearchType2 = EFI_SECTION_PE32;
+ } else {
+ SearchType1 = EFI_SECTION_PE32;
+ SearchType2 = EFI_SECTION_TE;
+ }
+
+ //
+ // Try to find a first exe section (if PcdPeiCoreImageLoaderSearchTeSectionFirst
+ // is true, TE will be searched first).
+ //
+ Status = PeiServicesFfsFindSectionData3 (
+ SearchType1,
+ 0,
+ FileHandle,
+ Pe32Data,
+ &AuthenticationState
+ );
+ //
+ // If we didn't find a first exe section, try to find the second exe section.
+ //
+ if (EFI_ERROR (Status)) {
+ Status = PeiServicesFfsFindSectionData3 (
+ SearchType2,
+ 0,
+ FileHandle,
+ Pe32Data,
+ &AuthenticationState
+ );
+ }
+ return Status;
+}
+
+/**
Loads a PEIM into memory for subsequent execution. If there are compressed
images or images that need to be relocated into memory for performance reasons,
this service performs that transformation.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Memory/MemoryServices.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
index a906fb57d00..a833467f4d8 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Memory/MemoryServices.c
@@ -167,6 +167,88 @@ MigrateMemoryPages (
}
/**
+ Removes any FV HOBs whose base address is not in PEI installed memory.
+
+ @param[in] Private Pointer to PeiCore's private data structure.
+
+**/
+VOID
+RemoveFvHobsInTemporaryMemory (
+ IN PEI_CORE_INSTANCE *Private
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+
+ DEBUG ((DEBUG_INFO, "Removing FVs in FV HOB not already migrated to permanent memory.\n"));
+
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2 || GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ DEBUG ((DEBUG_INFO, " Found FV HOB.\n"));
+ DEBUG ((
+ DEBUG_INFO,
+ " BA=%016lx L=%016lx\n",
+ FirmwareVolumeHob->BaseAddress,
+ FirmwareVolumeHob->Length
+ ));
+ if (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress >= Private->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) (UINTN) FirmwareVolumeHob->BaseAddress + (FirmwareVolumeHob->Length - 1)) < Private->FreePhysicalMemoryTop)
+ )
+ ) {
+ DEBUG ((DEBUG_INFO, " Removing FV HOB to an FV in T-RAM (was not migrated).\n"));
+ Hob.Header->HobType = EFI_HOB_TYPE_UNUSED;
+ }
+ }
+ }
+}
+
+/**
+ Migrate the base address in firmware volume allocation HOBs
+ from temporary memory to PEI installed memory.
+
+ @param[in] PrivateData Pointer to PeiCore's private data structure.
+ @param[in] OrgFvHandle Address of FV Handle in temporary memory.
+ @param[in] FvHandle Address of FV Handle in permanent memory.
+
+**/
+VOID
+ConvertFvHob (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob;
+ EFI_HOB_FIRMWARE_VOLUME2 *FirmwareVolume2Hob;
+ EFI_HOB_FIRMWARE_VOLUME3 *FirmwareVolume3Hob;
+
+ DEBUG ((DEBUG_INFO, "Converting FVs in FV HOB.\n"));
+
+ for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
+ if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) {
+ FirmwareVolumeHob = Hob.FirmwareVolume;
+ if (FirmwareVolumeHob->BaseAddress == OrgFvHandle) {
+ FirmwareVolumeHob->BaseAddress = FvHandle;
+ }
+ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV2) {
+ FirmwareVolume2Hob = Hob.FirmwareVolume2;
+ if (FirmwareVolume2Hob->BaseAddress == OrgFvHandle) {
+ FirmwareVolume2Hob->BaseAddress = FvHandle;
+ }
+ } else if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV3) {
+ FirmwareVolume3Hob = Hob.FirmwareVolume3;
+ if (FirmwareVolume3Hob->BaseAddress == OrgFvHandle) {
+ FirmwareVolume3Hob->BaseAddress = FvHandle;
+ }
+ }
+ }
+}
+
+/**
Migrate MemoryBaseAddress in memory allocation HOBs
from the temporary memory to PEI installed memory.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.h
index 6c6c2e56599..07ace708d28 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.h
@@ -44,6 +44,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Guid/FirmwareFileSystem2.h>
#include <Guid/FirmwareFileSystem3.h>
#include <Guid/AprioriFileName.h>
+#include <Guid/MigratedFvInfo.h>
///
/// It is an FFS type extension used for PeiFindFileEx. It indicates current
@@ -395,6 +396,41 @@ PeimDispatchReadiness (
);
/**
+ Migrate a PEIM from temporary RAM to permanent memory.
+
+ @param PeimFileHandle Pointer to the FFS file header of the image.
+ @param MigratedFileHandle Pointer to the FFS file header of the migrated image.
+
+ @retval EFI_SUCCESS Sucessfully migrated the PEIM to permanent memory.
+
+**/
+EFI_STATUS
+EFIAPI
+MigratePeim (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN EFI_PEI_FILE_HANDLE MigratedFileHandle
+ );
+
+/**
+ Migrate FVs out of temporary RAM before the cache is flushed.
+
+ @param Private PeiCore's private data structure
+ @param SecCoreData Points to a data structure containing information about the PEI core's operating
+ environment, such as the size and location of temporary RAM, the stack location and
+ the BFV location.
+
+ @retval EFI_SUCCESS Succesfully migrated installed FVs from temporary RAM to permanent memory.
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory exists to allocate needed pages.
+
+**/
+EFI_STATUS
+EFIAPI
+EvacuateTempRam (
+ IN PEI_CORE_INSTANCE *Private,
+ IN CONST EFI_SEC_PEI_HAND_OFF *SecCoreData
+ );
+
+/**
Conduct PEIM dispatch.
@param SecCoreData Pointer to the data structure containing SEC to PEI handoff data
@@ -479,6 +515,50 @@ ConvertPpiPointers (
/**
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param OrgFvHandle Address of FV Handle in temporary memory.
+ @param FvHandle Address of FV Handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertPpiPointersFv (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ );
+
+/**
+
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
+
+**/
+VOID
+ConvertPeiCorePpiPointers (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_FV_HANDLE *CoreFvHandle
+ );
+
+/**
+
+ Dumps the PPI lists to debug output.
+
+ @param PrivateData Points to PeiCore's private instance data.
+
+**/
+VOID
+DumpPpiList (
+ IN PEI_CORE_INSTANCE *PrivateData
+ );
+
+/**
+
Install PPI services. It is implementation of EFI_PEI_SERVICE.InstallPpi.
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
@@ -809,6 +889,37 @@ PeiFfsFindNextFile (
);
/**
+ Go through the file to search SectionType section.
+ Search within encapsulation sections (compression and GUIDed) recursively,
+ until the match section is found.
+
+ @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param SectionType Filter to find only section of this type.
+ @param SectionInstance Pointer to the filter to find the specific instance of section.
+ @param Section From where to search.
+ @param SectionSize The file size to search.
+ @param OutputBuffer A pointer to the discovered section, if successful.
+ NULL if section not found.
+ @param AuthenticationStatus Updated upon return to point to the authentication status for this section.
+ @param IsFfs3Fv Indicates the FV format.
+
+ @return EFI_NOT_FOUND The match section is not found.
+ @return EFI_SUCCESS The match section is found.
+
+**/
+EFI_STATUS
+ProcessSection (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_SECTION_TYPE SectionType,
+ IN OUT UINTN *SectionInstance,
+ IN EFI_COMMON_SECTION_HEADER *Section,
+ IN UINTN SectionSize,
+ OUT VOID **OutputBuffer,
+ OUT UINT32 *AuthenticationStatus,
+ IN BOOLEAN IsFfs3Fv
+ );
+
+/**
Searches for the next matching section within the specified file.
@param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation
@@ -932,6 +1043,33 @@ MigrateMemoryPages (
);
/**
+ Removes any FV HOBs whose base address is not in PEI installed memory.
+
+ @param[in] Private Pointer to PeiCore's private data structure.
+
+**/
+VOID
+RemoveFvHobsInTemporaryMemory (
+ IN PEI_CORE_INSTANCE *Private
+ );
+
+/**
+ Migrate the base address in firmware volume allocation HOBs
+ from temporary memory to PEI installed memory.
+
+ @param[in] PrivateData Pointer to PeiCore's private data structure.
+ @param[in] OrgFvHandle Address of FV Handle in temporary memory.
+ @param[in] FvHandle Address of FV Handle in permanent memory.
+
+**/
+VOID
+ConvertFvHob (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle
+ );
+
+/**
Migrate MemoryBaseAddress in memory allocation HOBs
from the temporary memory to PEI installed memory.
@@ -1250,6 +1388,38 @@ InitializeImageServices (
);
/**
+ Loads and relocates a PE/COFF image in place.
+
+ @param Pe32Data The base address of the PE/COFF file that is to be loaded and relocated
+ @param ImageAddress The base address of the relocated PE/COFF image
+
+ @retval EFI_SUCCESS The file was loaded and relocated
+ @retval Others The file not be loaded and error occurred.
+
+**/
+EFI_STATUS
+LoadAndRelocatePeCoffImageInPlace (
+ IN VOID *Pe32Data,
+ IN VOID *ImageAddress
+ );
+
+/**
+ Find the PE32 Data for an FFS file.
+
+ @param FileHandle Pointer to the FFS file header of the image.
+ @param Pe32Data Pointer to a (VOID *) PE32 Data pointer.
+
+ @retval EFI_SUCCESS Image is successfully loaded.
+ @retval EFI_NOT_FOUND Fail to locate PE32 Data.
+
+**/
+EFI_STATUS
+PeiGetPe32Data (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ OUT VOID **Pe32Data
+ );
+
+/**
The wrapper function of PeiLoadImageLoadImage().
@param This Pointer to EFI_PEI_LOAD_FILE_PPI.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.inf
index dc50dbaa264..edd1ca93a28 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain.inf
@@ -76,6 +76,8 @@
## CONSUMES ## UNDEFINED # Locate PPI
## CONSUMES ## GUID # Used to compare with FV's file system GUID and get the FV's file system format
gEfiFirmwareFileSystem3Guid
+ gStatusCodeCallbackGuid
+ gEdkiiMigratedFvInfoGuid ## SOMETIMES_PRODUCES ## HOB
[Ppis]
gEfiPeiStatusCodePpiGuid ## SOMETIMES_CONSUMES # PeiReportStatusService is not ready if this PPI doesn't exist
@@ -109,6 +111,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnS3Boot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
# [BootMode]
# S3_RESUME ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
index fddcec9af15..d01cc76db35 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/PeiMain/PeiMain.c
@@ -319,8 +319,9 @@ PeiCore (
// PEI Core and PEIMs to get high performance.
//
OldCoreData->ShadowedPeiCore = (PEICORE_FUNCTION_POINTER) (UINTN) PeiCore;
- if ((HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot))
- || (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes) ||
+ (HandoffInformationTable->BootMode == BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnS3Boot)) ||
+ (HandoffInformationTable->BootMode != BOOT_ON_S3_RESUME && PcdGetBool (PcdShadowPeimOnBoot))) {
OldCoreData->ShadowedPeiCore = ShadowPeiCore (OldCoreData);
}
@@ -418,6 +419,23 @@ PeiCore (
ProcessPpiListFromSec ((CONST EFI_PEI_SERVICES **) &PrivateData.Ps, PpiList);
}
} else {
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ //
+ // When PcdMigrateTemporaryRamFirmwareVolumes is TRUE, alway shadow all
+ // PEIMs no matter the condition of PcdShadowPeimOnBoot and PcdShadowPeimOnS3Boot
+ //
+ DEBUG ((DEBUG_VERBOSE, "PPI lists before temporary RAM evacuation:\n"));
+ DumpPpiList (&PrivateData);
+
+ //
+ // Migrate installed content from Temporary RAM to Permanent RAM
+ //
+ EvacuateTempRam (&PrivateData, SecCoreData);
+
+ DEBUG ((DEBUG_VERBOSE, "PPI lists after temporary RAM evacuation:\n"));
+ DumpPpiList (&PrivateData);
+ }
+
//
// Try to locate Temporary RAM Done Ppi.
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Ppi/Ppi.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Ppi/Ppi.c
index 6210b19ac8c..e520de4e2a8 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Ppi/Ppi.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/Pei/Ppi/Ppi.c
@@ -200,6 +200,227 @@ ConvertPpiPointers (
/**
+ Migrate Notify Pointers inside an FV from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param OrgFvHandle Address of FV Handle in temporary memory.
+ @param FvHandle Address of FV Handle in permanent memory.
+ @param FvSize Size of the FV.
+
+**/
+VOID
+ConvertPpiPointersFv (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN UINTN OrgFvHandle,
+ IN UINTN FvHandle,
+ IN UINTN FvSize
+ )
+{
+ UINT8 Index;
+ UINTN Offset;
+ BOOLEAN OffsetPositive;
+ EFI_PEI_FIRMWARE_VOLUME_INFO_PPI *FvInfoPpi;
+ UINT8 GuidIndex;
+ EFI_GUID *Guid;
+ EFI_GUID *GuidCheckList[2];
+
+ GuidCheckList[0] = &gEfiPeiFirmwareVolumeInfoPpiGuid;
+ GuidCheckList[1] = &gEfiPeiFirmwareVolumeInfo2PpiGuid;
+
+ if (FvHandle > OrgFvHandle) {
+ OffsetPositive = TRUE;
+ Offset = FvHandle - OrgFvHandle;
+ } else {
+ OffsetPositive = FALSE;
+ Offset = OrgFvHandle - FvHandle;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "Converting PPI pointers in FV.\n"));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " OrgFvHandle at 0x%08x. FvHandle at 0x%08x. FvSize = 0x%x\n",
+ (UINTN) OrgFvHandle,
+ (UINTN) FvHandle,
+ FvSize
+ ));
+ DEBUG ((
+ DEBUG_VERBOSE,
+ " OrgFvHandle range: 0x%08x - 0x%08x\n",
+ OrgFvHandle,
+ OrgFvHandle + FvSize
+ ));
+
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Notify,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ }
+
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Notify,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ }
+
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ ConvertPointer (
+ (VOID **) &PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+
+ Guid = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid;
+ for (GuidIndex = 0; GuidIndex < ARRAY_SIZE (GuidCheckList); ++GuidIndex) {
+ //
+ // Don't use CompareGuid function here for performance reasons.
+ // Instead we compare the GUID as INT32 at a time and branch
+ // on the first failed comparison.
+ //
+ if ((((INT32 *)Guid)[0] == ((INT32 *)GuidCheckList[GuidIndex])[0]) &&
+ (((INT32 *)Guid)[1] == ((INT32 *)GuidCheckList[GuidIndex])[1]) &&
+ (((INT32 *)Guid)[2] == ((INT32 *)GuidCheckList[GuidIndex])[2]) &&
+ (((INT32 *)Guid)[3] == ((INT32 *)GuidCheckList[GuidIndex])[3])) {
+ FvInfoPpi = PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Ppi;
+ DEBUG ((DEBUG_VERBOSE, " FvInfo: %p -> ", FvInfoPpi->FvInfo));
+ if ((UINTN)FvInfoPpi->FvInfo == OrgFvHandle) {
+ ConvertPointer (
+ (VOID **)&FvInfoPpi->FvInfo,
+ OrgFvHandle,
+ OrgFvHandle + FvSize,
+ Offset,
+ OffsetPositive
+ );
+ DEBUG ((DEBUG_VERBOSE, "%p", FvInfoPpi->FvInfo));
+ }
+ DEBUG ((DEBUG_VERBOSE, "\n"));
+ break;
+ }
+ }
+ }
+}
+
+/**
+
+ Dumps the PPI lists to debug output.
+
+ @param PrivateData Points to PeiCore's private instance data.
+
+**/
+VOID
+DumpPpiList (
+ IN PEI_CORE_INSTANCE *PrivateData
+ )
+{
+ DEBUG_CODE_BEGIN ();
+ UINTN Index;
+
+ if (PrivateData == NULL) {
+ return;
+ }
+
+ for (Index = 0; Index < PrivateData->PpiData.CallbackNotifyList.CurrentCount; Index++) {
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "CallbackNotify[%2d] {%g} at 0x%x (%a)\n",
+ Index,
+ PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Notify->Guid,
+ (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw,
+ (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.CallbackNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
+ )
+ ? "CAR" : "Post-Memory"
+ )
+ ));
+ }
+ for (Index = 0; Index < PrivateData->PpiData.DispatchNotifyList.CurrentCount; Index++) {
+ DEBUG ((DEBUG_VERBOSE,
+ "DispatchNotify[%2d] {%g} at 0x%x (%a)\n",
+ Index,
+ PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Notify->Guid,
+ (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw,
+ (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw >=PrivateData->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.DispatchNotifyList.NotifyPtrs[Index].Raw) + sizeof (EFI_PEI_NOTIFY_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
+ )
+ ? "CAR" : "Post-Memory"
+ )
+ ));
+ }
+ for (Index = 0; Index < PrivateData->PpiData.PpiList.CurrentCount; Index++) {
+ DEBUG ((DEBUG_VERBOSE,
+ "PPI[%2d] {%g} at 0x%x (%a)\n",
+ Index,
+ PrivateData->PpiData.PpiList.PpiPtrs[Index].Ppi->Guid,
+ (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw,
+ (
+ !(
+ ((EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw >= PrivateData->PhysicalMemoryBegin) &&
+ (((EFI_PHYSICAL_ADDRESS) ((UINTN) PrivateData->PpiData.PpiList.PpiPtrs[Index].Raw) + sizeof (EFI_PEI_PPI_DESCRIPTOR)) < PrivateData->FreePhysicalMemoryTop)
+ )
+ ? "CAR" : "Post-Memory"
+ )
+ ));
+ }
+ DEBUG_CODE_END ();
+}
+
+/**
+
This function installs an interface in the PEI PPI database by GUID.
The purpose of the service is to publish an interface that other parties
can use to call additional PEIMs.
@@ -830,3 +1051,68 @@ ProcessPpiListFromSec (
}
}
+/**
+
+ Migrate PPI Pointers of PEI_CORE from temporary memory to permanent memory.
+
+ @param PrivateData Pointer to PeiCore's private data structure.
+ @param CoreFvHandle Address of PEI_CORE FV Handle in temporary memory.
+
+**/
+VOID
+ConvertPeiCorePpiPointers (
+ IN PEI_CORE_INSTANCE *PrivateData,
+ IN PEI_CORE_FV_HANDLE *CoreFvHandle
+ )
+{
+ EFI_FV_FILE_INFO FileInfo;
+ EFI_PHYSICAL_ADDRESS OrgImageBase;
+ EFI_PHYSICAL_ADDRESS MigratedImageBase;
+ UINTN PeiCoreModuleSize;
+ EFI_PEI_FILE_HANDLE PeiCoreFileHandle;
+ VOID *PeiCoreImageBase;
+ VOID *PeiCoreEntryPoint;
+ EFI_STATUS Status;
+
+ PeiCoreFileHandle = NULL;
+
+ //
+ // Find the PEI Core in the BFV in temporary memory.
+ //
+ Status = CoreFvHandle->FvPpi->FindFileByType (
+ CoreFvHandle->FvPpi,
+ EFI_FV_FILETYPE_PEI_CORE,
+ CoreFvHandle->FvHandle,
+ &PeiCoreFileHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ Status = CoreFvHandle->FvPpi->GetFileInfo (CoreFvHandle->FvPpi, PeiCoreFileHandle, &FileInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiGetPe32Data (PeiCoreFileHandle, &PeiCoreImageBase);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Find PEI Core EntryPoint in the BFV in temporary memory.
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, &PeiCoreEntryPoint);
+ ASSERT_EFI_ERROR (Status);
+
+ OrgImageBase = (UINTN) PeiCoreImageBase;
+ MigratedImageBase = (UINTN) _ModuleEntryPoint - ((UINTN) PeiCoreEntryPoint - (UINTN) PeiCoreImageBase);
+
+ //
+ // Size of loaded PEI_CORE in permanent memory.
+ //
+ PeiCoreModuleSize = (UINTN)FileInfo.BufferSize - ((UINTN) OrgImageBase - (UINTN) FileInfo.Buffer);
+
+ //
+ // Migrate PEI_CORE PPI pointers from temporary memory to newly
+ // installed PEI_CORE in permanent memory.
+ //
+ ConvertPpiPointersFv (PrivateData, (UINTN) OrgImageBase, (UINTN) MigratedImageBase, PeiCoreModuleSize);
+ }
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
index 0bf15b849f6..86896fe5012 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Core/PiSmmCore/PiSmmIpl.c
@@ -39,12 +39,6 @@
#define SMRAM_CAPABILITIES (EFI_MEMORY_WB | EFI_MEMORY_UC)
-#define MEMORY_CACHE_ATTRIBUTES (EFI_MEMORY_UC | EFI_MEMORY_WC | \
- EFI_MEMORY_WT | EFI_MEMORY_WB | \
- EFI_MEMORY_WP | EFI_MEMORY_UCE)
-
-#define MEMORY_PAGE_ATTRIBUTES (EFI_MEMORY_XP | EFI_MEMORY_RP | EFI_MEMORY_RO)
-
//
// Function prototypes from produced protocols
//
@@ -1710,7 +1704,7 @@ SmmIplEntry (
CpuArch = NULL;
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch);
if (!EFI_ERROR (Status)) {
- MemDesc.Attributes &= ~(MEMORY_CACHE_ATTRIBUTES | MEMORY_PAGE_ATTRIBUTES);
+ MemDesc.Attributes &= ~(EFI_CACHE_ATTRIBUTE_MASK | EFI_MEMORY_ATTRIBUTE_MASK);
MemDesc.Attributes |= EFI_MEMORY_WB;
Status = gDS->SetMemorySpaceAttributes (
mSmramCacheBase,
@@ -1727,7 +1721,7 @@ SmmIplEntry (
&MemDesc
);
DEBUG ((DEBUG_INFO, "SMRAM attributes: %016lx\n", MemDesc.Attributes));
- ASSERT ((MemDesc.Attributes & MEMORY_PAGE_ATTRIBUTES) == 0);
+ ASSERT ((MemDesc.Attributes & EFI_MEMORY_ATTRIBUTE_MASK) == 0);
);
}
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/MigratedFvInfo.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/MigratedFvInfo.h
new file mode 100644
index 00000000000..c41389444e6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/MigratedFvInfo.h
@@ -0,0 +1,22 @@
+/** @file
+ Migrated FV information
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EDKII_MIGRATED_FV_INFO_GUID_H__
+#define __EDKII_MIGRATED_FV_INFO_GUID_H__
+
+typedef struct {
+ UINT32 FvOrgBase; // original FV address
+ UINT32 FvNewBase; // new FV address
+ UINT32 FvDataBase; // original FV data
+ UINT32 FvLength; // Fv Length
+} EDKII_MIGRATED_FV_INFO;
+
+extern EFI_GUID gEdkiiMigratedFvInfoGuid;
+
+#endif // #ifndef __EDKII_MIGRATED_FV_INFO_GUID_H__
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
new file mode 100644
index 00000000000..33e6817bf66
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Guid/VarCheckPolicyMmi.h
@@ -0,0 +1,54 @@
+/** @file -- VarCheckPolicyMmiCommon.h
+This header contains communication definitions that are shared between DXE
+and the MM component of VarCheckPolicy.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef _VAR_CHECK_POLICY_MMI_COMMON_H_
+#define _VAR_CHECK_POLICY_MMI_COMMON_H_
+
+#define VAR_CHECK_POLICY_COMM_SIG SIGNATURE_32('V', 'C', 'P', 'C')
+#define VAR_CHECK_POLICY_COMM_REVISION 1
+
+#pragma pack(push, 1)
+
+typedef struct _VAR_CHECK_POLICY_COMM_HEADER {
+ UINT32 Signature;
+ UINT32 Revision;
+ UINT32 Command;
+ EFI_STATUS Result;
+} VAR_CHECK_POLICY_COMM_HEADER;
+
+typedef struct _VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS {
+ BOOLEAN State;
+} VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS;
+
+typedef struct _VAR_CHECK_POLICY_COMM_DUMP_PARAMS {
+ UINT32 PageRequested;
+ UINT32 TotalSize;
+ UINT32 PageSize;
+ BOOLEAN HasMore;
+} VAR_CHECK_POLICY_COMM_DUMP_PARAMS;
+
+#pragma pack(pop)
+
+// Make sure that we will hold at least the headers.
+#define VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE MAX((OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof (VAR_CHECK_POLICY_COMM_HEADER) + EFI_PAGES_TO_SIZE(1)), EFI_PAGES_TO_SIZE(4))
+#define VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE (VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE - \
+ (OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + \
+ sizeof(VAR_CHECK_POLICY_COMM_HEADER) + \
+ sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS)))
+STATIC_ASSERT (
+ VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE < VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE,
+ "an integer underflow may have occurred calculating VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE"
+ );
+
+#define VAR_CHECK_POLICY_COMMAND_DISABLE 0x0001
+#define VAR_CHECK_POLICY_COMMAND_IS_ENABLED 0x0002
+#define VAR_CHECK_POLICY_COMMAND_REGISTER 0x0003
+#define VAR_CHECK_POLICY_COMMAND_DUMP 0x0004
+#define VAR_CHECK_POLICY_COMMAND_LOCK 0x0005
+
+#endif // _VAR_CHECK_POLICY_MMI_COMMON_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/HiiLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/HiiLib.h
index f1681c37325..23682626576 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/HiiLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/HiiLib.h
@@ -1,7 +1,8 @@
/** @file
Public include file for the HII Library
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -123,16 +124,8 @@ HiiSetString (
;
/**
- Retrieves a string from a string package in a specific language. If the language
- is not specified, then a string from a string package in the current platform
- language is retrieved. If the string cannot be retrieved using the specified
- language or the current platform language, then the string is retrieved from
- the string package in the first language the string package supports. The
- returned string is allocated using AllocatePool(). The caller is responsible
- for freeing the allocated buffer using FreePool().
-
- If HiiHandle is NULL, then ASSERT().
- If StringId is 0, then ASSERT().
+ Retrieves a string from a string package in a specific language specified in Language
+ or in the best lanaguage. See HiiGetStringEx () for the details.
@param[in] HiiHandle A handle that was previously registered in the HII Database.
@param[in] StringId The identifier of the string to retrieved from the string
@@ -152,8 +145,49 @@ HiiGetString (
IN EFI_HII_HANDLE HiiHandle,
IN EFI_STRING_ID StringId,
IN CONST CHAR8 *Language OPTIONAL
- )
-;
+ );
+
+/**
+ Retrieves a string from a string package in a specific language or in the best
+ language at discretion of this function according to the priority of languages.
+ TryBestLanguage is used to get the string in the best language or in the language
+ specified in Language parameter. The behavior is,
+ If TryBestLanguage is TRUE, this function looks for the best language for the string.
+ - If the string can not be retrieved using the specified language or the current
+ platform language, then the string is retrieved from the string package in the
+ first language the string package supports.
+ If TryBestLanguage is FALSE, Language must be specified for retrieving the string.
+
+ The returned string is allocated using AllocatePool(). The caller is responsible
+ for freeing the allocated buffer using FreePool().
+
+ If HiiHandle is NULL, then ASSERT().
+ If StringId is 0, then ASSET.
+ If TryBestLanguage is FALE and Language is NULL, then ASSERT().
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+ @param[in] StringId The identifier of the string to retrieved from the string
+ package associated with HiiHandle.
+ @param[in] Language The language of the string to retrieve. If this parameter
+ is NULL, then the current platform language is used. The
+ format of Language must follow the language format assumed
+ the HII Database.
+ @param[in] TryBestLanguage If TRUE, try to get the best matching language from all
+ supported languages.If FALSE, the Language must be assigned
+ for the StringID.
+
+ @retval NULL The string specified by StringId is not present in the string package.
+ @retval Other The string was returned.
+
+**/
+EFI_STRING
+EFIAPI
+HiiGetStringEx (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language OPTIONAL,
+ IN BOOLEAN TryBestLanguage
+ );
/**
Retrieves a string from a string package named by GUID, in the specified language.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
new file mode 100644
index 00000000000..a06d689f633
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyHelperLib.h
@@ -0,0 +1,164 @@
+/** @file -- VariablePolicyHelperLib.h
+This library contains helper functions for marshalling and registering
+new policies with the VariablePolicy infrastructure.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _EDKII_VARIABLE_POLICY_HELPER_LIB_H_
+#define _EDKII_VARIABLE_POLICY_HELPER_LIB_H_
+
+#include <Protocol/VariablePolicy.h>
+
+/**
+ This helper function will allocate and populate a new VariablePolicy
+ structure for a policy that does not contain any sub-structures (such as
+ VARIABLE_LOCK_ON_VAR_STATE_POLICY).
+
+ NOTE: Caller will need to free structure once finished.
+
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] LockPolicyType LockPolicyType for the VariablePolicy.
+ @param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the
+ new policy.
+
+ @retval EFI_SUCCESS Operation completed successfully and structure is populated.
+ @retval EFI_INVALID_PARAMETER Namespace is NULL.
+ @retval EFI_INVALID_PARAMETER LockPolicyType is invalid for a basic structure.
+ @retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateBasicVariablePolicy (
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType,
+ OUT VARIABLE_POLICY_ENTRY **NewEntry
+ );
+
+
+/**
+ This helper function will allocate and populate a new VariablePolicy
+ structure for a policy with a lock type of VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE.
+
+ NOTE: Caller will need to free structure once finished.
+
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+ @param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+ @param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+ @param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the
+ new policy.
+
+ @retval EFI_SUCCESS Operation completed successfully and structure is populated.
+ @retval EFI_INVALID_PARAMETER Namespace, VarStateNamespace, VarStateName is NULL.
+ @retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateVarStateVariablePolicy (
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN CONST EFI_GUID *VarStateNamespace,
+ IN UINT8 VarStateValue,
+ IN CONST CHAR16 *VarStateName,
+ OUT VARIABLE_POLICY_ENTRY **NewEntry
+ );
+
+
+/**
+ This helper function does everything that CreateBasicVariablePolicy() does, but also
+ uses the passed in protocol to register the policy with the infrastructure.
+ Does not return a buffer, does not require the caller to free anything.
+
+ @param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] LockPolicyType LockPolicyType for the VariablePolicy.
+
+ @retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+ @retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterBasicVariablePolicy (
+ IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType
+ );
+
+
+/**
+ This helper function does everything that CreateBasicVariablePolicy() does, but also
+ uses the passed in protocol to register the policy with the infrastructure.
+ Does not return a buffer, does not require the caller to free anything.
+
+ @param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+ @param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+ @param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+
+ @retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+ @retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterVarStateVariablePolicy (
+ IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN CONST EFI_GUID *VarStateNamespace,
+ IN CONST CHAR16 *VarStateName,
+ IN UINT8 VarStateValue
+ );
+
+#endif // _EDKII_VARIABLE_POLICY_HELPER_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyLib.h
new file mode 100644
index 00000000000..7428b9d67f9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Library/VariablePolicyLib.h
@@ -0,0 +1,207 @@
+/** @file -- VariablePolicyLib.h
+Business logic for Variable Policy enforcement.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VARIABLE_POLICY_LIB_H_
+#define _VARIABLE_POLICY_LIB_H_
+
+#include <Protocol/VariablePolicy.h>
+
+/**
+ This API function validates and registers a new policy with
+ the policy enforcement engine.
+
+ @param[in] NewPolicy Pointer to the incoming policy structure.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally inconsistent.
+ @retval EFI_ALREADY_STARTED An identical matching policy already exists.
+ @retval EFI_WRITE_PROTECTED The interface has been locked until the next reboot.
+ @retval EFI_UNSUPPORTED Policy enforcement has been disabled. No reason to add more policies.
+ @retval EFI_ABORTED A calculation error has prevented this function from completing.
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any more policies.
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterVariablePolicy (
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy
+ );
+
+
+/**
+ This API function checks to see whether the parameters to SetVariable would
+ be allowed according to the current variable policies.
+
+ @param[in] VariableName Same as EFI_SET_VARIABLE.
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.
+ @param[in] Attributes Same as EFI_SET_VARIABLE.
+ @param[in] DataSize Same as EFI_SET_VARIABLE.
+ @param[in] Data Same as EFI_SET_VARIABLE.
+
+ @retval EFI_SUCCESS A matching policy allows this update.
+ @retval EFI_SUCCESS There are currently no policies that restrict this update.
+ @retval EFI_SUCCESS The protections have been disable until the next reboot.
+ @retval EFI_WRITE_PROTECTED Variable is currently locked.
+ @retval EFI_INVALID_PARAMETER Attributes or size are invalid.
+ @retval EFI_ABORTED A lock policy exists, but an error prevented evaluation.
+ @retval EFI_NOT_READY Library has not been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+ValidateSetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ );
+
+
+/**
+ This API function disables the variable policy enforcement. If it's
+ already been called once, will return EFI_ALREADY_STARTED.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Has already been called once this boot.
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot.
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platform PCD.
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableVariablePolicy (
+ VOID
+ );
+
+
+/**
+ This API function will dump the entire contents of the variable policy table.
+
+ Similar to GetVariable, the first call can be made with a 0 size and it will return
+ the size of the buffer required to hold the entire table.
+
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Size is 0.
+ @param[in,out] Size On input, the size of the output buffer. On output, the size
+ of the data returned.
+
+ @retval EFI_SUCCESS Policy data is in the output buffer and Size has been updated.
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero and Policy is NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy. Size updated with required size.
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+DumpVariablePolicy (
+ OUT UINT8 *Policy,
+ IN OUT UINT32 *Size
+ );
+
+
+/**
+ This API function returns whether or not the policy engine is
+ currently being enforced.
+
+ @retval TRUE
+ @retval FALSE
+ @retval FALSE Library has not yet been initialized.
+
+**/
+BOOLEAN
+EFIAPI
+IsVariablePolicyEnabled (
+ VOID
+ );
+
+
+/**
+ This API function locks the interface so that no more policy updates
+ can be performed or changes made to the enforcement until the next boot.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+LockVariablePolicy (
+ VOID
+ );
+
+
+/**
+ This API function returns whether or not the policy interface is locked
+ for the remainder of the boot.
+
+ @retval TRUE
+ @retval FALSE
+ @retval FALSE Library has not yet been initialized.
+
+**/
+BOOLEAN
+EFIAPI
+IsVariablePolicyInterfaceLocked (
+ VOID
+ );
+
+
+/**
+ This helper function initializes the library and sets
+ up any required internal structures or handlers.
+
+ Also registers the internal pointer for the GetVariable helper.
+
+ @param[in] GetVariableHelper A function pointer matching the EFI_GET_VARIABLE prototype that will be used to
+ check policy criteria that involve the existence of other variables.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED The initialize function has been called more than once without a call to
+ deinitialize.
+
+**/
+EFI_STATUS
+EFIAPI
+InitVariablePolicyLib (
+ IN EFI_GET_VARIABLE GetVariableHelper
+ );
+
+
+/**
+ This helper function returns whether or not the library is currently initialized.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+EFIAPI
+IsVariablePolicyLibInitialized (
+ VOID
+ );
+
+
+/**
+ This helper function tears down the library.
+
+ Should generally only be used for test harnesses.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_READY Deinitialize was called without first calling initialize.
+
+**/
+EFI_STATUS
+EFIAPI
+DeinitVariablePolicyLib (
+ VOID
+ );
+
+
+#endif // _VARIABLE_POLICY_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/GenericMemoryTest.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/GenericMemoryTest.h
index 2fb218a1de2..4152e04d8af 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/GenericMemoryTest.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/GenericMemoryTest.h
@@ -54,12 +54,12 @@ EFI_STATUS
@param TestedMemorySize Return the tested extended memory size.
@param TotalMemorySize Return the whole system physical memory size.
The total memory size does not include memory in a slot with a disabled DIMM.
- @param ErrorOut TRUE if the memory error occured.
+ @param ErrorOut TRUE if the memory error occurred.
@param IfTestAbort Indicates that the user pressed "ESC" to skip the memory test.
@retval EFI_SUCCESS One block of memory passed the test.
@retval EFI_NOT_FOUND All memory blocks have already been tested.
- @retval EFI_DEVICE_ERROR Memory device error occured, and no agent can handle it.
+ @retval EFI_DEVICE_ERROR Memory device error occurred, and no agent can handle it.
**/
typedef
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/PeCoffImageEmulator.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/PeCoffImageEmulator.h
index 34417fbab58..cff63822194 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/PeCoffImageEmulator.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/PeCoffImageEmulator.h
@@ -1,13 +1,6 @@
/** @file
Copyright (c) 2019, Linaro, Ltd. All rights reserved.<BR>
-
- This program and the accompanying materials are licensed and made available
- under the terms and conditions of the BSD License which accompanies this
- distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/VariablePolicy.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/VariablePolicy.h
new file mode 100644
index 00000000000..98ab48d3e04
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Include/Protocol/VariablePolicy.h
@@ -0,0 +1,157 @@
+/** @file -- VariablePolicy.h
+
+This protocol allows communication with Variable Policy Engine.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef __EDKII_VARIABLE_POLICY_PROTOCOL__
+#define __EDKII_VARIABLE_POLICY_PROTOCOL__
+
+#define EDKII_VARIABLE_POLICY_PROTOCOL_REVISION 0x0000000000010000
+
+#define EDKII_VARIABLE_POLICY_PROTOCOL_GUID \
+ { \
+ 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } \
+ }
+
+#define VARIABLE_POLICY_ENTRY_REVISION 0x00010000
+
+#pragma pack(push, 1)
+typedef struct {
+ UINT32 Version;
+ UINT16 Size;
+ UINT16 OffsetToName;
+ EFI_GUID Namespace;
+ UINT32 MinSize;
+ UINT32 MaxSize;
+ UINT32 AttributesMustHave;
+ UINT32 AttributesCantHave;
+ UINT8 LockPolicyType;
+ UINT8 Padding[3];
+ // UINT8 LockPolicy[]; // Variable Length Field
+ // CHAR16 Name[] // Variable Length Field
+} VARIABLE_POLICY_ENTRY;
+
+#define VARIABLE_POLICY_NO_MIN_SIZE 0
+#define VARIABLE_POLICY_NO_MAX_SIZE MAX_UINT32
+#define VARIABLE_POLICY_NO_MUST_ATTR 0
+#define VARIABLE_POLICY_NO_CANT_ATTR 0
+
+#define VARIABLE_POLICY_TYPE_NO_LOCK 0
+#define VARIABLE_POLICY_TYPE_LOCK_NOW 1
+#define VARIABLE_POLICY_TYPE_LOCK_ON_CREATE 2
+#define VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE 3
+
+typedef struct {
+ EFI_GUID Namespace;
+ UINT8 Value;
+ UINT8 Padding;
+ // CHAR16 Name[]; // Variable Length Field
+} VARIABLE_LOCK_ON_VAR_STATE_POLICY;
+#pragma pack(pop)
+
+/**
+ This API function disables the variable policy enforcement. If it's
+ already been called once, will return EFI_ALREADY_STARTED.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Has already been called once this boot.
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot.
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platform PCD.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *DISABLE_VARIABLE_POLICY)(
+ VOID
+ );
+
+/**
+ This API function returns whether or not the policy engine is
+ currently being enforced.
+
+ @param[out] State Pointer to a return value for whether the policy enforcement
+ is currently enabled.
+
+ @retval EFI_SUCCESS
+ @retval Others An error has prevented this command from completing.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *IS_VARIABLE_POLICY_ENABLED)(
+ OUT BOOLEAN *State
+ );
+
+/**
+ This API function validates and registers a new policy with
+ the policy enforcement engine.
+
+ @param[in] NewPolicy Pointer to the incoming policy structure.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally inconsistent.
+ @retval EFI_ALREADY_STARTED An identical matching policy already exists.
+ @retval EFI_WRITE_PROTECTED The interface has been locked until the next reboot.
+ @retval EFI_ABORTED A calculation error has prevented this function from completing.
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any more policies.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *REGISTER_VARIABLE_POLICY)(
+ IN CONST VARIABLE_POLICY_ENTRY *PolicyEntry
+ );
+
+/**
+ This API function will dump the entire contents of the variable policy table.
+
+ Similar to GetVariable, the first call can be made with a 0 size and it will return
+ the size of the buffer required to hold the entire table.
+
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Size is 0.
+ @param[in,out] Size On input, the size of the output buffer. On output, the size
+ of the data returned.
+
+ @retval EFI_SUCCESS Policy data is in the output buffer and Size has been updated.
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero and Policy is NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy. Size updated with required size.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *DUMP_VARIABLE_POLICY)(
+ IN OUT UINT8 *Policy,
+ IN OUT UINT32 *Size
+ );
+
+/**
+ This API function locks the interface so that no more policy updates
+ can be performed or changes made to the enforcement until the next boot.
+
+ @retval EFI_SUCCESS
+ @retval Others An error has prevented this command from completing.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *LOCK_VARIABLE_POLICY)(
+ VOID
+ );
+
+typedef struct {
+ UINT64 Revision;
+ DISABLE_VARIABLE_POLICY DisableVariablePolicy;
+ IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled;
+ REGISTER_VARIABLE_POLICY RegisterVariablePolicy;
+ DUMP_VARIABLE_POLICY DumpVariablePolicy;
+ LOCK_VARIABLE_POLICY LockVariablePolicy;
+} _EDKII_VARIABLE_POLICY_PROTOCOL;
+
+typedef _EDKII_VARIABLE_POLICY_PROTOCOL EDKII_VARIABLE_POLICY_PROTOCOL;
+
+extern EFI_GUID gEdkiiVariablePolicyProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
index aa8324ff66c..570000eca3a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.c
@@ -4,6 +4,7 @@
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2018, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2020, ARM Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -1102,3 +1103,18 @@ SerialPortSetAttributes (
return RETURN_SUCCESS;
}
+/** Base Serial Port 16550 Library Constructor
+
+ @retval RETURN_SUCCESS Success.
+**/
+EFI_STATUS
+EFIAPI
+BaseSerialPortLib16550 (
+ VOID
+ )
+{
+ // Nothing to do here. This constructor is added to
+ // enable the chain of constructor invocation for
+ // dependent libraries.
+ return RETURN_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
index b043cc99de9..ed12b57d8f5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
@@ -2,6 +2,8 @@
# SerialPortLib instance for 16550 UART.
#
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, ARM Limited. All rights reserved.
+#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -14,6 +16,7 @@
MODULE_TYPE = BASE
VERSION_STRING = 1.1
LIBRARY_CLASS = SerialPortLib
+ CONSTRUCTOR = BaseSerialPortLib16550
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootManagerUiLib/BootManager.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootManagerUiLib/BootManager.c
index 58cf5cd6ec2..09bc7ffb0e2 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootManagerUiLib/BootManager.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BootManagerUiLib/BootManager.c
@@ -535,9 +535,9 @@ UpdateBootManager (
mKeyInput++;
//
- // Don't display the hidden/inactive boot option
+ // Don't display hidden boot options, but retain inactive ones.
//
- if (((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) || ((BootOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0)) {
+ if ((BootOption[Index].Attributes & LOAD_OPTION_HIDDEN) != 0) {
continue;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliDecompress.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliDecompress.c
index fde29cb2911..9908a1bb7ec 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliDecompress.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/BrotliCustomDecompressLib/BrotliDecompress.c
@@ -8,29 +8,6 @@
#include <BrotliDecompressLibInternal.h>
/**
- Dummy malloc function for compiler.
-**/
-VOID *
-BrDummyMalloc (
- IN size_t Size
- )
-{
- ASSERT (FALSE);
- return NULL;
-}
-
-/**
- Dummy free function for compiler.
-**/
-VOID
-BrDummyFree (
- IN VOID * Ptr
- )
-{
- ASSERT (FALSE);
-}
-
-/**
Allocation routine used by BROTLI decompression.
@param Ptr Pointer to the BROTLI_BUFF instance.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
index bc749a5ac37..3ae5420a0f0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c
@@ -837,7 +837,7 @@ GetDeviceInfoFromHandleAndUpdateLength (
ControllerNameStringSize = FPDT_MAX_PERF_RECORD_SIZE - (*Length) - 1;
}
- UnicodeStrToAsciiStrS(StringPtr, ComponentNameString, ControllerNameStringSize);
+ UnicodeStrnToAsciiStrS(StringPtr, ControllerNameStringSize - 1, ComponentNameString, ControllerNameStringSize, &ControllerNameStringSize);
//
// Add a space in the end of the ControllerName
@@ -879,7 +879,7 @@ GetDeviceInfoFromHandleAndUpdateLength (
AsciiStringPtr = ComponentNameString;
}
- UnicodeStrToAsciiStrS(StringPtr, AsciiStringPtr, DevicePathStringSize);
+ UnicodeStrnToAsciiStrS(StringPtr, DevicePathStringSize - 1, AsciiStringPtr, DevicePathStringSize, &DevicePathStringSize);
*Length += (UINT8)DevicePathStringSize;
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxePrintLibPrint2Protocol/PrintLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxePrintLibPrint2Protocol/PrintLib.c
index e9f88ce24e7..dfbac7f5503 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxePrintLibPrint2Protocol/PrintLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/DxePrintLibPrint2Protocol/PrintLib.c
@@ -592,79 +592,6 @@ UnicodeSPrintAsciiFormat (
return NumberOfPrinted;
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Converts a decimal value to a Null-terminated Unicode string.
-
- Converts the decimal number specified by Value to a Null-terminated Unicode
- string specified by Buffer containing at most Width characters. No padding of spaces
- is ever performed. If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
- The number of Unicode characters in Buffer is returned not including the Null-terminator.
- If the conversion contains more than Width characters, then only the first
- Width characters are returned, and the total number of characters
- required to perform the conversion is returned.
- Additional conversion parameters are specified in Flags.
-
- The Flags bit LEFT_JUSTIFY is always ignored.
- All conversions are left justified in Buffer.
- If Width is 0, PREFIX_ZERO is ignored in Flags.
- If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
- are inserted every 3rd digit starting from the right.
- If RADIX_HEX is set in Flags, then the output buffer will be
- formatted in hexadecimal format.
- If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
- then Buffer is padded with '0' characters so the combination of the optional '-'
- sign character, '0' characters, digit characters for Value, and the Null-terminator
- add up to Width characters.
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Buffer is NULL, then ASSERT().
- If Buffer is not aligned on a 16-bit boundary, then ASSERT().
- If unsupported bits are set in Flags, then ASSERT().
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
-
- @param Buffer Pointer to the output buffer for the produced Null-terminated
- Unicode string.
- @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
- @param Value The 64-bit signed value to convert to a string.
- @param Width The maximum number of Unicode characters to place in Buffer, not including
- the Null-terminator.
-
- @return The number of Unicode characters in Buffer not including the Null-terminator.
-
-**/
-UINTN
-EFIAPI
-UnicodeValueToString (
- IN OUT CHAR16 *Buffer,
- IN UINTN Flags,
- IN INT64 Value,
- IN UINTN Width
- )
-{
- RETURN_STATUS Status;
- UINTN BufferSize;
-
- if (Width == 0) {
- BufferSize = (MAXIMUM_VALUE_CHARACTERS + 1) * sizeof (CHAR16);
- } else {
- BufferSize = (Width + 1) * sizeof (CHAR16);
- }
-
- Status = mPrint2SProtocol->UnicodeValueToStringS (Buffer, BufferSize, Flags, Value, Width);
- if (RETURN_ERROR (Status)) {
- return 0;
- }
-
- return StrnLenS (Buffer, BufferSize / sizeof (CHAR16));
-}
-
-#endif
-
/**
Converts a decimal value to a Null-terminated Unicode string.
@@ -1071,78 +998,6 @@ AsciiSPrintUnicodeFormat (
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Converts a decimal value to a Null-terminated ASCII string.
-
- Converts the decimal number specified by Value to a Null-terminated ASCII string
- specified by Buffer containing at most Width characters. No padding of spaces
- is ever performed.
- If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
- The number of ASCII characters in Buffer is returned not including the Null-terminator.
- If the conversion contains more than Width characters, then only the first Width
- characters are returned, and the total number of characters required to perform
- the conversion is returned.
- Additional conversion parameters are specified in Flags.
- The Flags bit LEFT_JUSTIFY is always ignored.
- All conversions are left justified in Buffer.
- If Width is 0, PREFIX_ZERO is ignored in Flags.
- If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
- are inserted every 3rd digit starting from the right.
- If RADIX_HEX is set in Flags, then the output buffer will be
- formatted in hexadecimal format.
- If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
- then Buffer is padded with '0' characters so the combination of the optional '-'
- sign character, '0' characters, digit characters for Value, and the Null-terminator
- add up to Width characters.
-
- If Buffer is NULL, then ASSERT().
- If unsupported bits are set in Flags, then ASSERT().
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
-
- @param Buffer Pointer to the output buffer for the produced Null-terminated
- ASCII string.
- @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
- @param Value The 64-bit signed value to convert to a string.
- @param Width The maximum number of ASCII characters to place in Buffer, not including
- the Null-terminator.
-
- @return The number of ASCII characters in Buffer not including the Null-terminator.
-
-**/
-UINTN
-EFIAPI
-AsciiValueToString (
- OUT CHAR8 *Buffer,
- IN UINTN Flags,
- IN INT64 Value,
- IN UINTN Width
- )
-{
- RETURN_STATUS Status;
- UINTN BufferSize;
-
- if (Width == 0) {
- BufferSize = (MAXIMUM_VALUE_CHARACTERS + 1) * sizeof (CHAR8);
- } else {
- BufferSize = (Width + 1) * sizeof (CHAR8);
- }
-
- Status = mPrint2SProtocol->AsciiValueToStringS (Buffer, BufferSize, Flags, Value, Width);
- if (RETURN_ERROR (Status)) {
- return 0;
- }
-
- return AsciiStrnLenS (Buffer, BufferSize / sizeof (CHAR8));
-}
-
-#endif
-
/**
Converts a decimal value to a Null-terminated Ascii string.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
index 017bb4cde88..85db3b0140f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorer.c
@@ -821,13 +821,9 @@ LibFindFileSystem (
if (Info == NULL) {
VolumeLabel = L"NO FILE SYSTEM INFO";
} else {
- if (Info->VolumeLabel == NULL) {
- VolumeLabel = L"NULL VOLUME LABEL";
- } else {
- VolumeLabel = Info->VolumeLabel;
- if (*VolumeLabel == 0x0000) {
- VolumeLabel = L"NO VOLUME LABEL";
- }
+ VolumeLabel = Info->VolumeLabel;
+ if (*VolumeLabel == 0x0000) {
+ VolumeLabel = L"NO VOLUME LABEL";
}
}
MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR);
@@ -1412,12 +1408,14 @@ LibUpdateFileExplorer (
if (NewFileContext->IsDir) {
RemoveEntryList (&NewMenuEntry->Link);
LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
- LibGetFileHandleFromMenu (NewMenuEntry, &FileHandle);
- Status = LibFindFiles (FileHandle, NewFileContext->FileName, NewFileContext->DeviceHandle);
+ Status = LibGetFileHandleFromMenu (NewMenuEntry, &FileHandle);
if (!EFI_ERROR (Status)) {
- LibUpdateFileExplorePage ();
- } else {
- LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
+ Status = LibFindFiles (FileHandle, NewFileContext->FileName, NewFileContext->DeviceHandle);
+ if (!EFI_ERROR (Status)) {
+ LibUpdateFileExplorePage ();
+ } else {
+ LibFreeMenu (gFileExplorerPrivate.FsOptionMenu);
+ }
}
LibDestroyMenuEntry (NewMenuEntry);
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni
index 52e5eec5f32..070cdf38ea1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/FileExplorerLib/FileExplorerString.uni
@@ -9,7 +9,7 @@
//
// Abstract:
//
-// String definitions for file exporer library.
+// String definitions for file explorer library.
//
// Revision History:
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt
index 61052234019..c03b2128971 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt
@@ -1,4 +1,4 @@
-LzmaCustomDecompressLib is based on the LZMA SDK 18.05.
-LZMA SDK 18.05 was placed in the public domain on
-2018-04-30. It was released on the
+LzmaCustomDecompressLib is based on the LZMA SDK 19.00.
+LZMA SDK 19.00 was placed in the public domain on
+2019-02-21. It was released on the
http://www.7-zip.org/sdk.html website.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
index 0a38438c6d0..0b0838552b0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
@@ -1,11 +1,11 @@
## @file
# LzmaArchCustomDecompressLib produces LZMA custom decompression algorithm with the converter for the different arch code.
#
-# It is based on the LZMA SDK 18.05
-# LZMA SDK 18.05 was placed in the public domain on 2018-04-30.
+# It is based on the LZMA SDK 19.00
+# LZMA SDK 19.00 was placed in the public domain on 2019-02-21.
# It was released on the http://www.7-zip.org/sdk.html website.
#
-# Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
index 65cd5f6103a..13f3543789d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
@@ -1,11 +1,11 @@
## @file
# LzmaCustomDecompressLib produces LZMA custom decompression algorithm.
#
-# It is based on the LZMA SDK 18.05.
-# LZMA SDK 18.05 was placed in the public domain on 2018-04-30.
+# It is based on the LZMA SDK 19.00.
+# LZMA SDK 19.00 was placed in the public domain on 2019-02-21.
# It was released on the http://www.7-zip.org/sdk.html website.
#
-# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c
index 43c7c458dd0..8c4b26e25f9 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c
@@ -127,6 +127,10 @@ GetDecodedSizeOfBuf(
in DestinationSize and the size of the scratch
buffer was returned in ScratchSize.
+ @retval RETURN_UNSUPPORTED DestinationSize cannot be output because the
+ uncompressed buffer size (in bytes) does not fit
+ in a UINT32. Output parameters have not been
+ modified.
**/
RETURN_STATUS
EFIAPI
@@ -142,6 +146,9 @@ LzmaUefiDecompressGetInfo (
ASSERT(SourceSize >= LZMA_HEADER_SIZE);
DecodedSize = GetDecodedSizeOfBuf((UINT8*)Source);
+ if (DecodedSize > MAX_UINT32) {
+ return RETURN_UNSUPPORTED;
+ }
*DestinationSize = (UINT32)DecodedSize;
*ScratchSize = SCRATCH_BUFFER_REQUEST_SIZE;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h
index 87183667ff9..e333431adda 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompressLibInternal.h
@@ -9,6 +9,7 @@
#ifndef __LZMADECOMPRESSLIB_INTERNAL_H__
#define __LZMADECOMPRESSLIB_INTERNAL_H__
+#include <Base.h>
#include <PiPei.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
@@ -45,6 +46,10 @@
in DestinationSize and the size of the scratch
buffer was returned in ScratchSize.
+ @retval RETURN_UNSUPPORTED DestinationSize cannot be output because the
+ uncompressed buffer size (in bytes) does not fit
+ in a UINT32. Output parameters have not been
+ modified.
**/
RETURN_STATUS
EFIAPI
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zTypes.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zTypes.h
index 7b156539960..ddd1402b06d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zTypes.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zTypes.h
@@ -1,5 +1,5 @@
/* 7zTypes.h -- Basic types
-2017-07-17 : Igor Pavlov : Public domain */
+2018-08-04 : Igor Pavlov : Public domain */
#ifndef __7Z_TYPES_H
#define __7Z_TYPES_H
@@ -107,7 +107,8 @@ typedef UInt32 SizeT;
typedef size_t SizeT;
#endif
-typedef int Bool;
+typedef int BoolInt;
+/* typedef BoolInt Bool; */
#define True 1
#define False 0
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h
index f3fb623aa6c..c176823a4dd 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/7zVersion.h
@@ -1,7 +1,7 @@
-#define MY_VER_MAJOR 18
-#define MY_VER_MINOR 05
+#define MY_VER_MAJOR 19
+#define MY_VER_MINOR 00
#define MY_VER_BUILD 0
-#define MY_VERSION_NUMBERS "18.05"
+#define MY_VERSION_NUMBERS "19.00"
#define MY_VERSION MY_VERSION_NUMBERS
#ifdef MY_CPU_NAME
@@ -10,7 +10,7 @@
#define MY_VERSION_CPU MY_VERSION
#endif
-#define MY_DATE "2018-04-30"
+#define MY_DATE "2019-02-21"
#undef MY_COPYRIGHT
#undef MY_VERSION_COPYRIGHT_DATE
#define MY_AUTHOR_NAME "Igor Pavlov"
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h
index 056116dde34..bd429388024 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/CpuArch.h
@@ -1,5 +1,5 @@
/* CpuArch.h -- CPU specific code
-2017-09-04 : Igor Pavlov : Public domain */
+2018-02-18 : Igor Pavlov : Public domain */
#ifndef __CPU_ARCH_H
#define __CPU_ARCH_H
@@ -318,15 +318,16 @@ enum
void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d);
-Bool x86cpuid_CheckAndRead(Cx86cpuid *p);
+BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p);
int x86cpuid_GetFirm(const Cx86cpuid *p);
#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF))
#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF))
#define x86cpuid_GetStepping(ver) (ver & 0xF)
-Bool CPU_Is_InOrder();
-Bool CPU_Is_Aes_Supported();
+BoolInt CPU_Is_InOrder();
+BoolInt CPU_Is_Aes_Supported();
+BoolInt CPU_IsSupported_PageGB();
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c
index 2c5cf1e713c..46579e3b87d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzFind.c
@@ -1,5 +1,5 @@
/* LzFind.c -- Match finder for LZ algorithms
-2017-06-10 : Igor Pavlov : Public domain */
+2018-07-08 : Igor Pavlov : Public domain */
#include "Precomp.h"
@@ -140,7 +140,7 @@ static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
void MatchFinder_Construct(CMatchFinder *p)
{
- UInt32 i;
+ unsigned i;
p->bufferBase = NULL;
p->directInput = 0;
p->hash = NULL;
@@ -149,7 +149,7 @@ void MatchFinder_Construct(CMatchFinder *p)
for (i = 0; i < 256; i++)
{
- UInt32 r = i;
+ UInt32 r = (UInt32)i;
unsigned j;
for (j = 0; j < 8; j++)
r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1)));
@@ -370,6 +370,8 @@ static void MatchFinder_Normalize(CMatchFinder *p)
MatchFinder_ReduceOffsets(p, subValue);
}
+
+MY_NO_INLINE
static void MatchFinder_CheckLimits(CMatchFinder *p)
{
if (p->pos == kMaxValForNormalize)
@@ -381,10 +383,16 @@ static void MatchFinder_CheckLimits(CMatchFinder *p)
MatchFinder_SetLimits(p);
}
-static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
+
+/*
+ (lenLimit > maxLen)
+*/
+MY_FORCE_INLINE
+static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
- UInt32 *distances, UInt32 maxLen)
+ UInt32 *distances, unsigned maxLen)
{
+ /*
son[_cyclicBufferPos] = curMatch;
for (;;)
{
@@ -402,7 +410,8 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
break;
if (maxLen < len)
{
- *distances++ = maxLen = len;
+ maxLen = len;
+ *distances++ = len;
*distances++ = delta - 1;
if (len == lenLimit)
return distances;
@@ -410,15 +419,58 @@ static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos,
}
}
}
+ */
+
+ const Byte *lim = cur + lenLimit;
+ son[_cyclicBufferPos] = curMatch;
+ do
+ {
+ UInt32 delta = pos - curMatch;
+ if (delta >= _cyclicBufferSize)
+ break;
+ {
+ ptrdiff_t diff;
+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
+ diff = (ptrdiff_t)0 - delta;
+ if (cur[maxLen] == cur[maxLen + diff])
+ {
+ const Byte *c = cur;
+ while (*c == c[diff])
+ {
+ if (++c == lim)
+ {
+ distances[0] = (UInt32)(lim - cur);
+ distances[1] = delta - 1;
+ return distances + 2;
+ }
+ }
+ {
+ unsigned len = (unsigned)(c - cur);
+ if (maxLen < len)
+ {
+ maxLen = len;
+ distances[0] = (UInt32)len;
+ distances[1] = delta - 1;
+ distances += 2;
+ }
+ }
+ }
+ }
+ }
+ while (--cutValue);
+
+ return distances;
}
+
+MY_FORCE_INLINE
UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
UInt32 *distances, UInt32 maxLen)
{
- CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
- UInt32 len0 = 0, len1 = 0;
+ CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+ unsigned len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
@@ -428,9 +480,10 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
return distances;
}
{
- CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
- UInt32 len = (len0 < len1 ? len0 : len1);
+ unsigned len = (len0 < len1 ? len0 : len1);
+ UInt32 pair0 = pair[0];
if (pb[len] == cur[len])
{
if (++len != lenLimit && pb[len] == cur[len])
@@ -439,11 +492,12 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
break;
if (maxLen < len)
{
- *distances++ = maxLen = len;
+ maxLen = (UInt32)len;
+ *distances++ = (UInt32)len;
*distances++ = delta - 1;
if (len == lenLimit)
{
- *ptr1 = pair[0];
+ *ptr1 = pair0;
*ptr0 = pair[1];
return distances;
}
@@ -470,9 +524,9 @@ UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byt
static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
{
- CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
- CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
- UInt32 len0 = 0, len1 = 0;
+ CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1;
+ CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1);
+ unsigned len0 = 0, len1 = 0;
for (;;)
{
UInt32 delta = pos - curMatch;
@@ -482,9 +536,9 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
return;
}
{
- CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
+ CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
const Byte *pb = cur - delta;
- UInt32 len = (len0 < len1 ? len0 : len1);
+ unsigned len = (len0 < len1 ? len0 : len1);
if (pb[len] == cur[len])
{
while (++len != lenLimit)
@@ -522,13 +576,13 @@ static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const
p->buffer++; \
if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
-#define MOVE_POS_RET MOVE_POS return offset;
+#define MOVE_POS_RET MOVE_POS return (UInt32)offset;
static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define GET_MATCHES_HEADER2(minLen, ret_op) \
- UInt32 lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
- lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
+ unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \
+ lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
cur = p->buffer;
#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
@@ -537,22 +591,22 @@ static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
#define GET_MATCHES_FOOTER(offset, maxLen) \
- offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
- distances + offset, maxLen) - distances); MOVE_POS_RET;
+ offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \
+ distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET;
#define SKIP_FOOTER \
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
+ SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
#define UPDATE_maxLen { \
ptrdiff_t diff = (ptrdiff_t)0 - d2; \
const Byte *c = cur + maxLen; \
const Byte *lim = cur + lenLimit; \
for (; c != lim; c++) if (*(c + diff) != *c) break; \
- maxLen = (UInt32)(c - cur); }
+ maxLen = (unsigned)(c - cur); }
static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 offset;
+ unsigned offset;
GET_MATCHES_HEADER(2)
HASH2_CALC;
curMatch = p->hash[hv];
@@ -563,7 +617,7 @@ static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 offset;
+ unsigned offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hv];
@@ -574,7 +628,8 @@ UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 h2, d2, maxLen, offset, pos;
+ UInt32 h2, d2, pos;
+ unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(3)
@@ -596,12 +651,12 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
UPDATE_maxLen
- distances[0] = maxLen;
+ distances[0] = (UInt32)maxLen;
distances[1] = d2 - 1;
offset = 2;
if (maxLen == lenLimit)
{
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
@@ -611,7 +666,8 @@ static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 h2, h3, d2, d3, maxLen, offset, pos;
+ UInt32 h2, h3, d2, d3, pos;
+ unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(4)
@@ -634,7 +690,8 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
- distances[0] = maxLen = 2;
+ maxLen = 2;
+ distances[0] = 2;
distances[1] = d2 - 1;
offset = 2;
}
@@ -650,10 +707,10 @@ static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[(size_t)offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit)
{
- SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
+ SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p));
MOVE_POS_RET;
}
}
@@ -743,7 +800,8 @@ static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 h2, h3, d2, d3, maxLen, offset, pos;
+ UInt32 h2, h3, d2, d3, pos;
+ unsigned maxLen, offset;
UInt32 *hash;
GET_MATCHES_HEADER(4)
@@ -766,7 +824,8 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur)
{
- distances[0] = maxLen = 2;
+ maxLen = 2;
+ distances[0] = 2;
distances[1] = d2 - 1;
offset = 2;
}
@@ -782,7 +841,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (offset != 0)
{
UPDATE_maxLen
- distances[(size_t)offset - 2] = maxLen;
+ distances[(size_t)offset - 2] = (UInt32)maxLen;
if (maxLen == lenLimit)
{
p->son[p->cyclicBufferPos] = curMatch;
@@ -793,7 +852,7 @@ static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
if (maxLen < 3)
maxLen = 3;
- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances + offset, maxLen) - (distances));
MOVE_POS_RET
}
@@ -879,12 +938,12 @@ static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
{
- UInt32 offset;
+ unsigned offset;
GET_MATCHES_HEADER(3)
HASH_ZIP_CALC;
curMatch = p->hash[hv];
p->hash[hv] = p->pos;
- offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
+ offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
distances, 2) - (distances));
MOVE_POS_RET
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c
index 690c1f6964f..ddde99ed8fe 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/C/LzmaDec.c
@@ -1,15 +1,15 @@
/* LzmaDec.c -- LZMA Decoder
-2018-02-28 : Igor Pavlov : Public domain */
+2018-07-04 : Igor Pavlov : Public domain */
#include "Precomp.h"
-/* #include "CpuArch.h" */
-#include "LzmaDec.h"
-
#ifndef EFIAPI
#include <string.h>
#endif
+/* #include "CpuArch.h" */
+#include "LzmaDec.h"
+
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
@@ -21,7 +21,7 @@
#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
-#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
@@ -68,7 +68,7 @@
#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
-#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound)
#define UPDATE_0_CHECK range = bound;
#define UPDATE_1_CHECK range -= bound; code -= bound;
#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
@@ -541,7 +541,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
curLen = ((rem < len) ? (unsigned)rem : len);
pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0);
- processedPos += curLen;
+ processedPos += (UInt32)curLen;
len -= curLen;
if (curLen <= dicBufSize - pos)
@@ -549,7 +549,7 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
Byte *dest = dic + dicPos;
ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
const Byte *lim = dest + curLen;
- dicPos += curLen;
+ dicPos += (SizeT)curLen;
do
*(dest) = (Byte)*(dest + src);
while (++dest != lim);
@@ -574,14 +574,14 @@ int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit
p->buf = buf;
p->range = range;
p->code = code;
- p->remainLen = len;
+ p->remainLen = (UInt32)len;
p->dicPos = dicPos;
p->processedPos = processedPos;
p->reps[0] = rep0;
p->reps[1] = rep1;
p->reps[2] = rep2;
p->reps[3] = rep3;
- p->state = state;
+ p->state = (UInt32)state;
return SZ_OK;
}
@@ -603,8 +603,8 @@ static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
p->checkDicSize = p->prop.dicSize;
- p->processedPos += len;
- p->remainLen -= len;
+ p->processedPos += (UInt32)len;
+ p->remainLen -= (UInt32)len;
while (len != 0)
{
len--;
@@ -852,7 +852,7 @@ static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inS
}
-void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState)
{
p->remainLen = kMatchSpecLenStart + 1;
p->tempBufSize = 0;
@@ -981,10 +981,10 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
p->tempBufSize = rem;
if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
{
- int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem);
if (dummyRes == DUMMY_ERROR)
{
- (*srcLen) += lookAhead;
+ (*srcLen) += (SizeT)lookAhead;
*status = LZMA_STATUS_NEEDS_MORE_INPUT;
return SZ_OK;
}
@@ -1007,9 +1007,9 @@ SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *sr
return SZ_ERROR_FAIL; /* some internal error */
lookAhead -= rem;
}
- (*srcLen) += lookAhead;
+ (*srcLen) += (SizeT)lookAhead;
src += lookAhead;
- inSize -= lookAhead;
+ inSize -= (SizeT)lookAhead;
p->tempBufSize = 0;
}
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-history.txt b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-history.txt
index 8d9b7f82573..5990cf76ad0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-history.txt
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-history.txt
@@ -1,6 +1,28 @@
HISTORY of the LZMA SDK
-----------------------
+19.00 2019-02-21
+-------------------------
+- Encryption strength for 7z archives was increased:
+ the size of random initialization vector was increased from 64-bit to 128-bit,
+ and the pseudo-random number generator was improved.
+- The bug in 7zIn.c code was fixed.
+
+
+18.06 2018-12-30
+-------------------------
+- The speed for LZMA/LZMA2 compressing was increased by 3-10%,
+ and there are minor changes in compression ratio.
+- Some bugs were fixed.
+- The bug in 7-Zip 18.02-18.05 was fixed:
+ There was memory leak in multithreading xz decoder - XzDecMt_Decode(),
+ if xz stream contains only one block.
+- The changes for MSVS compiler makefiles:
+ - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64)
+ instead of "CPU" macroname with values (AMD64, ARM64).
+ - the makefiles by default now use static version of the run-time library.
+
+
18.05 2018-04-30
-------------------------
- The speed for LZMA/LZMA2 compressing was increased
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-sdk.txt b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-sdk.txt
index 203653faaa3..28e05a7d717 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-sdk.txt
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/LzmaCustomDecompressLib/Sdk/DOC/lzma-sdk.txt
@@ -1,4 +1,4 @@
-LZMA SDK 18.05
+LZMA SDK 19.00
--------------
LZMA SDK provides the documentation, samples, header files,
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
index 16d0570bec2..60cc6fdf977 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptExecute.c
@@ -369,7 +369,7 @@ ScriptIoWrite (
return EFI_SUCCESS;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_IO_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_IO_WRITE OP code.
@param Script Pointer to the node which is to be interpreted.
@@ -598,7 +598,7 @@ ScriptMemoryWrite (
return EFI_SUCCESS;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
@param[in] Script Pointer to the node which is to be interpreted.
@@ -859,7 +859,7 @@ ScriptPciCfgWrite (
return ScriptPciCfg2Write (Width, 0, Address, Count, Buffer);
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
@param Script The pointer of typed node in boot script table
@@ -887,7 +887,7 @@ BootScriptExecutePciCfgWrite (
return ScriptPciCfgWrite (Width, Address, Count, Buffer);
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
@param Script The pointer of typed node in boot script table
@param AndMask Mask value for 'and' operation
@@ -931,7 +931,7 @@ BootScriptExecuteIoReadWrite (
return Status;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
@param Script The pointer of typed node in boot script table
@param AndMask Mask value for 'and' operation
@@ -975,7 +975,7 @@ BootScriptExecuteMemoryReadWrite (
return Status;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
@param Script The pointer of typed node in boot script table
@param AndMask Mask value for 'and' operation
@@ -1023,7 +1023,7 @@ BootScriptExecutePciCfgReadWrite (
return Status;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
@param Script The pointer of typed node in boot script table
@@ -1054,7 +1054,7 @@ BootScriptExecuteSmbusExecute (
);
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
@param Script The pointer of typed node in boot script table
@@ -1075,7 +1075,7 @@ BootScriptExecuteStall (
return EFI_SUCCESS;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
@param Script The pointer of typed node in boot script table
@retval EFI_SUCCESS The operation was executed successfully
@@ -1099,7 +1099,7 @@ BootScriptExecuteDispatch (
return Status;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
@param Script The pointer of typed node in boot script table
@retval EFI_SUCCESS The operation was executed successfully
@@ -1124,7 +1124,7 @@ BootScriptExecuteDispatch2 (
return Status;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
@param Script The pointer of typed node in boot script table
@param AndMask Mask value for 'and' operation
@@ -1325,7 +1325,7 @@ CheckAndOrMask (
return;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
@param Script The pointer of typed node in boot script table
@param AndMask Mask value for 'and' operation
@@ -1382,7 +1382,7 @@ BootScriptExecuteIoPoll (
}
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
@param Script The pointer of S3 boot script
@@ -1415,7 +1415,7 @@ BootScriptExecutePciCfg2Write (
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
@param Script The pointer of S3 boot script
@param AndMask Mask value for 'and' operation
@@ -1463,7 +1463,7 @@ BootScriptExecutePciCfg2ReadWrite (
return Status;
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
@param Script The pointer of S3 boot script
@param AndMask Mask value for 'and' operation
@@ -1522,7 +1522,7 @@ BootScriptPciCfgPoll (
}
/**
- Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
+ Interpret the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
@param Script The pointer of S3 Boot Script
@param AndMask Mask value for 'and' operation
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
index f932414fa30..08f973f7112 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/PiDxeS3BootScriptLib/BootScriptSave.c
@@ -1,7 +1,7 @@
/** @file
Save the S3 data to S3 boot script.
- Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -124,7 +124,7 @@ VOID *mRegistrationSmmReadyToLock = NULL;
BOOLEAN mS3BootScriptTableAllocated = FALSE;
BOOLEAN mS3BootScriptTableSmmAllocated = FALSE;
EFI_SMM_SYSTEM_TABLE2 *mBootScriptSmst = NULL;
-BOOLEAN mAcpiS3Enable = TRUE;
+BOOLEAN mS3BootScriptAcpiS3Enable = TRUE;
/**
This is an internal function to add a terminate node the entry, recalculate the table
@@ -438,7 +438,7 @@ S3BootScriptLibInitialize (
EFI_PHYSICAL_ADDRESS Buffer;
if (!PcdGetBool (PcdAcpiS3Enable)) {
- mAcpiS3Enable = FALSE;
+ mS3BootScriptAcpiS3Enable = FALSE;
DEBUG ((DEBUG_INFO, "%a: Skip S3BootScript because ACPI S3 disabled.\n", gEfiCallerBaseName));
return RETURN_SUCCESS;
}
@@ -569,7 +569,7 @@ S3BootScriptLibDeinitialize (
{
EFI_STATUS Status;
- if (!mAcpiS3Enable) {
+ if (!mS3BootScriptAcpiS3Enable) {
return RETURN_SUCCESS;
}
@@ -821,7 +821,7 @@ S3BootScriptGetEntryAddAddress (
{
UINT8* NewEntryPtr;
- if (!mAcpiS3Enable) {
+ if (!mS3BootScriptAcpiS3Enable) {
return NULL;
}
@@ -2410,4 +2410,3 @@ S3BootScriptCompare (
return EFI_SUCCESS;
}
-
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h
index 80024b41a9e..2485ebfb49f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxLibPrivate.h
@@ -43,5 +43,30 @@ typedef struct {
#pragma pack()
+/**
+ Constructor for SmmLockBox library.
+ This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+SmmLockBoxMmConstructor (
+ VOID
+ );
+
+/**
+ Destructor for SmmLockBox library.
+ This is used to uninstall SmmLockBoxCommunication configuration table
+ if it has been installed in Constructor.
+
+ @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+SmmLockBoxMmDestructor (
+ VOID
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxMmLib.c
index 73f65b47dab..911e1e04b85 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxMmLib.c
@@ -6,16 +6,16 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiSmm.h>
-#include <Library/SmmServicesTableLib.h>
+#include <PiMm.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/LockBoxLib.h>
#include <Library/DebugLib.h>
#include <Guid/SmmLockBox.h>
#include <Guid/EndOfS3Resume.h>
-#include <Protocol/SmmReadyToLock.h>
-#include <Protocol/SmmEndOfDxe.h>
+#include <Protocol/MmReadyToLock.h>
+#include <Protocol/MmEndOfDxe.h>
#include <Protocol/SmmSxDispatch2.h>
#include "SmmLockBoxLibPrivate.h"
@@ -49,13 +49,13 @@ InternalGetSmmLockBoxContext (
//
// Check if gEfiSmmLockBoxCommunicationGuid is installed by someone
//
- for (Index = 0; Index < gSmst->NumberOfTableEntries; Index++) {
- if (CompareGuid (&gSmst->SmmConfigurationTable[Index].VendorGuid, &gEfiSmmLockBoxCommunicationGuid)) {
+ for (Index = 0; Index < gMmst->NumberOfTableEntries; Index++) {
+ if (CompareGuid (&gMmst->MmConfigurationTable[Index].VendorGuid, &gEfiSmmLockBoxCommunicationGuid)) {
//
// Found. That means some other library instance is already run.
// No need to install again, just return.
//
- return (SMM_LOCK_BOX_CONTEXT *)gSmst->SmmConfigurationTable[Index].VendorTable;
+ return (SMM_LOCK_BOX_CONTEXT *)gMmst->MmConfigurationTable[Index].VendorTable;
}
}
@@ -142,8 +142,8 @@ SmmLockBoxSmmEndOfDxeNotify (
//
// Locate SmmSxDispatch2 protocol.
//
- Status = gSmst->SmmLocateProtocol (
- &gEfiSmmSxDispatch2ProtocolGuid,
+ Status = gMmst->MmLocateProtocol (
+ &gEfiMmSxDispatchProtocolGuid,
NULL,
(VOID **)&SxDispatch
);
@@ -191,29 +191,24 @@ SmmLockBoxEndOfS3ResumeNotify (
Constructor for SmmLockBox library.
This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
- @param[in] ImageHandle Image handle of this driver.
- @param[in] SystemTable A Pointer to the EFI System Table.
-
@retval EFI_SUCEESS
@return Others Some error occurs.
**/
EFI_STATUS
-EFIAPI
-SmmLockBoxSmmConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+SmmLockBoxMmConstructor (
+ VOID
)
{
EFI_STATUS Status;
SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;
- DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Enter\n"));
+ DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Enter\n"));
//
// Register SmmReadyToLock notification.
//
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmReadyToLockProtocolGuid,
+ Status = gMmst->MmRegisterProtocolNotify (
+ &gEfiMmReadyToLockProtocolGuid,
SmmLockBoxSmmReadyToLockNotify,
&mSmmLockBoxRegistrationSmmReadyToLock
);
@@ -222,8 +217,8 @@ SmmLockBoxSmmConstructor (
//
// Register SmmEndOfDxe notification.
//
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmEndOfDxeProtocolGuid,
+ Status = gMmst->MmRegisterProtocolNotify (
+ &gEfiMmEndOfDxeProtocolGuid,
SmmLockBoxSmmEndOfDxeNotify,
&mSmmLockBoxRegistrationSmmEndOfDxe
);
@@ -232,7 +227,7 @@ SmmLockBoxSmmConstructor (
//
// Register EndOfS3Resume notification.
//
- Status = gSmst->SmmRegisterProtocolNotify (
+ Status = gMmst->MmRegisterProtocolNotify (
&gEdkiiEndOfS3ResumeGuid,
SmmLockBoxEndOfS3ResumeNotify,
&mSmmLockBoxRegistrationEndOfS3Resume
@@ -249,7 +244,7 @@ SmmLockBoxSmmConstructor (
// No need to install again, just return.
//
DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - already installed\n"));
- DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Exit\n"));
+ DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Exit\n"));
return EFI_SUCCESS;
}
@@ -263,8 +258,8 @@ SmmLockBoxSmmConstructor (
}
mSmmLockBoxContext.LockBoxDataAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)&mLockBoxQueue;
- Status = gSmst->SmmInstallConfigurationTable (
- gSmst,
+ Status = gMmst->MmInstallConfigurationTable (
+ gMmst,
&gEfiSmmLockBoxCommunicationGuid,
&mSmmLockBoxContext,
sizeof(mSmmLockBoxContext)
@@ -274,7 +269,7 @@ SmmLockBoxSmmConstructor (
DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxContext - %x\n", (UINTN)&mSmmLockBoxContext));
DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib LockBoxDataAddress - %x\n", (UINTN)&mLockBoxQueue));
- DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmConstructor - Exit\n"));
+ DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmConstructor - Exit\n"));
return Status;
}
@@ -284,26 +279,21 @@ SmmLockBoxSmmConstructor (
This is used to uninstall SmmLockBoxCommunication configuration table
if it has been installed in Constructor.
- @param[in] ImageHandle Image handle of this driver.
- @param[in] SystemTable A Pointer to the EFI System Table.
-
@retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.
**/
EFI_STATUS
-EFIAPI
-SmmLockBoxSmmDestructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+SmmLockBoxMmDestructor (
+ VOID
)
{
EFI_STATUS Status;
- DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxSmmDestructor in %a module\n", gEfiCallerBaseName));
+ DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SmmLockBoxMmDestructor in %a module\n", gEfiCallerBaseName));
if (mSmmConfigurationTableInstalled) {
- Status = gSmst->SmmInstallConfigurationTable (
- gSmst,
+ Status = gMmst->MmInstallConfigurationTable (
+ gMmst,
&gEfiSmmLockBoxCommunicationGuid,
NULL,
0
@@ -316,8 +306,8 @@ SmmLockBoxSmmDestructor (
//
// Unregister SmmReadyToLock notification.
//
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmReadyToLockProtocolGuid,
+ Status = gMmst->MmRegisterProtocolNotify (
+ &gEfiMmReadyToLockProtocolGuid,
NULL,
&mSmmLockBoxRegistrationSmmReadyToLock
);
@@ -327,8 +317,8 @@ SmmLockBoxSmmDestructor (
//
// Unregister SmmEndOfDxe notification.
//
- Status = gSmst->SmmRegisterProtocolNotify (
- &gEfiSmmEndOfDxeProtocolGuid,
+ Status = gMmst->MmRegisterProtocolNotify (
+ &gEfiMmEndOfDxeProtocolGuid,
NULL,
&mSmmLockBoxRegistrationSmmEndOfDxe
);
@@ -338,7 +328,7 @@ SmmLockBoxSmmDestructor (
//
// Unregister EndOfS3Resume notification.
//
- Status = gSmst->SmmRegisterProtocolNotify (
+ Status = gMmst->MmRegisterProtocolNotify (
&gEdkiiEndOfS3ResumeGuid,
NULL,
&mSmmLockBoxRegistrationEndOfS3Resume
@@ -453,7 +443,7 @@ SaveLockBox (
//
// Allocate SMRAM buffer
//
- Status = gSmst->SmmAllocatePages (
+ Status = gMmst->MmAllocatePages (
AllocateAnyPages,
EfiRuntimeServicesData,
EFI_SIZE_TO_PAGES (Length),
@@ -468,14 +458,14 @@ SaveLockBox (
//
// Allocate LockBox
//
- Status = gSmst->SmmAllocatePool (
+ Status = gMmst->MmAllocatePool (
EfiRuntimeServicesData,
sizeof(*LockBox),
(VOID **)&LockBox
);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
- gSmst->SmmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length));
+ gMmst->MmFreePages (SmramBuffer, EFI_SIZE_TO_PAGES (Length));
DEBUG ((DEBUG_INFO, "SmmLockBoxSmmLib SaveLockBox - Exit (%r)\n", EFI_OUT_OF_RESOURCES));
return EFI_OUT_OF_RESOURCES;
}
@@ -662,7 +652,7 @@ UpdateLockBox (
DEBUG_INFO,
"SmmLockBoxSmmLib UpdateLockBox - Allocate new buffer to enlarge.\n"
));
- Status = gSmst->SmmAllocatePages (
+ Status = gMmst->MmAllocatePages (
AllocateAnyPages,
EfiRuntimeServicesData,
EFI_SIZE_TO_PAGES (Offset + Length),
@@ -679,7 +669,7 @@ UpdateLockBox (
//
CopyMem ((VOID *)(UINTN)SmramBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
ZeroMem ((VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
- gSmst->SmmFreePages (LockBox->SmramBuffer, EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length));
+ gMmst->MmFreePages (LockBox->SmramBuffer, EFI_SIZE_TO_PAGES ((UINTN)LockBox->Length));
LockBox->SmramBuffer = SmramBuffer;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
index ef117dd73ac..e32f0ba5600 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
@@ -15,8 +15,8 @@
MODULE_TYPE = DXE_SMM_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = LockBoxLib|DXE_SMM_DRIVER
- CONSTRUCTOR = SmmLockBoxSmmConstructor
- DESTRUCTOR = SmmLockBoxSmmDestructor
+ CONSTRUCTOR = SmmLockBoxTraditionalConstructor
+ DESTRUCTOR = SmmLockBoxTraditionalDestructor
#
# The following information is for reference only and not required by the build tools.
@@ -25,7 +25,8 @@
#
[Sources]
- SmmLockBoxSmmLib.c
+ SmmLockBoxTraditionalMmLib.c
+ SmmLockBoxMmLib.c
SmmLockBoxLibPrivate.h
[Packages]
@@ -33,14 +34,14 @@
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
- SmmServicesTableLib
+ MmServicesTableLib
BaseLib
DebugLib
[Protocols]
- gEfiSmmReadyToLockProtocolGuid ## NOTIFY
- gEfiSmmEndOfDxeProtocolGuid ## NOTIFY
- gEfiSmmSxDispatch2ProtocolGuid ## NOTIFY
+ gEfiMmReadyToLockProtocolGuid ## NOTIFY
+ gEfiMmEndOfDxeProtocolGuid ## NOTIFY
+ gEfiMmSxDispatchProtocolGuid ## NOTIFY
[Guids]
## SOMETIMES_CONSUMES ## UNDEFINED # SmmSystemTable
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.c
new file mode 100644
index 00000000000..6eb8bc8a487
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.c
@@ -0,0 +1,53 @@
+/** @file
+
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include "SmmLockBoxLibPrivate.h"
+
+/**
+ Constructor for SmmLockBox library.
+ This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxStandaloneMmConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return SmmLockBoxMmConstructor ();
+}
+
+/**
+ Destructor for SmmLockBox library.
+ This is used to uninstall SmmLockBoxCommunication configuration table
+ if it has been installed in Constructor.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxStandaloneMmDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return SmmLockBoxMmDestructor ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf
new file mode 100644
index 00000000000..f9a84eb2400
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf
@@ -0,0 +1,53 @@
+## @file
+# SMM LockBox library instance.
+#
+# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmLockBoxStandaloneMmLib
+ FILE_GUID = 3C05978B-30CA-4544-9C5A-AB99265EFC31
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = LockBoxLib|MM_STANDALONE
+ CONSTRUCTOR = SmmLockBoxStandaloneMmConstructor
+ DESTRUCTOR = SmmLockBoxStandaloneMmDestructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ SmmLockBoxStandaloneMmLib.c
+ SmmLockBoxMmLib.c
+ SmmLockBoxLibPrivate.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MmServicesTableLib
+ BaseLib
+ DebugLib
+
+[Protocols]
+ gEfiMmReadyToLockProtocolGuid ## NOTIFY
+ gEfiMmEndOfDxeProtocolGuid ## NOTIFY
+ gEfiMmSxDispatchProtocolGuid ## NOTIFY
+
+[Guids]
+ ## SOMETIMES_CONSUMES ## UNDEFINED # SmmSystemTable
+ ## SOMETIMES_PRODUCES ## UNDEFINED # SmmSystemTable
+ gEfiSmmLockBoxCommunicationGuid
+ ## CONSUMES ## UNDEFINED # Protocol notify
+ gEdkiiEndOfS3ResumeGuid
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxTraditionalMmLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxTraditionalMmLib.c
new file mode 100644
index 00000000000..21c710a78af
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxTraditionalMmLib.c
@@ -0,0 +1,53 @@
+/** @file
+
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiSmm.h>
+
+#include "SmmLockBoxLibPrivate.h"
+
+/**
+ Constructor for SmmLockBox library.
+ This is used to set SmmLockBox context, which will be used in PEI phase in S3 boot path later.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS
+ @return Others Some error occurs.
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxTraditionalConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return SmmLockBoxMmConstructor ();
+}
+
+/**
+ Destructor for SmmLockBox library.
+ This is used to uninstall SmmLockBoxCommunication configuration table
+ if it has been installed in Constructor.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCEESS The destructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmLockBoxTraditionalDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return SmmLockBoxMmDestructor ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.c
index 5504ad7f520..44091baf949 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.c
@@ -1,5 +1,5 @@
/** @file
- Report Status Code Library for SMM Phase.
+ Report Status Code Library for MM Phase.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -8,7 +8,7 @@
#include <Library/ReportStatusCodeLib.h>
#include <Library/DebugLib.h>
-#include <Library/SmmServicesTableLib.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PcdLib.h>
@@ -16,10 +16,12 @@
#include <Guid/StatusCodeDataTypeId.h>
#include <Guid/StatusCodeDataTypeDebug.h>
-#include <Protocol/SmmStatusCode.h>
+#include <Protocol/MmStatusCode.h>
-EFI_SMM_REPORT_STATUS_CODE mReportStatusCode = NULL;
-EFI_SMM_STATUS_CODE_PROTOCOL *mStatusCodeProtocol = NULL;
+#include "ReportStatusCodeLib.h"
+
+EFI_MM_REPORT_STATUS_CODE mReportStatusCode = NULL;
+EFI_MM_STATUS_CODE_PROTOCOL *mStatusCodeProtocol = NULL;
/**
@@ -29,14 +31,14 @@ EFI_SMM_STATUS_CODE_PROTOCOL *mStatusCodeProtocol = NULL;
NULL is returned if no status code service is available.
**/
-EFI_SMM_REPORT_STATUS_CODE
+EFI_MM_REPORT_STATUS_CODE
InternalGetReportStatusCode (
VOID
)
{
EFI_STATUS Status;
- Status = gSmst->SmmLocateProtocol (&gEfiSmmStatusCodeProtocolGuid, NULL, (VOID**)&mStatusCodeProtocol);
+ Status = InternalLocateProtocol (&gEfiMmStatusCodeProtocolGuid, NULL, (VOID**)&mStatusCodeProtocol);
if (!EFI_ERROR (Status) && mStatusCodeProtocol != NULL) {
return mStatusCodeProtocol->ReportStatusCode;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.h
new file mode 100644
index 00000000000..bbd45aa035a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLib.h
@@ -0,0 +1,36 @@
+/** @file
+ Report Status Code Library for MM Phase.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _MM_RSC_LIB_H_
+#define _MM_RSC_LIB_H_
+
+/**
+ Returns the first protocol instance that matches the given protocol.
+
+ @param[in] Protocol Provides the protocol to search for.
+ @param[in] Registration Optional registration key returned from
+ RegisterProtocolNotify().
+ @param[out] Interface On return, a pointer to the first interface that matches Protocol and
+ Registration.
+
+ @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in
+ Interface.
+ @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
+ Registration.
+ @retval EFI_INVALID_PARAMETER Interface is NULL.
+ Protocol is NULL.
+
+**/
+EFI_STATUS
+InternalLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration, OPTIONAL
+ OUT VOID **Interface
+ );
+
+#endif // _MM_RSC_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibStandaloneMm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibStandaloneMm.c
new file mode 100644
index 00000000000..e1ba0ff58a7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibStandaloneMm.c
@@ -0,0 +1,38 @@
+/** @file
+ Abstraction layer for MM service table used by MM ReportStatusCodeLib.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/MmServicesTableLib.h>
+
+/**
+ Returns the first protocol instance that matches the given protocol.
+
+ @param[in] Protocol Provides the protocol to search for.
+ @param[in] Registration Optional registration key returned from
+ RegisterProtocolNotify().
+ @param[out] Interface On return, a pointer to the first interface that matches Protocol and
+ Registration.
+
+ @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in
+ Interface.
+ @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
+ Registration.
+ @retval EFI_INVALID_PARAMETER Interface is NULL.
+ Protocol is NULL.
+
+**/
+EFI_STATUS
+InternalLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration, OPTIONAL
+ OUT VOID **Interface
+ )
+{
+ return gMmst->MmLocateProtocol (Protocol, Registration, Interface);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibTraditional.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibTraditional.c
new file mode 100644
index 00000000000..1ddf2815b4b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/ReportStatusCodeLibTraditional.c
@@ -0,0 +1,38 @@
+/** @file
+ Abstraction layer for SMM service table used by SMM ReportStatusCodeLib.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/SmmServicesTableLib.h>
+
+/**
+ Returns the first protocol instance that matches the given protocol.
+
+ @param[in] Protocol Provides the protocol to search for.
+ @param[in] Registration Optional registration key returned from
+ RegisterProtocolNotify().
+ @param[out] Interface On return, a pointer to the first interface that matches Protocol and
+ Registration.
+
+ @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in
+ Interface.
+ @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and
+ Registration.
+ @retval EFI_INVALID_PARAMETER Interface is NULL.
+ Protocol is NULL.
+
+**/
+EFI_STATUS
+InternalLocateProtocol (
+ IN EFI_GUID *Protocol,
+ IN VOID *Registration, OPTIONAL
+ OUT VOID **Interface
+ )
+{
+ return gSmst->SmmLocateProtocol (Protocol, Registration, Interface);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
index 26f2b06600f..6f07f9c42f5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
@@ -28,6 +28,8 @@
[Sources]
ReportStatusCodeLib.c
+ ReportStatusCodeLib.h
+ ReportStatusCodeLibTraditional.c
[Packages]
MdePkg/MdePkg.dec
@@ -45,7 +47,7 @@
gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED
[Protocols]
- gEfiSmmStatusCodeProtocolGuid ## CONSUMES
+ gEfiMmStatusCodeProtocolGuid ## CONSUMES
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/StandaloneMmReportStatusCodeLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/StandaloneMmReportStatusCodeLib.inf
new file mode 100644
index 00000000000..48e029ca5c3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmReportStatusCodeLib/StandaloneMmReportStatusCodeLib.inf
@@ -0,0 +1,53 @@
+## @file
+# Standalone MM report status code library.
+#
+# Retrieve status code and report status code in MM phase.
+#
+# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = StandaloneMmReportStatusCodeLib
+ FILE_GUID = 17C7FC8C-8C5D-497E-9C0E-C21255B30E04
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = ReportStatusCodeLib|MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ReportStatusCodeLib.c
+ ReportStatusCodeLib.h
+ ReportStatusCodeLibStandaloneMm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ BaseMemoryLib
+ MmServicesTableLib
+ DebugLib
+ MemoryAllocationLib
+
+[Guids]
+ gEfiStatusCodeSpecificDataGuid ## SOMETIMES_CONSUMES ## UNDEFINED
+ gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES ## UNDEFINED
+
+[Protocols]
+ gEfiMmStatusCodeProtocolGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.c
new file mode 100644
index 00000000000..5ec94f93b22
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.c
@@ -0,0 +1,102 @@
+/** @file
+ MM driver instance of SmiHandlerProfile Library.
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+#include <Library/SmiHandlerProfileLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Guid/SmiHandlerProfile.h>
+
+SMI_HANDLER_PROFILE_PROTOCOL *mSmiHandlerProfile;
+
+/**
+ This function is called by SmmChildDispatcher module to report
+ a new SMI handler is registered, to SmmCore.
+
+ @param HandlerGuid The GUID to identify the type of the handler.
+ For the SmmChildDispatch protocol, the HandlerGuid
+ must be the GUID of SmmChildDispatch protocol.
+ @param Handler The SMI handler.
+ @param CallerAddress The address of the module who registers the SMI handler.
+ @param Context The context of the SMI handler.
+ For the SmmChildDispatch protocol, the Context
+ must match the one defined for SmmChildDispatch protocol.
+ @param ContextSize The size of the context in bytes.
+ For the SmmChildDispatch protocol, the Context
+ must match the one defined for SmmChildDispatch protocol.
+
+ @retval EFI_SUCCESS The information is recorded.
+ @retval EFI_UNSUPPORTED The feature is unsupported.
+ @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.
+**/
+EFI_STATUS
+EFIAPI
+SmiHandlerProfileRegisterHandler (
+ IN EFI_GUID *HandlerGuid,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
+ IN PHYSICAL_ADDRESS CallerAddress,
+ IN VOID *Context, OPTIONAL
+ IN UINTN ContextSize OPTIONAL
+ )
+{
+ if (mSmiHandlerProfile != NULL) {
+ return mSmiHandlerProfile->RegisterHandler (mSmiHandlerProfile, HandlerGuid, Handler, CallerAddress, Context, ContextSize);
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is called by SmmChildDispatcher module to report
+ an existing SMI handler is unregistered, to SmmCore.
+
+ @param HandlerGuid The GUID to identify the type of the handler.
+ For the SmmChildDispatch protocol, the HandlerGuid
+ must be the GUID of SmmChildDispatch protocol.
+ @param Handler The SMI handler.
+ @param Context The context of the SMI handler.
+ If it is NOT NULL, it will be used to check what is registered.
+ @param ContextSize The size of the context in bytes.
+ If Context is NOT NULL, it will be used to check what is registered.
+
+ @retval EFI_SUCCESS The original record is removed.
+ @retval EFI_UNSUPPORTED The feature is unsupported.
+ @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.
+**/
+EFI_STATUS
+EFIAPI
+SmiHandlerProfileUnregisterHandler (
+ IN EFI_GUID *HandlerGuid,
+ IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
+ IN VOID *Context, OPTIONAL
+ IN UINTN ContextSize OPTIONAL
+ )
+{
+ if (mSmiHandlerProfile != NULL) {
+ return mSmiHandlerProfile->UnregisterHandler (mSmiHandlerProfile, HandlerGuid, Handler, Context, ContextSize);
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ The common constructor function for SMI handler profile.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+**/
+EFI_STATUS
+MmSmiHandlerProfileLibInitialization (
+ VOID
+ )
+{
+ gMmst->MmLocateProtocol (
+ &gSmiHandlerProfileGuid,
+ NULL,
+ (VOID **) &mSmiHandlerProfile
+ );
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.h
new file mode 100644
index 00000000000..278a697eed6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/MmSmiHandlerProfileLib.h
@@ -0,0 +1,23 @@
+/** @file
+ MM driver instance of SmiHandlerProfile Library.
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _MM_SMI_HANDLER_PROFILE_LIB_H_
+#define _MM_SMI_HANDLER_PROFILE_LIB_H_
+
+/**
+ The common constructor function for SMI handler profile.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+**/
+EFI_STATUS
+MmSmiHandlerProfileLibInitialization (
+ VOID
+ );
+
+#endif //_SMM_SMI_HANDLER_PROFILE_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.c
index 190c848aa4c..cb85583259c 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.c
@@ -2,87 +2,17 @@
SMM driver instance of SmiHandlerProfile Library.
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiSmm.h>
-#include <Library/SmiHandlerProfileLib.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Guid/SmiHandlerProfile.h>
+#include <PiMm.h>
-SMI_HANDLER_PROFILE_PROTOCOL *mSmiHandlerProfile;
+#include "MmSmiHandlerProfileLib.h"
/**
- This function is called by SmmChildDispatcher module to report
- a new SMI handler is registered, to SmmCore.
-
- @param HandlerGuid The GUID to identify the type of the handler.
- For the SmmChildDispatch protocol, the HandlerGuid
- must be the GUID of SmmChildDispatch protocol.
- @param Handler The SMI handler.
- @param CallerAddress The address of the module who registers the SMI handler.
- @param Context The context of the SMI handler.
- For the SmmChildDispatch protocol, the Context
- must match the one defined for SmmChildDispatch protocol.
- @param ContextSize The size of the context in bytes.
- For the SmmChildDispatch protocol, the Context
- must match the one defined for SmmChildDispatch protocol.
-
- @retval EFI_SUCCESS The information is recorded.
- @retval EFI_UNSUPPORTED The feature is unsupported.
- @retval EFI_OUT_OF_RESOURCES There is no enough resource to record the information.
-**/
-EFI_STATUS
-EFIAPI
-SmiHandlerProfileRegisterHandler (
- IN EFI_GUID *HandlerGuid,
- IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
- IN PHYSICAL_ADDRESS CallerAddress,
- IN VOID *Context, OPTIONAL
- IN UINTN ContextSize OPTIONAL
- )
-{
- if (mSmiHandlerProfile != NULL) {
- return mSmiHandlerProfile->RegisterHandler (mSmiHandlerProfile, HandlerGuid, Handler, CallerAddress, Context, ContextSize);
- }
- return EFI_UNSUPPORTED;
-}
-
-/**
- This function is called by SmmChildDispatcher module to report
- an existing SMI handler is unregistered, to SmmCore.
-
- @param HandlerGuid The GUID to identify the type of the handler.
- For the SmmChildDispatch protocol, the HandlerGuid
- must be the GUID of SmmChildDispatch protocol.
- @param Handler The SMI handler.
- @param Context The context of the SMI handler.
- If it is NOT NULL, it will be used to check what is registered.
- @param ContextSize The size of the context in bytes.
- If Context is NOT NULL, it will be used to check what is registered.
-
- @retval EFI_SUCCESS The original record is removed.
- @retval EFI_UNSUPPORTED The feature is unsupported.
- @retval EFI_NOT_FOUND There is no record for the HandlerGuid and handler.
-**/
-EFI_STATUS
-EFIAPI
-SmiHandlerProfileUnregisterHandler (
- IN EFI_GUID *HandlerGuid,
- IN EFI_SMM_HANDLER_ENTRY_POINT2 Handler,
- IN VOID *Context, OPTIONAL
- IN UINTN ContextSize OPTIONAL
- )
-{
- if (mSmiHandlerProfile != NULL) {
- return mSmiHandlerProfile->UnregisterHandler (mSmiHandlerProfile, HandlerGuid, Handler, Context, ContextSize);
- }
- return EFI_UNSUPPORTED;
-}
-
-/**
- The constructor function for SMI handler profile.
+ The constructor function for traditional MM SMI handler profile.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@@ -92,15 +22,9 @@ SmiHandlerProfileUnregisterHandler (
EFI_STATUS
EFIAPI
SmmSmiHandlerProfileLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
)
{
- gSmst->SmmLocateProtocol (
- &gSmiHandlerProfileGuid,
- NULL,
- (VOID **) &mSmiHandlerProfile
- );
- return EFI_SUCCESS;
+ return MmSmiHandlerProfileLibInitialization ();
}
-
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
index 2bccd7e098e..39de9be6bce 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
@@ -27,6 +27,8 @@
#
[Sources]
+ MmSmiHandlerProfileLib.c
+ MmSmiHandlerProfileLib.h
SmmSmiHandlerProfileLib.c
[Packages]
@@ -34,7 +36,7 @@
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
- SmmServicesTableLib
+ MmServicesTableLib
[Guids]
gSmiHandlerProfileGuid ## CONSUMES ## GUID # Locate protocol
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.c
new file mode 100644
index 00000000000..8b43fea9101
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.c
@@ -0,0 +1,31 @@
+/** @file
+ Standalone MM driver instance of SmiHandlerProfile Library.
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include "MmSmiHandlerProfileLib.h"
+
+/**
+ The constructor function for standalone MM SMI handler profile.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmSmiHandlerProfileLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return MmSmiHandlerProfileLibInitialization ();
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.inf
new file mode 100644
index 00000000000..eb6880820e1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Standalone MM driver instance of SmiHandlerProfile Library.
+#
+# This library instance provides real functionality for SmmChildDispatcher module.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = StandaloneMmSmiHandlerProfileLib
+ FILE_GUID = 1F2ED27B-A01D-4867-B993-9B710E5926C5
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x10000032
+ LIBRARY_CLASS = SmiHandlerProfileLib|MM_STANDALONE
+ CONSTRUCTOR = StandaloneMmSmiHandlerProfileLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MmSmiHandlerProfileLib.c
+ MmSmiHandlerProfileLib.h
+ StandaloneMmSmiHandlerProfileLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MmServicesTableLib
+
+[Guids]
+ gSmiHandlerProfileGuid ## CONSUMES ## GUID # Locate protocol
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
index 8d2aa1d12da..12b05e197e0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
@@ -12,7 +12,7 @@
FILE_GUID = 6DFD6E9F-9278-48D8-8F45-B6CFF2C2B69C
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
- LIBRARY_CLASS = TpmMeasurementLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ LIBRARY_CLASS = TpmMeasurementLib|SEC PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
MODULE_UNI_FILE = TpmMeasurementLibNull.uni
#
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
index 77039dd739d..aa240ab0963 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
@@ -2,8 +2,8 @@
Library functions which relates with booting.
Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
-Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2015-2021 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1985,17 +1985,17 @@ EfiBootManagerBoot (
gBS->UnloadImage (ImageHandle);
}
//
- // Report Status Code with the failure status to indicate that the failure to load boot option
- //
- BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status);
- BootOption->Status = Status;
- //
// Destroy the RAM disk
//
if (RamDiskDevicePath != NULL) {
BmDestroyRamDisk (RamDiskDevicePath);
FreePool (RamDiskDevicePath);
}
+ //
+ // Report Status Code with the failure status to indicate that the failure to load boot option
+ //
+ BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status);
+ BootOption->Status = Status;
return;
}
}
@@ -2064,13 +2064,6 @@ EfiBootManagerBoot (
Status = gBS->StartImage (ImageHandle, &BootOption->ExitDataSize, &BootOption->ExitData);
DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));
BootOption->Status = Status;
- if (EFI_ERROR (Status)) {
- //
- // Report Status Code with the failure status to indicate that boot failure
- //
- BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED, Status);
- }
- PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);
//
// Destroy the RAM disk
@@ -2080,6 +2073,15 @@ EfiBootManagerBoot (
FreePool (RamDiskDevicePath);
}
+ if (EFI_ERROR (Status)) {
+ //
+ // Report Status Code with the failure status to indicate that boot failure
+ //
+ BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED, Status);
+ }
+ PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);
+
+
//
// Clear the Watchdog Timer after the image returns
//
@@ -2465,7 +2467,8 @@ EfiBootManagerRefreshAllBootOption (
This function is called to get or create the boot option for the Boot Manager Menu.
The Boot Manager Menu is shown after successfully booting a boot option.
- Assume the BootManagerMenuFile is in the same FV as the module links to this library.
+ This function will first try to search the BootManagerMenuFile is in the same FV as
+ the module links to this library. If fails, it will search in all FVs.
@param BootOption Return the boot option of the Boot Manager Menu
@@ -2517,7 +2520,7 @@ BmRegisterBootManagerMenu (
if (DevicePath == NULL) {
Data = NULL;
- Status = GetSectionFromFv (
+ Status = GetSectionFromAnyFv (
PcdGetPtr (PcdBootManagerMenuFile),
EFI_SECTION_PE32,
0,
@@ -2535,7 +2538,7 @@ BmRegisterBootManagerMenu (
//
// Get BootManagerMenu application's description from EFI User Interface Section.
//
- Status = GetSectionFromFv (
+ Status = GetSectionFromAnyFv (
PcdGetPtr (PcdBootManagerMenuFile),
EFI_SECTION_USER_INTERFACE,
0,
@@ -2585,7 +2588,7 @@ BmRegisterBootManagerMenu (
EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
);
- return EfiBootManagerAddLoadOptionVariable (BootOption, 0);
+ return EfiBootManagerAddLoadOptionVariable (BootOption, (UINTN) -1);
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
index 7b247dea3f9..6c2ddac80ba 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiLib.c
@@ -3605,7 +3605,7 @@ HiiCreateCheckBoxOpCode (
EFI_IFR_CHECKBOX OpCode;
UINTN Position;
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE))) == 0);
ZeroMem (&OpCode, sizeof (OpCode));
OpCode.Question.QuestionId = QuestionId;
@@ -3674,7 +3674,7 @@ HiiCreateNumericOpCode (
UINTN Position;
UINTN Length;
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE))) == 0);
Length = 0;
ZeroMem (&OpCode, sizeof (OpCode));
@@ -3773,7 +3773,7 @@ HiiCreateStringOpCode (
EFI_IFR_STRING OpCode;
UINTN Position;
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE))) == 0);
ZeroMem (&OpCode, sizeof (OpCode));
OpCode.Question.Header.Prompt = Prompt;
@@ -3841,7 +3841,7 @@ HiiCreateOneOfOpCode (
UINTN Length;
ASSERT (OptionsOpCodeHandle != NULL);
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
ZeroMem (&OpCode, sizeof (OpCode));
OpCode.Question.Header.Prompt = Prompt;
@@ -3912,7 +3912,7 @@ HiiCreateOrderedListOpCode (
UINTN Position;
ASSERT (OptionsOpCodeHandle != NULL);
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE | EFI_IFR_FLAG_OPTIONS_ONLY))) == 0);
ZeroMem (&OpCode, sizeof (OpCode));
OpCode.Question.Header.Prompt = Prompt;
@@ -4009,7 +4009,7 @@ HiiCreateDateOpCode (
EFI_IFR_DATE OpCode;
UINTN Position;
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE))) == 0);
ASSERT ((DateFlags & (~(EFI_QF_DATE_YEAR_SUPPRESS | EFI_QF_DATE_MONTH_SUPPRESS | EFI_QF_DATE_DAY_SUPPRESS | EFI_QF_DATE_STORAGE))) == 0);
ZeroMem (&OpCode, sizeof (OpCode));
@@ -4074,7 +4074,7 @@ HiiCreateTimeOpCode (
EFI_IFR_TIME OpCode;
UINTN Position;
- ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED))) == 0);
+ ASSERT ((QuestionFlags & (~(EFI_IFR_FLAG_READ_ONLY | EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED | EFI_IFR_FLAG_REST_STYLE))) == 0);
ASSERT ((TimeFlags & (~(QF_TIME_HOUR_SUPPRESS | QF_TIME_MINUTE_SUPPRESS | QF_TIME_SECOND_SUPPRESS | QF_TIME_STORAGE))) == 0);
ZeroMem (&OpCode, sizeof (OpCode));
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiString.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiString.c
index 2dc82434d82..c1c227710e1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiString.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/UefiHiiLib/HiiString.c
@@ -1,7 +1,8 @@
/** @file
HII Library implementation that uses DXE protocols and services.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -190,16 +191,8 @@ HiiGetPackageString (
}
/**
- Retrieves a string from a string package in a specific language. If the language
- is not specified, then a string from a string package in the current platform
- language is retrieved. If the string can not be retrieved using the specified
- language or the current platform language, then the string is retrieved from
- the string package in the first language the string package supports. The
- returned string is allocated using AllocatePool(). The caller is responsible
- for freeing the allocated buffer using FreePool().
-
- If HiiHandle is NULL, then ASSERT().
- If StringId is 0, then ASSET.
+ Retrieves a string from a string package in a specific language specified in Language
+ or in the best lanaguage. See HiiGetStringEx () for the details.
@param[in] HiiHandle A handle that was previously registered in the HII Database.
@param[in] StringId The identifier of the string to retrieved from the string
@@ -221,6 +214,51 @@ HiiGetString (
IN CONST CHAR8 *Language OPTIONAL
)
{
+ return HiiGetStringEx (HiiHandle, StringId, Language, TRUE);
+}
+
+/**
+ Retrieves a string from a string package in a specific language or in the best
+ language at discretion of this function according to the priority of languages.
+ TryBestLanguage is used to get the string in the best language or in the language
+ specified in Language parameter. The behavior is,
+ If TryBestLanguage is TRUE, this function looks for the best language for the string.
+ - If the string can not be retrieved using the specified language or the current
+ platform language, then the string is retrieved from the string package in the
+ first language the string package supports.
+ If TryBestLanguage is FALSE, Language must be specified for retrieving the string.
+
+ The returned string is allocated using AllocatePool(). The caller is responsible
+ for freeing the allocated buffer using FreePool().
+
+ If HiiHandle is NULL, then ASSERT().
+ If StringId is 0, then ASSET.
+ If TryBestLanguage is FALE and Language is NULL, then ASSERT().
+
+ @param[in] HiiHandle A handle that was previously registered in the HII Database.
+ @param[in] StringId The identifier of the string to retrieved from the string
+ package associated with HiiHandle.
+ @param[in] Language The language of the string to retrieve. If this parameter
+ is NULL, then the current platform language is used. The
+ format of Language must follow the language format assumed
+ the HII Database.
+ @param[in] TryBestLanguage If TRUE, try to get the best matching language from all
+ supported languages.If FALSE, the Language must be assigned
+ for the StringID.
+
+ @retval NULL The string specified by StringId is not present in the string package.
+ @retval Other The string was returned.
+
+**/
+EFI_STRING
+EFIAPI
+HiiGetStringEx (
+ IN EFI_HII_HANDLE HiiHandle,
+ IN EFI_STRING_ID StringId,
+ IN CONST CHAR8 *Language OPTIONAL,
+ IN BOOLEAN TryBestLanguage
+ )
+{
EFI_STATUS Status;
UINTN StringSize;
CHAR16 TempString;
@@ -231,7 +269,10 @@ HiiGetString (
ASSERT (HiiHandle != NULL);
ASSERT (StringId != 0);
-
+ //
+ // Language must be specified if TryBestLanguage = FALSE.
+ //
+ ASSERT (!(!TryBestLanguage && Language == NULL));
//
// Initialize all allocated buffers to NULL
//
@@ -261,21 +302,26 @@ HiiGetString (
Language = "";
}
- //
- // Get the best matching language from SupportedLanguages
- //
- BestLanguage = GetBestLanguage (
- SupportedLanguages,
- FALSE, // RFC 4646 mode
- Language, // Highest priority
- PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
- SupportedLanguages, // Lowest priority
- NULL
- );
- if (BestLanguage == NULL) {
- goto Error;
+ if (TryBestLanguage) {
+ //
+ // Get the best matching language from SupportedLanguages
+ //
+ BestLanguage = GetBestLanguage (
+ SupportedLanguages,
+ FALSE, // RFC 4646 mode
+ Language, // Highest priority
+ PlatformLanguage != NULL ? PlatformLanguage : "", // Next highest priority
+ SupportedLanguages, // Lowest priority
+ NULL
+ );
+ if (BestLanguage == NULL) {
+ goto Error;
+ }
+ } else {
+ BestLanguage = (CHAR8 *) Language;
}
+
//
// Retrieve the size of the string in the string package for the BestLanguage
//
@@ -337,7 +383,7 @@ Error:
if (PlatformLanguage != NULL) {
FreePool (PlatformLanguage);
}
- if (BestLanguage != NULL) {
+ if (TryBestLanguage && BestLanguage != NULL) {
FreePool (BestLanguage);
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckLib/VarCheckLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckLib/VarCheckLib.c
index 74b7471b12d..568f26fe39a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckLib/VarCheckLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckLib/VarCheckLib.c
@@ -1,7 +1,7 @@
/** @file
Implementation functions and structures for var check services.
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -655,6 +655,13 @@ VarCheckLibSetVariableCheck (
DataSize,
Data
);
+ if (Status == EFI_WRITE_PROTECTED && RequestSource == VarCheckFromTrusted) {
+ //
+ // If RequestSource is trusted, then allow variable to be set even if it
+ // is write protected.
+ //
+ continue;
+ }
if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_INFO, "Variable Check handler fail %r - %g:%s\n", Status, VendorGuid, VariableName));
return Status;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
new file mode 100644
index 00000000000..38a05d345fc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.c
@@ -0,0 +1,345 @@
+/** @file -- VarCheckPolicyLib.c
+This is a NULL library instance that leverages the VarCheck interface
+and the business logic behind the VariablePolicy code to make its decisions.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/VarCheckLib.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SafeIntLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/MmCommunication.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+#include <Guid/VarCheckPolicyMmi.h>
+
+#include "VarCheckPolicyLib.h"
+
+//================================================
+// As a VarCheck library, we're linked into the VariableServices
+// and may not be able to call them indirectly. To get around this,
+// use the internal GetVariable function to query the variable store.
+//================================================
+EFI_STATUS
+EFIAPI
+VariableServiceGetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes OPTIONAL,
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data
+ );
+
+
+UINT8 mSecurityEvalBuffer[VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE];
+
+// Pagination Cache Variables
+UINT8 *mPaginationCache = NULL;
+UINTN mPaginationCacheSize = 0;
+UINT32 mCurrentPaginationCommand = 0;
+
+
+/**
+ MM Communication Handler to recieve commands from the DXE protocol for
+ Variable Policies. This communication channel is used to register new policies
+ and poll and toggle the enforcement of variable policies.
+
+ @param[in] DispatchHandle All parameters standard to MM communications convention.
+ @param[in] RegisterContext All parameters standard to MM communications convention.
+ @param[in,out] CommBuffer All parameters standard to MM communications convention.
+ @param[in,out] CommBufferSize All parameters standard to MM communications convention.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER CommBuffer or CommBufferSize is null pointer.
+ @retval EFI_INVALID_PARAMETER CommBuffer size is wrong.
+ @retval EFI_INVALID_PARAMETER Revision or signature don't match.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibMmiHandler (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *RegisterContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ UINTN InternalCommBufferSize;
+ VOID *InternalCommBuffer;
+ EFI_STATUS Status;
+ EFI_STATUS SubCommandStatus;
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyCommmHeader;
+ VAR_CHECK_POLICY_COMM_HEADER *InternalPolicyCommmHeader;
+ VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *IsEnabledParams;
+ VAR_CHECK_POLICY_COMM_DUMP_PARAMS *DumpParamsIn;
+ VAR_CHECK_POLICY_COMM_DUMP_PARAMS *DumpParamsOut;
+ UINT8 *DumpInputBuffer;
+ UINT8 *DumpOutputBuffer;
+ UINTN DumpTotalPages;
+ VARIABLE_POLICY_ENTRY *PolicyEntry;
+ UINTN ExpectedSize;
+ UINT32 TempSize;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Validate some input parameters.
+ //
+ // If either of the pointers are NULL, we can't proceed.
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ DEBUG(( DEBUG_INFO, "%a - Invalid comm buffer pointers!\n", __FUNCTION__ ));
+ return EFI_INVALID_PARAMETER;
+ }
+ // Make sure that the buffer does not overlap SMM.
+ // This should be covered by the SmiManage infrastructure, but just to be safe...
+ InternalCommBufferSize = *CommBufferSize;
+ if (InternalCommBufferSize > VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE ||
+ !VarCheckPolicyIsBufferOutsideValid((UINTN)CommBuffer, (UINT64)InternalCommBufferSize)) {
+ DEBUG ((DEBUG_ERROR, "%a - Invalid CommBuffer supplied! 0x%016lX[0x%016lX]\n", __FUNCTION__, CommBuffer, InternalCommBufferSize));
+ return EFI_INVALID_PARAMETER;
+ }
+ // If the size does not meet a minimum threshold, we cannot proceed.
+ ExpectedSize = sizeof(VAR_CHECK_POLICY_COMM_HEADER);
+ if (InternalCommBufferSize < ExpectedSize) {
+ DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, InternalCommBufferSize, ExpectedSize ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Before proceeding any further, copy the buffer internally so that we can compare
+ // without worrying about TOCTOU.
+ //
+ InternalCommBuffer = &mSecurityEvalBuffer[0];
+ CopyMem(InternalCommBuffer, CommBuffer, InternalCommBufferSize);
+ PolicyCommmHeader = CommBuffer;
+ InternalPolicyCommmHeader = InternalCommBuffer;
+ // Check the revision and the signature of the comm header.
+ if (InternalPolicyCommmHeader->Signature != VAR_CHECK_POLICY_COMM_SIG ||
+ InternalPolicyCommmHeader->Revision != VAR_CHECK_POLICY_COMM_REVISION) {
+ DEBUG(( DEBUG_INFO, "%a - Signature or revision are incorrect!\n", __FUNCTION__ ));
+ // We have verified the buffer is not null and have enough size to hold Result field.
+ PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+ return EFI_SUCCESS;
+ }
+
+ // If we're in the middle of a paginated dump and any other command is sent,
+ // pagination cache must be cleared.
+ if (mPaginationCache != NULL && InternalPolicyCommmHeader->Command != mCurrentPaginationCommand) {
+ FreePool (mPaginationCache);
+ mPaginationCache = NULL;
+ mPaginationCacheSize = 0;
+ mCurrentPaginationCommand = 0;
+ }
+
+ //
+ // Now we can process the command as it was sent.
+ //
+ PolicyCommmHeader->Result = EFI_ABORTED; // Set a default return for incomplete commands.
+ switch(InternalPolicyCommmHeader->Command) {
+ case VAR_CHECK_POLICY_COMMAND_DISABLE:
+ PolicyCommmHeader->Result = DisableVariablePolicy();
+ break;
+
+ case VAR_CHECK_POLICY_COMMAND_IS_ENABLED:
+ // Make sure that we're dealing with a reasonable size.
+ // This add should be safe because these are fixed sizes so far.
+ ExpectedSize += sizeof(VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS);
+ if (InternalCommBufferSize < ExpectedSize) {
+ DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, InternalCommBufferSize, ExpectedSize ));
+ PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ // Now that we know we've got a valid size, we can fill in the rest of the data.
+ IsEnabledParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)((UINT8*)CommBuffer + sizeof(VAR_CHECK_POLICY_COMM_HEADER));
+ IsEnabledParams->State = IsVariablePolicyEnabled();
+ PolicyCommmHeader->Result = EFI_SUCCESS;
+ break;
+
+ case VAR_CHECK_POLICY_COMMAND_REGISTER:
+ // Make sure that we're dealing with a reasonable size.
+ // This add should be safe because these are fixed sizes so far.
+ ExpectedSize += sizeof(VARIABLE_POLICY_ENTRY);
+ if (InternalCommBufferSize < ExpectedSize) {
+ DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, InternalCommBufferSize, ExpectedSize ));
+ PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ // At the very least, we can assume that we're working with a valid policy entry.
+ // Time to compare its internal size.
+ PolicyEntry = (VARIABLE_POLICY_ENTRY*)((UINT8*)InternalCommBuffer + sizeof(VAR_CHECK_POLICY_COMM_HEADER));
+ if (PolicyEntry->Version != VARIABLE_POLICY_ENTRY_REVISION ||
+ PolicyEntry->Size < sizeof(VARIABLE_POLICY_ENTRY) ||
+ EFI_ERROR(SafeUintnAdd(sizeof(VAR_CHECK_POLICY_COMM_HEADER), PolicyEntry->Size, &ExpectedSize)) ||
+ InternalCommBufferSize < ExpectedSize) {
+ DEBUG(( DEBUG_INFO, "%a - Bad policy entry contents!\n", __FUNCTION__ ));
+ PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ PolicyCommmHeader->Result = RegisterVariablePolicy( PolicyEntry );
+ break;
+
+ case VAR_CHECK_POLICY_COMMAND_DUMP:
+ // Make sure that we're dealing with a reasonable size.
+ // This add should be safe because these are fixed sizes so far.
+ ExpectedSize += sizeof(VAR_CHECK_POLICY_COMM_DUMP_PARAMS) + VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
+ if (InternalCommBufferSize < ExpectedSize) {
+ DEBUG(( DEBUG_INFO, "%a - Bad comm buffer size! %d < %d\n", __FUNCTION__, InternalCommBufferSize, ExpectedSize ));
+ PolicyCommmHeader->Result = EFI_INVALID_PARAMETER;
+ break;
+ }
+
+ // Now that we know we've got a valid size, we can fill in the rest of the data.
+ DumpParamsIn = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(InternalPolicyCommmHeader + 1);
+ DumpParamsOut = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyCommmHeader + 1);
+
+ // If we're requesting the first page, initialize the cache and get the sizes.
+ if (DumpParamsIn->PageRequested == 0) {
+ if (mPaginationCache != NULL) {
+ FreePool (mPaginationCache);
+ mPaginationCache = NULL;
+ }
+
+ // Determine what the required size is going to be.
+ DumpParamsOut->TotalSize = 0;
+ DumpParamsOut->PageSize = 0;
+ DumpParamsOut->HasMore = FALSE;
+ TempSize = 0;
+ SubCommandStatus = DumpVariablePolicy (NULL, &TempSize);
+ if (SubCommandStatus == EFI_BUFFER_TOO_SMALL && TempSize > 0) {
+ mCurrentPaginationCommand = VAR_CHECK_POLICY_COMMAND_DUMP;
+ mPaginationCacheSize = TempSize;
+ DumpParamsOut->TotalSize = TempSize;
+ mPaginationCache = AllocatePool (mPaginationCacheSize);
+ if (mPaginationCache == NULL) {
+ SubCommandStatus = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ // If we've allocated our pagination cache, we're good to cache.
+ if (mPaginationCache != NULL) {
+ SubCommandStatus = DumpVariablePolicy (mPaginationCache, &TempSize);
+ }
+
+ // Populate the remaining fields and we can boogie.
+ if (!EFI_ERROR (SubCommandStatus) && mPaginationCache != NULL) {
+ DumpParamsOut->HasMore = TRUE;
+ }
+ } else if (mPaginationCache != NULL) {
+ DumpParamsOut->TotalSize = (UINT32)mPaginationCacheSize;
+ DumpOutputBuffer = (UINT8*)(DumpParamsOut + 1);
+
+ // Make sure that we don't over-index the cache.
+ DumpTotalPages = mPaginationCacheSize / VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
+ if (mPaginationCacheSize % VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE != 0) {
+ DumpTotalPages++;
+ }
+ if (DumpParamsIn->PageRequested > DumpTotalPages) {
+ SubCommandStatus = EFI_INVALID_PARAMETER;
+ } else {
+ // Figure out how far into the page cache we need to go for our next page.
+ // We know the blind subtraction won't be bad because we already checked for page 0.
+ DumpInputBuffer = &mPaginationCache[VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE * (DumpParamsIn->PageRequested - 1)];
+ TempSize = VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
+ // If we're getting the last page, adjust the PageSize.
+ if (DumpParamsIn->PageRequested == DumpTotalPages) {
+ TempSize = mPaginationCacheSize % VAR_CHECK_POLICY_MM_DUMP_BUFFER_SIZE;
+ }
+ CopyMem (DumpOutputBuffer, DumpInputBuffer, TempSize);
+ DumpParamsOut->PageSize = TempSize;
+ // If we just got the last page, settle up the cache.
+ if (DumpParamsIn->PageRequested == DumpTotalPages) {
+ DumpParamsOut->HasMore = FALSE;
+ FreePool (mPaginationCache);
+ mPaginationCache = NULL;
+ mPaginationCacheSize = 0;
+ mCurrentPaginationCommand = 0;
+ // Otherwise, we could do more here.
+ } else {
+ DumpParamsOut->HasMore = TRUE;
+ }
+
+ // If we made it this far, we're basically good.
+ SubCommandStatus = EFI_SUCCESS;
+ }
+ // If we've requested any other page than 0 and the cache is empty, we must have timed out.
+ } else {
+ DumpParamsOut->TotalSize = 0;
+ DumpParamsOut->PageSize = 0;
+ DumpParamsOut->HasMore = FALSE;
+ SubCommandStatus = EFI_TIMEOUT;
+ }
+
+ // There's currently no use for this, but it shouldn't be hard to implement.
+ PolicyCommmHeader->Result = SubCommandStatus;
+ break;
+
+ case VAR_CHECK_POLICY_COMMAND_LOCK:
+ PolicyCommmHeader->Result = LockVariablePolicy();
+ break;
+
+ default:
+ // Mark unknown requested command as EFI_UNSUPPORTED.
+ DEBUG(( DEBUG_INFO, "%a - Invalid command requested! %d\n", __FUNCTION__, PolicyCommmHeader->Command ));
+ PolicyCommmHeader->Result = EFI_UNSUPPORTED;
+ break;
+ }
+
+ DEBUG(( DEBUG_VERBOSE, "%a - Command %d returning %r.\n", __FUNCTION__,
+ PolicyCommmHeader->Command, PolicyCommmHeader->Result ));
+
+ return Status;
+}
+
+
+/**
+ Constructor function of VarCheckPolicyLib to register VarCheck handler and
+ SW MMI handlers.
+
+ @retval EFI_SUCCESS The constructor executed correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibCommonConstructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE DiscardedHandle;
+
+ // Initialize the business logic with the internal GetVariable handler.
+ Status = InitVariablePolicyLib( VariableServiceGetVariable );
+
+ // Only proceed with init if the business logic could be initialized.
+ if (!EFI_ERROR( Status )) {
+ // Register the VarCheck handler for SetVariable filtering.
+ // Forward the check to the business logic of the library.
+ VarCheckLibRegisterSetVariableCheckHandler( ValidateSetVariable );
+
+ // Register the MMI handlers for receiving policy commands.
+ DiscardedHandle = NULL;
+ Status = gMmst->MmiHandlerRegister( VarCheckPolicyLibMmiHandler,
+ &gVarCheckPolicyLibMmiHandlerGuid,
+ &DiscardedHandle );
+ }
+ // Otherwise, there's not much we can do.
+ else {
+ DEBUG(( DEBUG_ERROR, "%a - Cannot Initialize VariablePolicyLib! %r\n", __FUNCTION__, Status ));
+ ASSERT_EFI_ERROR( Status );
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.h
new file mode 100644
index 00000000000..fddf1bc1d2c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.h
@@ -0,0 +1,42 @@
+/** @file -- VarCheckPolicyLib.h
+This internal header file defines the common interface of constructor for
+VarCheckPolicyLib.
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _VAR_CHECK_POLICY_LIB_H_
+#define _VAR_CHECK_POLICY_LIB_H_
+
+/**
+ Common constructor function of VarCheckPolicyLib to register VarCheck handler
+ and SW MMI handlers.
+
+ @retval EFI_SUCCESS The constructor executed correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibCommonConstructor (
+ VOID
+ );
+
+/**
+ This function is wrapper function to validate the buffer.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM/MMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM/MMRAM.
+**/
+BOOLEAN
+EFIAPI
+VarCheckPolicyIsBufferOutsideValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ );
+
+#endif // _VAR_CHECK_POLICY_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
new file mode 100644
index 00000000000..f7e97db434c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
@@ -0,0 +1,43 @@
+## @file VarCheckPolicyLib.inf
+# This is an instance of a VarCheck lib that leverages the business logic behind
+# the VariablePolicy code to make its decisions.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VarCheckPolicyLib
+ FILE_GUID = 9C28A48F-C884-4B1F-8B95-DEF125448023
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+ CONSTRUCTOR = VarCheckPolicyLibTraditionalConstructor
+
+
+[Sources]
+ VarCheckPolicyLib.c
+ VarCheckPolicyLibTraditional.c
+ VarCheckPolicyLib.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ VarCheckLib
+ VariablePolicyLib
+ VariablePolicyHelperLib
+ SafeIntLib
+ MmServicesTableLib
+
+
+[Guids]
+ gVarCheckPolicyLibMmiHandlerGuid ## CONSUME ## Used to register for MM Communication events.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
new file mode 100644
index 00000000000..eedeeed15d3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.uni
@@ -0,0 +1,12 @@
+// /** @file
+// VarCheckPolicyLib.uni
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "NULL library implementation that conforms to the VarCheck interface to allow VariablePolicy engine to enforce policies"
+
+#string STR_MODULE_DESCRIPTION #language en-US "NULL library implementation that conforms to the VarCheck interface to allow VariablePolicy engine to enforce policies"
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.c
new file mode 100644
index 00000000000..5e93b46f57d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.c
@@ -0,0 +1,50 @@
+/** @file -- VarCheckPolicyLibStandaloneMm.c
+This is an instance of a VarCheck lib constructor for Standalone MM.
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/StandaloneMmMemLib.h>
+
+#include "VarCheckPolicyLib.h"
+
+/**
+ Standalone MM constructor function of VarCheckPolicyLib to invoke common
+ constructor routine.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor executed correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibStandaloneConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return VarCheckPolicyLibCommonConstructor ();
+}
+
+/**
+ This function is wrapper function to validate the buffer.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architectureand not overlap with MMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with MMRAM.
+**/
+BOOLEAN
+EFIAPI
+VarCheckPolicyIsBufferOutsideValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return MmIsBufferOutsideMmValid (Buffer, Length);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.inf
new file mode 100644
index 00000000000..adea452074c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.inf
@@ -0,0 +1,47 @@
+## @file VarCheckPolicyLibStandaloneMm.inf
+# This is an instance of a VarCheck lib that leverages the business logic behind
+# the VariablePolicy code to make its decisions.
+#
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VarCheckPolicyLibStandaloneMm
+ FILE_GUID = 44B09E3D-5EDA-4673-ABCF-C8AE4560C8EC
+ MODULE_TYPE = MM_STANDALONE
+ PI_SPECIFICATION_VERSION = 0x00010032
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|MM_STANDALONE
+ CONSTRUCTOR = VarCheckPolicyLibStandaloneConstructor
+
+
+[Sources]
+ VarCheckPolicyLib.c
+ VarCheckPolicyLibStandaloneMm.c
+ VarCheckPolicyLib.h
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemLib
+ MemoryAllocationLib
+ VarCheckLib
+ VariablePolicyLib
+ VariablePolicyHelperLib
+ SafeIntLib
+ MmServicesTableLib
+
+[Guids]
+ gVarCheckPolicyLibMmiHandlerGuid ## CONSUME ## Used to register for MM Communication events.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibTraditional.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibTraditional.c
new file mode 100644
index 00000000000..43a10c4de33
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibTraditional.c
@@ -0,0 +1,50 @@
+/** @file -- VarCheckPolicyLibTraditional.c
+This is an instance of a VarCheck lib constructor for traditional SMM.
+
+Copyright (c) Microsoft Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/SmmMemLib.h>
+
+#include "VarCheckPolicyLib.h"
+
+/**
+ Traditional constructor function of VarCheckPolicyLib to invoke common
+ constructor routine.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor executed correctly.
+
+**/
+EFI_STATUS
+EFIAPI
+VarCheckPolicyLibTraditionalConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return VarCheckPolicyLibCommonConstructor ();
+}
+
+/**
+ This function is wrapper function to validate the buffer.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+EFIAPI
+VarCheckPolicyIsBufferOutsideValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return SmmIsBufferOutsideSmmValid (Buffer, Length);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
new file mode 100644
index 00000000000..1f1f9c1d060
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.c
@@ -0,0 +1,401 @@
+/** @file -- VariablePolicyHelperLib.c
+This library contains helper functions for marshalling and registering
+new policies with the VariablePolicy infrastructure.
+
+This library is currently written against VariablePolicy revision 0x00010000.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/VariablePolicy.h>
+
+/**
+ This internal helper function populates the header structure,
+ all common fields, and takes care of fix-ups.
+
+ NOTE: Only use this internally. Assumes correctly-sized buffers.
+
+ @param[out] EntPtr Pointer to the buffer to be populated.
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] LockPolicyType LockPolicyType for the VariablePolicy.
+
+**/
+STATIC
+VOID
+PopulateCommonData (
+ OUT VARIABLE_POLICY_ENTRY *EntPtr,
+ IN CONST EFI_GUID *Namespace,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType
+ )
+{
+ EntPtr->Version = VARIABLE_POLICY_ENTRY_REVISION;
+ CopyGuid( &EntPtr->Namespace, Namespace );
+ EntPtr->MinSize = MinSize;
+ EntPtr->MaxSize = MaxSize;
+ EntPtr->AttributesMustHave = AttributesMustHave;
+ EntPtr->AttributesCantHave = AttributesCantHave;
+ EntPtr->LockPolicyType = LockPolicyType;
+
+ // NOTE: As a heler, fix up MaxSize for compatibility with the old model.
+ if (EntPtr->MaxSize == 0) {
+ EntPtr->MaxSize = VARIABLE_POLICY_NO_MAX_SIZE;
+ }
+
+ return;
+}
+
+
+/**
+ This helper function will allocate and populate a new VariablePolicy
+ structure for a policy that does not contain any sub-structures (such as
+ VARIABLE_LOCK_ON_VAR_STATE_POLICY).
+
+ NOTE: Caller will need to free structure once finished.
+
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] LockPolicyType LockPolicyType for the VariablePolicy.
+ @param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the
+ new policy.
+
+ @retval EFI_SUCCESS Operation completed successfully and structure is populated.
+ @retval EFI_INVALID_PARAMETER Namespace is NULL.
+ @retval EFI_INVALID_PARAMETER LockPolicyType is invalid for a basic structure.
+ @retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateBasicVariablePolicy (
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType,
+ OUT VARIABLE_POLICY_ENTRY **NewEntry
+ )
+{
+ UINTN TotalSize;
+ UINTN NameSize;
+ VARIABLE_POLICY_ENTRY *EntPtr;
+ CHAR16 *CopyName;
+
+ // Check some initial invalid parameters for this function.
+ if (Namespace == NULL || NewEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK &&
+ LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW &&
+ LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set NameSize to suppress incorrect compiler/analyzer warnings
+ //
+ NameSize = 0;
+
+ // Now we've gotta determine the total size of the buffer required for
+ // the VariablePolicy structure.
+ TotalSize = sizeof( VARIABLE_POLICY_ENTRY );
+ if (Name != NULL) {
+ NameSize = StrnSizeS( Name, MAX_UINT16 );
+ TotalSize += NameSize;
+ }
+ // Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.
+ ASSERT( TotalSize <= MAX_UINT16 );
+ if (TotalSize > MAX_UINT16) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Allocate a buffer to hold all the data. We're on the home stretch.
+ *NewEntry = AllocatePool( TotalSize );
+ if (*NewEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // If we're still here, we're basically done.
+ // Copy the data and GET... OUT....
+ EntPtr = *NewEntry;
+ PopulateCommonData ( EntPtr,
+ Namespace,
+ MinSize,
+ MaxSize,
+ AttributesMustHave,
+ AttributesCantHave,
+ LockPolicyType );
+ EntPtr->Size = (UINT16)TotalSize; // This is safe because we've already checked.
+ EntPtr->OffsetToName = sizeof(VARIABLE_POLICY_ENTRY);
+ if (Name != NULL) {
+ CopyName = (CHAR16*)((UINT8*)EntPtr + EntPtr->OffsetToName);
+ CopyMem( CopyName, Name, NameSize );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This helper function will allocate and populate a new VariablePolicy
+ structure for a policy with a lock type of VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE.
+
+ NOTE: Caller will need to free structure once finished.
+
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+ @param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+ @param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+ @param[out] NewEntry If successful, will be set to a pointer to the allocated buffer containing the
+ new policy.
+
+ @retval EFI_SUCCESS Operation completed successfully and structure is populated.
+ @retval EFI_INVALID_PARAMETER Namespace, VarStateNamespace, VarStateName is NULL.
+ @retval EFI_BUFFER_TOO_SMALL Finished structure would not fit in UINT16 size.
+ @retval EFI_OUT_OF_RESOURCES Could not allocate sufficient space for structure.
+
+**/
+EFI_STATUS
+EFIAPI
+CreateVarStateVariablePolicy (
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN CONST EFI_GUID *VarStateNamespace,
+ IN UINT8 VarStateValue,
+ IN CONST CHAR16 *VarStateName,
+ OUT VARIABLE_POLICY_ENTRY **NewEntry
+ )
+{
+ UINTN TotalSize;
+ UINTN NameSize;
+ UINTN VarStateNameSize;
+ VARIABLE_POLICY_ENTRY *EntPtr;
+ CHAR16 *CopyName;
+ VARIABLE_LOCK_ON_VAR_STATE_POLICY *CopyPolicy;
+
+ // Check some initial invalid parameters for this function.
+ if (Namespace == NULL || VarStateNamespace == NULL ||
+ VarStateName == NULL || NewEntry == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Now we've gotta determine the total size of the buffer required for
+ // the VariablePolicy structure.
+ VarStateNameSize = StrnSizeS( VarStateName, MAX_UINT16 );
+ TotalSize = sizeof( VARIABLE_POLICY_ENTRY ) +
+ sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
+ VarStateNameSize;
+ if (Name != NULL) {
+ NameSize = StrnSizeS( Name, MAX_UINT16 );
+ TotalSize += NameSize;
+ }
+ // Make sure the size fits within a VARIABLE_POLICY_ENTRY.Size.
+ ASSERT( TotalSize <= MAX_UINT16 );
+ if (TotalSize > MAX_UINT16) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // Allocate a buffer to hold all the data. We're on the home stretch.
+ *NewEntry = AllocatePool( TotalSize );
+ if (*NewEntry == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // If we're still here, we're basically done.
+ // Copy the data and GET... OUT....
+ EntPtr = *NewEntry;
+ PopulateCommonData ( EntPtr,
+ Namespace,
+ MinSize,
+ MaxSize,
+ AttributesMustHave,
+ AttributesCantHave,
+ VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE );
+ EntPtr->Size = (UINT16)TotalSize; // This is safe because we've already checked.
+ EntPtr->OffsetToName = sizeof(VARIABLE_POLICY_ENTRY) +
+ sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY) +
+ (UINT16)VarStateNameSize;
+
+ CopyPolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)EntPtr + sizeof(VARIABLE_POLICY_ENTRY));
+ CopyName = (CHAR16*)((UINT8*)CopyPolicy + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY));
+ CopyGuid( &CopyPolicy->Namespace, VarStateNamespace );
+ CopyPolicy->Value = VarStateValue;
+ CopyMem( CopyName, VarStateName, VarStateNameSize );
+
+ if (Name != NULL) {
+ CopyName = (CHAR16*)((UINT8*)EntPtr + EntPtr->OffsetToName);
+ CopyMem( CopyName, Name, NameSize );
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This helper function does everything that CreateBasicVariablePolicy() does, but also
+ uses the passed in protocol to register the policy with the infrastructure.
+ Does not return a buffer, does not require the caller to free anything.
+
+ @param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] LockPolicyType LockPolicyType for the VariablePolicy.
+
+ @retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+ @retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterBasicVariablePolicy (
+ IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN UINT8 LockPolicyType
+ )
+{
+ VARIABLE_POLICY_ENTRY *NewEntry;
+ EFI_STATUS Status;
+
+ // Check the simple things.
+ if (VariablePolicy == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Create the new entry and make sure that everything worked.
+ NewEntry = NULL;
+ Status = CreateBasicVariablePolicy( Namespace,
+ Name,
+ MinSize,
+ MaxSize,
+ AttributesMustHave,
+ AttributesCantHave,
+ LockPolicyType,
+ &NewEntry );
+
+ // If that was successful, attempt to register the new policy.
+ if (!EFI_ERROR( Status )) {
+ Status = VariablePolicy->RegisterVariablePolicy( NewEntry );
+ }
+
+ // If we allocated the buffer, free the buffer.
+ if (NewEntry != NULL) {
+ FreePool( NewEntry );
+ }
+
+ return Status;
+}
+
+
+/**
+ This helper function does everything that CreateBasicVariablePolicy() does, but also
+ uses the passed in protocol to register the policy with the infrastructure.
+ Does not return a buffer, does not require the caller to free anything.
+
+ @param[in] VariablePolicy Pointer to a valid instance of the VariablePolicy protocol.
+ @param[in] Namespace Pointer to an EFI_GUID for the target variable namespace that this policy will protect.
+ @param[in] Name [Optional] If provided, a pointer to the CHAR16 array for the target variable name.
+ Otherwise, will create a policy that targets an entire namespace.
+ @param[in] MinSize MinSize for the VariablePolicy.
+ @param[in] MaxSize MaxSize for the VariablePolicy.
+ @param[in] AttributesMustHave AttributesMustHave for the VariablePolicy.
+ @param[in] AttributesCantHave AttributesCantHave for the VariablePolicy.
+ @param[in] VarStateNamespace Pointer to the EFI_GUID for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Namespace.
+ @param[in] VarStateName Pointer to the CHAR16 array for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Name.
+ @param[in] VarStateValue Value for the VARIABLE_LOCK_ON_VAR_STATE_POLICY.Value.
+
+ @retval EFI_INVALID_PARAMETER VariablePolicy pointer is NULL.
+ @retval EFI_STATUS Status returned by CreateBasicVariablePolicy() or RegisterVariablePolicy().
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterVarStateVariablePolicy (
+ IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy,
+ IN CONST EFI_GUID *Namespace,
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN UINT32 MinSize,
+ IN UINT32 MaxSize,
+ IN UINT32 AttributesMustHave,
+ IN UINT32 AttributesCantHave,
+ IN CONST EFI_GUID *VarStateNamespace,
+ IN CONST CHAR16 *VarStateName,
+ IN UINT8 VarStateValue
+ )
+{
+ VARIABLE_POLICY_ENTRY *NewEntry;
+ EFI_STATUS Status;
+
+ // Check the simple things.
+ if (VariablePolicy == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Create the new entry and make sure that everything worked.
+ NewEntry = NULL;
+ Status = CreateVarStateVariablePolicy( Namespace,
+ Name,
+ MinSize,
+ MaxSize,
+ AttributesMustHave,
+ AttributesCantHave,
+ VarStateNamespace,
+ VarStateValue,
+ VarStateName,
+ &NewEntry );
+
+ // If that was successful, attempt to register the new policy.
+ if (!EFI_ERROR( Status )) {
+ Status = VariablePolicy->RegisterVariablePolicy( NewEntry );
+ }
+
+ // If we allocated the buffer, free the buffer.
+ if (NewEntry != NULL) {
+ FreePool( NewEntry );
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
new file mode 100644
index 00000000000..18f87ed6d80
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
@@ -0,0 +1,35 @@
+## @file VariablePolicyHelperLib.inf
+# This library contains helper functions for marshalling and registering
+# new policies with the VariablePolicy infrastructure.
+#
+# This library is currently written against VariablePolicy revision 0x00010000.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = VariablePolicyHelperLib
+ # MODULE_UNI_FILE = VariablePolicyHelperLib.uni
+ FILE_GUID = B3C2206B-FDD1-4AED-8352-FC5EC34C5630
+ VERSION_STRING = 1.0
+ MODULE_TYPE = BASE
+ LIBRARY_CLASS = VariablePolicyHelperLib
+
+
+[Sources]
+ VariablePolicyHelperLib.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MemoryAllocationLib
+ BaseMemoryLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
new file mode 100644
index 00000000000..39cbf11a4ce
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.uni
@@ -0,0 +1,12 @@
+// /** @file
+// VariablePolicyHelperLib.uni
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Library containing helper functions for marshalling and registering new policies with the VariablePolicy infrastructure"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Library containing helper functions for marshalling and registering new policies with the VariablePolicy infrastructure"
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md
new file mode 100644
index 00000000000..6f176060b9a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/ReadMe.md
@@ -0,0 +1,406 @@
+---
+title: UEFI Variable Policy Whitepaper
+version: 1.0
+copyright: Copyright (c) Microsoft Corporation.
+---
+
+# UEFI Variable Policy
+
+## Summary
+
+UEFI Variable Policy spec aims to describe the DXE protocol interface
+which allows enforcing certain rules on certain UEFI variables. The
+protocol allows communication with the Variable Policy Engine which
+performs the policy enforcement.
+
+The Variable Policy is comprised of a set of policy entries which
+describe, per UEFI variable (identified by namespace GUID and variable
+name) the following rules:
+
+- Required variable attributes
+- Prohibited variable attributes
+- Minimum variable size
+- Maximum variable size
+- Locking:
+ - Locking "immediately"
+ - Locking on creation
+ - Locking based on a state of another variable
+
+The spec assumes that the Variable Policy Engine runs in a trusted
+enclave, potentially off the main CPU that runs UEFI. For that reason,
+it is assumed that the Variable Policy Engine has no concept of UEFI
+events, and that the communication from the DXE driver to the trusted
+enclave is proprietary.
+
+At power-on, the Variable Policy Engine is:
+
+- Enabled -- present policy entries are evaluated on variable access
+ calls.
+- Unlocked -- new policy entries can be registered.
+
+Policy is expected to be clear on power-on. Policy is volatile and not
+preserved across system reset.
+
+## DXE Protocol
+
+```h
+typedef struct {
+ UINT64 Revision;
+ DISABLE_VARIABLE_POLICY DisableVariablePolicy;
+ IS_VARIABLE_POLICY_ENABLED IsVariablePolicyEnabled;
+ REGISTER_VARIABLE_POLICY RegisterVariablePolicy;
+ DUMP_VARIABLE_POLICY DumpVariablePolicy;
+ LOCK_VARIABLE_POLICY LockVariablePolicy;
+} _VARIABLE_POLICY_PROTOCOL;
+
+typedef _VARIABLE_POLICY_PROTOCOL VARIABLE_POLICY_PROTOCOL;
+
+extern EFI_GUID gVariablePolicyProtocolGuid;
+```
+
+```text
+## Include/Protocol/VariablePolicy.h
+ gVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
+```
+
+### DisableVariablePolicy
+
+Function prototype:
+
+```c
+EFI_STATUS
+EFIAPI
+DisableVariablePolicy (
+ VOID
+ );
+```
+
+`DisableVariablePolicy` call disables the Variable Policy Engine, so
+that the present policy entries are no longer taken into account on
+variable access calls. This call effectively turns off the variable
+policy verification for this boot. This also disables UEFI
+Authenticated Variable protections including Secure Boot.
+`DisableVariablePolicy` can only be called once during boot. If called
+more than once, it will return `EFI_ALREADY_STARTED`. Note, this process
+is irreversible until the next system reset -- there is no
+"EnablePolicy" protocol function.
+
+_IMPORTANT NOTE:_ It is strongly recommended that VariablePolicy *NEVER*
+be disabled in "normal, production boot conditions". It is expected to always
+be enforced. The most likely reasons to disable are for Manufacturing and
+Refurbishing scenarios. If in doubt, leave the `gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable`
+PCD set to `FALSE` and VariablePolicy will always be enabled.
+
+### IsVariablePolicyEnabled
+
+Function prototype:
+
+```c
+EFI_STATUS
+EFIAPI
+IsVariablePolicyEnabled (
+ OUT BOOLEAN *State
+ );
+```
+
+`IsVariablePolicyEnabled` accepts a pointer to a Boolean in which it
+will store `TRUE` if Variable Policy Engine is enabled, or `FALSE` if
+Variable Policy Engine is disabled. The function returns `EFI_SUCCESS`.
+
+### RegisterVariablePolicy
+
+Function prototype:
+
+```c
+EFI_STATUS
+EFIAPI
+RegisterVariablePolicy (
+ IN CONST VARIABLE_POLICY_ENTRY *PolicyEntry
+ );
+```
+
+`RegisterVariablePolicy` call accepts a pointer to a policy entry
+structure and returns the status of policy registration. If the
+Variable Policy Engine is not locked and the policy structures are
+valid, the function will return `EFI_SUCCESS`. If the Variable Policy
+Engine is locked, `RegisterVariablePolicy` call will return
+`EFI_WRITE_PROTECTED` and will not register the policy entry. Bulk
+registration is not supported at this time due to the requirements
+around error handling on each policy registration.
+
+Upon successful registration of a policy entry, Variable Policy Engine
+will then evaluate this entry on subsequent variable access calls (as
+long as Variable Policy Engine hasn't been disabled).
+
+### DumpVariablePolicy
+
+Function prototype:
+
+```c
+EFI_STATUS
+EFIAPI
+DumpVariablePolicy (
+ OUT UINT8 *Policy,
+ IN OUT UINT32 *Size
+ );
+```
+
+`DumpVariablePolicy` call accepts a pointer to a buffer and a pointer to
+the size of the buffer as parameters and returns the status of placing
+the policy into the buffer. On first call to `DumpVariablePolicy` one
+should pass `NULL` as the buffer and a pointer to 0 as the `Size` variable
+and `DumpVariablePolicy` will return `EFI_BUFFER_TOO_SMALL` and will
+populate the `Size` parameter with the size of the needed buffer to
+store the policy. This way, the caller can allocate the buffer of
+correct size and call `DumpVariablePolicy` again. The function will
+populate the buffer with policy and return `EFI_SUCCESS`.
+
+### LockVariablePolicy
+
+Function prototype:
+
+```c
+EFI_STATUS
+EFIAPI
+LockVariablePolicy (
+ VOID
+ );
+```
+
+`LockVariablePolicy` locks the Variable Policy Engine, i.e. prevents any
+new policy entries from getting registered in this boot
+(`RegisterVariablePolicy` calls will fail with `EFI_WRITE_PROTECTED`
+status code returned).
+
+## Policy Structure
+
+The structure below is meant for the DXE protocol calling interface,
+when communicating to the Variable Policy Engine, thus the pragma pack
+directive. How these policies are stored in memory is up to the
+implementation.
+
+```c
+#pragma pack(1)
+typedef struct {
+ UINT32 Version;
+ UINT16 Size;
+ UINT16 OffsetToName;
+ EFI_GUID Namespace;
+ UINT32 MinSize;
+ UINT32 MaxSize;
+ UINT32 AttributesMustHave;
+ UINT32 AttributesCantHave;
+ UINT8 LockPolicyType;
+ UINT8 Reserved[3];
+ // UINT8 LockPolicy[]; // Variable Length Field
+ // CHAR16 Name[]; // Variable Length Field
+} VARIABLE_POLICY_ENTRY;
+```
+
+The struct `VARIABLE_POLICY_ENTRY` above describes the layout for a policy
+entry. The first element, `Size`, is the size of the policy entry, then
+followed by `OffsetToName` -- the number of bytes from the beginning of
+the struct to the name of the UEFI variable targeted by the policy
+entry. The name can contain wildcards to match more than one variable,
+more on this in the Wildcards section. The rest of the struct elements
+are self-explanatory.
+
+```cpp
+#define VARIABLE_POLICY_TYPE_NO_LOCK 0
+#define VARIABLE_POLICY_TYPE_LOCK_NOW 1
+#define VARIABLE_POLICY_TYPE_LOCK_ON_CREATE 2
+#define VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE 3
+```
+
+`LockPolicyType` can have the following values:
+
+- `VARIABLE_POLICY_TYPE_NO_LOCK` -- means that no variable locking is performed. However,
+ the attribute and size constraints are still enforced. LockPolicy
+ field is size 0.
+- `VARIABLE_POLICY_TYPE_LOCK_NOW` -- means that the variable starts being locked
+ immediately after policy entry registration. If the variable doesn't
+ exist at this point, being LockedNow means it cannot be created on
+ this boot. LockPolicy field is size 0.
+- `VARIABLE_POLICY_TYPE_LOCK_ON_CREATE` -- means that the variable starts being locked
+ after it is created. This allows for variable creation and
+ protection after LockVariablePolicy() function has been called. The
+ LockPolicy field is size 0.
+- `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE` -- means that the Variable Policy Engine will
+ examine the state/contents of another variable to determine if the
+ variable referenced in the policy entry is locked.
+
+```c
+typedef struct {
+ EFI_GUID Namespace;
+ UINT8 Value;
+ UINT8 Reserved;
+ // CHAR16 Name[]; // Variable Length Field
+} VARIABLE_LOCK_ON_VAR_STATE_POLICY;
+```
+
+If `LockPolicyType` is `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE`, then the final element in the
+policy entry struct is of type `VARIABLE_LOCK_ON_VAR_STATE_POLICY`, which
+lists the namespace GUID, name (no wildcards here), and value of the
+variable which state determines the locking of the variable referenced
+in the policy entry. The "locking" variable must be 1 byte in terms of
+payload size. If the Referenced variable contents match the Value of the
+`VARIABLE_LOCK_ON_VAR_STATE_POLICY` structure, the lock will be considered
+active and the target variable will be locked. If the Reference variable
+does not exist (ie. returns `EFI_NOT_FOUND`), this policy will be
+considered inactive.
+
+## Variable Name Wildcards
+
+Two types of wildcards can be used in the UEFI variable name field in a
+policy entry:
+
+1. If the Name is a zero-length array (easily checked by comparing
+ fields `Size` and `OffsetToName` -- if they're the same, then the
+ `Name` is zero-length), then all variables in the namespace specified
+ by the provided GUID are targeted by the policy entry.
+2. Character "#" in the `Name` corresponds to one numeric character
+ (0-9, A-F, a-f). For example, string "Boot####" in the `Name`
+ field of the policy entry will make it so that the policy entry will
+ target variables named "Boot0001", "Boot0002", etc.
+
+Given the above two types of wildcards, one variable can be targeted by
+more than one policy entry, thus there is a need to establish the
+precedence rule: a more specific match is applied. When a variable
+access operation is performed, Variable Policy Engine should first check
+the variable being accessed against the policy entries without
+wildcards, then with 1 wildcard, then with 2 wildcards, etc., followed
+in the end by policy entries that match the whole namespace. One can
+still imagine a situation where two policy entries with the same number
+of wildcards match the same variable -- for example, policy entries with
+Names "Boot00##" and "Boot##01" will both match variable "Boot0001".
+Such situation can (and should) be avoided by designing mutually
+exclusive Name strings with wildcards, however, if it occurs, then the
+policy entry that was registered first will be used. After the most
+specific match is selected, all other policies are ignored.
+
+## Available Testing
+
+This functionality is current supported by two kinds of tests: there is a host-based
+unit test for the core business logic (this test accompanies the `VariablePolicyLib`
+implementation that lives in `MdeModulePkg/Library`) and there is a functional test
+for the protocol and its interfaces (this test lives in the `MdeModulePkg/Test/ShellTest`
+directory).
+
+### Host-Based Unit Test
+
+There is a test that can be run as part of the Host-Based Unit Testing
+infrastructure provided by EDK2 PyTools (documented elsewhere). It will test
+all internal guarantees and is where you will find test cases for most of the
+policy matching and security of the Variable Policy Engine.
+
+### Shell-Based Functional Test
+
+This test -- [Variable Policy Functional Unit Test](https://github.com/microsoft/mu_plus/tree/release/202005/UefiTestingPkg/FunctionalSystemTests/VarPolicyUnitTestApp) -- can be built as a
+UEFI Shell application and run to validate that the Variable Policy Engine
+is correctly installed and enforcing policies on the target system.
+
+NOTE: This test _must_ be run prior to calling `DisableVariablePolicy` for all
+test cases to pass. For this reason, it is recommended to run this on a test-built
+FW for complete results, and then again on a production-built FW for release
+results.
+
+## Use Cases
+
+The below examples are hypothetical scenarios based on real-world requirements
+that demonstrate how Variable Policies could be constructed to solve various
+problems.
+
+### UEFI Setup Variables (Example 1)
+
+Variables containing values of the setup options exposed via UEFI
+menu (setup variables). These would be locked based on a state of
+another variable, "ReadyToBoot", which would be set to 1 at the
+ReadyToBoot event. Thus, the policy for the setup variables would be
+of type `LockOnVarState`, with the "ReadyToBoot" listed as the name of
+the variable, appropriate GUID listed as the namespace, and 1 as
+value. Entry into the trusted UEFI menu app doesn't signal
+ReadyToBoot, but booting to any device does, and the setup variables
+are write-protected. The "ReadyToBoot" variable would need to be
+locked-on-create. *(THIS IS ESSENTIALLY LOCK ON EVENT, BUT SINCE THE
+POLICY ENGINE IS NOT IN THE UEFI ENVIRONMENT VARIABLES ARE USED)*
+
+For example, "AllowPXEBoot" variable locked by "ReadyToBoot" variable.
+
+(NOTE: In the below example, the emphasized fields ('Namespace', 'Value', and 'Name')
+are members of the `VARIABLE_LOCK_ON_VAR_STATE_POLICY` structure.)
+
+Size | ...
+---- | ---
+OffsetToName | ...
+NameSpace | ...
+MinSize | ...
+MaxSize | ...
+AttributesMustHave | ...
+AttributesCantHave | ...
+LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE`
+_Namespace_ | ...
+_Value_ | 1
+_Name_ | "ReadyToBoot"
+//Name | "AllowPXEBoot"
+
+### Manufacturing VPD (Example 2)
+
+Manufacturing Variable Provisioning Data (VPD) is stored in
+variables and is created while in Manufacturing (MFG) Mode. In MFG
+Mode Variable Policy Engine is disabled, thus these VPD variables
+can be created. These variables are locked with lock policy type
+`LockNow`, so that these variables can't be tampered with in Customer
+Mode. To overwrite or clear VPD, the device would need to MFG mode,
+which is standard practice for refurbishing/remanufacturing
+scenarios.
+
+Example: "DisplayPanelCalibration" variable...
+
+Size | ...
+---- | ---
+OffsetToName | ...
+NameSpace | ...
+MinSize | ...
+MaxSize | ...
+AttributesMustHave | ...
+AttributesCantHave | ...
+LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_NOW`
+// Name | "DisplayPanelCalibration"
+
+### 3rd Party Calibration Data (Example 3)
+
+Bluetooth pre-pairing variables are locked-on-create because these
+get created by an OS application when Variable Policy is in effect.
+
+Example: "KeyboardBTPairing" variable
+
+Size | ...
+---- | ---
+OffsetToName | ...
+NameSpace | ...
+MinSize | ...
+MaxSize | ...
+AttributesMustHave | ...
+AttributesCantHave | ...
+LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_ON_CREATE`
+// Name | "KeyboardBTPairing"
+
+### Software-based Variable Policy (Example 4)
+
+Example: "Boot####" variables (a name string with wildcards that
+will match variables "Boot0000" to "BootFFFF") locked by "LockBootOrder"
+variable.
+
+Size | ...
+---- | ---
+OffsetToName | ...
+NameSpace | ...
+MinSize | ...
+MaxSize | ...
+AttributesMustHave | ...
+AttributesCantHave | ...
+LockPolicyType | `VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE`
+_Namespace_ | ...
+_Value_ | 1
+_Name_ | "LockBootOrder"
+//Name | "Boot####"
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
new file mode 100644
index 00000000000..3200a842c1b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitNull.c
@@ -0,0 +1,46 @@
+/** @file -- VariablePolicyExtraInitNull.c
+This file contains extra init and deinit routines that don't do anything
+extra.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+
+/**
+ An extra init hook that enables the RuntimeDxe library instance to
+ register VirtualAddress change callbacks. Among other things.
+
+ @retval EFI_SUCCESS Everything is good. Continue with init.
+ @retval Others Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraInit (
+ VOID
+ )
+{
+ // NULL implementation.
+ return EFI_SUCCESS;
+}
+
+
+/**
+ An extra deinit hook that enables the RuntimeDxe library instance to
+ register VirtualAddress change callbacks. Among other things.
+
+ @retval EFI_SUCCESS Everything is good. Continue with deinit.
+ @retval Others Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraDeinit (
+ VOID
+ )
+{
+ // NULL implementation.
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
new file mode 100644
index 00000000000..c69a776efcf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyExtraInitRuntimeDxe.c
@@ -0,0 +1,85 @@
+/** @file -- VariablePolicyExtraInitRuntimeDxe.c
+This file contains extra init and deinit routines that register and unregister
+VariableAddressChange callbacks.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+extern EFI_GET_VARIABLE mGetVariableHelper;
+extern UINT8 *mPolicyTable;
+STATIC BOOLEAN mIsVirtualAddrConverted;
+STATIC EFI_EVENT mVariablePolicyLibVirtualAddressChangeEvent = NULL;
+
+/**
+ For the RuntimeDxe version of this lib, convert internal pointer addresses to virtual addresses.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context, which
+ is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+VariablePolicyLibVirtualAddressCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRT->ConvertPointer (0, (VOID **)&mPolicyTable);
+ gRT->ConvertPointer (0, (VOID **)&mGetVariableHelper);
+ mIsVirtualAddrConverted = TRUE;
+}
+
+
+/**
+ An extra init hook that enables the RuntimeDxe library instance to
+ register VirtualAddress change callbacks. Among other things.
+
+ @retval EFI_SUCCESS Everything is good. Continue with init.
+ @retval Others Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraInit (
+ VOID
+ )
+{
+ return gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ VariablePolicyLibVirtualAddressCallback,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mVariablePolicyLibVirtualAddressChangeEvent);
+}
+
+
+/**
+ An extra deinit hook that enables the RuntimeDxe library instance to
+ register VirtualAddress change callbacks. Among other things.
+
+ @retval EFI_SUCCESS Everything is good. Continue with deinit.
+ @retval Others Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraDeinit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ if (mIsVirtualAddrConverted) {
+ Status = gBS->CloseEvent (mVariablePolicyLibVirtualAddressChangeEvent);
+ }
+ else {
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
new file mode 100644
index 00000000000..702513fe56a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.c
@@ -0,0 +1,830 @@
+/** @file -- VariablePolicyLib.c
+Business logic for Variable Policy enforcement.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Library/SafeIntLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+
+// IMPORTANT NOTE: This library is currently rife with multiple return statements
+// for error handling. A refactor should remove these at some point.
+
+//
+// This library was designed with advanced unit-test features.
+// This define handles the configuration.
+#ifdef INTERNAL_UNIT_TEST
+#undef STATIC
+#define STATIC // Nothing...
+#endif
+
+// An abstracted GetVariable interface that enables configuration regardless of the environment.
+EFI_GET_VARIABLE mGetVariableHelper = NULL;
+
+// Master switch to lock this entire interface. Does not stop enforcement,
+// just prevents the configuration from being changed for the rest of the boot.
+STATIC BOOLEAN mInterfaceLocked = FALSE;
+
+// Master switch to disable the entire interface for a single boot.
+// This will disable all policy enforcement for the duration of the boot.
+STATIC BOOLEAN mProtectionDisabled = FALSE;
+
+// Table to hold all the current policies.
+UINT8 *mPolicyTable = NULL;
+STATIC UINT32 mCurrentTableSize = 0;
+STATIC UINT32 mCurrentTableUsage = 0;
+STATIC UINT32 mCurrentTableCount = 0;
+
+#define POLICY_TABLE_STEP_SIZE 0x1000
+
+// NOTE: DO NOT USE THESE MACROS on any structure that has not been validated.
+// Current table data has already been sanitized.
+#define GET_NEXT_POLICY(CurPolicy) (VARIABLE_POLICY_ENTRY*)((UINT8*)CurPolicy + CurPolicy->Size)
+#define GET_POLICY_NAME(CurPolicy) (CHAR16*)((UINTN)CurPolicy + CurPolicy->OffsetToName)
+
+#define MATCH_PRIORITY_EXACT 0
+#define MATCH_PRIORITY_MAX MATCH_PRIORITY_EXACT
+#define MATCH_PRIORITY_MIN MAX_UINT8
+
+
+/**
+ An extra init hook that enables the RuntimeDxe library instance to
+ register VirtualAddress change callbacks. Among other things.
+
+ @retval EFI_SUCCESS Everything is good. Continue with init.
+ @retval Others Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraInit (
+ VOID
+ );
+
+/**
+ An extra deinit hook that enables the RuntimeDxe library instance to
+ register VirtualAddress change callbacks. Among other things.
+
+ @retval EFI_SUCCESS Everything is good. Continue with deinit.
+ @retval Others Uh... don't continue.
+
+**/
+EFI_STATUS
+VariablePolicyExtraDeinit (
+ VOID
+ );
+
+
+/**
+ This helper function determines whether the structure of an incoming policy
+ is valid and internally consistent.
+
+ @param[in] NewPolicy Pointer to the incoming policy structure.
+
+ @retval TRUE
+ @retval FALSE Pointer is NULL, size is wrong, strings are empty, or
+ substructures overlap.
+
+**/
+STATIC
+BOOLEAN
+IsValidVariablePolicyStructure (
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy
+ )
+{
+ EFI_STATUS Status;
+ UINTN EntryEnd;
+ CHAR16 *CheckChar;
+ UINTN WildcardCount;
+
+ // Sanitize some quick values.
+ if (NewPolicy == NULL || NewPolicy->Size == 0 ||
+ // Structure size should be at least as long as the minumum structure and a NULL string.
+ NewPolicy->Size < sizeof(VARIABLE_POLICY_ENTRY) ||
+ // Check for the known revision.
+ NewPolicy->Version != VARIABLE_POLICY_ENTRY_REVISION) {
+ return FALSE;
+ }
+
+ // Calculate the theoretical end of the structure and make sure
+ // that the structure can fit in memory.
+ Status = SafeUintnAdd( (UINTN)NewPolicy, NewPolicy->Size, &EntryEnd );
+ if (EFI_ERROR( Status )) {
+ return FALSE;
+ }
+
+ // Check for a valid Max Size.
+ if (NewPolicy->MaxSize == 0) {
+ return FALSE;
+ }
+
+ // Check for the valid list of lock policies.
+ if (NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_NO_LOCK &&
+ NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_NOW &&
+ NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_CREATE &&
+ NewPolicy->LockPolicyType != VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE)
+ {
+ return FALSE;
+ }
+
+ // If the policy type is VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE, make sure that the matching state variable Name
+ // terminates before the OffsetToName for the matching policy variable Name.
+ if (NewPolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
+ // Adjust CheckChar to the offset of the LockPolicy->Name.
+ Status = SafeUintnAdd( (UINTN)NewPolicy + sizeof(VARIABLE_POLICY_ENTRY),
+ sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY),
+ (UINTN*)&CheckChar );
+ if (EFI_ERROR( Status ) || EntryEnd <= (UINTN)CheckChar) {
+ return FALSE;
+ }
+ while (*CheckChar != CHAR_NULL) {
+ if (EntryEnd <= (UINTN)CheckChar) {
+ return FALSE;
+ }
+ CheckChar++;
+ }
+ // At this point we should have either exeeded the structure or be pointing at the last char in LockPolicy->Name.
+ // We should check to make sure that the policy Name comes immediately after this charcter.
+ if ((UINTN)++CheckChar != (UINTN)NewPolicy + NewPolicy->OffsetToName) {
+ return FALSE;
+ }
+ // If the policy type is any other value, make sure that the LockPolicy structure has a zero length.
+ } else {
+ if (NewPolicy->OffsetToName != sizeof(VARIABLE_POLICY_ENTRY)) {
+ return FALSE;
+ }
+ }
+
+ // Check to make sure that the name has a terminating character
+ // before the end of the structure.
+ // We've already checked that the name is within the bounds of the structure.
+ if (NewPolicy->Size != NewPolicy->OffsetToName) {
+ CheckChar = (CHAR16*)((UINTN)NewPolicy + NewPolicy->OffsetToName);
+ WildcardCount = 0;
+ while (*CheckChar != CHAR_NULL) {
+ // Make sure there aren't excessive wildcards.
+ if (*CheckChar == '#') {
+ WildcardCount++;
+ if (WildcardCount > MATCH_PRIORITY_MIN) {
+ return FALSE;
+ }
+ }
+ // Make sure you're still within the bounds of the policy structure.
+ if (EntryEnd <= (UINTN)CheckChar) {
+ return FALSE;
+ }
+ CheckChar++;
+ }
+
+ // Finally, we should be pointed at the very last character in Name, so we should be right
+ // up against the end of the structure.
+ if ((UINTN)++CheckChar != EntryEnd) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ This helper function evaluates a policy and determines whether it matches the target
+ variable. If matched, will also return a value corresponding to the priority of the match.
+
+ The rules for "best match" are listed in the Variable Policy Spec.
+ Perfect name matches will return 0.
+ Single wildcard characters will return the number of wildcard characters.
+ Full namespaces will return MAX_UINT8.
+
+ @param[in] EvalEntry Pointer to the policy entry being evaluated.
+ @param[in] VariableName Same as EFI_SET_VARIABLE.
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.
+ @param[out] MatchPriority [Optional] On finding a match, this value contains the priority of the match.
+ Lower number == higher priority. Only valid if a match found.
+
+ @retval TRUE Current entry matches the target variable.
+ @retval FALSE Current entry does not match at all.
+
+**/
+STATIC
+BOOLEAN
+EvaluatePolicyMatch (
+ IN CONST VARIABLE_POLICY_ENTRY *EvalEntry,
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ OUT UINT8 *MatchPriority OPTIONAL
+ )
+{
+ BOOLEAN Result;
+ CHAR16 *PolicyName;
+ UINT8 CalculatedPriority;
+ UINTN Index;
+
+ Result = FALSE;
+ CalculatedPriority = MATCH_PRIORITY_EXACT;
+
+ // Step 1: If the GUID doesn't match, we're done. No need to evaluate anything else.
+ if (!CompareGuid( &EvalEntry->Namespace, VendorGuid )) {
+ goto Exit;
+ }
+
+ // If the GUID matches, check to see whether there is a Name associated
+ // with the policy. If not, this policy matches the entire namespace.
+ // Missing Name is indicated by size being equal to name.
+ if (EvalEntry->Size == EvalEntry->OffsetToName) {
+ CalculatedPriority = MATCH_PRIORITY_MIN;
+ Result = TRUE;
+ goto Exit;
+ }
+
+ // Now that we know the name exists, get it.
+ PolicyName = GET_POLICY_NAME( EvalEntry );
+
+ // Evaluate the name against the policy name and check for a match.
+ // Account for any wildcards.
+ Index = 0;
+ Result = TRUE;
+ // Keep going until the end of both strings.
+ while (PolicyName[Index] != CHAR_NULL || VariableName[Index] != CHAR_NULL) {
+ // If we don't have a match...
+ if (PolicyName[Index] != VariableName[Index] || PolicyName[Index] == '#') {
+ // If this is a numerical wildcard, we can consider
+ // it a match if we alter the priority.
+ if (PolicyName[Index] == L'#' &&
+ ((L'0' <= VariableName[Index] && VariableName[Index] <= L'9') ||
+ (L'A' <= VariableName[Index] && VariableName[Index] <= L'F') ||
+ (L'a' <= VariableName[Index] && VariableName[Index] <= L'f'))) {
+ if (CalculatedPriority < MATCH_PRIORITY_MIN) {
+ CalculatedPriority++;
+ }
+ // Otherwise, not a match.
+ } else {
+ Result = FALSE;
+ goto Exit;
+ }
+ }
+ Index++;
+ }
+
+Exit:
+ if (Result && MatchPriority != NULL) {
+ *MatchPriority = CalculatedPriority;
+ }
+ return Result;
+}
+
+
+/**
+ This helper function walks the current policy table and returns a pointer
+ to the best match, if any are found. Leverages EvaluatePolicyMatch() to
+ determine "best".
+
+ @param[in] VariableName Same as EFI_SET_VARIABLE.
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.
+ @param[out] ReturnPriority [Optional] If pointer is provided, return the
+ priority of the match. Same as EvaluatePolicyMatch().
+ Only valid if a match is returned.
+
+ @retval VARIABLE_POLICY_ENTRY* Best match that was found.
+ @retval NULL No match was found.
+
+**/
+STATIC
+VARIABLE_POLICY_ENTRY*
+GetBestPolicyMatch (
+ IN CONST CHAR16 *VariableName,
+ IN CONST EFI_GUID *VendorGuid,
+ OUT UINT8 *ReturnPriority OPTIONAL
+ )
+{
+ VARIABLE_POLICY_ENTRY *BestResult;
+ VARIABLE_POLICY_ENTRY *CurrentEntry;
+ UINT8 MatchPriority;
+ UINT8 CurrentPriority;
+ UINTN Index;
+
+ BestResult = NULL;
+ MatchPriority = MATCH_PRIORITY_EXACT;
+
+ // Walk all entries in the table, looking for matches.
+ CurrentEntry = (VARIABLE_POLICY_ENTRY*)mPolicyTable;
+ for (Index = 0; Index < mCurrentTableCount; Index++) {
+ // Check for a match.
+ if (EvaluatePolicyMatch( CurrentEntry, VariableName, VendorGuid, &CurrentPriority )) {
+ // If match is better, take it.
+ if (BestResult == NULL || CurrentPriority < MatchPriority) {
+ BestResult = CurrentEntry;
+ MatchPriority = CurrentPriority;
+ }
+
+ // If you've hit the highest-priority match, can exit now.
+ if (MatchPriority == 0) {
+ break;
+ }
+ }
+
+ // If we're still in the loop, move to the next entry.
+ CurrentEntry = GET_NEXT_POLICY( CurrentEntry );
+ }
+
+ // If a return priority was requested, return it.
+ if (ReturnPriority != NULL) {
+ *ReturnPriority = MatchPriority;
+ }
+
+ return BestResult;
+}
+
+
+/**
+ This API function validates and registers a new policy with
+ the policy enforcement engine.
+
+ @param[in] NewPolicy Pointer to the incoming policy structure.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally inconsistent.
+ @retval EFI_ALREADY_STARTED An identical matching policy already exists.
+ @retval EFI_WRITE_PROTECTED The interface has been locked until the next reboot.
+ @retval EFI_UNSUPPORTED Policy enforcement has been disabled. No reason to add more policies.
+ @retval EFI_ABORTED A calculation error has prevented this function from completing.
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any more policies.
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+RegisterVariablePolicy (
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *MatchPolicy;
+ UINT8 MatchPriority;
+ UINT32 NewSize;
+ UINT8 *NewTable;
+
+ if (!IsVariablePolicyLibInitialized()) {
+ return EFI_NOT_READY;
+ }
+ if (mInterfaceLocked) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ if (!IsValidVariablePolicyStructure( NewPolicy )) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check to see whether an exact matching policy already exists.
+ MatchPolicy = GetBestPolicyMatch( GET_POLICY_NAME( NewPolicy ),
+ &NewPolicy->Namespace,
+ &MatchPriority );
+ if (MatchPolicy != NULL && MatchPriority == MATCH_PRIORITY_EXACT) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ // If none exists, create it.
+ // If we need more space, allocate that now.
+ Status = SafeUint32Add( mCurrentTableUsage, NewPolicy->Size, &NewSize );
+ if (EFI_ERROR( Status )) {
+ return EFI_ABORTED;
+ }
+ if (NewSize > mCurrentTableSize) {
+ // Use NewSize to calculate the new table size in units of POLICY_TABLE_STEP_SIZE.
+ NewSize = (NewSize % POLICY_TABLE_STEP_SIZE) > 0 ?
+ (NewSize / POLICY_TABLE_STEP_SIZE) + 1 :
+ (NewSize / POLICY_TABLE_STEP_SIZE);
+ // Calculate the new table size in absolute bytes.
+ Status = SafeUint32Mult( NewSize, POLICY_TABLE_STEP_SIZE, &NewSize );
+ if (EFI_ERROR( Status )) {
+ return EFI_ABORTED;
+ }
+
+ // Reallocate and copy the table.
+ NewTable = AllocateRuntimePool( NewSize );
+ if (NewTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem( NewTable, mPolicyTable, mCurrentTableUsage );
+ mCurrentTableSize = NewSize;
+ if (mPolicyTable != NULL) {
+ FreePool( mPolicyTable );
+ }
+ mPolicyTable = NewTable;
+ }
+ // Copy the policy into the table.
+ CopyMem( mPolicyTable + mCurrentTableUsage, NewPolicy, NewPolicy->Size );
+ mCurrentTableUsage += NewPolicy->Size;
+ mCurrentTableCount += 1;
+
+ // We're done here.
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This API function checks to see whether the parameters to SetVariable would
+ be allowed according to the current variable policies.
+
+ @param[in] VariableName Same as EFI_SET_VARIABLE.
+ @param[in] VendorGuid Same as EFI_SET_VARIABLE.
+ @param[in] Attributes Same as EFI_SET_VARIABLE.
+ @param[in] DataSize Same as EFI_SET_VARIABLE.
+ @param[in] Data Same as EFI_SET_VARIABLE.
+
+ @retval EFI_SUCCESS A matching policy allows this update.
+ @retval EFI_SUCCESS There are currently no policies that restrict this update.
+ @retval EFI_SUCCESS The protections have been disable until the next reboot.
+ @retval EFI_WRITE_PROTECTED Variable is currently locked.
+ @retval EFI_INVALID_PARAMETER Attributes or size are invalid.
+ @retval EFI_ABORTED A lock policy exists, but an error prevented evaluation.
+ @retval EFI_NOT_READY Library has not been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+ValidateSetVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN UINT32 Attributes,
+ IN UINTN DataSize,
+ IN VOID *Data
+ )
+{
+ BOOLEAN IsDel;
+ VARIABLE_POLICY_ENTRY *ActivePolicy;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ VARIABLE_LOCK_ON_VAR_STATE_POLICY *StateVarPolicy;
+ CHAR16 *StateVarName;
+ UINTN StateVarSize;
+ UINT8 StateVar;
+
+ ReturnStatus = EFI_SUCCESS;
+
+ if (!IsVariablePolicyLibInitialized()) {
+ ReturnStatus = EFI_NOT_READY;
+ goto Exit;
+ }
+
+ // Bail if the protections are currently disabled.
+ if (mProtectionDisabled) {
+ ReturnStatus = EFI_SUCCESS;
+ goto Exit;
+ }
+
+ // Determine whether this is a delete operation.
+ // If so, it will affect which tests are applied.
+ if ((DataSize == 0) && ((Attributes & EFI_VARIABLE_APPEND_WRITE) == 0)) {
+ IsDel = TRUE;
+ } else {
+ IsDel = FALSE;
+ }
+
+ // Find an active policy if one exists.
+ ActivePolicy = GetBestPolicyMatch( VariableName, VendorGuid, NULL );
+
+ // If we have an active policy, check it against the incoming data.
+ if (ActivePolicy != NULL) {
+ //
+ // Only enforce size and attribute constraints when updating data, not deleting.
+ if (!IsDel) {
+ // Check for size constraints.
+ if ((ActivePolicy->MinSize > 0 && DataSize < ActivePolicy->MinSize) ||
+ (ActivePolicy->MaxSize > 0 && DataSize > ActivePolicy->MaxSize)) {
+ ReturnStatus = EFI_INVALID_PARAMETER;
+ DEBUG(( DEBUG_VERBOSE, "%a - Bad Size. 0x%X <> 0x%X-0x%X\n", __FUNCTION__,
+ DataSize, ActivePolicy->MinSize, ActivePolicy->MaxSize ));
+ goto Exit;
+ }
+
+ // Check for attribute constraints.
+ if ((ActivePolicy->AttributesMustHave & Attributes) != ActivePolicy->AttributesMustHave ||
+ (ActivePolicy->AttributesCantHave & Attributes) != 0) {
+ ReturnStatus = EFI_INVALID_PARAMETER;
+ DEBUG(( DEBUG_VERBOSE, "%a - Bad Attributes. 0x%X <> 0x%X:0x%X\n", __FUNCTION__,
+ Attributes, ActivePolicy->AttributesMustHave, ActivePolicy->AttributesCantHave ));
+ goto Exit;
+ }
+ }
+
+ //
+ // Lock policy check.
+ //
+ // Check for immediate lock.
+ if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_NOW) {
+ ReturnStatus = EFI_WRITE_PROTECTED;
+ goto Exit;
+ // Check for lock on create.
+ } else if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_ON_CREATE) {
+ StateVarSize = 0;
+ Status = mGetVariableHelper( VariableName,
+ VendorGuid,
+ NULL,
+ &StateVarSize,
+ NULL );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ ReturnStatus = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+ // Check for lock on state variable.
+ } else if (ActivePolicy->LockPolicyType == VARIABLE_POLICY_TYPE_LOCK_ON_VAR_STATE) {
+ StateVarPolicy = (VARIABLE_LOCK_ON_VAR_STATE_POLICY*)((UINT8*)ActivePolicy + sizeof(VARIABLE_POLICY_ENTRY));
+ StateVarName = (CHAR16*)((UINT8*)StateVarPolicy + sizeof(VARIABLE_LOCK_ON_VAR_STATE_POLICY));
+ StateVarSize = sizeof(StateVar);
+ Status = mGetVariableHelper( StateVarName,
+ &StateVarPolicy->Namespace,
+ NULL,
+ &StateVarSize,
+ &StateVar );
+
+ // If the variable was found, check the state. If matched, this variable is locked.
+ if (!EFI_ERROR( Status )) {
+ if (StateVar == StateVarPolicy->Value) {
+ ReturnStatus = EFI_WRITE_PROTECTED;
+ goto Exit;
+ }
+ // EFI_NOT_FOUND and EFI_BUFFER_TOO_SMALL indicate that the state doesn't match.
+ } else if (Status != EFI_NOT_FOUND && Status != EFI_BUFFER_TOO_SMALL) {
+ // We don't know what happened, but it isn't good.
+ ReturnStatus = EFI_ABORTED;
+ goto Exit;
+ }
+ }
+ }
+
+Exit:
+ DEBUG(( DEBUG_VERBOSE, "%a - Variable (%g:%s) returning %r.\n", __FUNCTION__, VendorGuid, VariableName, ReturnStatus ));
+ return ReturnStatus;
+}
+
+
+/**
+ This API function disables the variable policy enforcement. If it's
+ already been called once, will return EFI_ALREADY_STARTED.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Has already been called once this boot.
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot.
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platform PCD.
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+DisableVariablePolicy (
+ VOID
+ )
+{
+ if (!IsVariablePolicyLibInitialized()) {
+ return EFI_NOT_READY;
+ }
+ if (mProtectionDisabled) {
+ return EFI_ALREADY_STARTED;
+ }
+ if (mInterfaceLocked) {
+ return EFI_WRITE_PROTECTED;
+ }
+ if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
+ return EFI_WRITE_PROTECTED;
+ }
+ mProtectionDisabled = TRUE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This API function will dump the entire contents of the variable policy table.
+
+ Similar to GetVariable, the first call can be made with a 0 size and it will return
+ the size of the buffer required to hold the entire table.
+
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Size is 0.
+ @param[in,out] Size On input, the size of the output buffer. On output, the size
+ of the data returned.
+
+ @retval EFI_SUCCESS Policy data is in the output buffer and Size has been updated.
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero and Policy is NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy. Size updated with required size.
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+DumpVariablePolicy (
+ OUT UINT8 *Policy,
+ IN OUT UINT32 *Size
+ )
+{
+ if (!IsVariablePolicyLibInitialized()) {
+ return EFI_NOT_READY;
+ }
+
+ // Check the parameters.
+ if (Size == NULL || (*Size > 0 && Policy == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Make sure the size is sufficient to hold the policy table.
+ if (*Size < mCurrentTableUsage) {
+ *Size = mCurrentTableUsage;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ // If we're still here, copy the table and bounce.
+ CopyMem( Policy, mPolicyTable, mCurrentTableUsage );
+ *Size = mCurrentTableUsage;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This API function returns whether or not the policy engine is
+ currently being enforced.
+
+ @retval TRUE
+ @retval FALSE
+ @retval FALSE Library has not yet been initialized.
+
+**/
+BOOLEAN
+EFIAPI
+IsVariablePolicyEnabled (
+ VOID
+ )
+{
+ if (!IsVariablePolicyLibInitialized()) {
+ return FALSE;
+ }
+ return !mProtectionDisabled;
+}
+
+
+/**
+ This API function locks the interface so that no more policy updates
+ can be performed or changes made to the enforcement until the next boot.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_READY Library has not yet been initialized.
+
+**/
+EFI_STATUS
+EFIAPI
+LockVariablePolicy (
+ VOID
+ )
+{
+ if (!IsVariablePolicyLibInitialized()) {
+ return EFI_NOT_READY;
+ }
+ if (mInterfaceLocked) {
+ return EFI_WRITE_PROTECTED;
+ }
+ mInterfaceLocked = TRUE;
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This API function returns whether or not the policy interface is locked
+ for the remainder of the boot.
+
+ @retval TRUE
+ @retval FALSE
+ @retval FALSE Library has not yet been initialized.
+
+**/
+BOOLEAN
+EFIAPI
+IsVariablePolicyInterfaceLocked (
+ VOID
+ )
+{
+ if (!IsVariablePolicyLibInitialized()) {
+ return FALSE;
+ }
+ return mInterfaceLocked;
+}
+
+
+/**
+ This helper function initializes the library and sets
+ up any required internal structures or handlers.
+
+ Also registers the internal pointer for the GetVariable helper.
+
+ @param[in] GetVariableHelper A function pointer matching the EFI_GET_VARIABLE prototype that will be used to
+ check policy criteria that involve the existence of other variables.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED The initialize function has been called more than once without a call to
+ deinitialize.
+
+**/
+EFI_STATUS
+EFIAPI
+InitVariablePolicyLib (
+ IN EFI_GET_VARIABLE GetVariableHelper
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (mGetVariableHelper != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ if (!EFI_ERROR( Status )) {
+ Status = VariablePolicyExtraInit();
+ }
+
+ if (!EFI_ERROR( Status )) {
+ // Save an internal pointer to the GetVariableHelper.
+ mGetVariableHelper = GetVariableHelper;
+
+ // Initialize the global state.
+ mInterfaceLocked = FALSE;
+ mProtectionDisabled = FALSE;
+ mPolicyTable = NULL;
+ mCurrentTableSize = 0;
+ mCurrentTableUsage = 0;
+ mCurrentTableCount = 0;
+ }
+
+ return Status;
+}
+
+
+/**
+ This helper function returns whether or not the library is currently initialized.
+
+ @retval TRUE
+ @retval FALSE
+
+**/
+BOOLEAN
+EFIAPI
+IsVariablePolicyLibInitialized (
+ VOID
+ )
+{
+ return (mGetVariableHelper != NULL);
+}
+
+
+/**
+ This helper function tears down the library.
+
+ Should generally only be used for test harnesses.
+
+ @retval EFI_SUCCESS
+ @retval EFI_NOT_READY Deinitialize was called without first calling initialize.
+
+**/
+EFI_STATUS
+EFIAPI
+DeinitVariablePolicyLib (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ if (mGetVariableHelper == NULL) {
+ return EFI_NOT_READY;
+ }
+
+ if (!EFI_ERROR( Status )) {
+ Status = VariablePolicyExtraDeinit();
+ }
+
+ if (!EFI_ERROR( Status )) {
+ mGetVariableHelper = NULL;
+ mInterfaceLocked = FALSE;
+ mProtectionDisabled = FALSE;
+ mCurrentTableSize = 0;
+ mCurrentTableUsage = 0;
+ mCurrentTableCount = 0;
+
+ if (mPolicyTable != NULL) {
+ FreePool( mPolicyTable );
+ mPolicyTable = NULL;
+ }
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
new file mode 100644
index 00000000000..31a3e2ce5a2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
@@ -0,0 +1,48 @@
+## @file VariablePolicyLib.inf
+# Business logic for Variable Policy enforcement.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = VariablePolicyLib
+ FILE_GUID = E9ECD342-159A-4F24-9FDF-65724027C594
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_DRIVER
+ LIBRARY_CLASS = VariablePolicyLib|DXE_DRIVER DXE_SMM_DRIVER MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ANY
+#
+
+
+[Sources]
+ VariablePolicyLib.c
+ VariablePolicyExtraInitNull.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ SafeIntLib
+ PcdLib
+
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable ## CONSUMES
+
+
+[BuildOptions]
+ MSFT:NOOPT_*_*_CC_FLAGS = -DINTERNAL_UNIT_TEST
+ GCC:NOOPT_*_*_CC_FLAGS = -DINTERNAL_UNIT_TEST
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
new file mode 100644
index 00000000000..2227ec42782
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.uni
@@ -0,0 +1,12 @@
+// /** @file
+// VariablePolicyLib.uni
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Library containing the business logic for the VariablePolicy engine"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Library containing the business logic for the VariablePolicy engine"
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
new file mode 100644
index 00000000000..b1b2d40f78c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
@@ -0,0 +1,51 @@
+## @file VariablePolicyLibRuntimeDxe.inf
+# Business logic for Variable Policy enforcement.
+# This instance is specifically for RuntimeDxe and contains
+# extra routines to register for VirtualAddressChangeEvents.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = VariablePolicyLibRuntimeDxe
+ FILE_GUID = 205F7F0E-8EAC-4914-8390-1B90DD7E2A27
+ VERSION_STRING = 1.0
+ MODULE_TYPE = DXE_RUNTIME_DRIVER
+ LIBRARY_CLASS = VariablePolicyLib|DXE_RUNTIME_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = ANY
+#
+
+
+[Sources]
+ VariablePolicyLib.c
+ VariablePolicyExtraInitRuntimeDxe.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ SafeIntLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ PcdLib
+
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable ## CONSUMES
+
+
+[Guids]
+ gEfiEventVirtualAddressChangeGuid
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.ci.yaml
index bd7d0c061d3..81c07c46bc3 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.ci.yaml
@@ -2,9 +2,29 @@
# CI configuration for MdeModulePkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ ## options defined .pytool/Plugin/LicenseCheck
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ "Library/BrotliCustomDecompressLib/brotli",
+ "Universal/RegularExpressionDxe/oniguruma",
+ "Library/LzmaCustomDecompressLib/Sdk/DOC",
+ "Library/LzmaCustomDecompressLib/Sdk/C"
+ ]
+ },
## options defined ci/Plugin/CompilerPlugin
"CompilerPlugin": {
"DscPath": "MdeModulePkg.dsc"
@@ -86,7 +106,9 @@
"FVMAIN",
"VARCHECKPCD",
"Getxx",
- "lzturbo"
+ "lzturbo",
+ "musthave",
+ "canthave"
],
"AdditionalIncludePaths": [] # Additional paths to spell check relative to package root (wildcards supported)
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dec b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dec
index 6ee04dea112..a45b324adbd 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dec
@@ -4,11 +4,11 @@
# and libraries instances, which are used for those modules.
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
-# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
# (C) Copyright 2016 - 2019 Hewlett Packard Enterprise Development LP<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-# Copyright (c) 2016, Microsoft Corporation<BR>
+# Copyright (c) Microsoft Corporation.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -31,6 +31,9 @@
## @libraryclass Defines a set of methods to reset whole system.
ResetSystemLib|Include/Library/ResetSystemLib.h
+ ## @libraryclass Business logic for storing and testing variable policies
+ VariablePolicyLib|Include/Library/VariablePolicyLib.h
+
## @libraryclass Defines a set of helper functions for resetting the system.
ResetUtilityLib|Include/Library/ResetUtilityLib.h
@@ -146,6 +149,11 @@
#
DisplayUpdateProgressLib|Include/Library/DisplayUpdateProgressLib.h
+ ## @libraryclass This library contains helper functions for marshalling and
+ # registering new policies with the VariablePolicy infrastructure.
+ #
+ VariablePolicyHelperLib|Include/Library/VariablePolicyHelperLib.h
+
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@@ -377,6 +385,10 @@
## Include/Guid/EndofS3Resume.h
gEdkiiEndOfS3ResumeGuid = { 0x96f5296d, 0x05f7, 0x4f3c, {0x84, 0x67, 0xe4, 0x56, 0x89, 0x0e, 0x0c, 0xb5 } }
+ ## Used (similar to Variable Services) to communicate policies to the enforcement engine.
+ # {DA1B0D11-D1A7-46C4-9DC9-F3714875C6EB}
+ gVarCheckPolicyLibMmiHandlerGuid = { 0xda1b0d11, 0xd1a7, 0x46c4, { 0x9d, 0xc9, 0xf3, 0x71, 0x48, 0x75, 0xc6, 0xeb }}
+
## Include/Guid/S3SmmInitDone.h
gEdkiiS3SmmInitDoneGuid = { 0x8f9d4825, 0x797d, 0x48fc, { 0x84, 0x71, 0x84, 0x50, 0x25, 0x79, 0x2e, 0xf6 } }
@@ -389,6 +401,9 @@
## GUID indicates the capsule is to store Capsule On Disk file names.
gEdkiiCapsuleOnDiskNameGuid = { 0x98c80a4f, 0xe16b, 0x4d11, { 0x93, 0x9a, 0xab, 0xe5, 0x61, 0x26, 0x3, 0x30 } }
+ ## Include/Guid/MigratedFvInfo.h
+ gEdkiiMigratedFvInfoGuid = { 0xc1ab12f7, 0x74aa, 0x408d, { 0xa2, 0xf4, 0xc6, 0xce, 0xfd, 0x17, 0x98, 0x71 } }
+
[Ppis]
## Include/Ppi/AtaController.h
gPeiAtaControllerPpiGuid = { 0xa45e60d1, 0xc719, 0x44aa, { 0xb0, 0x7a, 0xaa, 0x77, 0x7f, 0x85, 0x90, 0x6d }}
@@ -624,6 +639,9 @@
# 0x80000006 | Incorrect error code provided.
#
+ ## Include/Protocol/VariablePolicy.h
+ gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } }
+
[PcdsFeatureFlag]
## Indicates if the platform can support update capsule across a system reset.<BR><BR>
# TRUE - Supports update capsule across a system reset.<BR>
@@ -760,19 +778,6 @@
# @Prompt Enable PCI bridge IO alignment probe.
gEfiMdeModulePkgTokenSpaceGuid.PcdPciBridgeIoAlignmentProbe|FALSE|BOOLEAN|0x0001004e
- ## Indicates if StatusCode is reported via Serial port.<BR><BR>
- # TRUE - Reports StatusCode via Serial port.<BR>
- # FALSE - Does not report StatusCode via Serial port.<BR>
- # @Prompt Enable StatusCode via Serial port.
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE|BOOLEAN|0x00010022
-
- ## Indicates if StatusCode is stored in memory.
- # The memory is boot time memory in PEI Phase and is runtime memory in DXE Phase.<BR><BR>
- # TRUE - Stores StatusCode in memory.<BR>
- # FALSE - Does not store StatusCode in memory.<BR>
- # @Prompt Enable StatusCode via memory.
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE|BOOLEAN|0x00010023
-
## Indicates if PEI phase StatusCode will be replayed in DXE phase.<BR><BR>
# TRUE - Replays PEI phase StatusCode in DXE phased.<BR>
# FALSE - Does not replay PEI phase StatusCode in DXE phase.<BR>
@@ -1129,6 +1134,15 @@
# @Prompt Variable storage size.
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000|UINT32|0x30000005
+ ## Toggle for whether the VariablePolicy engine should allow disabling.
+ # The engine is enabled at power-on, but the interface allows the platform to
+ # disable enforcement for servicing flexibility. If this PCD is disabled, it will block the ability to
+ # disable the enforcement and VariablePolicy enforcement will always be ON.
+ # TRUE - VariablePolicy can be disabled by request through the interface (until interface is locked)
+ # FALSE - VariablePolicy interface will not accept requests to disable and is ALWAYS ON
+ # @Prompt Allow VariablePolicy enforcement to be disabled.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable|FALSE|BOOLEAN|0x30000020
+
## FFS filename to find the ACPI tables.
# @Prompt FFS name of ACPI tables storage.
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile|{ 0x25, 0x4e, 0x37, 0x7e, 0x01, 0x8e, 0xee, 0x4f, 0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd }|VOID*|0x30000016
@@ -1233,6 +1247,15 @@
# @Prompt Shadow Peim and PeiCore on boot
gEfiMdeModulePkgTokenSpaceGuid.PcdShadowPeimOnBoot|TRUE|BOOLEAN|0x30001029
+ ## Enable the feature that evacuate temporary memory to permanent memory or not<BR><BR>
+ # Set FALSE as default, if the developer need this feature to avoid this vulnerability, please
+ # enable it to shadow all PEIMs no matter the behavior controled by PcdShadowPeimOnBoot or
+ # PcdShadowPeimOnS3Boot<BR>
+ # TRUE - Evacuate temporary memory, the actions include copy memory, convert PPI pointers and so on.<BR>
+ # FALSE - Do nothing, for example, no copy memory, no convert PPI pointers and so on.<BR>
+ # @Prompt Evacuate temporary memory to permanent memory
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes|FALSE|BOOLEAN|0x3000102A
+
## The mask is used to control memory profile behavior.<BR><BR>
# BIT0 - Enable UEFI memory profile.<BR>
# BIT1 - Enable SMRAM profile.<BR>
@@ -1337,7 +1360,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy|0x0000000|UINT64|0x00001048
## PCI Serial Device Info. It is an array of Device, Function, and Power Management
- # information that describes the path that contains zero or more PCI to PCI briges
+ # information that describes the path that contains zero or more PCI to PCI bridges
# followed by a PCI serial device. Each array entry is 4-bytes in length. The
# first byte is the PCI Device Number, then second byte is the PCI Function Number,
# and the last two bytes are the offset to the PCI power management capabilities
@@ -1390,7 +1413,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0xdc, 0x5b, 0xc2, 0xee, 0xf2, 0x67, 0x95, 0x4d, 0xb1, 0xd5, 0xf8, 0x1b, 0x20, 0x39, 0xd1, 0x1d }|VOID*|0x0001006b
## This PCD points to the formset GUID of the driver health management form
- # The form will be popped up by BDS core when there are Configuration Required driver health intances.
+ # The form will be popped up by BDS core when there are Configuration Required driver health instances.
# Platform can customize the PCD to point to different formset.
# @Prompt Driver Health Management Form
gEfiMdeModulePkgTokenSpaceGuid.PcdDriverHealthConfigureForm|{ 0xf4, 0xd9, 0x96, 0x42, 0xfc, 0xf6, 0xde, 0x4d, 0x86, 0x85, 0x8c, 0xe2, 0xd7, 0x9d, 0x90, 0xf0 }|VOID*|0x0001006c
@@ -1506,6 +1529,12 @@
# @Prompt Enable Capsule On Disk support.
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport|FALSE|BOOLEAN|0x0000002d
+ ## Maximum permitted encapsulation levels of sections in a firmware volume,
+ # in the DXE phase. Minimum value is 1. Sections nested more deeply are
+ # rejected.
+ # @Prompt Maximum permitted FwVol section nesting depth (exclusive).
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFwVolDxeMaxEncapsulationDepth|0x10|UINT32|0x00000030
+
[PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## This PCD defines the Console output row. The default value is 25 according to UEFI spec.
# This PCD could be set to 0 then console output would be at max column and max row.
@@ -1987,7 +2016,7 @@
# @Prompt Enable Capsule In Ram support.
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport|TRUE|BOOLEAN|0x0000002e
- ## Full device path of plaform specific device to store Capsule On Disk temp relocation file.<BR>
+ ## Full device path of platform specific device to store Capsule On Disk temp relocation file.<BR>
# If this PCD is set, Capsule On Disk temp relocation file will be stored in the device specified
# by this PCD, instead of the EFI System Partition that stores capsule image file.
# @Prompt Capsule On Disk relocation device path.
@@ -2001,6 +2030,25 @@
# @Prompt TCG Platform Firmware Profile revision.
gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision|0|UINT32|0x00010077
+ ## Indicates if StatusCode is reported via Serial port.<BR><BR>
+ # TRUE - Reports StatusCode via Serial port.<BR>
+ # FALSE - Does not report StatusCode via Serial port.<BR>
+ # @Prompt Enable StatusCode via Serial port.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE|BOOLEAN|0x00010022
+
+ ## Indicates if StatusCode is stored in memory.
+ # The memory is boot time memory in PEI Phase and is runtime memory in DXE Phase.<BR><BR>
+ # TRUE - Stores StatusCode in memory.<BR>
+ # FALSE - Does not store StatusCode in memory.<BR>
+ # @Prompt Enable StatusCode via memory.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE|BOOLEAN|0x00010023
+
+ ## Indicates if the PCIe Resizable BAR Capability Supported.<BR><BR>
+ # TRUE - PCIe Resizable BAR Capability is supported.<BR>
+ # FALSE - PCIe Resizable BAR Capability is not supported.<BR>
+ # @Prompt Enable PCIe Resizable BAR Capability support.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPcieResizableBarSupport|FALSE|BOOLEAN|0x10000024
+
[PcdsPatchableInModule]
## Specify memory size with page number for PEI code when
# Loading Module at Fixed Address feature is enabled.
@@ -2051,6 +2099,15 @@
# @Prompt If there is any test key used by the platform.
gEfiMdeModulePkgTokenSpaceGuid.PcdTestKeyUsed|FALSE|BOOLEAN|0x00030003
+ ## This dynamic PCD holds the base address of the Guest-Hypervisor Communication Block (GHCB) pool allocation.
+ # @Prompt GHCB Pool Base Address
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0|UINT64|0x00030007
+
+ ## This dynamic PCD holds the total size of the Guest-Hypervisor Communication Block (GHCB) pool allocation.
+ # The amount of memory allocated for GHCBs is dependent on the number of APs.
+ # @Prompt GHCB Pool Size
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0|UINT64|0x00030008
+
[PcdsDynamicEx]
## This dynamic PCD enables the default variable setting.
# Its value is the default store ID value. The default value is zero as Standard default.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dsc b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dsc
index 3419ffc2ebd..6edad06f28b 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.dsc
@@ -2,7 +2,8 @@
# EFI/PI Reference Module Package for All Architectures
#
# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -18,6 +19,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
#
# Entry point
@@ -58,6 +61,7 @@
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
#
# Generic Modules
#
@@ -97,6 +101,8 @@
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
DisplayUpdateProgressLib|MdeModulePkg/Library/DisplayUpdateProgressLibGraphics/DisplayUpdateProgressLibGraphics.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+ MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
[LibraryClasses.EBC.PEIM]
IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
@@ -129,6 +135,7 @@
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibFmp/DxeRuntimeCapsuleLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
[LibraryClasses.common.SMM_CORE]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
@@ -163,6 +170,8 @@
MemoryAllocationLib|MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf
+ MemLib|StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
@@ -222,6 +231,7 @@
MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
MdeModulePkg/Library/BaseMemoryAllocationLibNull/BaseMemoryAllocationLibNull.inf
+ MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
@@ -306,6 +316,10 @@
MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+ MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+ MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
+ MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLibStandaloneMm.inf
MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
@@ -451,6 +465,7 @@
MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
<LibraryClasses>
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
NULL|MdeModulePkg/Library/VarCheckHiiLib/VarCheckHiiLib.inf
NULL|MdeModulePkg/Library/VarCheckPcdLib/VarCheckPcdLib.inf
@@ -463,8 +478,11 @@
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
+ MdeModulePkg/Library/SmmReportStatusCodeLib/StandaloneMmReportStatusCodeLib.inf
MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
+ MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf
MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.inf
MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
MdeModulePkg/Library/SmmMemoryAllocationProfileLib/SmmMemoryAllocationProfileLib.inf
MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationProfileLib.inf
@@ -474,13 +492,16 @@
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxSmmLib.inf
+ MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxStandaloneMmLib.inf
MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
MdeModulePkg/Library/SmmSmiHandlerProfileLib/SmmSmiHandlerProfileLib.inf
+ MdeModulePkg/Library/SmmSmiHandlerProfileLib/StandaloneMmSmiHandlerProfileLib.inf
MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaArchCustomDecompressLib.inf
MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.inf
MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
+ MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmmDxe.inf
MdeModulePkg/Universal/RegularExpressionDxe/RegularExpressionDxe.inf
@@ -491,5 +512,4 @@
MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
[BuildOptions]
- *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.uni
index 2007e0596c4..27889a72805 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/MdeModulePkg.uni
@@ -4,7 +4,7 @@
// It also provides the definitions(including PPIs/PROTOCOLs/GUIDs and library classes)
// and libraries instances, which are used for those modules.
//
-// Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
//
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
@@ -129,6 +129,13 @@
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdVariableStoreSize_HELP #language en-US "The size of volatile buffer. This buffer is used to store VOLATILE attribute variables."
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAllowVariablePolicyEnforcementDisable_PROMPT #language en-US "Allow VariablePolicy enforcement to be disabled."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAllowVariablePolicyEnforcementDisable_HELP #language en-US "If this PCD is disabled, it will block the ability to<BR>\n"
+ "disable the enforcement and VariablePolicy enforcement will always be ON.<BR>\n"
+ "TRUE - VariablePolicy can be disabled by request through the interface (until interface is locked)<BR>\n"
+ "FALSE - VariablePolicy interface will not accept requests to disable and is ALWAYS ON<BR>\n"
+
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiTableStorageFile_PROMPT #language en-US "FFS name of ACPI tables storage"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiTableStorageFile_HELP #language en-US "FFS filename to find the ACPI tables."
@@ -214,6 +221,12 @@
"TRUE - Shadow PEIM on S3 boot path after memory is ready.<BR>\n"
"FALSE - Not shadow PEIM on S3 boot path after memory is ready.<BR>"
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMigrateTemporaryRamFirmwareVolumes_HELP #language en-US "Enable the feature that evacuate temporary memory to permanent memory or not.<BR><BR>\n"
+ "It will allocate page to save the temporary PEIMs resided in NEM(or CAR) to the permanent memory and change all pointers pointed to the NEM(or CAR) to permanent memory.<BR><BR>\n"
+ "After then, there are no pointer pointed to NEM(or CAR) and TOCTOU volnerability can be avoid.<BR><BR>\n"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdMigrateTemporaryRamFirmwareVolumes_PROMPT #language en-US "Enable the feature that evacuate temporary memory to permanent memory or not"
+
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiDefaultOemId_PROMPT #language en-US "Default OEM ID for ACPI table creation"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdAcpiDefaultOemId_HELP #language en-US "Default OEM ID for ACPI table creation, its length must be 0x6 bytes to follow ACPI specification."
@@ -300,7 +313,7 @@
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSerialPciDeviceInfo_PROMPT #language en-US "PCI Serial Device Info"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSerialPciDeviceInfo_HELP #language en-US "PCI Serial Device Info. It is an array of Device, Function, and Power Management\n"
- "information that describes the path that contains zero or more PCI to PCI briges\n"
+ "information that describes the path that contains zero or more PCI to PCI bridges\n"
"followed by a PCI serial device. Each array entry is 4-bytes in length. The\n"
"first byte is the PCI Device Number, then second byte is the PCI Function Number,\n"
"and the last two bytes are the offset to the PCI power management capabilities\n"
@@ -867,7 +880,7 @@
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdDriverHealthConfigureForm_PROMPT #language en-US "Driver Health Management Form"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdDriverHealthConfigureForm_HELP #language en-US "This PCD points to the formset GUID of the driver health management form\n"
- "The form will be popped up by BDS core when there are Configuration Required driver health intances.\n"
+ "The form will be popped up by BDS core when there are Configuration Required driver health instances.\n"
"Platform can customize the PCD to point to different formset."
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdSetupVideoHorizontalResolution_PROMPT #language en-US "Video Horizontal Resolution of Text Setup"
@@ -1147,6 +1160,12 @@
"Note:<BR>"
"If Both Capsule In Ram and Capsule On Disk are provisioned at the same time, the Capsule On Disk will be bypassed."
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFwVolDxeMaxEncapsulationDepth_PROMPT #language en-US "Maximum permitted FwVol section nesting depth (exclusive)."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdFwVolDxeMaxEncapsulationDepth_HELP #language en-US "Maximum permitted encapsulation levels of sections in a firmware volume,<BR>"
+ "in the DXE phase. Minimum value is 1. Sections nested more deeply are<BR>"
+ "rejected."
+
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_PROMPT #language en-US "Enable Capsule In Ram support"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCapsuleInRamSupport_HELP #language en-US "Capsule In Ram is to use memory to deliver the capsules that will be processed after system reset.<BR><BR>"
@@ -1154,9 +1173,9 @@
" TRUE - Capsule In Ram is supported.<BR>"
" FALSE - Capsule In Ram is not supported."
-#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PROMPT #language en-US "Capsule On Disk relacation device path."
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_PROMPT #language en-US "Capsule On Disk relocation device path."
-#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP #language en-US "Full device path of plaform specific device to store Capsule On Disk temp relocation file.<BR>"
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdCodRelocationDevPath_HELP #language en-US "Full device path of platform specific device to store Capsule On Disk temp relocation file.<BR>"
"If this PCD is set, Capsule On Disk temp relocation file will be stored in the device specified by this PCD, instead of the EFI System Partition that stores capsule image file."
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdNullPointerDetectionPropertyMask_PROMPT #language en-US "Enable NULL pointer detection"
@@ -1297,3 +1316,17 @@
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdTcgPfpMeasurementRevision_PROMPT #language en-US "TCG Platform Firmware Profile revision"
#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdTcgPfpMeasurementRevision_HELP #language en-US "Indicates which TCG Platform Firmware Profile revision the EDKII firmware follows."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdGhcbBase_PROMPT #language en-US "Guest-Hypervisor Communication Block (GHCB) Pool Base Address"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdGhcbBase_HELP #language en-US "Used with SEV-ES support to identify an address range that is not to be encrypted."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdGhcbSize_PROMPT #language en-US "Guest-Hypervisor Communication Block (GHCB) Pool Base Size"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdGhcbSize_HELP #language en-US "Used with SEV-ES support to identify the size of the address range that is not to be encrypted."
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarSupport_PROMPT #language en-US "Enable PCIe Resizable BAR Capability Supported"
+
+#string STR_gEfiMdeModulePkgTokenSpaceGuid_PcdPcieResizableBarSupport_HELP #language en-US "Indicates if the PCIe Resizable BAR Capability Supported.<BR><BR>\n"
+ "TRUE - PCIe Resizable BAR Capability is supported.<BR>\n"
+ "FALSE - PCIe Resizable BAR Capability is not supported.<BR>"
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Test/MdeModulePkgHostTest.dsc b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
index 3fcacdc0b7b..2c76c21ee21 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Test/MdeModulePkgHostTest.dsc
@@ -19,6 +19,9 @@
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+[LibraryClasses]
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+
[Components]
MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeServicesTableLib.inf
@@ -30,3 +33,11 @@
ResetSystemLib|MdeModulePkg/Library/DxeResetSystemLib/DxeResetSystemLib.inf
UefiRuntimeServicesTableLib|MdeModulePkg/Library/DxeResetSystemLib/UnitTest/MockUefiRuntimeServicesTableLib.inf
}
+
+ MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.inf {
+ <LibraryClasses>
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+ <PcdsFixedAtBuild>
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable|TRUE
+ }
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.c
index 53a6a8cde00..f71b71ca9d4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiSdt.c
@@ -68,8 +68,8 @@ FindTableByBuffer (
while (CurrentLink != StartLink) {
CurrentTableList = EFI_ACPI_TABLE_LIST_FROM_LINK (CurrentLink);
- if (((UINTN)CurrentTableList->PageAddress <= (UINTN)Buffer) &&
- ((UINTN)CurrentTableList->PageAddress + EFI_PAGES_TO_SIZE(CurrentTableList->NumberOfPages) > (UINTN)Buffer)) {
+ if (((UINTN)CurrentTableList->Table <= (UINTN)Buffer) &&
+ ((UINTN)CurrentTableList->Table + CurrentTableList->TableSize > (UINTN)Buffer)) {
//
// Good! Found Table.
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
index 7d749abe7ec..243627f4d38 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTable.h
@@ -55,18 +55,21 @@
// Link is the linked list data.
// Version is the versions of the ACPI tables that this table belongs in.
// Table is a pointer to the table.
-// PageAddress is the address of the pages allocated for the table.
-// NumberOfPages is the number of pages allocated at PageAddress.
+// TableSize is the size of the table
// Handle is used to identify a particular table.
+// PoolAllocation carries the allocation type:
+// FALSE: Table points to EFI_SIZE_TO_PAGES(TableSize) pages allocated using
+// gBS->AllocatePages ()
+// TRUE: Table points to TableSize bytes allocated using gBS->AllocatePool ()
//
typedef struct {
UINT32 Signature;
LIST_ENTRY Link;
EFI_ACPI_TABLE_VERSION Version;
EFI_ACPI_COMMON_HEADER *Table;
- EFI_PHYSICAL_ADDRESS PageAddress;
- UINTN NumberOfPages;
+ UINTN TableSize;
UINTN Handle;
+ BOOLEAN PoolAllocation;
} EFI_ACPI_TABLE_LIST;
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
index 35c2e816baf..4ba0c6f6d61 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
@@ -355,28 +355,39 @@ ReallocateAcpiTableBuffer (
NewMaxTableNumber * sizeof (UINT32);
}
- //
- // Allocate memory in the lower 32 bit of address range for
- // compatibility with ACPI 1.0 OS.
- //
- // This is done because ACPI 1.0 pointers are 32 bit values.
- // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
- // There is no architectural reason these should be below 4GB, it is purely
- // for convenience of implementation that we force memory below 4GB.
- //
- PageAddress = 0xFFFFFFFF;
- Status = gBS->AllocatePages (
- mAcpiTableAllocType,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES (TotalSize),
- &PageAddress
- );
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ //
+ // Allocate memory in the lower 32 bit of address range for
+ // compatibility with ACPI 1.0 OS.
+ //
+ // This is done because ACPI 1.0 pointers are 32 bit values.
+ // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
+ // There is no architectural reason these should be below 4GB, it is purely
+ // for convenience of implementation that we force memory below 4GB.
+ //
+ PageAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ mAcpiTableAllocType,
+ EfiACPIReclaimMemory,
+ EFI_SIZE_TO_PAGES (TotalSize),
+ &PageAddress
+ );
+ } else {
+ Status = gBS->AllocatePool (
+ EfiACPIReclaimMemory,
+ TotalSize,
+ (VOID **)&Pointer
+ );
+ }
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
- Pointer = (UINT8 *) (UINTN) PageAddress;
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ Pointer = (UINT8 *)(UINTN)PageAddress;
+ }
+
ZeroMem (Pointer, TotalSize);
AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
@@ -406,21 +417,26 @@ ReallocateAcpiTableBuffer (
}
CopyMem (AcpiTableInstance->Xsdt, TempPrivateData.Xsdt, (sizeof (EFI_ACPI_DESCRIPTION_HEADER) + mEfiAcpiMaxNumTables * sizeof (UINT64)));
- //
- // Calculate orignal ACPI table buffer size
- //
- TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT
- mEfiAcpiMaxNumTables * sizeof (UINT64);
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ //
+ // Calculate orignal ACPI table buffer size
+ //
+ TotalSize = sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 XSDT
+ mEfiAcpiMaxNumTables * sizeof (UINT64);
+
+ if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
+ TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT
+ mEfiAcpiMaxNumTables * sizeof (UINT32) +
+ sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT
+ mEfiAcpiMaxNumTables * sizeof (UINT32);
+ }
- if ((PcdGet32 (PcdAcpiExposedTableVersions) & EFI_ACPI_TABLE_VERSION_1_0B) != 0) {
- TotalSize += sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 1.0 RSDT
- mEfiAcpiMaxNumTables * sizeof (UINT32) +
- sizeof (EFI_ACPI_DESCRIPTION_HEADER) + // for ACPI 2.0/3.0 RSDT
- mEfiAcpiMaxNumTables * sizeof (UINT32);
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1,
+ EFI_SIZE_TO_PAGES (TotalSize));
+ } else {
+ gBS->FreePool (TempPrivateData.Rsdt1);
}
- gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TempPrivateData.Rsdt1, EFI_SIZE_TO_PAGES (TotalSize));
-
//
// Update the Max ACPI table number
//
@@ -429,6 +445,26 @@ ReallocateAcpiTableBuffer (
}
/**
+ Free the memory associated with the provided EFI_ACPI_TABLE_LIST instance.
+
+ @param TableEntry EFI_ACPI_TABLE_LIST instance pointer
+
+**/
+STATIC
+VOID
+FreeTableMemory (
+ EFI_ACPI_TABLE_LIST *TableEntry
+ )
+{
+ if (TableEntry->PoolAllocation) {
+ gBS->FreePool (TableEntry->Table);
+ } else {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)TableEntry->Table,
+ EFI_SIZE_TO_PAGES (TableEntry->TableSize));
+ }
+}
+
+/**
This function adds an ACPI table to the table list. It will detect FACS and
allocate the correct type of memory and properly align the table.
@@ -454,14 +490,15 @@ AddTableToList (
OUT UINTN *Handle
)
{
- EFI_STATUS Status;
- EFI_ACPI_TABLE_LIST *CurrentTableList;
- UINT32 CurrentTableSignature;
- UINT32 CurrentTableSize;
- UINT32 *CurrentRsdtEntry;
- VOID *CurrentXsdtEntry;
- UINT64 Buffer64;
- BOOLEAN AddToRsdt;
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_LIST *CurrentTableList;
+ UINT32 CurrentTableSignature;
+ UINT32 CurrentTableSize;
+ UINT32 *CurrentRsdtEntry;
+ VOID *CurrentXsdtEntry;
+ EFI_PHYSICAL_ADDRESS AllocPhysAddress;
+ UINT64 Buffer64;
+ BOOLEAN AddToRsdt;
//
// Check for invalid input parameters
@@ -496,8 +533,9 @@ AddTableToList (
// There is no architectural reason these should be below 4GB, it is purely
// for convenience of implementation that we force memory below 4GB.
//
- CurrentTableList->PageAddress = 0xFFFFFFFF;
- CurrentTableList->NumberOfPages = EFI_SIZE_TO_PAGES (CurrentTableSize);
+ AllocPhysAddress = 0xFFFFFFFF;
+ CurrentTableList->TableSize = CurrentTableSize;
+ CurrentTableList->PoolAllocation = FALSE;
//
// Allocation memory type depends on the type of the table
@@ -518,9 +556,21 @@ AddTableToList (
Status = gBS->AllocatePages (
AllocateMaxAddress,
EfiACPIMemoryNVS,
- CurrentTableList->NumberOfPages,
- &CurrentTableList->PageAddress
+ EFI_SIZE_TO_PAGES (CurrentTableList->TableSize),
+ &AllocPhysAddress
);
+ } else if (mAcpiTableAllocType == AllocateAnyPages) {
+ //
+ // If there is no allocation limit, there is also no need to use page
+ // based allocations for ACPI tables, which may be wasteful on platforms
+ // such as AArch64 that allocate multiples of 64 KB
+ //
+ Status = gBS->AllocatePool (
+ EfiACPIReclaimMemory,
+ CurrentTableList->TableSize,
+ (VOID **)&CurrentTableList->Table
+ );
+ CurrentTableList->PoolAllocation = TRUE;
} else {
//
// All other tables are ACPI reclaim memory, no alignment requirements.
@@ -528,9 +578,10 @@ AddTableToList (
Status = gBS->AllocatePages (
mAcpiTableAllocType,
EfiACPIReclaimMemory,
- CurrentTableList->NumberOfPages,
- &CurrentTableList->PageAddress
+ EFI_SIZE_TO_PAGES (CurrentTableList->TableSize),
+ &AllocPhysAddress
);
+ CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *)(UINTN)AllocPhysAddress;
}
//
// Check return value from memory alloc.
@@ -539,10 +590,10 @@ AddTableToList (
gBS->FreePool (CurrentTableList);
return EFI_OUT_OF_RESOURCES;
}
- //
- // Update the table pointer with the allocated memory start
- //
- CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *) (UINTN) CurrentTableList->PageAddress;
+
+ if (!CurrentTableList->PoolAllocation) {
+ CurrentTableList->Table = (EFI_ACPI_COMMON_HEADER *)(UINTN)AllocPhysAddress;
+ }
//
// Initialize the table contents
@@ -575,7 +626,7 @@ AddTableToList (
if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Fadt1 != NULL) ||
((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0 && AcpiTableInstance->Fadt3 != NULL)
) {
- gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
+ FreeTableMemory (CurrentTableList);
gBS->FreePool (CurrentTableList);
return EFI_ACCESS_DENIED;
}
@@ -729,7 +780,7 @@ AddTableToList (
if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Facs1 != NULL) ||
((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0 && AcpiTableInstance->Facs3 != NULL)
) {
- gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
+ FreeTableMemory (CurrentTableList);
gBS->FreePool (CurrentTableList);
return EFI_ACCESS_DENIED;
}
@@ -813,7 +864,7 @@ AddTableToList (
if (((Version & EFI_ACPI_TABLE_VERSION_1_0B) != 0 && AcpiTableInstance->Dsdt1 != NULL) ||
((Version & ACPI_TABLE_VERSION_GTE_2_0) != 0 && AcpiTableInstance->Dsdt3 != NULL)
) {
- gBS->FreePages (CurrentTableList->PageAddress, CurrentTableList->NumberOfPages);
+ FreeTableMemory (CurrentTableList);
gBS->FreePool (CurrentTableList);
return EFI_ACCESS_DENIED;
}
@@ -1449,7 +1500,7 @@ DeleteTable (
//
// Free the Table
//
- gBS->FreePages (Table->PageAddress, Table->NumberOfPages);
+ FreeTableMemory (Table);
RemoveEntryList (&(Table->Link));
gBS->FreePool (Table);
}
@@ -1694,19 +1745,29 @@ AcpiTableAcpiTableConstructor (
RsdpTableSize += sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
}
- PageAddress = 0xFFFFFFFF;
- Status = gBS->AllocatePages (
- mAcpiTableAllocType,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES (RsdpTableSize),
- &PageAddress
- );
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ PageAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ mAcpiTableAllocType,
+ EfiACPIReclaimMemory,
+ EFI_SIZE_TO_PAGES (RsdpTableSize),
+ &PageAddress
+ );
+ } else {
+ Status = gBS->AllocatePool (
+ EfiACPIReclaimMemory,
+ RsdpTableSize,
+ (VOID **)&Pointer
+ );
+ }
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
- Pointer = (UINT8 *) (UINTN) PageAddress;
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ Pointer = (UINT8 *)(UINTN)PageAddress;
+ }
ZeroMem (Pointer, RsdpTableSize);
AcpiTableInstance->Rsdp1 = (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *) Pointer;
@@ -1728,29 +1789,44 @@ AcpiTableAcpiTableConstructor (
mEfiAcpiMaxNumTables * sizeof (UINT32);
}
- //
- // Allocate memory in the lower 32 bit of address range for
- // compatibility with ACPI 1.0 OS.
- //
- // This is done because ACPI 1.0 pointers are 32 bit values.
- // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
- // There is no architectural reason these should be below 4GB, it is purely
- // for convenience of implementation that we force memory below 4GB.
- //
- PageAddress = 0xFFFFFFFF;
- Status = gBS->AllocatePages (
- mAcpiTableAllocType,
- EfiACPIReclaimMemory,
- EFI_SIZE_TO_PAGES (TotalSize),
- &PageAddress
- );
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ //
+ // Allocate memory in the lower 32 bit of address range for
+ // compatibility with ACPI 1.0 OS.
+ //
+ // This is done because ACPI 1.0 pointers are 32 bit values.
+ // ACPI 2.0 OS and all 64 bit OS must use the 64 bit ACPI table addresses.
+ // There is no architectural reason these should be below 4GB, it is purely
+ // for convenience of implementation that we force memory below 4GB.
+ //
+ PageAddress = 0xFFFFFFFF;
+ Status = gBS->AllocatePages (
+ mAcpiTableAllocType,
+ EfiACPIReclaimMemory,
+ EFI_SIZE_TO_PAGES (TotalSize),
+ &PageAddress
+ );
+ } else {
+ Status = gBS->AllocatePool (
+ EfiACPIReclaimMemory,
+ TotalSize,
+ (VOID **)&Pointer
+ );
+ }
if (EFI_ERROR (Status)) {
- gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiTableInstance->Rsdp1, EFI_SIZE_TO_PAGES (RsdpTableSize));
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)AcpiTableInstance->Rsdp1,
+ EFI_SIZE_TO_PAGES (RsdpTableSize));
+ } else {
+ gBS->FreePool (AcpiTableInstance->Rsdp1);
+ }
return EFI_OUT_OF_RESOURCES;
}
- Pointer = (UINT8 *) (UINTN) PageAddress;
+ if (mAcpiTableAllocType != AllocateAnyPages) {
+ Pointer = (UINT8 *)(UINTN)PageAddress;
+ }
ZeroMem (Pointer, TotalSize);
AcpiTableInstance->Rsdt1 = (EFI_ACPI_DESCRIPTION_HEADER *) Pointer;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.c
index 13879398ee4..28d9e82fc04 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.c
@@ -1,11 +1,11 @@
/** @file
- This module collects performance data for SMM driver boot records and S3 Suspend Performance Record.
+ This module collects performance data for MM driver boot records and S3 Suspend Performance Record.
This module registers report status code listener to collect performance data
- for SMM driver boot records and S3 Suspend Performance Record.
+ for MM driver boot records and S3 Suspend Performance Record.
Caution: This module requires additional review when modified.
- This driver will have external input - communicate buffer in SMM mode.
+ This driver will have external input - communicate buffer in MM mode.
This external input must be validated carefully to avoid security issue like
buffer overflow, integer overflow.
@@ -16,13 +16,13 @@
**/
-#include <PiSmm.h>
+#include <PiMm.h>
-#include <Protocol/SmmReportStatusCodeHandler.h>
+#include <Protocol/MmReportStatusCodeHandler.h>
#include <Guid/FirmwarePerformance.h>
-#include <Library/SmmServicesTableLib.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/TimerLib.h>
@@ -30,23 +30,22 @@
#include <Library/PcdLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiBootServicesTableLib.h>
#include <Library/SynchronizationLib.h>
-#include <Library/SmmMemLib.h>
+#include "FirmwarePerformanceCommon.h"
-SMM_BOOT_PERFORMANCE_TABLE *mSmmBootPerformanceTable = NULL;
+SMM_BOOT_PERFORMANCE_TABLE *mMmBootPerformanceTable = NULL;
-EFI_SMM_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
+EFI_MM_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
UINT64 mSuspendStartTime = 0;
BOOLEAN mS3SuspendLockBoxSaved = FALSE;
UINT32 mBootRecordSize = 0;
UINT8 *mBootRecordBuffer = NULL;
-SPIN_LOCK mSmmFpdtLock;
-BOOLEAN mSmramIsOutOfResource = FALSE;
+SPIN_LOCK mMmFpdtLock;
+BOOLEAN mMmramIsOutOfResource = FALSE;
/**
- Report status code listener for SMM. This is used to record the performance
+ Report status code listener for MM. This is used to record the performance
data for S3 Suspend Start and S3 Suspend End in FPDT.
@param[in] CodeType Indicates the type of status code being reported.
@@ -66,7 +65,7 @@ BOOLEAN mSmramIsOutOfResource = FALSE;
**/
EFI_STATUS
EFIAPI
-FpdtStatusCodeListenerSmm (
+FpdtStatusCodeListenerMm (
IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
@@ -89,19 +88,19 @@ FpdtStatusCodeListenerSmm (
// Collect one or more Boot records in boot time
//
if (Data != NULL && CompareGuid (&Data->Type, &gEdkiiFpdtExtendedFirmwarePerformanceGuid)) {
- AcquireSpinLock (&mSmmFpdtLock);
+ AcquireSpinLock (&mMmFpdtLock);
//
// Get the boot performance data.
//
- CopyMem (&mSmmBootPerformanceTable, Data + 1, Data->Size);
- mBootRecordBuffer = ((UINT8 *) (mSmmBootPerformanceTable)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE);
+ CopyMem (&mMmBootPerformanceTable, Data + 1, Data->Size);
+ mBootRecordBuffer = ((UINT8 *) (mMmBootPerformanceTable)) + sizeof (SMM_BOOT_PERFORMANCE_TABLE);
- ReleaseSpinLock (&mSmmFpdtLock);
+ ReleaseSpinLock (&mMmFpdtLock);
return EFI_SUCCESS;
}
if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
- DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerSmm: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableSmm\n"));
+ DEBUG ((DEBUG_ERROR, "FpdtStatusCodeListenerMm: Performance data reported through gEfiFirmwarePerformanceGuid will not be collected by FirmwarePerformanceDataTableMm\n"));
return EFI_UNSUPPORTED;
}
@@ -157,7 +156,7 @@ FpdtStatusCodeListenerSmm (
/**
Communication service SMI Handler entry.
- This SMI handler provides services for report SMM boot records.
+ This SMI handler provides services for report MM boot records.
Caution: This function may receive untrusted input.
Communicate buffer and buffer size are external input, so this function will do basic validation.
@@ -166,7 +165,7 @@ FpdtStatusCodeListenerSmm (
@param[in] RegisterContext Points to an optional handler context which was specified when the
handler was registered.
@param[in, out] CommBuffer A pointer to a collection of data in memory that will
- be conveyed from a non-SMM environment into an SMM environment.
+ be conveyed from a non-MM environment into an MM environment.
@param[in, out] CommBufferSize The size of the CommBuffer.
@retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
@@ -207,8 +206,8 @@ FpdtSmiHandler (
return EFI_SUCCESS;
}
- if (!SmmIsBufferOutsideSmmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
- DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM communication data buffer in SMRAM or overflow!\n"));
+ if (!IsBufferOutsideMmValid ((UINTN)CommBuffer, TempCommBufferSize)) {
+ DEBUG ((DEBUG_ERROR, "FpdtSmiHandler: MM communication data buffer in MMRAM or overflow!\n"));
return EFI_SUCCESS;
}
@@ -218,8 +217,8 @@ FpdtSmiHandler (
switch (SmmCommData->Function) {
case SMM_FPDT_FUNCTION_GET_BOOT_RECORD_SIZE :
- if (mSmmBootPerformanceTable != NULL) {
- mBootRecordSize = mSmmBootPerformanceTable->Header.Length - sizeof (SMM_BOOT_PERFORMANCE_TABLE);
+ if (mMmBootPerformanceTable != NULL) {
+ mBootRecordSize = mMmBootPerformanceTable->Header.Length - sizeof (SMM_BOOT_PERFORMANCE_TABLE);
}
SmmCommData->BootRecordSize = mBootRecordSize;
break;
@@ -244,8 +243,8 @@ FpdtSmiHandler (
BootRecordSize = mBootRecordSize - BootRecordOffset;
}
SmmCommData->BootRecordSize = BootRecordSize;
- if (!SmmIsBufferOutsideSmmValid ((UINTN)BootRecordData, BootRecordSize)) {
- DEBUG ((EFI_D_ERROR, "FpdtSmiHandler: SMM Data buffer in SMRAM or overflow!\n"));
+ if (!IsBufferOutsideMmValid ((UINTN)BootRecordData, BootRecordSize)) {
+ DEBUG ((DEBUG_ERROR, "FpdtSmiHandler: MM Data buffer in MMRAM or overflow!\n"));
Status = EFI_ACCESS_DENIED;
break;
}
@@ -267,20 +266,15 @@ FpdtSmiHandler (
}
/**
- The module Entry Point of the Firmware Performance Data Table SMM driver.
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
+ The module Entry Point of the Firmware Performance Data Table MM driver.
@retval EFI_SUCCESS The entry point is executed successfully.
@retval Other Some error occurs when executing this entry point.
**/
EFI_STATUS
-EFIAPI
-FirmwarePerformanceSmmEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+FirmwarePerformanceCommonEntryPoint (
+ VOID
)
{
EFI_STATUS Status;
@@ -289,13 +283,13 @@ FirmwarePerformanceSmmEntryPoint (
//
// Initialize spin lock
//
- InitializeSpinLock (&mSmmFpdtLock);
+ InitializeSpinLock (&mMmFpdtLock);
//
- // Get SMM Report Status Code Handler Protocol.
+ // Get MM Report Status Code Handler Protocol.
//
- Status = gSmst->SmmLocateProtocol (
- &gEfiSmmRscHandlerProtocolGuid,
+ Status = gMmst->MmLocateProtocol (
+ &gEfiMmRscHandlerProtocolGuid,
NULL,
(VOID **) &mRscHandlerProtocol
);
@@ -304,14 +298,14 @@ FirmwarePerformanceSmmEntryPoint (
//
// Register report status code listener for BootRecords and S3 Suspend Start and End.
//
- Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerSmm);
+ Status = mRscHandlerProtocol->Register (FpdtStatusCodeListenerMm);
ASSERT_EFI_ERROR (Status);
//
// Register SMI handler.
//
Handle = NULL;
- Status = gSmst->SmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &Handle);
+ Status = gMmst->MmiHandlerRegister (FpdtSmiHandler, &gEfiFirmwarePerformanceGuid, &Handle);
ASSERT_EFI_ERROR (Status);
return Status;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.h
new file mode 100644
index 00000000000..8fd5a8cdce6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceCommon.h
@@ -0,0 +1,50 @@
+/** @file
+ This module collects performance data for SMM driver boot records and S3 Suspend Performance Record.
+
+ This module registers report status code listener to collect performance data
+ for SMM driver boot records and S3 Suspend Performance Record.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - communicate buffer in SMM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ FpdtSmiHandler() will receive untrusted input and do basic validation.
+
+ Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c), Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FW_PERF_COMMON_H_
+#define _FW_PERF_COMMON_H_
+
+/**
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+IsBufferOutsideMmValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ );
+
+/**
+ The module Entry Point of the Firmware Performance Data Table MM driver.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+FirmwarePerformanceCommonEntryPoint (
+ VOID
+ );
+
+#endif // _FW_PERF_COMMON_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
index ba6c48b27f6..10704a62a66 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceSmm.inf
@@ -26,7 +26,9 @@
#
[Sources]
- FirmwarePerformanceSmm.c
+ FirmwarePerformanceCommon.c
+ FirmwarePerformanceCommon.h
+ FirmwarePerformanceTraditional.c
[Packages]
MdePkg/MdePkg.dec
@@ -34,7 +36,7 @@
[LibraryClasses]
UefiDriverEntryPoint
- SmmServicesTableLib
+ MmServicesTableLib
BaseLib
DebugLib
TimerLib
@@ -42,12 +44,11 @@
PcdLib
BaseMemoryLib
MemoryAllocationLib
- UefiBootServicesTableLib
SynchronizationLib
SmmMemLib
[Protocols]
- gEfiSmmRscHandlerProtocolGuid ## CONSUMES
+ gEfiMmRscHandlerProtocolGuid ## CONSUMES
[Guids]
## SOMETIMES_PRODUCES ## UNDEFINED # SaveLockBox
@@ -61,7 +62,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd ## CONSUMES
[Depex]
- gEfiSmmRscHandlerProtocolGuid
+ gEfiMmRscHandlerProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
FirmwarePerformanceSmmExtra.uni
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.c
new file mode 100644
index 00000000000..2071b7b60a7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.c
@@ -0,0 +1,61 @@
+/** @file
+ This module collects performance data for MM driver boot records and S3 Suspend Performance Record.
+
+ This module registers report status code listener to collect performance data
+ for MM driver boot records and S3 Suspend Performance Record.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - communicate buffer in MM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ FpdtSmiHandler() will receive untrusted input and do basic validation.
+
+ Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c), Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/StandaloneMmMemLib.h>
+#include "FirmwarePerformanceCommon.h"
+
+/**
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+IsBufferOutsideMmValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return MmIsBufferOutsideMmValid (Buffer, Length);
+}
+
+/**
+ The module Entry Point of the Firmware Performance Data Table MM driver.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI MM System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+FirmwarePerformanceStandaloneMmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return FirmwarePerformanceCommonEntryPoint ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.inf
new file mode 100644
index 00000000000..e92463884aa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceStandaloneMm.inf
@@ -0,0 +1,66 @@
+## @file
+# This module collects performance data for SMM driver boot records and S3 Suspend Performance Record.
+#
+# This module registers report status code listener to collect performance data
+# for SMM boot performance records and S3 Suspend Performance Record.
+#
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FirmwarePerformanceStandaloneMm
+ FILE_GUID = 827AC29D-E52D-4B1A-874A-C6577E0699CF
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ ENTRY_POINT = FirmwarePerformanceStandaloneMmEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ FirmwarePerformanceCommon.c
+ FirmwarePerformanceCommon.h
+ FirmwarePerformanceStandaloneMm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ StandaloneMmDriverEntryPoint
+ MmServicesTableLib
+ BaseLib
+ DebugLib
+ TimerLib
+ LockBoxLib
+ PcdLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ SynchronizationLib
+ MemLib
+
+[Protocols]
+ gEfiMmRscHandlerProtocolGuid ## CONSUMES
+
+[Guids]
+ ## SOMETIMES_PRODUCES ## UNDEFINED # SaveLockBox
+ ## PRODUCES ## UNDEFINED # SmiHandlerRegister
+ ## SOMETIMES_CONSUMES ## UNDEFINED # StatusCode Data
+ gEfiFirmwarePerformanceGuid
+ gEdkiiFpdtExtendedFirmwarePerformanceGuid ## SOMETIMES_PRODUCES ## UNDEFINED # StatusCode Data
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendStart ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdProgressCodeS3SuspendEnd ## CONSUMES
+
+[Depex]
+ gEfiMmRscHandlerProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceTraditional.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceTraditional.c
new file mode 100644
index 00000000000..004971134d5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTableSmm/FirmwarePerformanceTraditional.c
@@ -0,0 +1,61 @@
+/** @file
+ This module collects performance data for MM driver boot records and S3 Suspend Performance Record.
+
+ This module registers report status code listener to collect performance data
+ for MM driver boot records and S3 Suspend Performance Record.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - communicate buffer in MM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+
+ FpdtSmiHandler() will receive untrusted input and do basic validation.
+
+ Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c), Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiSmm.h>
+
+#include <Library/SmmMemLib.h>
+#include "FirmwarePerformanceCommon.h"
+
+/**
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+IsBufferOutsideMmValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return SmmIsBufferOutsideSmmValid (Buffer, Length);
+}
+
+/**
+ The module Entry Point of the Firmware Performance Data Table MM driver.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+FirmwarePerformanceSmmEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return FirmwarePerformanceCommonEntryPoint ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c
index 74f2018f3fe..eaa73ae9afd 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveState.c
@@ -889,7 +889,7 @@ BootScriptCompare (
@retval EFI_OUT_OF_RESOURCES No enough resource
@retval EFI_SUCCESS Succesfully installed the ScriptSave driver.
- @retval other Errors occured.
+ @retval other Errors occurred.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c
index b97b31c453f..436aec6d80b 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Acpi/SmmS3SaveState/SmmS3SaveState.c
@@ -887,7 +887,7 @@ BootScriptCompare (
@retval EFI_OUT_OF_RESOURCES No enough resource
@retval EFI_SUCCESS Succesfully installed the ScriptSave driver.
- @retval other Errors occured.
+ @retval other Errors occurred.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/BdsDxe/BdsEntry.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
index b9f7d1f06c7..8e027fee03f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/BdsDxe/BdsEntry.c
@@ -785,7 +785,7 @@ BdsEntry (
FilePath = FileDevicePath (NULL, EFI_REMOVABLE_MEDIA_FILE_NAME);
if (FilePath == NULL) {
- DEBUG ((DEBUG_ERROR, "Fail to allocate memory for defualt boot file path. Unable to boot.\n"));
+ DEBUG ((DEBUG_ERROR, "Fail to allocate memory for default boot file path. Unable to boot.\n"));
CpuDeadLoop ();
}
Status = EfiBootManagerInitializeLoadOption (
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
index 0aeed8c8d19..e2d85ccddc5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.c
@@ -1,5 +1,5 @@
/** @file
- Console Splitter Driver. Any Handle that attatched console I/O protocols
+ Console Splitter Driver. Any Handle that attached console I/O protocols
(Console In device, Console Out device, Console Error device, Simple Pointer
protocol, Absolute Pointer protocol) can be bound by this driver.
@@ -13,7 +13,7 @@
Each virtual handle, that supports the Console I/O protocol, will be produced
in the driver entry point. The virtual handle are added on driver entry and
- never removed. Such design ensures sytem function well during none console
+ never removed. Such design ensures system function well during none console
device situation.
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
@@ -381,7 +381,7 @@ ToggleStateSyncInitialization (
}
/**
- Reinitialization for toggle state sync.
+ Re-initialization for toggle state sync.
@param Private Text In Splitter pointer.
@@ -594,7 +594,7 @@ ConSplitterDriverEntry(
structure.
@retval EFI_OUT_OF_RESOURCES Out of resources.
- @retval EFI_SUCCESS Text Input Devcie's private data has been constructed.
+ @retval EFI_SUCCESS Text Input Device's private data has been constructed.
@retval other Failed to construct private data.
**/
@@ -761,7 +761,7 @@ ConSplitterTextOutConstructor (
}
//
- // Initilize console output splitter's private data.
+ // Initialize console output splitter's private data.
//
ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode;
@@ -860,7 +860,7 @@ ConSplitterTextOutConstructor (
@param Guid The specified protocol.
@retval EFI_SUCCESS The specified protocol is supported on this device.
- @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtul handle.
+ @retval EFI_UNSUPPORTED The specified protocol attempts to be installed on virtual handle.
@retval other Failed to open specified protocol on this device.
**/
@@ -1108,7 +1108,7 @@ ConSplitterStart (
}
//
- // Open InterfaceGuid on the virtul handle.
+ // Open InterfaceGuid on the virtual handle.
//
Status = gBS->OpenProtocol (
ControllerHandle,
@@ -1174,7 +1174,7 @@ ConSplitterConInDriverBindingStart (
//
// Start ConSplitter on ControllerHandle, and create the virtual
- // agrogated console device on first call Start for a SimpleTextIn handle.
+ // aggregated console device on first call Start for a SimpleTextIn handle.
//
Status = ConSplitterStart (
This,
@@ -1241,7 +1241,7 @@ ConSplitterSimplePointerDriverBindingStart (
//
// Start ConSplitter on ControllerHandle, and create the virtual
- // agrogated console device on first call Start for a SimplePointer handle.
+ // aggregated console device on first call Start for a SimplePointer handle.
//
Status = ConSplitterStart (
This,
@@ -1287,7 +1287,7 @@ ConSplitterAbsolutePointerDriverBindingStart (
//
// Start ConSplitter on ControllerHandle, and create the virtual
- // agrogated console device on first call Start for a AbsolutePointer handle.
+ // aggregated console device on first call Start for a AbsolutePointer handle.
//
Status = ConSplitterStart (
This,
@@ -1338,7 +1338,7 @@ ConSplitterConOutDriverBindingStart (
//
// Start ConSplitter on ControllerHandle, and create the virtual
- // agrogated console device on first call Start for a ConsoleOut handle.
+ // aggregated console device on first call Start for a ConsoleOut handle.
//
Status = ConSplitterStart (
This,
@@ -1451,7 +1451,7 @@ ConSplitterStdErrDriverBindingStart (
//
// Start ConSplitter on ControllerHandle, and create the virtual
- // agrogated console device on first call Start for a StandardError handle.
+ // aggregated console device on first call Start for a StandardError handle.
//
Status = ConSplitterStart (
This,
@@ -1476,7 +1476,7 @@ ConSplitterStdErrDriverBindingStart (
// their MaxMode and QueryData should be the intersection of both.
//
Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL, NULL);
- ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK));
+ ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK));
return Status;
}
@@ -1522,7 +1522,7 @@ ConSplitterStop (
return Status;
}
//
- // close the protocol refered.
+ // close the protocol referred.
//
gBS->CloseProtocol (
ControllerHandle,
@@ -1543,7 +1543,7 @@ ConSplitterStop (
/**
- Stop Console In ConSplitter on ControllerHandle by closing Console In Devcice GUID.
+ Stop Console In ConSplitter on ControllerHandle by closing Console In Device GUID.
@param This Driver Binding protocol instance pointer.
@param ControllerHandle Handle of device to stop driver on
@@ -1718,7 +1718,7 @@ ConSplitterAbsolutePointerDriverBindingStop (
/**
- Stop Console Out ConSplitter on device handle by closing Console Out Devcice GUID.
+ Stop Console Out ConSplitter on device handle by closing Console Out Devcie GUID.
@param This Driver Binding protocol instance pointer.
@param ControllerHandle Handle of device to stop driver on
@@ -2725,7 +2725,7 @@ ConSplitterGetIntersectionBetweenConOutAndStrErr (
/**
- Add Grahpics Output modes into Consplitter Text Out list.
+ Add Graphics Output modes into Consplitter Text Out list.
@param Private Text Out Splitter pointer.
@param GraphicsOutput Graphics Output protocol pointer.
@@ -3392,7 +3392,7 @@ ConSplitterTextOutDeleteDevice (
return EFI_SUCCESS;
}
//
- // Max Mode is realy an intersection of the QueryMode command to all
+ // Max Mode is really an intersection of the QueryMode command to all
// devices. So we must copy the QueryMode of the first device to
// QueryData.
//
@@ -3430,7 +3430,7 @@ ConSplitterTextOutDeleteDevice (
/**
- Reset the input device and optionaly run diagnostics
+ Reset the input device and optionally run diagnostics
@param This Protocol instance pointer.
@param ExtendedVerification Driver may perform diagnostics on reset.
@@ -3514,7 +3514,7 @@ ConSplitterTextInExDequeueKey (
/**
Reads the next keystroke from the input device. The WaitForKey Event can
- be used to test for existance of a keystroke via WaitForEvent () call.
+ be used to test for existence of a keystroke via WaitForEvent () call.
@param Private Protocol instance pointer.
@param Key Driver may perform diagnostics on reset.
@@ -3587,7 +3587,7 @@ ConSplitterTextInPrivateReadKeyStroke (
/**
Reads the next keystroke from the input device. The WaitForKey Event can
- be used to test for existance of a keystroke via WaitForEvent () call.
+ be used to test for existence of a keystroke via WaitForEvent () call.
@param This Protocol instance pointer.
@param Key Driver may perform diagnostics on reset.
@@ -3631,7 +3631,7 @@ ConSplitterTextInReadKeyStroke (
spliter event. This will cause the calling code to call
ConSplitterTextInReadKeyStroke ().
- @param Event The Event assoicated with callback.
+ @param Event The Event associated with callback.
@param Context Context registered when Event was created.
**/
@@ -3681,7 +3681,7 @@ ConSplitterTextInWaitForKey (
pressed.
@retval TRUE Key be pressed matches a registered key.
- @retval FLASE Match failed.
+ @retval FALSE Match failed.
**/
BOOLEAN
@@ -3715,7 +3715,7 @@ IsKeyRegistered (
/**
- Reset the input device and optionaly run diagnostics
+ Reset the input device and optionally run diagnostics
@param This Protocol instance pointer.
@param ExtendedVerification Driver may perform diagnostics on reset.
@@ -3769,7 +3769,7 @@ ConSplitterTextInResetEx (
/**
Reads the next keystroke from the input device. The WaitForKey Event can
- be used to test for existance of a keystroke via WaitForEvent () call.
+ be used to test for existence of a keystroke via WaitForEvent () call.
@param This Protocol instance pointer.
@param KeyData A pointer to a buffer that is filled in with the
@@ -3978,7 +3978,7 @@ ConSplitterTextInSetState (
@retval EFI_SUCCESS The notification function was registered
successfully.
- @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necesssary data
+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data
structures.
@retval EFI_INVALID_PARAMETER KeyData or KeyNotificationFunction or NotifyHandle is NULL.
@@ -4126,7 +4126,7 @@ ConSplitterTextInUnregisterKeyNotify (
/**
- Reset the input device and optionaly run diagnostics
+ Reset the input device and optionally run diagnostics
@param This Protocol instance pointer.
@param ExtendedVerification Driver may perform diagnostics on reset.
@@ -4174,7 +4174,7 @@ ConSplitterSimplePointerReset (
/**
Reads the next keystroke from the input device. The WaitForKey Event can
- be used to test for existance of a keystroke via WaitForEvent () call.
+ be used to test for existence of a keystroke via WaitForEvent () call.
@param Private Protocol instance pointer.
@param State The state information of simple pointer device.
@@ -4279,12 +4279,12 @@ ConSplitterSimplePointerGetState (
/**
- This event agregates all the events of the ConIn devices in the spliter.
+ This event aggregates all the events of the ConIn devices in the spliter.
If any events of physical ConIn devices are signaled, signal the ConIn
spliter event. This will cause the calling code to call
ConSplitterTextInReadKeyStroke ().
- @param Event The Event assoicated with callback.
+ @param Event The Event associated with callback.
@param Context Context registered when Event was created.
**/
@@ -4493,12 +4493,12 @@ ConSplitterAbsolutePointerGetState (
/**
- This event agregates all the events of the pointer devices in the splitter.
+ This event aggregates all the events of the pointer devices in the splitter.
If any events of physical pointer devices are signaled, signal the pointer
splitter event. This will cause the calling code to call
ConSplitterAbsolutePointerGetState ().
- @param Event The Event assoicated with callback.
+ @param Event The Event associated with callback.
@param Context Context registered when Event was created.
**/
@@ -4537,10 +4537,10 @@ ConSplitterAbsolutePointerWaitForInput (
/**
- Reset the text output device hardware and optionaly run diagnostics
+ Reset the text output device hardware and optionally run diagnostics
@param This Protocol instance pointer.
- @param ExtendedVerification Driver may perform more exhaustive verfication
+ @param ExtendedVerification Driver may perform more exhaustive verification
operation of the device during reset.
@retval EFI_SUCCESS The text output device was reset.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
index fdc79cd3465..066278c4579 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitter.h
@@ -1852,7 +1852,7 @@ ConSplitterGraphicsOutputSetMode (
@retval EFI_SUCCESS The Blt operation completed.
@retval EFI_INVALID_PARAMETER BltOperation is not valid.
- @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
+ @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video
buffer.
**/
@@ -1966,7 +1966,7 @@ ConSplitterUgaDrawSetMode (
@retval EFI_SUCCESS The Blt operation completed.
@retval EFI_INVALID_PARAMETER BltOperation is not valid.
- @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
+ @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
index 73b71c8ac43..a2038cc74c1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterGraphics.c
@@ -238,7 +238,7 @@ ConSplitterGraphicsOutputSetMode (
@retval EFI_SUCCESS The Blt operation completed.
@retval EFI_INVALID_PARAMETER BltOperation is not valid.
- @retval EFI_DEVICE_ERROR A hardware error occured writting to the video
+ @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video
buffer.
**/
@@ -513,7 +513,7 @@ ConSplitterUgaDrawSetMode (
@retval EFI_SUCCESS The Blt operation completed.
@retval EFI_INVALID_PARAMETER BltOperation is not valid.
- @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer.
+ @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
index 3bebe65a6e6..cd231d936b7 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.c
@@ -33,7 +33,7 @@ GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = {
EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK),
0,
0,
- TRUE
+ FALSE
},
(GRAPHICS_CONSOLE_MODE_DATA *) NULL,
(EFI_GRAPHICS_OUTPUT_BLT_PIXEL *) NULL
@@ -214,7 +214,7 @@ Error:
@param[in] HorizontalResolution The size of video screen in pixels in the X dimension.
@param[in] VerticalResolution The size of video screen in pixels in the Y dimension.
- @param[in] GopModeNumber The graphics mode number which graphis console is based on.
+ @param[in] GopModeNumber The graphics mode number which graphics console is based on.
@param[out] TextModeCount The total number of text modes that graphics console supports.
@param[out] TextModeData The buffer to the text modes column and row information.
Caller is responsible to free it when it's non-NULL.
@@ -491,7 +491,7 @@ GraphicsConsoleControllerDriverStart (
Mode = Private->GraphicsOutput->Mode;
if (EFI_ERROR (Status) && Mode->MaxMode != 0) {
//
- // Set default mode failed or device don't support default mode, then get the current mode information
+ // If set default mode failed or device doesn't support default mode, then get the current mode information
//
HorizontalResolution = Mode->Info->HorizontalResolution;
VerticalResolution = Mode->Info->VerticalResolution;
@@ -501,7 +501,7 @@ GraphicsConsoleControllerDriverStart (
}
if (ModeNumber != Private->GraphicsOutput->Mode->Mode) {
//
- // Current graphics mode is not set or is not set to the mode which we has found,
+ // Current graphics mode is not set or is not set to the mode which we have found,
// set the new graphic mode.
//
Status = Private->GraphicsOutput->SetMode (Private->GraphicsOutput, ModeNumber);
@@ -740,7 +740,7 @@ GraphicsConsoleControllerDriverStop (
Check if the current specific mode supported the user defined resolution
for the Graphics Console device based on Graphics Output Protocol.
- If yes, set the graphic devcice's current mode to this specific mode.
+ If yes, set the graphic device's current mode to this specific mode.
@param GraphicsOutput Graphics Output Protocol instance pointer.
@param HorizontalResolution User defined horizontal resolution
@@ -843,7 +843,7 @@ EfiLocateHiiProtocol (
Reset the text output device hardware and optionally run diagnostics.
Implements SIMPLE_TEXT_OUTPUT.Reset().
- If ExtendeVerification is TRUE, then perform dependent Graphics Console
+ If ExtendedVerification is TRUE, then perform dependent Graphics Console
device reset, and set display mode to mode 0.
If ExtendedVerification is FALSE, only set display mode to mode 0.
@@ -1713,7 +1713,7 @@ GraphicsConsoleConOutEnableCursor (
}
/**
- Gets Graphics Console devcie's foreground color and background color.
+ Gets Graphics Console device's foreground color and background color.
@param This Protocol instance pointer.
@param Foreground Returned text foreground color.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
index 1d8cba07a3c..b523039d8c5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsole.h
@@ -205,7 +205,7 @@ GraphicsConsoleComponentNameGetControllerName (
Reset the text output device hardware and optionally run diagnostics.
Implements SIMPLE_TEXT_OUTPUT.Reset().
- If ExtendeVerification is TRUE, then perform dependent Graphics Console
+ If ExtendedVerification is TRUE, then perform dependent Graphics Console
device reset, and set display mode to mode 0.
If ExtendedVerification is FALSE, only set display mode to mode 0.
@@ -286,7 +286,7 @@ GraphicsConsoleConOutTestString (
supports
Implements SIMPLE_TEXT_OUTPUT.QueryMode().
- It returnes information for an available text mode that the Graphics Console supports.
+ It returns information for an available text mode that the Graphics Console supports.
In this driver,we only support text mode 80x25, which is defined as mode 0.
@param This Protocol instance pointer.
@@ -422,7 +422,7 @@ GraphicsConsoleConOutEnableCursor (
/**
Test to see if Graphics Console could be supported on the Controller.
- Graphics Console could be supported if Graphics Output Protocol or UGA Draw
+ Graphics Console could be supported if Graphics Output Protocol or UGADraw
Protocol exists on the Controller. (UGA Draw Protocol could be skipped
if PcdUgaConsumeSupport is set to FALSE.)
@@ -510,7 +510,7 @@ EfiLocateHiiProtocol (
/**
- Gets Graphics Console devcie's foreground color and background color.
+ Gets Graphics Console device's foreground color and background color.
@param This Protocol instance pointer.
@param Foreground Returned text foreground color.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
index 1706177c525..8a3b8b10854 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Console/TerminalDxe/Terminal.h
@@ -37,7 +37,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
-#define RAW_FIFO_MAX_NUMBER 256
+#define RAW_FIFO_MAX_NUMBER 255
#define FIFO_MAX_NUMBER 128
typedef struct {
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.c
index 6becabe522a..e9581006357 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.c
@@ -632,7 +632,7 @@ DebugPortWrite (
the DebugPort interface.
@retval EFI_NOT_READY There are no characters ready to read from the
DebugPort interface
- @retval EFI_DEVICE_ERROR A hardware failure occured... (from SerialIo)
+ @retval EFI_DEVICE_ERROR A hardware failure occurred... (from SerialIo)
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.h
index 3f2e332b280..d9ce3c0d8b6 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DebugPortDxe/DebugPort.h
@@ -378,7 +378,7 @@ DebugPortWrite (
the DebugPort interface.
@retval EFI_NOT_READY There are no characters ready to read from the
DebugPort interface
- @retval EFI_DEVICE_ERROR A hardware failure occured... (from SerialIo)
+ @retval EFI_DEVICE_ERROR A hardware failure occurred... (from SerialIo)
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
index 65c95fb1b51..6e3a85d31b1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c
@@ -135,14 +135,17 @@ PartitionInstallMbrChildHandles (
EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode;
UINT32 BlockSize;
UINT32 MediaId;
- EFI_LBA LastBlock;
+ EFI_LBA LastSector;
EFI_PARTITION_INFO_PROTOCOL PartitionInfo;
Found = EFI_NOT_FOUND;
- BlockSize = BlockIo->Media->BlockSize;
- MediaId = BlockIo->Media->MediaId;
- LastBlock = BlockIo->Media->LastBlock;
+ BlockSize = BlockIo->Media->BlockSize;
+ MediaId = BlockIo->Media->MediaId;
+ LastSector = DivU64x32 (
+ MultU64x32 (BlockIo->Media->LastBlock + 1, BlockSize),
+ MBR_SIZE
+ ) - 1;
//
// Ensure the block size can hold the MBR
@@ -167,7 +170,7 @@ PartitionInstallMbrChildHandles (
Found = Status;
goto Done;
}
- if (!PartitionValidMbr (Mbr, LastBlock)) {
+ if (!PartitionValidMbr (Mbr, LastSector)) {
goto Done;
}
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
index c1e5eccf4e6..f183e9c884d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Disk/PartitionDxe/Partition.c
@@ -35,14 +35,22 @@ EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = {
//
// Prioritized function list to detect partition table.
+// Refer to UEFI Spec 13.3.2 Partition Discovery, the block device
+// should be scanned in below order:
+// 1. GPT
+// 2. ISO 9660 (El Torito) (or UDF)
+// 3. MBR
+// 4. no partiton found
+// Note: UDF is using a same method as booting from CD-ROM, so put it along
+// with CD-ROM check.
//
PARTITION_DETECT_ROUTINE mPartitionDetectRoutineTable[] = {
#ifdef VBOX
PartitionInstallAppleChildHandles,
#endif
PartitionInstallGptChildHandles,
- PartitionInstallMbrChildHandles,
PartitionInstallUdfChildHandles,
+ PartitionInstallMbrChildHandles,
NULL
};
@@ -1331,6 +1339,15 @@ PartitionInstallChildHandle (
} else {
FreePool (Private->DevicePath);
FreePool (Private);
+
+ //
+ // if the Status == EFI_ALREADY_STARTED, it means the child handles
+ // are already installed. So return EFI_SUCCESS to avoid do the next
+ // partition type check.
+ //
+ if (Status == EFI_ALREADY_STARTED) {
+ Status = EFI_SUCCESS;
+ }
}
return Status;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
index 8abab897888..5adc10c5980 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/FormDisplay.c
@@ -372,7 +372,7 @@ GetWidth (
{
CHAR16 *String;
UINTN Size;
- EFI_IFR_TEXT *TestOp;
+ EFI_IFR_TEXT *TextOp;
UINT16 ReturnWidth;
FORM_DISPLAY_ENGINE_STATEMENT *Statement;
@@ -394,9 +394,9 @@ GetWidth (
// See if the second text parameter is really NULL
//
if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
- TestOp = (EFI_IFR_TEXT *) Statement->OpCode;
- if (TestOp->TextTwo != 0) {
- String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);
+ TextOp = (EFI_IFR_TEXT *) Statement->OpCode;
+ if (TextOp->TextTwo != 0) {
+ String = GetToken (TextOp->TextTwo, gFormData->HiiHandle);
Size = StrLen (String);
FreePool (String);
}
@@ -2166,7 +2166,7 @@ HasOptionString (
FORM_DISPLAY_ENGINE_STATEMENT *Statement;
CHAR16 *String;
UINTN Size;
- EFI_IFR_TEXT *TestOp;
+ EFI_IFR_TEXT *TextOp;
Size = 0;
Statement = MenuOption->ThisTag;
@@ -2175,9 +2175,9 @@ HasOptionString (
// See if the second text parameter is really NULL
//
if (Statement->OpCode->OpCode == EFI_IFR_TEXT_OP) {
- TestOp = (EFI_IFR_TEXT *) Statement->OpCode;
- if (TestOp->TextTwo != 0) {
- String = GetToken (TestOp->TextTwo, gFormData->HiiHandle);
+ TextOp = (EFI_IFR_TEXT *) Statement->OpCode;
+ if (TextOp->TextTwo != 0) {
+ String = GetToken (TextOp->TextTwo, gFormData->HiiHandle);
Size = StrLen (String);
FreePool (String);
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
index b493e55534e..c21ccabbb7e 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DisplayEngineDxe/ProcessOptions.c
@@ -914,6 +914,116 @@ PasswordProcess (
}
/**
+ Print some debug message about mismatched menu info.
+
+ @param MenuOption The MenuOption for this Question.
+
+**/
+VOID
+PrintMismatchMenuInfo (
+ IN UI_MENU_OPTION *MenuOption
+)
+{
+ CHAR16 *FormTitleStr;
+ CHAR16 *FormSetTitleStr;
+ CHAR16 *OneOfOptionStr;
+ CHAR16 *QuestionName;
+ LIST_ENTRY *Link;
+ FORM_DISPLAY_ENGINE_STATEMENT *Question;
+ EFI_IFR_ORDERED_LIST *OrderList;
+ UINT8 Index;
+ EFI_HII_VALUE HiiValue;
+ EFI_HII_VALUE *QuestionValue;
+ DISPLAY_QUESTION_OPTION *Option;
+ UINT8 *ValueArray;
+ UINT8 ValueType;
+ EFI_IFR_FORM_SET *FormsetBuffer;
+ UINTN FormsetBufferSize;
+
+ Question = MenuOption->ThisTag;
+ HiiGetFormSetFromHiiHandle (gFormData->HiiHandle, &FormsetBuffer, &FormsetBufferSize);
+
+ FormSetTitleStr = GetToken (FormsetBuffer->FormSetTitle, gFormData->HiiHandle);
+ FormTitleStr = GetToken (gFormData->FormTitle, gFormData->HiiHandle);
+
+ DEBUG ((DEBUG_ERROR, "\n[%a]: Mismatch Formset : Formset Guid = %g, FormSet title = %s\n", gEfiCallerBaseName, &gFormData->FormSetGuid, FormSetTitleStr));
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Form : FormId = %d, Form title = %s.\n", gEfiCallerBaseName, gFormData->FormId, FormTitleStr));
+
+ if (Question->OpCode->OpCode == EFI_IFR_ORDERED_LIST_OP) {
+ QuestionName = GetToken (((EFI_IFR_ORDERED_LIST*)MenuOption->ThisTag->OpCode)->Question.Header.Prompt, gFormData->HiiHandle);
+ Link = GetFirstNode (&Question->OptionListHead);
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ ValueType = Option->OptionOpCode->Type;
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Error : OrderedList value in the array doesn't match with option value.\n", gEfiCallerBaseName));
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OrderedList: Name = %s.\n", gEfiCallerBaseName, QuestionName));
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OrderedList: OrderedList array value :\n", gEfiCallerBaseName));
+
+ OrderList = (EFI_IFR_ORDERED_LIST *) Question->OpCode;
+ for (Index = 0; Index < OrderList->MaxContainers; Index++) {
+ ValueArray = Question->CurrentValue.Buffer;
+ HiiValue.Value.u64 = GetArrayData (ValueArray, ValueType, Index);
+ DEBUG ((DEBUG_ERROR, " Value[%d] =%ld.\n", Index, HiiValue.Value.u64));
+ }
+ } else if (Question->OpCode->OpCode == EFI_IFR_ONE_OF_OP) {
+ QuestionName = GetToken (((EFI_IFR_ONE_OF*)MenuOption->ThisTag->OpCode)->Question.Header.Prompt, gFormData->HiiHandle);
+ QuestionValue = &Question->CurrentValue;
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch Error : OneOf value doesn't match with option value.\n", gEfiCallerBaseName));
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : Name = %s.\n", gEfiCallerBaseName, QuestionName));
+ switch (QuestionValue->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %ld.\n",gEfiCallerBaseName, QuestionValue->Value.u64));
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n",gEfiCallerBaseName, QuestionValue->Value.u32));
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n",gEfiCallerBaseName, QuestionValue->Value.u16));
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ DEBUG ((DEBUG_ERROR, "[%a]: Mismatch OneOf : OneOf value = %d.\n",gEfiCallerBaseName, QuestionValue->Value.u8));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ }
+
+ Index = 0;
+ Link = GetFirstNode (&Question->OptionListHead);
+ while (!IsNull (&Question->OptionListHead, Link)) {
+ Option = DISPLAY_QUESTION_OPTION_FROM_LINK (Link);
+ OneOfOptionStr = GetToken (Option->OptionOpCode->Option, gFormData->HiiHandle);
+ switch (Option->OptionOpCode->Type) {
+ case EFI_IFR_TYPE_NUM_SIZE_64:
+ DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %ld, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u64, OneOfOptionStr));
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_32:
+ DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u32, OneOfOptionStr));
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_16:
+ DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u16, OneOfOptionStr));
+ break;
+
+ case EFI_IFR_TYPE_NUM_SIZE_8:
+ DEBUG ((DEBUG_ERROR, "[%a]: Option %d : Option Value = %d, Option Name = %s.\n",gEfiCallerBaseName, Index, Option->OptionOpCode->Value.u8, OneOfOptionStr));
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ Link = GetNextNode (&Question->OptionListHead, Link);
+ Index++;
+ }
+}
+
+/**
Process a Question's Option (whether selected or un-selected).
@param MenuOption The MenuOption for this Question.
@@ -1012,6 +1122,11 @@ ProcessOptions (
OneOfOption = ValueToOption (Question, &HiiValue);
if (OneOfOption == NULL) {
+ //
+ // Print debug msg for the mistach menu.
+ //
+ PrintMismatchMenuInfo (MenuOption);
+
if (SkipErrorValue) {
//
// Just try to get the option string, skip the value which not has option.
@@ -1084,6 +1199,11 @@ ProcessOptions (
continue;
}
+ //
+ // Print debug msg for the mistach menu.
+ //
+ PrintMismatchMenuInfo (MenuOption);
+
if (SkipErrorValue) {
//
// Not report error, just get the correct option string info.
@@ -1154,6 +1274,11 @@ ProcessOptions (
OneOfOption = ValueToOption (Question, QuestionValue);
if (OneOfOption == NULL) {
+ //
+ // Print debug msg for the mistach menu.
+ //
+ PrintMismatchMenuInfo (MenuOption);
+
if (SkipErrorValue) {
//
// Not report error, just get the correct option string info.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.uni
index e7f16c41849..92cd5a1cbc2 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSample.uni
@@ -2,7 +2,7 @@
// This is a sample HII driver.
//
// This driver shows how HII protocol, VFR and UNI files are used to create a HII
-// driver which can be dipslayed and configured by a UEFI HII Form Browser.
+// driver which can be displayed and configured by a UEFI HII Form Browser.
//
// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
index 27e20f2c06b..7fdbff3dc51 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
@@ -2,7 +2,7 @@
# This is a sample HII driver.
#
# This driver shows how HII protocol, VFR and UNI files are used to create a HII
-# driver which can be dipslayed and configured by a UEFI HII Form Browser.
+# driver which can be displayed and configured by a UEFI HII Form Browser.
#
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
#
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
index 07fd95f841b..ba208564dba 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/NVDataStruc.h
@@ -1,6 +1,7 @@
/** @file
-Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>*
+(C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
Module Name:
@@ -92,6 +93,8 @@ typedef struct {
UINT16 BitNumeric : 12;
MY_BITS_DATA MyBitData;
MY_EFI_UNION_DATA MyUnionData;
+ UINT8 QuestionXUefiKeywordRestStyle;
+ UINT8 QuestionNonXUefiKeywordRestStyle;
} DRIVER_SAMPLE_CONFIGURATION;
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
index 94a4cd1ff85..ddec2c0e1c4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/Vfr.vfr
@@ -3,6 +3,7 @@
// Sample Setup formset.
//
// Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
//**/
@@ -290,6 +291,41 @@ formset
endoneof;
//
+ // This is an HII option which has REST_STYLE flag and x-UEFI namespace
+ // UNI string associated. This HII option could be configured by either in-band
+ // edk2 setup browser or the remote management in out-of-band such as Redfish
+ // service. This HII option is configured through EFI_KEYWORD_HANDLER_PROTOCOL.
+ //
+ oneof varid = MyIfrNVData.QuestionXUefiKeywordRestStyle,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT_X_UEFI),
+ help = STRING_TOKEN(STR_ONE_OF_PROMPT_X_UEFI_HELP),
+ flags = RESET_REQUIRED | REST_STYLE,
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = 0;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT;
+ option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 3, flags = 0;
+ endoneof;
+
+
+ //
+ // This is a HII option which has REST_STYLE flag but without the x-UEFI namespace
+ // UNI string associated. This HII option could be configured by either
+ // setup browser or the remote management in out-of-band such as Redfish
+ // service. This HII option is configured through EFI HII Configuration Routing
+ // Protocol becasue it doesn't have x-UEFI namespace UNI string.
+ //
+ numeric varid = MyIfrNVData.QuestionNonXUefiKeywordRestStyle,
+ prompt = STRING_TOKEN(STR_ONE_OF_PROMPT_NON_X_UEFI),
+ help = STRING_TOKEN(STR_ONE_OF_PROMPT_NON_X_UEFI_HELP),
+ flags = RESET_REQUIRED | REST_STYLE,
+ minimum = 0,
+ maximum = 0xf0,
+ step = 0, // Stepping of 0 equates to a manual entering
+ // of a value, otherwise it will be adjusted by "+"/"-"
+ default = 0, // defaultstore could be used to specify the default type
+ // If no defaultstore is specified, it implies Standard Default
+ endnumeric;
+
+ //
// Define a string (EFI_IFR_STRING)
//
string varid = MyIfrNVData.MyStringData,
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
index bafa194c638..8a3e286bec9 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/DriverSampleDxe/VfrStrings.uni
@@ -1,6 +1,7 @@
// *++
//
// Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Module Name:
@@ -56,6 +57,13 @@
#language x-UEFI-ns "iSCSIBootEnable"
#string STR_CHECK_KEYWORD_SUPPORT #language en-US "Check iSCSI Boot Enable"
#language fr-FR "Check iSCSI Boot Enable"
+#string STR_ONE_OF_PROMPT_X_UEFI #language en-US "x-UEFI HII Option"
+ #language fr-FR "x-UEFI HII Option"
+ #language x-UEFI-ns "xUefiHiiOption"
+#string STR_ONE_OF_PROMPT_X_UEFI_HELP #language en-US "This is an HII option which has REST_STYLE flag and x-UEFI namespace UNI string associated. This HII option could be configured by either in-band edk2 setup browser or the remote management in out-of-band such as Redfish service. This HII option is configured through EFI_KEYWORD_HANDLER_PROTOCOL."
+#string STR_ONE_OF_PROMPT_NON_X_UEFI #language en-US "Non x-UEFI HII Option"
+ #language fr-FR "Non x-UEFI HII Option"
+#string STR_ONE_OF_PROMPT_NON_X_UEFI_HELP #language en-US "This is a HII option which has REST_STYLE flag but without the x-UEFI namespace UNI string associated. This HII option could be configured by either setup browser or the remote management in out-of-band such as Redfish service. This HII option is configured through EFI HII Configuration Routing Protocol becasue it doesn't have x-UEFI namespace UNI string."
#string STR_ONE_OF_HELP #language en-US "My one-of help is going to be a long string to test out the efficiency of the ability of the I am tired of typing capabilities"
#language fr-FR "Mi uno- de ayuda va a ser una cadena larga a probar fuera de la eficacia de la capacidad del yo es cansada de capacidades el pulsar."
#string STR_ONE_OF_TEXT1 #language en-US "My one-of text #1"
@@ -259,12 +267,12 @@
#language fr-FR ""
#string STR_SUBMITTED_CALLBACK_TEST_PROMPT #language en-US "Submitted callback test"
#language fr-FR "Submitted callback test"
-#string STR_SUBMITTED_CALLBACK_TEST_HELP #language en-US "Change the value and press F10 to submmit will pop up a dialogue to show SUBMITTED Callback has been triggered"
- #language fr-FR "Change the value and press F10 to submmit will pop up a dialogue to show SUBMITTED Callback has been triggered"
+#string STR_SUBMITTED_CALLBACK_TEST_HELP #language en-US "Change the value and press F10 to submit will pop up a dialogue to show SUBMITTED Callback has been triggered"
+ #language fr-FR "Change the value and press F10 to submit will pop up a dialogue to show SUBMITTED Callback has been triggered"
#string STR_POPUP_TEST_PROMPT #language en-US "Select it to invoke Hii Popup Protocol"
#language fr-FR "Select it to invoke Hii Popup Protocol"
-#string STR_POPUP_TEST_HELP #language en-US "Select this question will pop up a message box, then user can decide whether exit curret form or not"
- #language fr-FR "Select this question will pop up a message box, then user can decide whether exit curret form or not"
+#string STR_POPUP_TEST_HELP #language en-US "Select this question will pop up a message box, then user can decide whether exit current form or not"
+ #language fr-FR "Select this question will pop up a message box, then user can decide whether exit current form or not"
#string STR_POPUP_STRING #language en-US "Are you sure to exit current form?"
#language fr-FR "Are you sure to exit current form?"
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c
index a2f3e1c1490..36aa83fea60 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDebugger/EdbCommand.c
@@ -218,7 +218,7 @@ EFI_DEBUGGER_COMMAND_SET mDebuggerCommandSet[] = {
L"TRACE - show/clear trace instruction branch\n",
L"The trace command will show or clear the latest instruction branch.\n\n",
L"TRACE [c]\n"
- L" (No Argument) - Show current instrcution branch\n"
+ L" (No Argument) - Show current instruction branch\n"
L" c - Clear current instruction branch\n",
L"",
{SCAN_NULL, CHAR_NULL},
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
index 39f2e462b19..ff09bb17f65 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
@@ -1,5 +1,5 @@
## @file
-# Module that produces EBC Interprete and EBC Debug Support protocols.
+# Module that produces EBC Interpreter and EBC Debug Support protocols.
#
# This module implements EFI Byte Code (EBC) Virtual Machine that can provide
# platform and processor-independent mechanisms for loading and executing EFI
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.uni b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.uni
index 746d8b91183..cbe0c3f1cc8 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/EbcDxe/EbcDxe.uni
@@ -1,5 +1,5 @@
// /** @file
-// Module that produces EBC Interprete and EBC Debug Support protocols.
+// Module that produces EBC Interpreter and EBC Debug Support protocols.
//
// This module implements EFI Byte Code (EBC) Virtual Machine that can provide
// platform and processor-independent mechanisms for loading and executing EFI
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
index 794b1a776da..45481aff898 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/FvSimpleFileSystemDxe/FvSimpleFileSystem.c
@@ -362,7 +362,7 @@ RemoveLastItemFromPath (
@param Path The pointer to the string containing the path.
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return Path in all other instances.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
index 0ae02e85b3f..e06a932b5e5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigRouting.c
@@ -5497,7 +5497,6 @@ HiiBlockToConfig (
UINTN Index;
UINT8 *TemBuffer;
CHAR16 *TemString;
- CHAR16 TemChar;
TmpBuffer = NULL;
@@ -5564,10 +5563,13 @@ HiiBlockToConfig (
//
// Copy <ConfigHdr> and an additional '&' to <ConfigResp>
//
- TemChar = *StringPtr;
- *StringPtr = '\0';
- AppendToMultiString(Config, ConfigRequest);
- *StringPtr = TemChar;
+ TemString = AllocateCopyPool (sizeof (CHAR16) * (StringPtr - ConfigRequest + 1), ConfigRequest);
+ if (TemString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ TemString[StringPtr - ConfigRequest] = '\0';
+ AppendToMultiString(Config, TemString);
+ FreePool (TemString);
//
// Parse each <RequestElement> if exists
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
index 5b00256fb48..345bf066a2a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
@@ -317,7 +317,7 @@ InstallFileLoadProtocol (
EFI_FIRMWARE_VOLUME_PROTOCOL on the handle of the FFS. This notification function
also handles the situation when LZMA decoder driver loaded later than FirmwareVolume driver.
- @param Event The event that occured
+ @param Event The event that occurred
@param Context Context of event. Not used in this nofication function.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c
index 69eae3f77d5..f339af6e38f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.c
@@ -539,12 +539,12 @@ InitializeMemoryTest (
@param[out] TestedMemorySize Return the tested extended memory size.
@param[out] TotalMemorySize Return the whole system physical memory size.
The total memory size does not include memory in a slot with a disabled DIMM.
- @param[out] ErrorOut TRUE if the memory error occured.
+ @param[out] ErrorOut TRUE if the memory error occurred.
@param[in] IfTestAbort Indicates that the user pressed "ESC" to skip the memory test.
@retval EFI_SUCCESS One block of memory passed the test.
@retval EFI_NOT_FOUND All memory blocks have already been tested.
- @retval EFI_DEVICE_ERROR Memory device error occured, and no agent can handle it.
+ @retval EFI_DEVICE_ERROR Memory device error occurred, and no agent can handle it.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h
index e9af28030b1..fca393fc3ca 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/MemoryTest/GenericMemoryTestDxe/LightMemoryTest.h
@@ -280,12 +280,12 @@ InitializeMemoryTest (
@param[out] TestedMemorySize Return the tested extended memory size.
@param[out] TotalMemorySize Return the whole system physical memory size.
The total memory size does not include memory in a slot with a disabled DIMM.
- @param[out] ErrorOut TRUE if the memory error occured.
+ @param[out] ErrorOut TRUE if the memory error occurred.
@param[in] IfTestAbort Indicates that the user pressed "ESC" to skip the memory test.
@retval EFI_SUCCESS One block of memory passed the test.
@retval EFI_NOT_FOUND All memory blocks have already been tested.
- @retval EFI_DEVICE_ERROR Memory device error occured, and no agent can handle it.
+ @retval EFI_DEVICE_ERROR Memory device error occurred, and no agent can handle it.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c
index b07d0ff679e..0917be95ca9 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c
@@ -776,7 +776,7 @@ InitOverridesMapping (
// Check buffer overflow
//
if ((DriverImageInfo->DriverImagePath == NULL) || (VariableIndex < (UINT8 *) DriverDevicePath) ||
- (VariableIndex < (UINT8 *) VariableBuffer + BufferSize)) {
+ (VariableIndex > (UINT8 *) VariableBuffer + BufferSize)) {
Corrupted = TRUE;
break;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PrintDxe/Print.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PrintDxe/Print.c
index d572eb1e50a..38e15e296c5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PrintDxe/Print.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/PrintDxe/Print.c
@@ -17,7 +17,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
/**
Implementaion of the UnicodeValueToString service in EFI_PRINT2_PROTOCOL.
- If the macro DISABLE_NEW_DEPRECATED_INTERFACES is defined, then ASSERT().
@param Buffer The pointer to the output buffer for the produced
Null-terminated Unicode string.
@@ -27,9 +26,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
@param Width The maximum number of Unicode characters to place in Buffer,
not including the Null-terminator.
- @return If the macro DISABLE_NEW_DEPRECATED_INTERFACES is defined, return 0.
- Otherwise, return the number of Unicode characters in Buffer not
- including the Null-terminator.
+ @return 0.
+
**/
UINTN
@@ -41,28 +39,16 @@ PrintDxeUnicodeValueToString (
IN UINTN Width
)
{
-#ifdef DISABLE_NEW_DEPRECATED_INTERFACES
- //
- // If the macro DISABLE_NEW_DEPRECATED_INTERFACES is defined, then the
- // PrintLib API UnicodeValueToString is already deprecated.
- // In this case, ASSERT will be triggered and zero will be returned for the
- // implementation of the UnicodeValueToString service in EFI_PRINT2_PROTOCOL
- // to indicate that the service is no longer supported.
- //
DEBUG ((DEBUG_ERROR, "PrintDxe: The UnicodeValueToString service in EFI_PRINT2_PROTOCOL is no longer supported for security reason.\n"));
DEBUG ((DEBUG_ERROR, "PrintDxe: Please consider using the UnicodeValueToStringS service in EFI_PRINT2S_PROTOCOL.\n"));
ASSERT (FALSE);
return 0;
-#else
- return UnicodeValueToString (Buffer, Flags, Value, Width);
-#endif
+
}
/**
Implementaion of the AsciiValueToString service in EFI_PRINT2_PROTOCOL.
- If the macro DISABLE_NEW_DEPRECATED_INTERFACES is defined, then ASSERT().
-
@param Buffer A pointer to the output buffer for the produced
Null-terminated ASCII string.
@param Flags The bitmask of flags that specify left justification, zero
@@ -71,9 +57,7 @@ PrintDxeUnicodeValueToString (
@param Width The maximum number of ASCII characters to place in Buffer,
not including the Null-terminator.
- @return If the macro DISABLE_NEW_DEPRECATED_INTERFACES is defined, return 0.
- Otherwise, return the number of ASCII characters in Buffer not
- including the Null-terminator.
+ @return 0.
**/
UINTN
@@ -85,21 +69,12 @@ PrintDxeAsciiValueToString (
IN UINTN Width
)
{
-#ifdef DISABLE_NEW_DEPRECATED_INTERFACES
- //
- // If the macro DISABLE_NEW_DEPRECATED_INTERFACES is defined, then the
- // PrintLib API AsciiValueToString is already deprecated.
- // In this case, ASSERT will be triggered and zero will be returned for the
- // implementation of the AsciiValueToString service in EFI_PRINT2_PROTOCOL
- // to indicate that the service is no longer supported.
- //
+
DEBUG ((DEBUG_ERROR, "PrintDxe: The AsciiValueToString service in EFI_PRINT2_PROTOCOL is no longer supported for security reason.\n"));
DEBUG ((DEBUG_ERROR, "PrintDxe: Please consider using the AsciiValueToStringS service in EFI_PRINT2S_PROTOCOL.\n"));
ASSERT (FALSE);
return 0;
-#else
- return AsciiValueToString (Buffer, Flags, Value, Width);
-#endif
+
}
EFI_HANDLE mPrintThunkHandle = NULL;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.c
index 14fdf1b8268..a5788673c71 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/RegularExpressionDxe/OnigurumaUefiPort.c
@@ -93,6 +93,6 @@ void* memcpy (void *dest, const void *src, unsigned int count)
void* memset (void *dest, char ch, unsigned int count)
{
- return SetMem (dest, ch, count);
+ return SetMem (dest, count, ch);
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterCommon.c
index 3186b6cd004..9f473436c91 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterCommon.c
@@ -7,7 +7,7 @@
**/
-#include "ReportStatusCodeRouterSmm.h"
+#include "ReportStatusCodeRouterCommon.h"
LIST_ENTRY mCallbackListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallbackListHead);
@@ -17,11 +17,11 @@ LIST_ENTRY mCallbackListHead = INITIALIZE_LIST_HEAD_VARIABLE (mCallba
//
UINT32 mStatusCodeNestStatus = 0;
-EFI_SMM_STATUS_CODE_PROTOCOL mSmmStatusCodeProtocol = {
+EFI_MM_STATUS_CODE_PROTOCOL mSmmStatusCodeProtocol = {
ReportDispatcher
};
-EFI_SMM_RSC_HANDLER_PROTOCOL mSmmRscHandlerProtocol = {
+EFI_MM_RSC_HANDLER_PROTOCOL mSmmRscHandlerProtocol = {
Register,
Unregister
};
@@ -45,18 +45,18 @@ EFI_SMM_RSC_HANDLER_PROTOCOL mSmmRscHandlerProtocol = {
EFI_STATUS
EFIAPI
Register (
- IN EFI_SMM_RSC_HANDLER_CALLBACK Callback
+ IN EFI_MM_RSC_HANDLER_CALLBACK Callback
)
{
LIST_ENTRY *Link;
- SMM_RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
+ MM_RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
if (Callback == NULL) {
return EFI_INVALID_PARAMETER;
}
for (Link = GetFirstNode (&mCallbackListHead); !IsNull (&mCallbackListHead, Link); Link = GetNextNode (&mCallbackListHead, Link)) {
- CallbackEntry = CR (Link, SMM_RSC_HANDLER_CALLBACK_ENTRY, Node, SMM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE);
+ CallbackEntry = CR (Link, MM_RSC_HANDLER_CALLBACK_ENTRY, Node, MM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE);
if (CallbackEntry->RscHandlerCallback == Callback) {
//
// If the function was already registered. It can't be registered again.
@@ -65,10 +65,10 @@ Register (
}
}
- CallbackEntry = (SMM_RSC_HANDLER_CALLBACK_ENTRY *)AllocatePool (sizeof (SMM_RSC_HANDLER_CALLBACK_ENTRY));
+ CallbackEntry = (MM_RSC_HANDLER_CALLBACK_ENTRY *)AllocatePool (sizeof (MM_RSC_HANDLER_CALLBACK_ENTRY));
ASSERT (CallbackEntry != NULL);
- CallbackEntry->Signature = SMM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE;
+ CallbackEntry->Signature = MM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE;
CallbackEntry->RscHandlerCallback = Callback;
InsertTailList (&mCallbackListHead, &CallbackEntry->Node);
@@ -92,18 +92,18 @@ Register (
EFI_STATUS
EFIAPI
Unregister (
- IN EFI_SMM_RSC_HANDLER_CALLBACK Callback
+ IN EFI_MM_RSC_HANDLER_CALLBACK Callback
)
{
LIST_ENTRY *Link;
- SMM_RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
+ MM_RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
if (Callback == NULL) {
return EFI_INVALID_PARAMETER;
}
for (Link = GetFirstNode (&mCallbackListHead); !IsNull (&mCallbackListHead, Link); Link = GetNextNode (&mCallbackListHead, Link)) {
- CallbackEntry = CR (Link, SMM_RSC_HANDLER_CALLBACK_ENTRY, Node, SMM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE);
+ CallbackEntry = CR (Link, MM_RSC_HANDLER_CALLBACK_ENTRY, Node, MM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE);
if (CallbackEntry->RscHandlerCallback == Callback) {
//
// If the function is found in list, delete it and return.
@@ -121,8 +121,8 @@ Unregister (
/**
Provides an interface that a software module can call to report a status code.
- @param This EFI_SMM_STATUS_CODE_PROTOCOL instance.
- @param Type Indicates the type of status code being reported.
+ @param This EFI_MM_STATUS_CODE_PROTOCOL instance.
+ @param CodeType Indicates the type of status code being reported.
@param Value Describes the current status of a hardware or software entity.
This included information about the class and subclass that is used to
classify the entity as well as an operation.
@@ -140,16 +140,16 @@ Unregister (
EFI_STATUS
EFIAPI
ReportDispatcher (
- IN CONST EFI_SMM_STATUS_CODE_PROTOCOL *This,
- IN EFI_STATUS_CODE_TYPE Type,
+ IN CONST EFI_MM_STATUS_CODE_PROTOCOL *This,
+ IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
- IN CONST EFI_GUID *CallerId OPTIONAL,
+ IN CONST EFI_GUID *CallerId,
IN EFI_STATUS_CODE_DATA *Data OPTIONAL
)
{
LIST_ENTRY *Link;
- SMM_RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
+ MM_RSC_HANDLER_CALLBACK_ENTRY *CallbackEntry;
//
// Use atom operation to avoid the reentant of report.
@@ -160,13 +160,13 @@ ReportDispatcher (
}
for (Link = GetFirstNode (&mCallbackListHead); !IsNull (&mCallbackListHead, Link);) {
- CallbackEntry = CR (Link, SMM_RSC_HANDLER_CALLBACK_ENTRY, Node, SMM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE);
+ CallbackEntry = CR (Link, MM_RSC_HANDLER_CALLBACK_ENTRY, Node, MM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE);
//
// The handler may remove itself, so get the next handler in advance.
//
Link = GetNextNode (&mCallbackListHead, Link);
CallbackEntry->RscHandlerCallback (
- Type,
+ CodeType,
Value,
Instance,
(EFI_GUID*)CallerId,
@@ -186,20 +186,15 @@ ReportDispatcher (
/**
Entry point of Generic Status Code Driver.
- This function is the entry point of SMM Status Code Router .
- It produces SMM Report Stataus Code Handler and Status Code protocol.
-
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
+ This function is the common entry point of MM Status Code Router.
+ It produces MM Report Status Code Handler and Status Code protocol.
@retval EFI_SUCCESS The entry point is executed successfully.
**/
EFI_STATUS
-EFIAPI
-GenericStatusCodeSmmEntry (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+GenericStatusCodeCommonEntry (
+ VOID
)
{
EFI_STATUS Status;
@@ -210,9 +205,9 @@ GenericStatusCodeSmmEntry (
//
// Install SmmRscHandler Protocol
//
- Status = gSmst->SmmInstallProtocolInterface (
+ Status = gMmst->MmInstallProtocolInterface (
&Handle,
- &gEfiSmmRscHandlerProtocolGuid,
+ &gEfiMmRscHandlerProtocolGuid,
EFI_NATIVE_INTERFACE,
&mSmmRscHandlerProtocol
);
@@ -221,9 +216,9 @@ GenericStatusCodeSmmEntry (
//
// Install SmmStatusCode Protocol
//
- Status = gSmst->SmmInstallProtocolInterface (
+ Status = gMmst->MmInstallProtocolInterface (
&Handle,
- &gEfiSmmStatusCodeProtocolGuid,
+ &gEfiMmStatusCodeProtocolGuid,
EFI_NATIVE_INTERFACE,
&mSmmStatusCodeProtocol
);
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterCommon.h
index 86e428ddaa9..13c3fff2957 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterCommon.h
@@ -6,28 +6,26 @@
**/
-#ifndef __REPORT_STATUS_CODE_ROUTER_SMM_H__
-#define __REPORT_STATUS_CODE_ROUTER_SMM_H__
+#ifndef __REPORT_STATUS_CODE_ROUTER_COMMON_H__
+#define __REPORT_STATUS_CODE_ROUTER_COMMON_H__
-
-#include <Protocol/SmmReportStatusCodeHandler.h>
-#include <Protocol/SmmStatusCode.h>
+#include <Protocol/MmReportStatusCodeHandler.h>
+#include <Protocol/MmStatusCode.h>
#include <Library/BaseLib.h>
#include <Library/SynchronizationLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/SmmServicesTableLib.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
-#define SMM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE SIGNATURE_32 ('s', 'h', 'c', 'e')
+#define MM_RSC_HANDLER_CALLBACK_ENTRY_SIGNATURE SIGNATURE_32 ('s', 'h', 'c', 'e')
typedef struct {
UINTN Signature;
- EFI_SMM_RSC_HANDLER_CALLBACK RscHandlerCallback;
+ EFI_MM_RSC_HANDLER_CALLBACK RscHandlerCallback;
LIST_ENTRY Node;
-} SMM_RSC_HANDLER_CALLBACK_ENTRY;
+} MM_RSC_HANDLER_CALLBACK_ENTRY;
/**
Register the callback function for ReportStatusCode() notification.
@@ -48,7 +46,7 @@ typedef struct {
EFI_STATUS
EFIAPI
Register (
- IN EFI_SMM_RSC_HANDLER_CALLBACK Callback
+ IN EFI_MM_RSC_HANDLER_CALLBACK Callback
);
/**
@@ -67,14 +65,14 @@ Register (
EFI_STATUS
EFIAPI
Unregister (
- IN EFI_SMM_RSC_HANDLER_CALLBACK Callback
+ IN EFI_MM_RSC_HANDLER_CALLBACK Callback
);
/**
Provides an interface that a software module can call to report a status code.
- @param This EFI_SMM_STATUS_CODE_PROTOCOL instance.
- @param Type Indicates the type of status code being reported.
+ @param This EFI_MM_STATUS_CODE_PROTOCOL instance.
+ @param CodeType Indicates the type of status code being reported.
@param Value Describes the current status of a hardware or software entity.
This included information about the class and subclass that is used to
classify the entity as well as an operation.
@@ -92,12 +90,26 @@ Unregister (
EFI_STATUS
EFIAPI
ReportDispatcher (
- IN CONST EFI_SMM_STATUS_CODE_PROTOCOL *This,
- IN EFI_STATUS_CODE_TYPE Type,
+ IN CONST EFI_MM_STATUS_CODE_PROTOCOL *This,
+ IN EFI_STATUS_CODE_TYPE CodeType,
IN EFI_STATUS_CODE_VALUE Value,
IN UINT32 Instance,
- IN CONST EFI_GUID *CallerId OPTIONAL,
+ IN CONST EFI_GUID *CallerId,
IN EFI_STATUS_CODE_DATA *Data OPTIONAL
);
+/**
+ Entry point of Generic Status Code Driver.
+
+ This function is the common entry point of MM Status Code Router.
+ It produces MM Report Status Code Handler and Status Code protocol.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+GenericStatusCodeCommonEntry (
+ VOID
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
index 85ec7c20c97..a8c66bf085a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterSmm.inf
@@ -16,7 +16,7 @@
MODULE_TYPE = DXE_SMM_DRIVER
PI_SPECIFICATION_VERSION = 0x0001000A
VERSION_STRING = 1.0
- ENTRY_POINT = GenericStatusCodeSmmEntry
+ ENTRY_POINT = GenericStatusCodeTraditionalEntry
#
# The following information is for reference only and not required by the build tools.
@@ -25,15 +25,16 @@
#
[Sources]
- ReportStatusCodeRouterSmm.c
- ReportStatusCodeRouterSmm.h
+ ReportStatusCodeRouterCommon.c
+ ReportStatusCodeRouterCommon.h
+ ReportStatusCodeRouterTraditional.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
- SmmServicesTableLib
+ MmServicesTableLib
UefiDriverEntryPoint
DebugLib
BaseLib
@@ -41,8 +42,8 @@
MemoryAllocationLib
[Protocols]
- gEfiSmmRscHandlerProtocolGuid ## PRODUCES
- gEfiSmmStatusCodeProtocolGuid ## PRODUCES
+ gEfiMmRscHandlerProtocolGuid ## PRODUCES
+ gEfiMmStatusCodeProtocolGuid ## PRODUCES
[Depex]
TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.c
new file mode 100644
index 00000000000..718293bd7a2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.c
@@ -0,0 +1,33 @@
+/** @file
+ Report Status Code Router Driver which produces MM Report Stataus Code Handler Protocol
+ and MM Status Code Protocol.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "ReportStatusCodeRouterCommon.h"
+
+/**
+ Entry point of Generic Status Code Driver.
+
+ This function is the entry point of MM Status Code Router .
+ It produces MM Report Stataus Code Handler and Status Code protocol.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+GenericStatusCodeStandaloneMmEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return GenericStatusCodeCommonEntry ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.inf
new file mode 100644
index 00000000000..a471bcd1061
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterStandaloneMm.inf
@@ -0,0 +1,49 @@
+## @file
+# Report Status Code Router Driver which produces MM Report Stataus Code Handler Protocol and MM Status Code Protocol.
+#
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ReportStatusCodeRouterStandaloneMm
+ FILE_GUID = EAEEDEF9-ABE7-4B95-82B0-5A534C899B46
+ MODULE_TYPE = MM_STANDALONE
+ PI_SPECIFICATION_VERSION = 0x00010032
+ VERSION_STRING = 1.0
+ ENTRY_POINT = GenericStatusCodeStandaloneMmEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ReportStatusCodeRouterCommon.c
+ ReportStatusCodeRouterCommon.h
+ ReportStatusCodeRouterStandaloneMm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MmServicesTableLib
+ StandaloneMmDriverEntryPoint
+ DebugLib
+ BaseLib
+ SynchronizationLib
+ MemoryAllocationLib
+
+[Protocols]
+ gEfiMmRscHandlerProtocolGuid ## PRODUCES
+ gEfiMmStatusCodeProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterTraditional.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterTraditional.c
new file mode 100644
index 00000000000..8bbfaf88efc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/ReportStatusCodeRouter/Smm/ReportStatusCodeRouterTraditional.c
@@ -0,0 +1,33 @@
+/** @file
+ Report Status Code Router Driver which produces MM Report Stataus Code Handler Protocol
+ and MM Status Code Protocol.
+
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "ReportStatusCodeRouterCommon.h"
+
+/**
+ Entry point of Generic Status Code Driver.
+
+ This function is the entry point of SMM Status Code Router .
+ It produces SMM Report Stataus Code Handler and Status Code protocol.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+GenericStatusCodeTraditionalEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return GenericStatusCodeCommonEntry ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
index c86f6889880..dfe28b9d783 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Presentation.c
@@ -19,6 +19,7 @@ LIST_ENTRY mRefreshEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRefreshEv
UINT16 mCurFakeQestId;
FORM_DISPLAY_ENGINE_FORM gDisplayFormData;
BOOLEAN mFinishRetrieveCall = FALSE;
+BOOLEAN mDynamicFormUpdated = FALSE;
/**
Check whether the ConfigAccess protocol is available.
@@ -1762,6 +1763,7 @@ FormUpdateNotify (
)
{
mHiiPackageListUpdated = TRUE;
+ mDynamicFormUpdated = TRUE;
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
index 953c92bc5fe..cf2087b6094 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/SetupBrowserDxe/Setup.c
@@ -68,6 +68,7 @@ extern EFI_GUID mCurrentFormSetGuid;
extern EFI_HII_HANDLE mCurrentHiiHandle;
extern UINT16 mCurrentFormId;
extern FORM_DISPLAY_ENGINE_FORM gDisplayFormData;
+extern BOOLEAN mDynamicFormUpdated;
/**
Create a menu with specified formset GUID and form ID, and add it as a child
@@ -536,6 +537,7 @@ SendForm (
}
Selection->FormSet = FormSet;
mSystemLevelFormSet = FormSet;
+ mDynamicFormUpdated = FALSE;
//
// Display this formset
@@ -547,7 +549,11 @@ SendForm (
gCurrentSelection = NULL;
mSystemLevelFormSet = NULL;
- if (gFlagReconnect || gCallbackReconnect) {
+ //
+ // If callback update form dynamically, it's not exiting of the formset for user so system do not reconnect driver hanlde
+ // this time.
+ //
+ if (!mDynamicFormUpdated && (gFlagReconnect || gCallbackReconnect)) {
RetVal = ReconnectController (FormSet->DriverHandle);
if (!RetVal) {
PopupErrorMessage(BROWSER_RECONNECT_FAIL, NULL, NULL, NULL);
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/SerialStatusCodeWorker.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/SerialStatusCodeWorker.c
index 1676915d09d..a574fa67576 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/SerialStatusCodeWorker.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/SerialStatusCodeWorker.c
@@ -134,7 +134,7 @@ SerialStatusCodeReportWorker (
CharCount = AsciiSPrint (
Buffer,
sizeof (Buffer),
- "%a\n\r",
+ "%a",
((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii
);
} else {
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c
index da4a533323b..129e271d8a4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.c
@@ -2,7 +2,7 @@
Report Status Code Handler PEIM which produces general handlers and hook them
onto the PEI status code router.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -45,13 +45,13 @@ StatusCodeHandlerPeiEntry (
// If enable UseSerial, then initialize serial port.
// if enable UseMemory, then initialize memory status code worker.
//
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
Status = SerialPortInitialize();
ASSERT_EFI_ERROR (Status);
Status = RscHandlerPpi->Register (SerialStatusCodeReportWorker);
ASSERT_EFI_ERROR (Status);
}
- if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
+ if (PcdGetBool (PcdStatusCodeUseMemory)) {
Status = MemoryStatusCodeInitializeWorker ();
ASSERT_EFI_ERROR (Status);
Status = RscHandlerPpi->Register (MemoryStatusCodeReportWorker);
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
index 030cc654ff8..7b3e79a4017 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
@@ -53,11 +53,9 @@
[Ppis]
gEfiPeiRscHandlerPpiGuid ## CONSUMES
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
-
[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1|gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES
[Depex]
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/SerialStatusCodeWorker.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/SerialStatusCodeWorker.c
index 1d1a70ce721..555ae04b9a6 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/SerialStatusCodeWorker.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/SerialStatusCodeWorker.c
@@ -129,7 +129,7 @@ SerialStatusCodeReportWorker (
CharCount = AsciiSPrint (
Buffer,
sizeof (Buffer),
- "%a\n\r",
+ "%a",
((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii
);
} else {
@@ -151,6 +151,16 @@ SerialStatusCodeReportWorker (
//
SerialPortWrite ((UINT8 *) Buffer, CharCount);
+ //
+ // If register an unregister function of gEfiEventExitBootServicesGuid,
+ // then some log called in ExitBootServices() will be lost,
+ // so unregister the handler after receive the value of exit boot service.
+ //
+ if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE &&
+ Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {
+ UnregisterSerialBootTimeHandlers();
+ }
+
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.c
index f91332aaf02..3cdd0c43457 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.c
@@ -2,7 +2,7 @@
Status Code Handler Driver which produces general handlers and hook them
onto the DXE status code router.
- Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,26 +10,20 @@
#include "StatusCodeHandlerRuntimeDxe.h"
EFI_EVENT mVirtualAddressChangeEvent = NULL;
-static EFI_EVENT mExitBootServicesEvent = NULL;
EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
/**
Unregister status code callback functions only available at boot time from
report status code router when exiting boot services.
- @param Event Event whose notification function is being invoked.
- @param Context Pointer to the notification function's context, which is
- always zero in current implementation.
-
**/
VOID
EFIAPI
-UnregisterBootTimeHandlers (
- IN EFI_EVENT Event,
- IN VOID *Context
+UnregisterSerialBootTimeHandlers (
+ VOID
)
{
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
mRscHandlerProtocol->Unregister (SerialStatusCodeReportWorker);
}
}
@@ -80,14 +74,14 @@ InitializationDispatcherWorker (
// If enable UseSerial, then initialize serial port.
// if enable UseRuntimeMemory, then initialize runtime memory status code worker.
//
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
//
// Call Serial Port Lib API to initialize serial port.
//
Status = SerialPortInitialize ();
ASSERT_EFI_ERROR (Status);
}
- if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
+ if (PcdGetBool (PcdStatusCodeUseMemory)) {
Status = RtMemoryStatusCodeInitializeWorker ();
ASSERT_EFI_ERROR (Status);
}
@@ -115,7 +109,7 @@ InitializationDispatcherWorker (
//
// Dispatch records to devices based on feature flag.
//
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
SerialStatusCodeReportWorker (
Record[Index].CodeType,
Record[Index].Value,
@@ -124,7 +118,7 @@ InitializationDispatcherWorker (
NULL
);
}
- if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
+ if (PcdGetBool (PcdStatusCodeUseMemory)) {
RtMemoryStatusCodeReportWorker (
Record[Index].CodeType,
Record[Index].Value,
@@ -171,25 +165,16 @@ StatusCodeHandlerRuntimeDxeEntry (
//
InitializationDispatcherWorker ();
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
mRscHandlerProtocol->Register (SerialStatusCodeReportWorker, TPL_HIGH_LEVEL);
}
- if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
+ if (PcdGetBool (PcdStatusCodeUseMemory)) {
mRscHandlerProtocol->Register (RtMemoryStatusCodeReportWorker, TPL_HIGH_LEVEL);
}
Status = gBS->CreateEventEx (
EVT_NOTIFY_SIGNAL,
TPL_NOTIFY,
- UnregisterBootTimeHandlers,
- NULL,
- &gEfiEventExitBootServicesGuid,
- &mExitBootServicesEvent
- );
-
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
VirtualAddressChangeCallBack,
NULL,
&gEfiEventVirtualAddressChangeGuid,
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.h
index 918ddc8efa8..76d97d64aa4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.h
@@ -118,4 +118,15 @@ RtMemoryStatusCodeReportWorker (
IN EFI_STATUS_CODE_DATA *Data OPTIONAL
);
+/**
+ Unregister status code callback functions only available at boot time from
+ report status code router when exiting boot services.
+
+**/
+VOID
+EFIAPI
+UnregisterSerialBootTimeHandlers (
+ VOID
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
index a6d850b779a..d8ae0eed7cf 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
@@ -58,12 +58,10 @@
[Protocols]
gEfiRscHandlerProtocolGuid ## CONSUMES
-[FeaturePcd]
+[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeReplayIn ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
-
-[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize |128| gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES
[Depex]
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/MemoryStatusCodeWorker.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/MemoryStatusCodeWorker.c
index feabf95b054..44bbe907dbb 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/MemoryStatusCodeWorker.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/MemoryStatusCodeWorker.c
@@ -7,15 +7,15 @@
**/
-#include "StatusCodeHandlerSmm.h"
+#include "StatusCodeHandlerMm.h"
-RUNTIME_MEMORY_STATUSCODE_HEADER *mSmmMemoryStatusCodeTable;
+RUNTIME_MEMORY_STATUSCODE_HEADER *mMmMemoryStatusCodeTable;
/**
- Initialize SMM memory status code table as initialization for memory status code worker
+ Initialize MM memory status code table as initialization for memory status code worker
- @retval EFI_SUCCESS SMM memory status code table successfully initialized.
- @retval others Errors from gSmst->SmmInstallConfigurationTable().
+ @retval EFI_SUCCESS MM memory status code table successfully initialized.
+ @retval others Errors from gMmst->MmInstallConfigurationTable().
**/
EFI_STATUS
MemoryStatusCodeInitializeWorker (
@@ -25,17 +25,17 @@ MemoryStatusCodeInitializeWorker (
EFI_STATUS Status;
//
- // Allocate SMM memory status code pool.
+ // Allocate MM memory status code pool.
//
- mSmmMemoryStatusCodeTable = (RUNTIME_MEMORY_STATUSCODE_HEADER *)AllocateZeroPool (sizeof (RUNTIME_MEMORY_STATUSCODE_HEADER) + PcdGet16 (PcdStatusCodeMemorySize) * 1024);
- ASSERT (mSmmMemoryStatusCodeTable != NULL);
+ mMmMemoryStatusCodeTable = (RUNTIME_MEMORY_STATUSCODE_HEADER *)AllocateZeroPool (sizeof (RUNTIME_MEMORY_STATUSCODE_HEADER) + PcdGet16 (PcdStatusCodeMemorySize) * 1024);
+ ASSERT (mMmMemoryStatusCodeTable != NULL);
- mSmmMemoryStatusCodeTable->MaxRecordsNumber = (PcdGet16 (PcdStatusCodeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD);
- Status = gSmst->SmmInstallConfigurationTable (
- gSmst,
+ mMmMemoryStatusCodeTable->MaxRecordsNumber = (PcdGet16 (PcdStatusCodeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD);
+ Status = gMmst->MmInstallConfigurationTable (
+ gMmst,
&gMemoryStatusCodeRecordGuid,
- &mSmmMemoryStatusCodeTable,
- sizeof (mSmmMemoryStatusCodeTable)
+ &mMmMemoryStatusCodeTable,
+ sizeof (mMmMemoryStatusCodeTable)
);
return Status;
}
@@ -74,8 +74,8 @@ MemoryStatusCodeReportWorker (
//
// Locate current record buffer.
//
- Record = (MEMORY_STATUSCODE_RECORD *) (mSmmMemoryStatusCodeTable + 1);
- Record = &Record[mSmmMemoryStatusCodeTable->RecordIndex++];
+ Record = (MEMORY_STATUSCODE_RECORD *) (mMmMemoryStatusCodeTable + 1);
+ Record = &Record[mMmMemoryStatusCodeTable->RecordIndex++];
//
// Save status code.
@@ -92,12 +92,12 @@ MemoryStatusCodeReportWorker (
// so the first record is pointed by record index.
// If it is less then max number, index of the first record is zero.
//
- mSmmMemoryStatusCodeTable->NumberOfRecords++;
- if (mSmmMemoryStatusCodeTable->RecordIndex == mSmmMemoryStatusCodeTable->MaxRecordsNumber) {
+ mMmMemoryStatusCodeTable->NumberOfRecords++;
+ if (mMmMemoryStatusCodeTable->RecordIndex == mMmMemoryStatusCodeTable->MaxRecordsNumber) {
//
// Wrap around record index.
//
- mSmmMemoryStatusCodeTable->RecordIndex = 0;
+ mMmMemoryStatusCodeTable->RecordIndex = 0;
}
return EFI_SUCCESS;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/SerialStatusCodeWorker.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/SerialStatusCodeWorker.c
index 1e388943c2e..88cc5343727 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/SerialStatusCodeWorker.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/SerialStatusCodeWorker.c
@@ -6,7 +6,7 @@
**/
-#include "StatusCodeHandlerSmm.h"
+#include "StatusCodeHandlerMm.h"
/**
Convert status code value and extended data to readable ASCII string, send string to serial I/O device.
@@ -129,7 +129,7 @@ SerialStatusCodeReportWorker (
CharCount = AsciiSPrint (
Buffer,
sizeof (Buffer),
- "%a\n\r",
+ "%a",
((EFI_STATUS_CODE_STRING_DATA *) Data)->String.Ascii
);
} else {
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c
index 86fc10ab00a..a21f2aa2cc1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.c
@@ -1,15 +1,15 @@
/** @file
Status Code Handler Driver which produces general handlers and hook them
- onto the SMM status code router.
+ onto the MM status code router.
- Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "StatusCodeHandlerSmm.h"
+#include "StatusCodeHandlerMm.h"
-EFI_SMM_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
+EFI_MM_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL;
/**
@@ -28,41 +28,36 @@ InitializationDispatcherWorker (
// If enable UseSerial, then initialize serial port.
// if enable UseRuntimeMemory, then initialize runtime memory status code worker.
//
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
//
// Call Serial Port Lib API to initialize serial port.
//
Status = SerialPortInitialize ();
ASSERT_EFI_ERROR (Status);
}
- if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
+ if (PcdGetBool (PcdStatusCodeUseMemory)) {
Status = MemoryStatusCodeInitializeWorker ();
ASSERT_EFI_ERROR (Status);
}
}
/**
- Entry point of SMM Status Code Driver.
+ Entry point of Common MM Status Code Driver.
- This function is the entry point of SMM Status Code Driver.
-
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
+ This function is the entry point of MM Status Code Driver.
@retval EFI_SUCCESS The entry point is executed successfully.
**/
EFI_STATUS
-EFIAPI
-StatusCodeHandlerSmmEntry (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+StatusCodeHandlerCommonEntry (
+ VOID
)
{
EFI_STATUS Status;
- Status = gSmst->SmmLocateProtocol (
- &gEfiSmmRscHandlerProtocolGuid,
+ Status = gMmst->MmLocateProtocol (
+ &gEfiMmRscHandlerProtocolGuid,
NULL,
(VOID **) &mRscHandlerProtocol
);
@@ -73,10 +68,10 @@ StatusCodeHandlerSmmEntry (
//
InitializationDispatcherWorker ();
- if (FeaturePcdGet (PcdStatusCodeUseSerial)) {
+ if (PcdGetBool (PcdStatusCodeUseSerial)) {
mRscHandlerProtocol->Register (SerialStatusCodeReportWorker);
}
- if (FeaturePcdGet (PcdStatusCodeUseMemory)) {
+ if (PcdGetBool (PcdStatusCodeUseMemory)) {
mRscHandlerProtocol->Register (MemoryStatusCodeReportWorker);
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.h b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h
index dcc55997c39..af32819c65e 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.h
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerMm.h
@@ -7,10 +7,10 @@
**/
-#ifndef __STATUS_CODE_HANDLER_SMM_H__
-#define __STATUS_CODE_HANDLER_SMM_H__
+#ifndef __STATUS_CODE_HANDLER_MM_H__
+#define __STATUS_CODE_HANDLER_MM_H__
-#include <Protocol/SmmReportStatusCodeHandler.h>
+#include <Protocol/MmReportStatusCodeHandler.h>
#include <Guid/MemoryStatusCodeRecord.h>
#include <Guid/StatusCodeDataTypeId.h>
@@ -22,7 +22,7 @@
#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/UefiDriverEntryPoint.h>
-#include <Library/SmmServicesTableLib.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/SerialPortLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
@@ -32,7 +32,7 @@
//
#define MAX_DEBUG_MESSAGE_LENGTH 0x100
-extern RUNTIME_MEMORY_STATUSCODE_HEADER *mSmmMemoryStatusCodeTable;
+extern RUNTIME_MEMORY_STATUSCODE_HEADER *mMmMemoryStatusCodeTable;
/**
Locates Serial I/O Protocol as initialization for serial status code worker.
@@ -114,4 +114,17 @@ MemoryStatusCodeReportWorker (
IN EFI_STATUS_CODE_DATA *Data OPTIONAL
);
+/**
+ Entry point of Common MM Status Code Driver.
+
+ This function is the entry point of MM Status Code Driver.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+StatusCodeHandlerCommonEntry (
+ VOID
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
index 1d4992ac090..2dfeba718d3 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerSmm.inf
@@ -1,5 +1,5 @@
## @file
-# Status Code Handler Driver which produces general handlers and hook them onto the SMM status code router.
+# Status Code Handler Driver which produces general handlers and hook them onto the MM status code router.
#
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
@@ -17,7 +17,7 @@
MODULE_TYPE = DXE_SMM_DRIVER
PI_SPECIFICATION_VERSION = 0x0001000A
VERSION_STRING = 1.0
- ENTRY_POINT = StatusCodeHandlerSmmEntry
+ ENTRY_POINT = StatusCodeHandlerTraditionalMmEntry
#
# The following information is for reference only and not required by the build tools.
@@ -26,8 +26,9 @@
#
[Sources]
- StatusCodeHandlerSmm.c
- StatusCodeHandlerSmm.h
+ StatusCodeHandlerMm.c
+ StatusCodeHandlerMm.h
+ StatusCodeHandlerTraditional.c
SerialStatusCodeWorker.c
MemoryStatusCodeWorker.c
@@ -37,7 +38,7 @@
[LibraryClasses]
SerialPortLib
- SmmServicesTableLib
+ MmServicesTableLib
UefiDriverEntryPoint
PcdLib
PrintLib
@@ -51,17 +52,15 @@
gMemoryStatusCodeRecordGuid ## SOMETIMES_PRODUCES ## UNDEFINED # SmmSystemTable
[Protocols]
- gEfiSmmRscHandlerProtocolGuid ## CONSUMES
-
-[FeaturePcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
+ gEfiMmRscHandlerProtocolGuid ## CONSUMES
[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize |128| gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES
[Depex]
- gEfiSmmRscHandlerProtocolGuid
+ gEfiMmRscHandlerProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
StatusCodeHandlerSmmExtra.uni
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c
new file mode 100644
index 00000000000..7b9530ef32d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandalone.c
@@ -0,0 +1,31 @@
+/** @file
+ Abstraction layer that contains Standalone MM specific implementation for
+ Status Code Handler Driver.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "StatusCodeHandlerMm.h"
+
+/**
+ Entry point of Standalone MM Status Code Driver.
+
+ This function is the entry point of Standalone MM Status Code Driver.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI MM System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+StatusCodeHandlerStandaloneMmEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return StatusCodeHandlerCommonEntry ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf
new file mode 100644
index 00000000000..e0d2bd7e40e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerStandaloneMm.inf
@@ -0,0 +1,63 @@
+## @file
+# Status Code Handler Driver which produces general handlers and hook them onto the MM status code router.
+#
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) Microsoft Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = StatusCodeHandlerStandaloneMm
+ FILE_GUID = EBE7802F-5E11-4D4E-B463-22D2425D156B
+ MODULE_TYPE = MM_STANDALONE
+ PI_SPECIFICATION_VERSION = 0x00010032
+ VERSION_STRING = 1.0
+ ENTRY_POINT = StatusCodeHandlerStandaloneMmEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ StatusCodeHandlerMm.c
+ StatusCodeHandlerMm.h
+ StatusCodeHandlerStandalone.c
+ SerialStatusCodeWorker.c
+ MemoryStatusCodeWorker.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ SerialPortLib
+ MmServicesTableLib
+ StandaloneMmDriverEntryPoint
+ PcdLib
+ PrintLib
+ ReportStatusCodeLib
+ DebugLib
+ MemoryAllocationLib
+ BaseMemoryLib
+
+[Guids]
+ gEfiStatusCodeDataTypeStringGuid ## SOMETIMES_CONSUMES ## UNDEFINED
+ gMemoryStatusCodeRecordGuid ## SOMETIMES_PRODUCES ## UNDEFINED # MmSystemTable
+
+[Protocols]
+ gEfiMmRscHandlerProtocolGuid ## CONSUMES
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize |128| gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory ## SOMETIMES_CONSUMES
+
+[Depex]
+ gEfiMmRscHandlerProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c
new file mode 100644
index 00000000000..99c95fffd30
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/StatusCodeHandler/Smm/StatusCodeHandlerTraditional.c
@@ -0,0 +1,31 @@
+/** @file
+ Abstraction layer that contains Standalone MM specific implementation for
+ Status Code Handler Driver.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "StatusCodeHandlerMm.h"
+
+/**
+ Entry point of Traditional MM Status Code Driver.
+
+ This function is the entry point of Traditional MM Status Code Driver.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+StatusCodeHandlerTraditionalMmEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return StatusCodeHandlerCommonEntry ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.c
new file mode 100644
index 00000000000..5ed826043c6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.c
@@ -0,0 +1,565 @@
+/** @file
+ This is a host-based unit test for the VariableLockRequestToLock shim.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/VariablePolicyLib.h>
+#include <Library/VariablePolicyHelperLib.h>
+
+#include <Protocol/VariableLock.h>
+
+#define UNIT_TEST_NAME "VarPol/VarLock Shim Unit Test"
+#define UNIT_TEST_VERSION "1.0"
+
+///=== CODE UNDER TEST ===========================================================================
+
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ );
+
+///=== TEST DATA ==================================================================================
+
+//
+// Test GUID 1 {F955BA2D-4A2C-480C-BFD1-3CC522610592}
+//
+EFI_GUID mTestGuid1 = {
+ 0xf955ba2d, 0x4a2c, 0x480c, {0xbf, 0xd1, 0x3c, 0xc5, 0x22, 0x61, 0x5, 0x92}
+};
+
+//
+// Test GUID 2 {2DEA799E-5E73-43B9-870E-C945CE82AF3A}
+//
+EFI_GUID mTestGuid2 = {
+ 0x2dea799e, 0x5e73, 0x43b9, {0x87, 0xe, 0xc9, 0x45, 0xce, 0x82, 0xaf, 0x3a}
+};
+
+//
+// Test GUID 3 {698A2BFD-A616-482D-B88C-7100BD6682A9}
+//
+EFI_GUID mTestGuid3 = {
+ 0x698a2bfd, 0xa616, 0x482d, {0xb8, 0x8c, 0x71, 0x0, 0xbd, 0x66, 0x82, 0xa9}
+};
+
+#define TEST_VAR_1_NAME L"TestVar1"
+#define TEST_VAR_2_NAME L"TestVar2"
+#define TEST_VAR_3_NAME L"TestVar3"
+
+#define TEST_POLICY_ATTRIBUTES_NULL 0
+#define TEST_POLICY_MIN_SIZE_NULL 0
+#define TEST_POLICY_MAX_SIZE_NULL MAX_UINT32
+
+#define TEST_POLICY_MIN_SIZE_10 10
+#define TEST_POLICY_MAX_SIZE_200 200
+
+///=== HELPER FUNCTIONS ===========================================================================
+
+/**
+ Mocked version of GetVariable, for testing.
+
+ @param VariableName
+ @param VendorGuid
+ @param Attributes
+ @param DataSize
+ @param Data
+**/
+EFI_STATUS
+EFIAPI
+StubGetVariableNull (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ OUT UINT32 *Attributes, OPTIONAL
+ IN OUT UINTN *DataSize,
+ OUT VOID *Data OPTIONAL
+ )
+{
+ UINT32 MockedAttr;
+ UINTN MockedDataSize;
+ VOID *MockedData;
+ EFI_STATUS MockedReturn;
+
+ check_expected_ptr (VariableName);
+ check_expected_ptr (VendorGuid);
+ check_expected_ptr (DataSize);
+
+ MockedAttr = (UINT32)mock();
+ MockedDataSize = (UINTN)mock();
+ MockedData = (VOID*)(UINTN)mock();
+ MockedReturn = (EFI_STATUS)mock();
+
+ if (Attributes != NULL) {
+ *Attributes = MockedAttr;
+ }
+ if (Data != NULL && !EFI_ERROR (MockedReturn)) {
+ CopyMem (Data, MockedData, MockedDataSize);
+ }
+
+ *DataSize = MockedDataSize;
+
+ return MockedReturn;
+}
+
+//
+// Anything you think might be helpful that isn't a test itself.
+//
+
+/**
+ This is a common setup function that will ensure the library is always
+ initialized with the stubbed GetVariable.
+
+ Not used by all test cases, but by most.
+
+ @param[in] Context Unit test case context
+**/
+STATIC
+UNIT_TEST_STATUS
+EFIAPI
+LibInitMocked (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ return EFI_ERROR (InitVariablePolicyLib (StubGetVariableNull)) ? UNIT_TEST_ERROR_PREREQUISITE_NOT_MET : UNIT_TEST_PASSED;
+}
+
+/**
+ Common cleanup function to make sure that the library is always de-initialized
+ prior to the next test case.
+
+ @param[in] Context Unit test case context
+**/
+STATIC
+VOID
+EFIAPI
+LibCleanup (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ DeinitVariablePolicyLib();
+}
+
+///=== TEST CASES =================================================================================
+
+///===== SHIM SUITE ===========================================================
+
+/**
+ Test Case that locks a single variable using the Variable Lock Protocol.
+ The call is expected to succeed.
+
+ @param[in] Context Unit test case context
+**/
+UNIT_TEST_STATUS
+EFIAPI
+LockingWithoutAnyPoliciesShouldSucceed (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks the same variable twice using the Variable Lock Protocol.
+ Both calls are expected to succeed.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+LockingTwiceShouldSucceed (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using the Variable Policy Protocol then locks
+ the same variable using the Variable Lock Protocol.
+ Both calls are expected to succeed.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+LockingALockedVariableShouldSucceed (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewEntry;
+
+ //
+ // Create a variable policy that locks the variable.
+ //
+ Status = CreateBasicVariablePolicy (
+ &mTestGuid1,
+ TEST_VAR_1_NAME,
+ TEST_POLICY_MIN_SIZE_NULL,
+ TEST_POLICY_MAX_SIZE_200,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ VARIABLE_POLICY_TYPE_LOCK_NOW,
+ &NewEntry
+ );
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ //
+ // Register the new policy.
+ //
+ Status = RegisterVariablePolicy (NewEntry);
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ FreePool (NewEntry);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using the Variable Policy Protocol with a
+ policy other than LOCK_NOW then attempts to lock the same variable using the
+ Variable Lock Protocol. The call to Variable Policy is expected to succeed
+ and the call to Variable Lock is expected to fail.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+LockingAnUnlockedVariableShouldFail (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewEntry;
+
+ // Create a variable policy that locks the variable.
+ Status = CreateVarStateVariablePolicy (&mTestGuid1,
+ TEST_VAR_1_NAME,
+ TEST_POLICY_MIN_SIZE_NULL,
+ TEST_POLICY_MAX_SIZE_200,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ &mTestGuid2,
+ 1,
+ TEST_VAR_2_NAME,
+ &NewEntry);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ // Register the new policy.
+ Status = RegisterVariablePolicy (NewEntry);
+
+ // Configure the stub to not care about parameters. We're testing errors.
+ expect_any_always( StubGetVariableNull, VariableName );
+ expect_any_always( StubGetVariableNull, VendorGuid );
+ expect_any_always( StubGetVariableNull, DataSize );
+
+ // With a policy, make sure that writes still work, since the variable doesn't exist.
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // Attributes
+ will_return( StubGetVariableNull, 0 ); // Size
+ will_return( StubGetVariableNull, NULL ); // DataPtr
+ will_return( StubGetVariableNull, EFI_NOT_FOUND); // Status
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_TRUE (EFI_ERROR (Status));
+
+ FreePool (NewEntry);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using the Variable Policy Protocol with a
+ policy other than LOCK_NOW, but is currently locked. Then attempts to lock
+ the same variable using the Variable Lock Protocol. The call to Variable
+ Policy is expected to succeed and the call to Variable Lock also expected to
+ succeed.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+LockingALockedVariableWithMatchingDataShouldSucceed (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewEntry;
+ UINT8 Data;
+
+ // Create a variable policy that locks the variable.
+ Status = CreateVarStateVariablePolicy (&mTestGuid1,
+ TEST_VAR_1_NAME,
+ TEST_POLICY_MIN_SIZE_NULL,
+ TEST_POLICY_MAX_SIZE_200,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ &mTestGuid2,
+ 1,
+ TEST_VAR_2_NAME,
+ &NewEntry);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ // Register the new policy.
+ Status = RegisterVariablePolicy (NewEntry);
+
+ // Configure the stub to not care about parameters. We're testing errors.
+ expect_any_always( StubGetVariableNull, VariableName );
+ expect_any_always( StubGetVariableNull, VendorGuid );
+ expect_any_always( StubGetVariableNull, DataSize );
+
+ // With a policy, make sure that writes still work, since the variable doesn't exist.
+ Data = 1;
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // Attributes
+ will_return( StubGetVariableNull, sizeof (Data) ); // Size
+ will_return( StubGetVariableNull, &Data ); // DataPtr
+ will_return( StubGetVariableNull, EFI_SUCCESS); // Status
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_TRUE (!EFI_ERROR (Status));
+
+ FreePool (NewEntry);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using the Variable Policy Protocol with a
+ policy other than LOCK_NOW, but variable data does not match. Then attempts
+ to lock the same variable using the Variable Lock Protocol. The call to
+ Variable Policy is expected to succeed and the call to Variable Lock is
+ expected to fail.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+LockingALockedVariableWithNonMatchingDataShouldFail (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewEntry;
+ UINT8 Data;
+
+ // Create a variable policy that locks the variable.
+ Status = CreateVarStateVariablePolicy (&mTestGuid1,
+ TEST_VAR_1_NAME,
+ TEST_POLICY_MIN_SIZE_NULL,
+ TEST_POLICY_MAX_SIZE_200,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ &mTestGuid2,
+ 1,
+ TEST_VAR_2_NAME,
+ &NewEntry);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ // Register the new policy.
+ Status = RegisterVariablePolicy (NewEntry);
+
+ // Configure the stub to not care about parameters. We're testing errors.
+ expect_any_always( StubGetVariableNull, VariableName );
+ expect_any_always( StubGetVariableNull, VendorGuid );
+ expect_any_always( StubGetVariableNull, DataSize );
+
+ // With a policy, make sure that writes still work, since the variable doesn't exist.
+ Data = 2;
+ will_return( StubGetVariableNull, TEST_POLICY_ATTRIBUTES_NULL ); // Attributes
+ will_return( StubGetVariableNull, sizeof (Data) ); // Size
+ will_return( StubGetVariableNull, &Data ); // DataPtr
+ will_return( StubGetVariableNull, EFI_SUCCESS); // Status
+
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_TRUE (EFI_ERROR (Status));
+
+ FreePool (NewEntry);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test Case that locks a variable using Variable Lock Protocol Policy Protocol
+ then and then attempts to lock the same variable using the Variable Policy
+ Protocol. The call to Variable Lock is expected to succeed and the call to
+ Variable Policy is expected to fail.
+
+ @param[in] Context Unit test case context
+ **/
+UNIT_TEST_STATUS
+EFIAPI
+SettingPolicyForALockedVariableShouldFail (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewEntry;
+
+ // Lock the variable.
+ Status = VariableLockRequestToLock (NULL, TEST_VAR_1_NAME, &mTestGuid1);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ // Create a variable policy that locks the variable.
+ Status = CreateVarStateVariablePolicy (&mTestGuid1,
+ TEST_VAR_1_NAME,
+ TEST_POLICY_MIN_SIZE_NULL,
+ TEST_POLICY_MAX_SIZE_200,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ TEST_POLICY_ATTRIBUTES_NULL,
+ &mTestGuid2,
+ 1,
+ TEST_VAR_2_NAME,
+ &NewEntry);
+ UT_ASSERT_NOT_EFI_ERROR (Status);
+
+ // Register the new policy.
+ Status = RegisterVariablePolicy (NewEntry);
+ UT_ASSERT_TRUE (EFI_ERROR (Status));
+
+ FreePool (NewEntry);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Main entry point to this unit test application.
+
+ Sets up and runs the test suites.
+**/
+VOID
+EFIAPI
+UnitTestMain (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE ShimTests;
+
+ Framework = NULL;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION));
+
+ //
+ // Start setting up the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCallerBaseName, UNIT_TEST_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // Add all test suites and tests.
+ //
+ Status = CreateUnitTestSuite (
+ &ShimTests, Framework,
+ "Variable Lock Shim Tests", "VarPolicy.VarLockShim", NULL, NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for ShimTests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+ AddTestCase (
+ ShimTests,
+ "Locking a variable with no matching policies should always work", "EmptyPolicies",
+ LockingWithoutAnyPoliciesShouldSucceed, LibInitMocked, LibCleanup, NULL
+ );
+ AddTestCase (
+ ShimTests,
+ "Locking a variable twice should always work", "DoubleLock",
+ LockingTwiceShouldSucceed, LibInitMocked, LibCleanup, NULL
+ );
+ AddTestCase (
+ ShimTests,
+ "Locking a variable that's already locked by another policy should work", "LockAfterPolicy",
+ LockingALockedVariableShouldSucceed, LibInitMocked, LibCleanup, NULL
+ );
+ AddTestCase (
+ ShimTests,
+ "Locking a variable that already has an unlocked policy should fail", "LockAfterUnlockedPolicy",
+ LockingAnUnlockedVariableShouldFail, LibInitMocked, LibCleanup, NULL
+ );
+ AddTestCase (
+ ShimTests,
+ "Locking a variable that already has an locked policy should succeed", "LockAfterLockedPolicyMatchingData",
+ LockingALockedVariableWithMatchingDataShouldSucceed, LibInitMocked, LibCleanup, NULL
+ );
+ AddTestCase (
+ ShimTests,
+ "Locking a variable that already has an locked policy with matching data should succeed", "LockAfterLockedPolicyNonMatchingData",
+ LockingALockedVariableWithNonMatchingDataShouldFail, LibInitMocked, LibCleanup, NULL
+ );
+ AddTestCase (
+ ShimTests,
+ "Adding a policy for a variable that has previously been locked should always fail", "SetPolicyAfterLock",
+ SettingPolicyForALockedVariableShouldFail, LibInitMocked, LibCleanup, NULL
+ );
+
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework != NULL) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return;
+}
+
+///
+/// Avoid ECC error for function name that starts with lower case letter
+///
+#define Main main
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+
+ @param[in] Argc Number of arguments
+ @param[in] Argv Array of pointers to arguments
+
+ @retval 0 Success
+ @retval other Error
+**/
+INT32
+Main (
+ IN INT32 Argc,
+ IN CHAR8 *Argv[]
+ )
+{
+ UnitTestMain ();
+ return 0;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.inf
new file mode 100644
index 00000000000..7c74224da05
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/RuntimeDxeUnitTest/VariableLockRequestToLockUnitTest.inf
@@ -0,0 +1,36 @@
+## @file
+# This is a host-based unit test for the VariableLockRequestToLock shim.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010017
+ BASE_NAME = VariableLockRequestToLockUnitTest
+ FILE_GUID = A7388B6C-7274-4717-9649-BDC5DFD1FCBE
+ VERSION_STRING = 1.0
+ MODULE_TYPE = HOST_APPLICATION
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+ VariableLockRequestToLockUnitTest.c
+ ../VariableLockRequestToLock.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ UnitTestLib
+ DebugLib
+ VariablePolicyLib
+ VariablePolicyHelperLib
+ BaseMemoryLib
+ MemoryAllocationLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
index f053d1edfba..b2c2f1996b0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockDxe.c
@@ -5,6 +5,7 @@
MOR lock control unsupported.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -17,7 +18,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>
#include "Variable.h"
-extern EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyHelperLib.h>
/**
This service is an MOR/MorLock checker handler for the SetVariable().
@@ -78,11 +80,6 @@ MorLockInit (
);
//
- // Need set this variable to be read-only to prevent other module set it.
- //
- VariableLockRequestToLock (&mVariableLock, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, &gEfiMemoryOverwriteRequestControlLockGuid);
-
- //
// The MOR variable can effectively improve platform security only when the
// MorLock variable protects the MOR variable. In turn MorLock cannot be made
// secure without SMM support in the platform firmware (see above).
@@ -99,11 +96,6 @@ MorLockInit (
0, // DataSize
NULL // Data
);
- VariableLockRequestToLock (
- &mVariableLock,
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid
- );
return EFI_SUCCESS;
}
@@ -118,7 +110,39 @@ MorLockInitAtEndOfDxe (
VOID
)
{
- //
- // Do nothing.
- //
+ EFI_STATUS Status;
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;
+
+ // First, we obviously need to locate the VariablePolicy protocol.
+ Status = gBS->LocateProtocol( &gEdkiiVariablePolicyProtocolGuid, NULL, (VOID**)&VariablePolicy );
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status ));
+ return;
+ }
+
+ // If we're successful, go ahead and set the policies to protect the target variables.
+ Status = RegisterBasicVariablePolicy( VariablePolicy,
+ &gEfiMemoryOverwriteRequestControlLockGuid,
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
+ VARIABLE_POLICY_NO_MIN_SIZE,
+ VARIABLE_POLICY_NO_MAX_SIZE,
+ VARIABLE_POLICY_NO_MUST_ATTR,
+ VARIABLE_POLICY_NO_CANT_ATTR,
+ VARIABLE_POLICY_TYPE_LOCK_NOW );
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));
+ }
+ Status = RegisterBasicVariablePolicy( VariablePolicy,
+ &gEfiMemoryOverwriteControlDataGuid,
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ VARIABLE_POLICY_NO_MIN_SIZE,
+ VARIABLE_POLICY_NO_MAX_SIZE,
+ VARIABLE_POLICY_NO_MUST_ATTR,
+ VARIABLE_POLICY_NO_CANT_ATTR,
+ VARIABLE_POLICY_TYPE_LOCK_NOW );
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Could not lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));
+ }
+
+ return;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
index 55b14c2ddec..4cf5e472943 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/TcgMorLockSmm.c
@@ -5,6 +5,7 @@
This module adds Variable Hook and check MemoryOverwriteRequestControlLock.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -17,6 +18,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseMemoryLib.h>
#include "Variable.h"
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyHelperLib.h>
+#include <Library/VariablePolicyLib.h>
+
typedef struct {
CHAR16 *VariableName;
EFI_GUID *VendorGuid;
@@ -341,6 +346,11 @@ SetVariableCheckHandlerMor (
return EFI_SUCCESS;
}
+ // Permit deletion when policy is disabled.
+ if (!IsVariablePolicyEnabled() && ((Attributes == 0) || (DataSize == 0))) {
+ return EFI_SUCCESS;
+ }
+
//
// MorLock variable
//
@@ -412,6 +422,8 @@ MorLockInitAtEndOfDxe (
{
UINTN MorSize;
EFI_STATUS MorStatus;
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewPolicy;
if (!mMorLockInitializationRequired) {
//
@@ -484,11 +496,25 @@ MorLockInitAtEndOfDxe (
// The MOR variable is absent; the platform firmware does not support it.
// Lock the variable so that no other module may create it.
//
- VariableLockRequestToLock (
- NULL, // This
- MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
- &gEfiMemoryOverwriteControlDataGuid
- );
+ NewPolicy = NULL;
+ Status = CreateBasicVariablePolicy( &gEfiMemoryOverwriteControlDataGuid,
+ MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME,
+ VARIABLE_POLICY_NO_MIN_SIZE,
+ VARIABLE_POLICY_NO_MAX_SIZE,
+ VARIABLE_POLICY_NO_MUST_ATTR,
+ VARIABLE_POLICY_NO_CANT_ATTR,
+ VARIABLE_POLICY_TYPE_LOCK_NOW,
+ &NewPolicy );
+ if (!EFI_ERROR( Status )) {
+ Status = RegisterVariablePolicy( NewPolicy );
+ }
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_VARIABLE_NAME, Status ));
+ ASSERT_EFI_ERROR( Status );
+ }
+ if (NewPolicy != NULL) {
+ FreePool( NewPolicy );
+ }
//
// Delete the MOR Control Lock variable too (should it exists for some
@@ -504,9 +530,23 @@ MorLockInitAtEndOfDxe (
);
mMorLockPassThru = FALSE;
- VariableLockRequestToLock (
- NULL, // This
- MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
- &gEfiMemoryOverwriteRequestControlLockGuid
- );
+ NewPolicy = NULL;
+ Status = CreateBasicVariablePolicy( &gEfiMemoryOverwriteRequestControlLockGuid,
+ MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME,
+ VARIABLE_POLICY_NO_MIN_SIZE,
+ VARIABLE_POLICY_NO_MAX_SIZE,
+ VARIABLE_POLICY_NO_MUST_ATTR,
+ VARIABLE_POLICY_NO_CANT_ATTR,
+ VARIABLE_POLICY_TYPE_LOCK_NOW,
+ &NewPolicy );
+ if (!EFI_ERROR( Status )) {
+ Status = RegisterVariablePolicy( NewPolicy );
+ }
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, MEMORY_OVERWRITE_REQUEST_CONTROL_LOCK_NAME, Status ));
+ ASSERT_EFI_ERROR( Status );
+ }
+ if (NewPolicy != NULL) {
+ FreePool( NewPolicy );
+ }
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
index bed1c190d4a..049f62ae42d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VarCheck.c
@@ -3,6 +3,7 @@
and variable lock protocol based on VarCheckLib.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,54 +11,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "Variable.h"
/**
- Mark a variable that will become read-only after leaving the DXE phase of execution.
- Write request coming from SMM environment through EFI_SMM_VARIABLE_PROTOCOL is allowed.
-
- @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
- @param[in] VariableName A pointer to the variable name that will be made read-only subsequently.
- @param[in] VendorGuid A pointer to the vendor GUID that will be made read-only subsequently.
-
- @retval EFI_SUCCESS The variable specified by the VariableName and the VendorGuid was marked
- as pending to be read-only.
- @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
- Or VariableName is an empty string.
- @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or EFI_EVENT_GROUP_READY_TO_BOOT has
- already been signaled.
- @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock request.
-**/
-EFI_STATUS
-EFIAPI
-VariableLockRequestToLock (
- IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
- IN CHAR16 *VariableName,
- IN EFI_GUID *VendorGuid
- )
-{
- EFI_STATUS Status;
- VAR_CHECK_VARIABLE_PROPERTY Property;
-
- AcquireLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
- Status = VarCheckLibVariablePropertyGet (VariableName, VendorGuid, &Property);
- if (!EFI_ERROR (Status)) {
- Property.Property |= VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
- } else {
- Property.Revision = VAR_CHECK_VARIABLE_PROPERTY_REVISION;
- Property.Property = VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY;
- Property.Attributes = 0;
- Property.MinSize = 1;
- Property.MaxSize = MAX_UINTN;
- }
- Status = VarCheckLibVariablePropertySet (VariableName, VendorGuid, &Property);
-
- DEBUG ((EFI_D_INFO, "[Variable] Lock: %g:%s %r\n", VendorGuid, VariableName, Status));
-
- ReleaseLockOnlyAtBootTime (&mVariableModuleGlobal->VariableGlobal.VariableServicesLock);
-
- return Status;
-}
-
-/**
Register SetVariable check handler.
@param[in] Handler Pointer to check handler.
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index b2c9e597adf..63c5635fcca 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -597,6 +597,7 @@ Reclaim (
VOID *Point1;
BOOLEAN FoundAdded;
EFI_STATUS Status;
+ EFI_STATUS DoneStatus;
UINTN CommonVariableTotalSize;
UINTN CommonUserVariableTotalSize;
UINTN HwErrVariableTotalSize;
@@ -840,25 +841,30 @@ Reclaim (
}
Done:
+ DoneStatus = EFI_SUCCESS;
if (IsVolatile || mVariableModuleGlobal->VariableGlobal.EmuNvMode) {
- Status = SynchronizeRuntimeVariableCache (
- &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache,
- 0,
- VariableStoreHeader->Size
- );
- ASSERT_EFI_ERROR (Status);
+ DoneStatus = SynchronizeRuntimeVariableCache (
+ &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeVolatileCache,
+ 0,
+ VariableStoreHeader->Size
+ );
+ ASSERT_EFI_ERROR (DoneStatus);
FreePool (ValidBuffer);
} else {
//
// For NV variable reclaim, we use mNvVariableCache as the buffer, so copy the data back.
//
CopyMem (mNvVariableCache, (UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size);
- Status = SynchronizeRuntimeVariableCache (
- &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache,
- 0,
- VariableStoreHeader->Size
- );
- ASSERT_EFI_ERROR (Status);
+ DoneStatus = SynchronizeRuntimeVariableCache (
+ &mVariableModuleGlobal->VariableGlobal.VariableRuntimeCacheContext.VariableRuntimeNvCache,
+ 0,
+ VariableStoreHeader->Size
+ );
+ ASSERT_EFI_ERROR (DoneStatus);
+ }
+
+ if (!EFI_ERROR (Status) && EFI_ERROR (DoneStatus)) {
+ Status = DoneStatus;
}
return Status;
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
index 60f414e5faa..9ad517f6b3c 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableDxe.c
@@ -5,18 +5,34 @@
Copyright (C) 2013, Red Hat, Inc.
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Variable.h"
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
+EFI_STATUS
+EFIAPI
+ProtocolIsVariablePolicyEnabled (
+ OUT BOOLEAN *State
+ );
+
EFI_HANDLE mHandle = NULL;
EFI_EVENT mVirtualAddressChangeEvent = NULL;
VOID *mFtwRegistration = NULL;
VOID ***mVarCheckAddressPointer = NULL;
UINTN mVarCheckAddressPointerCount = 0;
EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock = { VariableLockRequestToLock };
+EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol = { EDKII_VARIABLE_POLICY_PROTOCOL_REVISION,
+ DisableVariablePolicy,
+ ProtocolIsVariablePolicyEnabled,
+ RegisterVariablePolicy,
+ DumpVariablePolicy,
+ LockVariablePolicy };
EDKII_VAR_CHECK_PROTOCOL mVarCheck = { VarCheckRegisterSetVariableCheckHandler,
VarCheckVariablePropertySet,
VarCheckVariablePropertyGet };
@@ -282,8 +298,13 @@ OnReadyToBoot (
VOID *Context
)
{
+ EFI_STATUS Status;
+
if (!mEndOfDxe) {
MorLockInitAtEndOfDxe ();
+
+ Status = LockVariablePolicy ();
+ ASSERT_EFI_ERROR (Status);
//
// Set the End Of DXE bit in case the EFI_END_OF_DXE_EVENT_GROUP_GUID event is not signaled.
//
@@ -322,8 +343,12 @@ OnEndOfDxe (
VOID *Context
)
{
+ EFI_STATUS Status;
+
DEBUG ((EFI_D_INFO, "[Variable]END_OF_DXE is signaled\n"));
MorLockInitAtEndOfDxe ();
+ Status = LockVariablePolicy ();
+ ASSERT_EFI_ERROR (Status);
mEndOfDxe = TRUE;
mVarCheckAddressPointer = VarCheckLibInitializeAtEndOfDxe (&mVarCheckAddressPointerCount);
//
@@ -467,6 +492,28 @@ FtwNotificationEvent (
/**
+ This API function returns whether or not the policy engine is
+ currently being enforced.
+
+ @param[out] State Pointer to a return value for whether the policy enforcement
+ is currently enabled.
+
+ @retval EFI_SUCCESS
+ @retval Others An error has prevented this command from completing.
+
+**/
+EFI_STATUS
+EFIAPI
+ProtocolIsVariablePolicyEnabled (
+ OUT BOOLEAN *State
+ )
+{
+ *State = IsVariablePolicyEnabled ();
+ return EFI_SUCCESS;
+}
+
+
+/**
Variable Driver main entry point. The Variable driver places the 4 EFI
runtime services in the EFI System Table and installs arch protocols
for variable read and write services being available. It also registers
@@ -576,6 +623,19 @@ VariableServiceInitialize (
);
ASSERT_EFI_ERROR (Status);
+ // Register and initialize the VariablePolicy engine.
+ Status = InitVariablePolicyLib (VariableServiceGetVariable);
+ ASSERT_EFI_ERROR (Status);
+ Status = VarCheckRegisterSetVariableCheckHandler (ValidateSetVariable);
+ ASSERT_EFI_ERROR (Status);
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &mHandle,
+ &gEdkiiVariablePolicyProtocolGuid,
+ &mVariablePolicyProtocol,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequestToLock.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequestToLock.c
new file mode 100644
index 00000000000..9fddf7be1f3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableLockRequestToLock.c
@@ -0,0 +1,94 @@
+/** @file
+ Temporary location of the RequestToLock shim code while projects
+ are moved to VariablePolicy. Should be removed when deprecated.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/VariablePolicyLib.h>
+#include <Library/VariablePolicyHelperLib.h>
+#include <Protocol/VariableLock.h>
+
+/**
+ DEPRECATED. THIS IS ONLY HERE AS A CONVENIENCE WHILE PORTING.
+ Mark a variable that will become read-only after leaving the DXE phase of
+ execution. Write request coming from SMM environment through
+ EFI_SMM_VARIABLE_PROTOCOL is allowed.
+
+ @param[in] This The VARIABLE_LOCK_PROTOCOL instance.
+ @param[in] VariableName A pointer to the variable name that will be made
+ read-only subsequently.
+ @param[in] VendorGuid A pointer to the vendor GUID that will be made
+ read-only subsequently.
+
+ @retval EFI_SUCCESS The variable specified by the VariableName and
+ the VendorGuid was marked as pending to be
+ read-only.
+ @retval EFI_INVALID_PARAMETER VariableName or VendorGuid is NULL.
+ Or VariableName is an empty string.
+ @retval EFI_ACCESS_DENIED EFI_END_OF_DXE_EVENT_GROUP_GUID or
+ EFI_EVENT_GROUP_READY_TO_BOOT has already been
+ signaled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource to hold the lock
+ request.
+**/
+EFI_STATUS
+EFIAPI
+VariableLockRequestToLock (
+ IN CONST EDKII_VARIABLE_LOCK_PROTOCOL *This,
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid
+ )
+{
+ EFI_STATUS Status;
+ VARIABLE_POLICY_ENTRY *NewPolicy;
+
+ DEBUG ((DEBUG_WARN, "!!! DEPRECATED INTERFACE !!! %a() will go away soon!\n", __FUNCTION__));
+ DEBUG ((DEBUG_WARN, "!!! DEPRECATED INTERFACE !!! Please move to use Variable Policy!\n"));
+ DEBUG ((DEBUG_WARN, "!!! DEPRECATED INTERFACE !!! Variable: %g %s\n", VendorGuid, VariableName));
+
+ NewPolicy = NULL;
+ Status = CreateBasicVariablePolicy(
+ VendorGuid,
+ VariableName,
+ VARIABLE_POLICY_NO_MIN_SIZE,
+ VARIABLE_POLICY_NO_MAX_SIZE,
+ VARIABLE_POLICY_NO_MUST_ATTR,
+ VARIABLE_POLICY_NO_CANT_ATTR,
+ VARIABLE_POLICY_TYPE_LOCK_NOW,
+ &NewPolicy
+ );
+ if (!EFI_ERROR( Status )) {
+ Status = RegisterVariablePolicy (NewPolicy);
+
+ //
+ // If the error returned is EFI_ALREADY_STARTED, we need to check the
+ // current database for the variable and see whether it's locked. If it's
+ // locked, we're still fine, but also generate a DEBUG_WARN message so the
+ // duplicate lock can be removed.
+ //
+ if (Status == EFI_ALREADY_STARTED) {
+ Status = ValidateSetVariable (VariableName, VendorGuid, 0, 0, NULL);
+ if (Status == EFI_WRITE_PROTECTED) {
+ DEBUG ((DEBUG_WARN, " Variable: %g %s is already locked!\n", VendorGuid, VariableName));
+ Status = EFI_SUCCESS;
+ } else {
+ DEBUG ((DEBUG_ERROR, " Variable: %g %s can not be locked!\n", VendorGuid, VariableName));
+ Status = EFI_ACCESS_DENIED;
+ }
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG(( DEBUG_ERROR, "%a - Failed to lock variable %s! %r\n", __FUNCTION__, VariableName, Status ));
+ }
+ if (NewPolicy != NULL) {
+ FreePool( NewPolicy );
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
new file mode 100644
index 00000000000..a733df0eefc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariablePolicySmmDxe.c
@@ -0,0 +1,573 @@
+/** @file -- VariablePolicySmmDxe.c
+This protocol allows communication with Variable Policy Engine.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/SafeIntLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include <Protocol/VariablePolicy.h>
+#include <Protocol/MmCommunication2.h>
+
+#include <Guid/VarCheckPolicyMmi.h>
+
+#include "Variable.h"
+
+EDKII_VARIABLE_POLICY_PROTOCOL mVariablePolicyProtocol;
+EFI_MM_COMMUNICATION2_PROTOCOL *mMmCommunication;
+
+VOID *mMmCommunicationBuffer;
+UINTN mMmCommunicationBufferSize;
+EFI_LOCK mMmCommunicationLock;
+
+/**
+ Internal helper function to consolidate communication method.
+
+ @param[in,out] CommBuffer
+ @param[in,out] CommSize Size of the CommBuffer.
+
+ @retval EFI_STATUS Result from communication method.
+
+**/
+STATIC
+EFI_STATUS
+InternalMmCommunicate (
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommSize
+ )
+{
+ EFI_STATUS Status;
+ if (CommBuffer == NULL || CommSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = mMmCommunication->Communicate (mMmCommunication, CommBuffer, CommBuffer, CommSize);
+ return Status;
+}
+
+
+/**
+ This API function disables the variable policy enforcement. If it's
+ already been called once, will return EFI_ALREADY_STARTED.
+
+ @retval EFI_SUCCESS
+ @retval EFI_ALREADY_STARTED Has already been called once this boot.
+ @retval EFI_WRITE_PROTECTED Interface has been locked until reboot.
+ @retval EFI_WRITE_PROTECTED Interface option is disabled by platform PCD.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolDisableVariablePolicy (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;
+ UINTN BufferSize;
+
+ // Check the PCD for convenience.
+ // This would also be rejected by the lib, but why go to MM if we don't have to?
+ if (!PcdGetBool (PcdAllowVariablePolicyEnforcementDisable)) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ // Set up the MM communication.
+ BufferSize = mMmCommunicationBufferSize;
+ CommHeader = mMmCommunicationBuffer;
+ PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+ CommHeader->MessageLength = BufferSize;
+ PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;
+ PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;
+ PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_DISABLE;
+
+ Status = InternalMmCommunicate (CommHeader, &BufferSize);
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
+}
+
+
+/**
+ This API function returns whether or not the policy engine is
+ currently being enforced.
+
+ @param[out] State Pointer to a return value for whether the policy enforcement
+ is currently enabled.
+
+ @retval EFI_SUCCESS
+ @retval Others An error has prevented this command from completing.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolIsVariablePolicyEnabled (
+ OUT BOOLEAN *State
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;
+ VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS *CommandParams;
+ UINTN BufferSize;
+
+ if (State == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ // Set up the MM communication.
+ BufferSize = mMmCommunicationBufferSize;
+ CommHeader = mMmCommunicationBuffer;
+ PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+ CommandParams = (VAR_CHECK_POLICY_COMM_IS_ENABLED_PARAMS*)(PolicyHeader + 1);
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+ CommHeader->MessageLength = BufferSize;
+ PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;
+ PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;
+ PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_IS_ENABLED;
+
+ Status = InternalMmCommunicate (CommHeader, &BufferSize);
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+ if (!EFI_ERROR( Status )) {
+ Status = PolicyHeader->Result;
+ *State = CommandParams->State;
+ }
+
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ return Status;
+}
+
+
+/**
+ This API function validates and registers a new policy with
+ the policy enforcement engine.
+
+ @param[in] NewPolicy Pointer to the incoming policy structure.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER NewPolicy is NULL or is internally inconsistent.
+ @retval EFI_ALREADY_STARTED An identical matching policy already exists.
+ @retval EFI_WRITE_PROTECTED The interface has been locked until the next reboot.
+ @retval EFI_UNSUPPORTED Policy enforcement has been disabled. No reason to add more policies.
+ @retval EFI_ABORTED A calculation error has prevented this function from completing.
+ @retval EFI_OUT_OF_RESOURCES Cannot grow the table to hold any more policies.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolRegisterVariablePolicy (
+ IN CONST VARIABLE_POLICY_ENTRY *NewPolicy
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;
+ VOID *PolicyBuffer;
+ UINTN BufferSize;
+ UINTN RequiredSize;
+
+ if (NewPolicy == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // First, make sure that the required size does not exceed the capabilities
+ // of the MmCommunication buffer.
+ RequiredSize = OFFSET_OF(EFI_MM_COMMUNICATE_HEADER, Data) + sizeof(VAR_CHECK_POLICY_COMM_HEADER);
+ Status = SafeUintnAdd( RequiredSize, NewPolicy->Size, &RequiredSize );
+ if (EFI_ERROR( Status ) || RequiredSize > mMmCommunicationBufferSize) {
+ DEBUG(( DEBUG_ERROR, "%a - Policy too large for buffer! %r, %d > %d \n", __FUNCTION__,
+ Status, RequiredSize, mMmCommunicationBufferSize ));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ // Set up the MM communication.
+ BufferSize = mMmCommunicationBufferSize;
+ CommHeader = mMmCommunicationBuffer;
+ PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+ PolicyBuffer = (VOID*)(PolicyHeader + 1);
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+ CommHeader->MessageLength = BufferSize;
+ PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;
+ PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;
+ PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_REGISTER;
+
+ // Copy the policy into place. This copy is safe because we've already tested above.
+ CopyMem( PolicyBuffer, NewPolicy, NewPolicy->Size );
+
+ Status = InternalMmCommunicate (CommHeader, &BufferSize);
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
+}
+
+
+/**
+ This helper function takes care of the overhead of formatting, sending, and interpreting
+ the results for a single DumpVariablePolicy request.
+
+ @param[in] PageRequested The page of the paginated results from MM. 0 for metadata.
+ @param[out] TotalSize The total size of the entire buffer. Returned as part of metadata.
+ @param[out] PageSize The size of the current page being returned. Not valid as part of metadata.
+ @param[out] HasMore A flag indicating whether there are more pages after this one.
+ @param[out] Buffer The start of the current page from MM.
+
+ @retval EFI_SUCCESS Output params have been updated (either metadata or dump page).
+ @retval EFI_INVALID_PARAMETER One of the output params is NULL.
+ @retval Others Response from MM handler.
+
+**/
+STATIC
+EFI_STATUS
+DumpVariablePolicyHelper (
+ IN UINT32 PageRequested,
+ OUT UINT32 *TotalSize,
+ OUT UINT32 *PageSize,
+ OUT BOOLEAN *HasMore,
+ OUT UINT8 **Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;
+ VAR_CHECK_POLICY_COMM_DUMP_PARAMS *CommandParams;
+ UINTN BufferSize;
+
+ if (TotalSize == NULL || PageSize == NULL || HasMore == NULL || Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Set up the MM communication.
+ BufferSize = mMmCommunicationBufferSize;
+ CommHeader = mMmCommunicationBuffer;
+ PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+ CommandParams = (VAR_CHECK_POLICY_COMM_DUMP_PARAMS*)(PolicyHeader + 1);
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+ CommHeader->MessageLength = BufferSize;
+ PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;
+ PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;
+ PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_DUMP;
+
+ CommandParams->PageRequested = PageRequested;
+
+ Status = InternalMmCommunicate (CommHeader, &BufferSize);
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+ if (!EFI_ERROR( Status )) {
+ Status = PolicyHeader->Result;
+ *TotalSize = CommandParams->TotalSize;
+ *PageSize = CommandParams->PageSize;
+ *HasMore = CommandParams->HasMore;
+ *Buffer = (UINT8*)(CommandParams + 1);
+ }
+
+ return Status;
+}
+
+
+/**
+ This API function will dump the entire contents of the variable policy table.
+
+ Similar to GetVariable, the first call can be made with a 0 size and it will return
+ the size of the buffer required to hold the entire table.
+
+ @param[out] Policy Pointer to the policy buffer. Can be NULL if Size is 0.
+ @param[in,out] Size On input, the size of the output buffer. On output, the size
+ of the data returned.
+
+ @retval EFI_SUCCESS Policy data is in the output buffer and Size has been updated.
+ @retval EFI_INVALID_PARAMETER Size is NULL, or Size is non-zero and Policy is NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size is insufficient to hold policy. Size updated with required size.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolDumpVariablePolicy (
+ OUT UINT8 *Policy OPTIONAL,
+ IN OUT UINT32 *Size
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Source;
+ UINT8 *Destination;
+ UINT32 PolicySize;
+ UINT32 PageSize;
+ BOOLEAN HasMore;
+ UINT32 PageIndex;
+
+ if (Size == NULL || (*Size > 0 && Policy == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ // Repeat this whole process until we either have a failure case or get the entire buffer.
+ do {
+ // First, we must check the zero page to determine the buffer size and
+ // reset the internal state.
+ PolicySize = 0;
+ PageSize = 0;
+ HasMore = FALSE;
+ Status = DumpVariablePolicyHelper (0, &PolicySize, &PageSize, &HasMore, &Source);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ // If we're good, we can at least check the required size now.
+ if (*Size < PolicySize) {
+ *Size = PolicySize;
+ Status = EFI_BUFFER_TOO_SMALL;
+ break;
+ }
+
+ // On further thought, let's update the size either way.
+ *Size = PolicySize;
+ // And get ready to ROCK.
+ Destination = Policy;
+
+ // Keep looping and copying until we're either done or freak out.
+ for (PageIndex = 1; !EFI_ERROR (Status) && HasMore && PageIndex < MAX_UINT32; PageIndex++) {
+ Status = DumpVariablePolicyHelper (PageIndex, &PolicySize, &PageSize, &HasMore, &Source);
+ if (!EFI_ERROR (Status)) {
+ CopyMem (Destination, Source, PageSize);
+ Destination += PageSize;
+ }
+ }
+
+ // Next, we check to see whether
+ } while (Status == EFI_TIMEOUT);
+
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ // There's currently no use for this, but it shouldn't be hard to implement.
+ return Status;
+}
+
+
+/**
+ This API function locks the interface so that no more policy updates
+ can be performed or changes made to the enforcement until the next boot.
+
+ @retval EFI_SUCCESS
+ @retval Others An error has prevented this command from completing.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ProtocolLockVariablePolicy (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ VAR_CHECK_POLICY_COMM_HEADER *PolicyHeader;
+ UINTN BufferSize;
+
+ AcquireLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ // Set up the MM communication.
+ BufferSize = mMmCommunicationBufferSize;
+ CommHeader = mMmCommunicationBuffer;
+ PolicyHeader = (VAR_CHECK_POLICY_COMM_HEADER*)&CommHeader->Data;
+ CopyGuid( &CommHeader->HeaderGuid, &gVarCheckPolicyLibMmiHandlerGuid );
+ CommHeader->MessageLength = BufferSize;
+ PolicyHeader->Signature = VAR_CHECK_POLICY_COMM_SIG;
+ PolicyHeader->Revision = VAR_CHECK_POLICY_COMM_REVISION;
+ PolicyHeader->Command = VAR_CHECK_POLICY_COMMAND_LOCK;
+
+ Status = InternalMmCommunicate (CommHeader, &BufferSize);
+ DEBUG(( DEBUG_VERBOSE, "%a - MmCommunication returned %r.\n", __FUNCTION__, Status ));
+
+ ReleaseLockOnlyAtBootTime (&mMmCommunicationLock);
+
+ return (EFI_ERROR( Status )) ? Status : PolicyHeader->Result;
+}
+
+
+/**
+ This helper function locates the shared comm buffer and assigns it to input pointers.
+
+ @param[in,out] BufferSize On input, the minimum buffer size required INCLUDING the MM communicate header.
+ On output, the size of the matching buffer found.
+ @param[out] LocatedBuffer A pointer to the matching buffer.
+
+ @retval EFI_SUCCESS
+ @retval EFI_INVALID_PARAMETER One of the output pointers was NULL.
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to allocate a comm buffer.
+
+**/
+STATIC
+EFI_STATUS
+InitMmCommonCommBuffer (
+ IN OUT UINTN *BufferSize,
+ OUT VOID **LocatedBuffer
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ // Make sure that we're working with good pointers.
+ if (BufferSize == NULL || LocatedBuffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Allocate the runtime memory for the comm buffer.
+ *LocatedBuffer = AllocateRuntimePool (*BufferSize);
+ if (*LocatedBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ *BufferSize = 0;
+ }
+
+ EfiInitializeLock (&mMmCommunicationLock, TPL_NOTIFY);
+
+ return Status;
+}
+
+
+/**
+ Convert internal pointer addresses to virtual addresses.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context The pointer to the notification function's context, which
+ is implementation-dependent.
+**/
+STATIC
+VOID
+EFIAPI
+VariablePolicyVirtualAddressCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EfiConvertPointer (0, (VOID **)&mMmCommunication);
+ EfiConvertPointer (0, (VOID **)&mMmCommunicationBuffer);
+}
+
+
+/**
+ The driver's entry point.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point executed successfully.
+ @retval other Some error occured when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+VariablePolicySmmDxeMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN ProtocolInstalled;
+ BOOLEAN VirtualAddressChangeRegistered;
+ EFI_EVENT VirtualAddressChangeEvent;
+
+ Status = EFI_SUCCESS;
+ ProtocolInstalled = FALSE;
+ VirtualAddressChangeRegistered = FALSE;
+
+ // Update the minimum buffer size.
+ mMmCommunicationBufferSize = VAR_CHECK_POLICY_MM_COMM_BUFFER_SIZE;
+ // Locate the shared comm buffer to use for sending MM commands.
+ Status = InitMmCommonCommBuffer( &mMmCommunicationBufferSize, &mMmCommunicationBuffer );
+ if (EFI_ERROR( Status )) {
+ DEBUG((DEBUG_ERROR, "%a - Failed to locate a viable MM comm buffer! %r\n", __FUNCTION__, Status));
+ ASSERT_EFI_ERROR( Status );
+ return Status;
+ }
+
+ // Locate the MmCommunication protocol.
+ Status = gBS->LocateProtocol( &gEfiMmCommunication2ProtocolGuid, NULL, (VOID**)&mMmCommunication );
+ if (EFI_ERROR( Status )) {
+ DEBUG((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol! %r\n", __FUNCTION__, Status));
+ ASSERT_EFI_ERROR( Status );
+ return Status;
+ }
+
+ // Configure the VariablePolicy protocol structure.
+ mVariablePolicyProtocol.Revision = EDKII_VARIABLE_POLICY_PROTOCOL_REVISION;
+ mVariablePolicyProtocol.DisableVariablePolicy = ProtocolDisableVariablePolicy;
+ mVariablePolicyProtocol.IsVariablePolicyEnabled = ProtocolIsVariablePolicyEnabled;
+ mVariablePolicyProtocol.RegisterVariablePolicy = ProtocolRegisterVariablePolicy;
+ mVariablePolicyProtocol.DumpVariablePolicy = ProtocolDumpVariablePolicy;
+ mVariablePolicyProtocol.LockVariablePolicy = ProtocolLockVariablePolicy;
+
+ // Register all the protocols and return the status.
+ Status = gBS->InstallMultipleProtocolInterfaces( &ImageHandle,
+ &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol,
+ NULL );
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Failed to install protocol! %r\n", __FUNCTION__, Status ));
+ goto Exit;
+ }
+ else {
+ ProtocolInstalled = TRUE;
+ }
+
+ // Normally, we might want to register a callback
+ // to lock the interface, but this is integrated
+ // into the existing callbacks in VaraiableSmm.c
+ // and VariableDxe.c.
+
+ //
+ // Register a VirtualAddressChange callback for the MmComm protocol and Comm buffer.
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ VariablePolicyVirtualAddressCallback,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &VirtualAddressChangeEvent);
+ if (EFI_ERROR( Status )) {
+ DEBUG(( DEBUG_ERROR, "%a - Failed to create VirtualAddressChange event! %r\n", __FUNCTION__, Status ));
+ goto Exit;
+ }
+ else {
+ VirtualAddressChangeRegistered = TRUE;
+ }
+
+
+Exit:
+ //
+ // If we're about to return a failed status (and unload this driver), we must first undo anything that
+ // has been successfully done.
+ if (EFI_ERROR( Status )) {
+ if (ProtocolInstalled) {
+ gBS->UninstallProtocolInterface( &ImageHandle, &gEdkiiVariablePolicyProtocolGuid, &mVariablePolicyProtocol );
+ }
+ if (VirtualAddressChangeRegistered) {
+ gBS->CloseEvent( VirtualAddressChangeEvent );
+ }
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
index 3b3cc85cd6a..a8f391fb27f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
@@ -10,6 +10,7 @@
# buffer overflow or integer overflow.
#
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -48,6 +49,7 @@
VarCheck.c
VariableExLib.c
SpeculationBarrierDxe.c
+ VariableLockRequestToLock.c
[Packages]
MdePkg/MdePkg.dec
@@ -70,6 +72,8 @@
TpmMeasurementLib
AuthVariableLib
VarCheckLib
+ VariablePolicyLib
+ VariablePolicyHelperLib
[Protocols]
gEfiFirmwareVolumeBlockProtocolGuid ## CONSUMES
@@ -79,6 +83,7 @@
gEfiVariableWriteArchProtocolGuid ## PRODUCES
gEfiVariableArchProtocolGuid ## PRODUCES
gEdkiiVariableLockProtocolGuid ## PRODUCES
+ gEdkiiVariablePolicyProtocolGuid ## CONSUMES
gEdkiiVarCheckProtocolGuid ## PRODUCES
[Guids]
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
index 86eaa973f77..1df47ec1a87 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.c
@@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/SmmVarCheck.h>
#include <Library/MmServicesTableLib.h>
+#include <Library/VariablePolicyLib.h>
#include <Guid/SmmVariableCommon.h>
#include "Variable.h"
@@ -689,6 +690,8 @@ SmmVariableHandler (
}
if (!mEndOfDxe) {
MorLockInitAtEndOfDxe ();
+ Status = LockVariablePolicy ();
+ ASSERT_EFI_ERROR (Status);
mEndOfDxe = TRUE;
VarCheckLibInitializeAtEndOfDxe (NULL);
//
@@ -974,8 +977,12 @@ SmmEndOfDxeCallback (
IN EFI_HANDLE Handle
)
{
+ EFI_STATUS Status;
+
DEBUG ((EFI_D_INFO, "[Variable]SMM_END_OF_DXE is signaled\n"));
MorLockInitAtEndOfDxe ();
+ Status = LockVariablePolicy ();
+ ASSERT_EFI_ERROR (Status);
mEndOfDxe = TRUE;
VarCheckLibInitializeAtEndOfDxe (NULL);
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
index 73de6a6777f..93a3e8da3d4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
@@ -19,6 +19,7 @@
# the authentication service provided in this driver will be broken, and the behavior is undefined.
#
# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -57,6 +58,7 @@
VariableExLib.c
TcgMorLockSmm.c
SpeculationBarrierSmm.c
+ VariableLockRequestToLock.c
[Packages]
MdePkg/MdePkg.dec
@@ -79,6 +81,8 @@
AuthVariableLib
VarCheckLib
UefiBootServicesTableLib
+ VariablePolicyLib
+ VariablePolicyHelperLib
[Protocols]
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
index 070135e657e..400f9e084a9 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.c
@@ -35,6 +35,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DebugLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseLib.h>
+#include <Library/MmUnblockMemoryLib.h>
#include <Guid/EventGroup.h>
#include <Guid/SmmVariableCommon.h>
@@ -66,6 +67,17 @@ EDKII_VARIABLE_LOCK_PROTOCOL mVariableLock;
EDKII_VAR_CHECK_PROTOCOL mVarCheck;
/**
+ The logic to initialize the VariablePolicy engine is in its own file.
+
+**/
+EFI_STATUS
+EFIAPI
+VariablePolicySmmDxeMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
Some Secure Boot Policy Variable may update following other variable changes(SecureBoot follows PK change, etc).
Record their initial State when variable write service is ready.
@@ -154,6 +166,7 @@ InitVariableCache (
)
{
VARIABLE_STORE_HEADER *VariableCacheStorePtr;
+ EFI_STATUS Status;
if (TotalVariableCacheSize == NULL) {
return EFI_INVALID_PARAMETER;
@@ -175,6 +188,18 @@ InitVariableCache (
if (*VariableCacheBuffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
+
+ //
+ // Request to unblock the newly allocated cache region to be accessible from inside MM
+ //
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) *VariableCacheBuffer,
+ EFI_SIZE_TO_PAGES (*TotalVariableCacheSize)
+ );
+ if (Status != EFI_UNSUPPORTED && EFI_ERROR (Status)) {
+ return Status;
+ }
+
VariableCacheStorePtr = *VariableCacheBuffer;
SetMem32 ((VOID *) VariableCacheStorePtr, *TotalVariableCacheSize, (UINT32) 0xFFFFFFFF);
@@ -1526,6 +1551,34 @@ SendRuntimeVariableCacheContextToSmm (
SmmRuntimeVarCacheContext->HobFlushComplete = &mHobFlushComplete;
//
+ // Request to unblock this region to be accessible from inside MM environment
+ // These fields "should" be all on the same page, but just to be on the safe side...
+ //
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS) ALIGN_VALUE ((UINTN) SmmRuntimeVarCacheContext->PendingUpdate - EFI_PAGE_SIZE + 1, EFI_PAGE_SIZE),
+ EFI_SIZE_TO_PAGES (sizeof(mVariableRuntimeCachePendingUpdate))
+ );
+ if (Status != EFI_UNSUPPORTED && EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS) ALIGN_VALUE ((UINTN) SmmRuntimeVarCacheContext->ReadLock - EFI_PAGE_SIZE + 1, EFI_PAGE_SIZE),
+ EFI_SIZE_TO_PAGES (sizeof(mVariableRuntimeCacheReadLock))
+ );
+ if (Status != EFI_UNSUPPORTED && EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ Status = MmUnblockMemoryRequest (
+ (EFI_PHYSICAL_ADDRESS) ALIGN_VALUE ((UINTN) SmmRuntimeVarCacheContext->HobFlushComplete - EFI_PAGE_SIZE + 1, EFI_PAGE_SIZE),
+ EFI_SIZE_TO_PAGES (sizeof(mHobFlushComplete))
+ );
+ if (Status != EFI_UNSUPPORTED && EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
// Send data to SMM.
//
Status = mMmCommunication2->Communicate (mMmCommunication2, CommBuffer, CommBuffer, &CommSize);
@@ -1796,6 +1849,9 @@ VariableSmmRuntimeInitialize (
&mVirtualAddressChangeEvent
);
+ // Initialize the VariablePolicy protocol and engine.
+ VariablePolicySmmDxeMain (ImageHandle, SystemTable);
+
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
index f3ba343eb9d..a307de493bf 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
@@ -14,6 +14,7 @@
# the authentication service provided in this driver will be broken, and the behavior is undefined.
#
# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -42,6 +43,7 @@
VariableParsing.c
VariableParsing.h
Variable.h
+ VariablePolicySmmDxe.c
[Packages]
MdePkg/MdePkg.dec
@@ -57,6 +59,9 @@
DxeServicesTableLib
UefiDriverEntryPoint
TpmMeasurementLib
+ SafeIntLib
+ PcdLib
+ MmUnblockMemoryLib
[Protocols]
gEfiVariableWriteArchProtocolGuid ## PRODUCES
@@ -68,11 +73,15 @@
gEfiSmmVariableProtocolGuid
gEdkiiVariableLockProtocolGuid ## PRODUCES
gEdkiiVarCheckProtocolGuid ## PRODUCES
+ gEdkiiVariablePolicyProtocolGuid ## PRODUCES
[FeaturePcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdEnableVariableRuntimeCache ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdVariableCollectStatistics ## CONSUMES
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAllowVariablePolicyEnforcementDisable ## CONSUMES
+
[Guids]
## PRODUCES ## GUID # Signature of Variable store header
## CONSUMES ## GUID # Signature of Variable store header
@@ -100,6 +109,9 @@
## SOMETIMES_CONSUMES ## Variable:L"dbt"
gEfiImageSecurityDatabaseGuid
+ gVarCheckPolicyLibMmiHandlerGuid
+ gEfiEndOfDxeEventGroupGuid
+
[Depex]
gEfiMmCommunication2ProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
index f0de26c072a..ef78519804e 100644
--- a/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdeModulePkg/Universal/Variable/RuntimeDxe/VariableStandaloneMm.inf
@@ -20,6 +20,7 @@
#
# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -57,6 +58,7 @@
VariableExLib.c
TcgMorLockSmm.c
SpeculationBarrierSmm.c
+ VariableLockRequestToLock.c
[Packages]
MdePkg/MdePkg.dec
@@ -74,6 +76,8 @@
StandaloneMmDriverEntryPoint
SynchronizationLib
VarCheckLib
+ VariablePolicyLib
+ VariablePolicyHelperLib
[Protocols]
gEfiSmmFirmwareVolumeBlockProtocolGuid ## CONSUMES
@@ -115,10 +119,10 @@
## SOMETIMES_PRODUCES ## Variable:L"VarErrorFlag"
gEdkiiVarErrorFlagGuid
-[FixedPcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES
+[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Base.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Base.h
index 60c2e085d5c..f5450a17876 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Base.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Base.h
@@ -1273,7 +1273,6 @@ typedef UINTN RETURN_STATUS;
**/
#define RETURN_ADDRESS(L) ((L == 0) ? _ReturnAddress() : (VOID *) 0)
#elif defined (__GNUC__) || defined (__clang__)
- void * __builtin_return_address (unsigned int level);
/**
Get the return address of the calling function.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Guid/SystemResourceTable.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Guid/SystemResourceTable.h
index 4b6ecc2b06b..28041886d28 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Guid/SystemResourceTable.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Guid/SystemResourceTable.h
@@ -2,6 +2,7 @@
Guid & data structure used for EFI System Resource Table (ESRT)
Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
@@ -44,6 +45,18 @@
#define LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT 0x00000007
#define LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES 0x00000008
+///
+/// LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX is defined as
+/// 0x4000 as of UEFI Specification 2.8B. This will be modified in the
+/// future to the correct value 0x3FFF. To ensure correct implementation,
+/// this change is preemptively made in the value defined below.
+///
+/// When the UEFI Specification is updated, this comment block can be
+/// removed.
+///
+#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MIN 0x00001000
+#define LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL_VENDOR_RANGE_MAX 0x00003FFF
+
typedef struct {
///
/// The firmware class field contains a GUID that identifies a firmware component
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Ia32/Nasm.inc b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Ia32/Nasm.inc
index dbfcb740800..8ff5193520a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Ia32/Nasm.inc
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Ia32/Nasm.inc
@@ -1,6 +1,6 @@
;------------------------------------------------------------------------------
;
-; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Abstract:
@@ -9,6 +9,18 @@
;
;------------------------------------------------------------------------------
+%macro SAVEPREVSSP 0
+ DB 0xF3, 0x0F, 0x01, 0xEA
+%endmacro
+
+%macro CLRSSBSY_EAX 0
+ DB 0x67, 0xF3, 0x0F, 0xAE, 0x30
+%endmacro
+
+%macro RSTORSSP_EAX 0
+ DB 0x67, 0xF3, 0x0F, 0x01, 0x28
+%endmacro
+
%macro SETSSBSY 0
DB 0xF3, 0x0F, 0x01, 0xE8
%endmacro
@@ -20,3 +32,41 @@
%macro INCSSP_EAX 0
DB 0xF3, 0x0F, 0xAE, 0xE8
%endmacro
+
+; NASM provides built-in macros STRUC and ENDSTRUC for structure definition.
+; For example, to define a structure called mytype containing a longword,
+; a word, a byte and a string of bytes, you might code
+;
+; struc mytype
+;
+; mt_long: resd 1
+; mt_word: resw 1
+; mt_byte: resb 1
+; mt_str: resb 32
+;
+; endstruc
+;
+; Below macros are help to map the C types and the RESB family of pseudo-instructions.
+; So that the above structure definition can be coded as
+;
+; struc mytype
+;
+; mt_long: CTYPE_UINT32 1
+; mt_word: CTYPE_UINT16 1
+; mt_byte: CTYPE_UINT8 1
+; mt_str: CTYPE_CHAR8 32
+;
+; endstruc
+%define CTYPE_UINT64 resq
+%define CTYPE_INT64 resq
+%define CTYPE_UINT32 resd
+%define CTYPE_INT32 resd
+%define CTYPE_UINT16 resw
+%define CTYPE_INT16 resw
+%define CTYPE_BOOLEAN resb
+%define CTYPE_UINT8 resb
+%define CTYPE_CHAR8 resb
+%define CTYPE_INT8 resb
+
+%define CTYPE_UINTN resd
+%define CTYPE_INTN resd
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Acpi10.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Acpi10.h
index d1398018aef..7a09adc2a13 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Acpi10.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Acpi10.h
@@ -2,6 +2,7 @@
ACPI 1.0b definitions from the ACPI Specification, revision 1.0b
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2020, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -358,7 +359,7 @@ typedef struct {
#define EFI_ACPI_DMA_TRANSFER_TYPE_MASK 0x03
#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x00
#define EFI_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x01
-#define EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x10
+#define EFI_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x02
//
// IO Information
@@ -377,6 +378,16 @@ typedef struct {
#define EFI_ACPI_MEMORY_NON_WRITABLE 0x00
//
+// Interrupt Vector Flags definitions for Extended Interrupt Descriptor
+// Ref ACPI specification 6.4.3.6
+//
+#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_PRODUCER_CONSUMER_MASK BIT0
+#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_MODE_MASK BIT1
+#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_POLARITY_MASK BIT2
+#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_SHARABLE_MASK BIT3
+#define EFI_ACPI_EXTENDED_INTERRUPT_FLAG_WAKE_CAPABLITY_MASK BIT4
+
+//
// Ensure proper structure formats
//
#pragma pack(1)
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/ArmErrorSourceTable.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/ArmErrorSourceTable.h
new file mode 100644
index 00000000000..cae9644b265
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/ArmErrorSourceTable.h
@@ -0,0 +1,357 @@
+/** @file
+ Arm Error Source Table as described in the
+ 'ACPI for the Armv8 RAS Extensions 1.1' Specification.
+
+ Copyright (c) 2020 Arm Limited.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document,
+ dated 28 September 2020.
+ (https://developer.arm.com/documentation/den0085/0101/)
+
+ @par Glossary
+ - Ref : Reference
+ - Id : Identifier
+**/
+
+#ifndef ARM_ERROR_SOURCE_TABLE_H_
+#define ARM_ERROR_SOURCE_TABLE_H_
+
+///
+/// "AEST" Arm Error Source Table
+///
+#define EFI_ACPI_6_3_ARM_ERROR_SOURCE_TABLE_SIGNATURE SIGNATURE_32('A', 'E', 'S', 'T')
+
+#define EFI_ACPI_ARM_ERROR_SOURCE_TABLE_REVISION 1
+
+#pragma pack(1)
+
+///
+/// Arm Error Source Table definition.
+///
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+} EFI_ACPI_ARM_ERROR_SOURCE_TABLE;
+
+///
+/// AEST Node structure.
+///
+typedef struct {
+ /// Node type:
+ /// 0x00 - Processor error node
+ /// 0x01 - Memory error node
+ /// 0x02 - SMMU error node
+ /// 0x03 - Vendor-defined error node
+ /// 0x04 - GIC error node
+ UINT8 Type;
+
+ /// Length of structure in bytes.
+ UINT16 Length;
+
+ /// Reserved - Must be zero.
+ UINT8 Reserved;
+
+ /// Offset from the start of the node to node-specific data.
+ UINT32 DataOffset;
+
+ /// Offset from the start of the node to the node interface structure.
+ UINT32 InterfaceOffset;
+
+ /// Offset from the start of the node to node interrupt array.
+ UINT32 InterruptArrayOffset;
+
+ /// Number of entries in the interrupt array.
+ UINT32 InterruptArrayCount;
+
+ // Generic node data
+
+ /// The timestamp frequency of the counter in Hz.
+ UINT64 TimestampRate;
+
+ /// Reserved - Must be zero.
+ UINT64 Reserved1;
+
+ /// The rate in Hz at which the Error Generation Counter decrements.
+ UINT64 ErrorInjectionCountdownRate;
+} EFI_ACPI_AEST_NODE_STRUCT;
+
+// AEST Node type definitions
+#define EFI_ACPI_AEST_NODE_TYPE_PROCESSOR 0x0
+#define EFI_ACPI_AEST_NODE_TYPE_MEMORY 0x1
+#define EFI_ACPI_AEST_NODE_TYPE_SMMU 0x2
+#define EFI_ACPI_AEST_NODE_TYPE_VENDOR_DEFINED 0x3
+#define EFI_ACPI_AEST_NODE_TYPE_GIC 0x4
+
+///
+/// AEST Node Interface structure.
+///
+typedef struct {
+ /// Interface type:
+ /// 0x0 - System register (SR)
+ /// 0x1 - Memory mapped (MMIO)
+ UINT8 Type;
+
+ /// Reserved - Must be zero.
+ UINT8 Reserved[3];
+
+ /// AEST node interface flags.
+ UINT32 Flags;
+
+ /// Base address of error group that contains the error node.
+ UINT64 BaseAddress;
+
+ /// Zero-based index of the first standard error record that
+ /// belongs to this node.
+ UINT32 StartErrorRecordIndex;
+
+ /// Number of error records in this node including both
+ /// implemented and unimplemented records.
+ UINT32 NumberErrorRecords;
+
+ /// A bitmap indicating the error records within this
+ /// node that are implemented in the current system.
+ UINT64 ErrorRecordImplemented;
+
+ /// A bitmap indicating the error records within this node that
+ /// support error status reporting through the ERRGSR register.
+ UINT64 ErrorRecordStatusReportingSupported;
+
+ /// A bitmap indicating the addressing mode used by each error
+ /// record within this node to populate the ERR<n>_ADDR register.
+ UINT64 AddressingMode;
+} EFI_ACPI_AEST_INTERFACE_STRUCT;
+
+// AEST Interface node type definitions.
+#define EFI_ACPI_AEST_INTERFACE_TYPE_SR 0x0
+#define EFI_ACPI_AEST_INTERFACE_TYPE_MMIO 0x1
+
+// AEST node interface flag definitions.
+#define EFI_ACPI_AEST_INTERFACE_FLAG_PRIVATE 0
+#define EFI_ACPI_AEST_INTERFACE_FLAG_SHARED BIT0
+#define EFI_ACPI_AEST_INTERFACE_FLAG_CLEAR_MISCX BIT1
+
+///
+/// AEST Node Interrupt structure.
+///
+typedef struct {
+ /// Interrupt type:
+ /// 0x0 - Fault Handling Interrupt
+ /// 0x1 - Error Recovery Interrupt
+ UINT8 InterruptType;
+
+ /// Reserved - Must be zero.
+ UINT8 Reserved[2];
+
+ /// Interrupt flags
+ /// Bits [31:1]: Must be zero.
+ /// Bit 0:
+ /// 0b - Interrupt is edge-triggered
+ /// 1b - Interrupt is level-triggered
+ UINT8 InterruptFlags;
+
+ /// GSIV of interrupt, if interrupt is an SPI or a PPI.
+ UINT32 InterruptGsiv;
+
+ /// If MSI is supported, then this field must be set to the
+ /// Identifier field of the IORT ITS Group node.
+ UINT8 ItsGroupRefId;
+
+ /// Reserved - must be zero.
+ UINT8 Reserved1[3];
+} EFI_ACPI_AEST_INTERRUPT_STRUCT;
+
+// AEST Interrupt node - interrupt type defintions.
+#define EFI_ACPI_AEST_INTERRUPT_TYPE_FAULT_HANDLING 0x0
+#define EFI_ACPI_AEST_INTERRUPT_TYPE_ERROR_RECOVERY 0x1
+
+// AEST Interrupt node - interrupt flag defintions.
+#define EFI_ACPI_AEST_INTERRUPT_FLAG_TRIGGER_TYPE_EDGE 0
+#define EFI_ACPI_AEST_INTERRUPT_FLAG_TRIGGER_TYPE_LEVEL BIT0
+
+///
+/// Cache Processor Resource structure.
+///
+typedef struct {
+ /// Reference to the cache structure in the PPTT table.
+ UINT32 CacheRefId;
+
+ /// Reserved
+ UINT32 Reserved;
+} EFI_ACPI_AEST_PROCESSOR_CACHE_RESOURCE_STRUCT;
+
+///
+/// TLB Processor Resource structure.
+///
+typedef struct {
+ /// TLB level from perspective of current processor.
+ UINT32 TlbRefId;
+
+ /// Reserved
+ UINT32 Reserved;
+} EFI_ACPI_AEST_PROCESSOR_TLB_RESOURCE_STRUCT;
+
+///
+/// Processor Generic Resource structure.
+///
+typedef struct {
+ /// Vendor-defined supplementary data.
+ UINT32 Data;
+} EFI_ACPI_AEST_PROCESSOR_GENERIC_RESOURCE_STRUCT;
+
+///
+/// AEST Processor Resource union.
+///
+typedef union {
+ /// Processor Cache resource.
+ EFI_ACPI_AEST_PROCESSOR_CACHE_RESOURCE_STRUCT Cache;
+
+ /// Processor TLB resource.
+ EFI_ACPI_AEST_PROCESSOR_TLB_RESOURCE_STRUCT Tlb;
+
+ /// Processor Generic resource.
+ EFI_ACPI_AEST_PROCESSOR_GENERIC_RESOURCE_STRUCT Generic;
+} EFI_ACPI_AEST_PROCESSOR_RESOURCE;
+
+///
+/// AEST Processor structure.
+///
+typedef struct {
+ /// AEST Node header
+ EFI_ACPI_AEST_NODE_STRUCT NodeHeader;
+
+ /// Processor ID of node.
+ UINT32 AcpiProcessorId;
+
+ /// Resource type of the processor node.
+ /// 0x0 - Cache
+ /// 0x1 - TLB
+ /// 0x2 - Generic
+ UINT8 ResourceType;
+
+ /// Reserved - must be zero.
+ UINT8 Reserved;
+
+ /// Processor structure flags.
+ UINT8 Flags;
+
+ /// Processor structure revision.
+ UINT8 Revision;
+
+ /// Processor affinity descriptor for the resource that this
+ /// error node pertains to.
+ UINT64 ProcessorAffinityLevelIndicator;
+
+ /// Processor resource
+ EFI_ACPI_AEST_PROCESSOR_RESOURCE Resource;
+
+ // Node Interface
+ // EFI_ACPI_AEST_INTERFACE_STRUCT NodeInterface;
+
+ // Node Interrupt Array
+ // EFI_ACPI_AEST_INTERRUPT_STRUCT NodeInterruptArray[n];
+} EFI_ACPI_AEST_PROCESSOR_STRUCT;
+
+// AEST Processor resource type definitions.
+#define EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_CACHE 0x0
+#define EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_TLB 0x1
+#define EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_GENERIC 0x2
+
+// AEST Processor flag definitions.
+#define EFI_ACPI_AEST_PROCESSOR_FLAG_GLOBAL BIT0
+#define EFI_ACPI_AEST_PROCESSOR_FLAG_SHARED BIT1
+
+///
+/// Memory Controller structure.
+///
+typedef struct {
+ /// AEST Node header
+ EFI_ACPI_AEST_NODE_STRUCT NodeHeader;
+
+ /// SRAT proximity domain.
+ UINT32 ProximityDomain;
+
+ // Node Interface
+ // EFI_ACPI_AEST_INTERFACE_STRUCT NodeInterface;
+
+ // Node Interrupt Array
+ // EFI_ACPI_AEST_INTERRUPT_STRUCT NodeInterruptArray[n];
+} EFI_ACPI_AEST_MEMORY_CONTROLLER_STRUCT;
+
+///
+/// SMMU structure.
+///
+typedef struct {
+ /// AEST Node header
+ EFI_ACPI_AEST_NODE_STRUCT NodeHeader;
+
+ /// Reference to the IORT table node that describes this SMMU.
+ UINT32 SmmuRefId;
+
+ /// Reference to the IORT table node that is associated with the
+ /// sub-component within this SMMU.
+ UINT32 SubComponentRefId;
+
+ // Node Interface
+ // EFI_ACPI_AEST_INTERFACE_STRUCT NodeInterface;
+
+ // Node Interrupt Array
+ // EFI_ACPI_AEST_INTERRUPT_STRUCT NodeInterruptArray[n];
+} EFI_ACPI_AEST_SMMU_STRUCT;
+
+///
+/// Vendor-Defined structure.
+///
+typedef struct {
+ /// AEST Node header
+ EFI_ACPI_AEST_NODE_STRUCT NodeHeader;
+
+ /// ACPI HID of the component.
+ UINT32 HardwareId;
+
+ /// The ACPI Unique identifier of the component.
+ UINT32 UniqueId;
+
+ /// Vendor-specific data, for example to identify this error source.
+ UINT8 VendorData[16];
+
+ // Node Interface
+ // EFI_ACPI_AEST_INTERFACE_STRUCT NodeInterface;
+
+ // Node Interrupt Array
+ // EFI_ACPI_AEST_INTERRUPT_STRUCT NodeInterruptArray[n];
+} EFI_ACPI_AEST_VENDOR_DEFINED_STRUCT;
+
+///
+/// GIC structure.
+///
+typedef struct {
+ /// AEST Node header
+ EFI_ACPI_AEST_NODE_STRUCT NodeHeader;
+
+ /// Type of GIC interface that is associated with this error node.
+ /// 0x0 - GIC CPU (GICC)
+ /// 0x1 - GIC Distributor (GICD)
+ /// 0x2 - GIC Resistributor (GICR)
+ /// 0x3 - GIC ITS (GITS)
+ UINT32 InterfaceType;
+
+ /// Identifier for the interface instance.
+ UINT32 GicInterfaceRefId;
+
+ // Node Interface
+ // EFI_ACPI_AEST_INTERFACE_STRUCT NodeInterface;
+
+ // Node Interrupt Array
+ // EFI_ACPI_AEST_INTERRUPT_STRUCT NodeInterruptArray[n];
+} EFI_ACPI_AEST_GIC_STRUCT;
+
+// AEST GIC interface type definitions.
+#define EFI_ACPI_AEST_GIC_INTERFACE_TYPE_GICC 0x0
+#define EFI_ACPI_AEST_GIC_INTERFACE_TYPE_GICD 0x1
+#define EFI_ACPI_AEST_GIC_INTERFACE_TYPE_GICR 0x2
+#define EFI_ACPI_AEST_GIC_INTERFACE_TYPE_GITS 0x3
+
+#pragma pack()
+
+#endif // ARM_ERROR_SOURCE_TABLE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl.h
new file mode 100644
index 00000000000..f373e146809
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl.h
@@ -0,0 +1,22 @@
+/** @file
+ Support for the latest CXL standard
+
+ The main header to reference all versions of CXL Base specification registers
+ from the MDE
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CXL_MAIN_H_
+#define _CXL_MAIN_H_
+
+#include <IndustryStandard/Cxl11.h>
+//
+// CXL assigned new Vendor ID
+//
+#define CXL_DVSEC_VENDOR_ID 0x1E98
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl11.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl11.h
new file mode 100644
index 00000000000..c3d88d38169
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Cxl11.h
@@ -0,0 +1,659 @@
+/** @file
+ CXL 1.1 Register definitions
+
+ This file contains the register definitions based on the Compute Express Link
+ (CXL) Specification Revision 1.1.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CXL11_H_
+#define _CXL11_H_
+
+#include <IndustryStandard/Pci.h>
+//
+// DVSEC Vendor ID
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.1.1 - Table 58
+// (subject to change as per CXL assigned Vendor ID)
+//
+#define INTEL_CXL_DVSEC_VENDOR_ID 0x8086
+
+//
+// CXL Flex Bus Device default device and function number
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.1.1
+//
+#define CXL_DEV_DEV 0
+#define CXL_DEV_FUNC 0
+
+//
+// Ensure proper structure formats
+//
+#pragma pack(1)
+
+/**
+ Macro used to verify the size of a data type at compile time and trigger a
+ STATIC_ASSERT() with an error message if the size of the data type does not
+ match the expected size.
+
+ @param TypeName Type name of data type to verify.
+ @param ExpectedSize The expected size, in bytes, of the data type specified
+ by TypeName.
+**/
+#define CXL_11_SIZE_ASSERT(TypeName, ExpectedSize) \
+ STATIC_ASSERT ( \
+ sizeof (TypeName) == ExpectedSize, \
+ "Size of " #TypeName \
+ " does not meet CXL 1.1 Specification requirements." \
+ )
+
+/**
+ Macro used to verify the offset of a field in a data type at compile time and
+ trigger a STATIC_ASSERT() with an error message if the offset of the field in
+ the data type does not match the expected offset.
+
+ @param TypeName Type name of data type to verify.
+ @param FieldName Field name in the data type specified by TypeName to
+ verify.
+ @param ExpectedOffset The expected offset, in bytes, of the field specified
+ by TypeName and FieldName.
+**/
+#define CXL_11_OFFSET_ASSERT(TypeName, FieldName, ExpectedOffset) \
+ STATIC_ASSERT ( \
+ OFFSET_OF (TypeName, FieldName) == ExpectedOffset, \
+ "Offset of " #TypeName "." #FieldName \
+ " does not meet CXL 1.1 Specification requirements." \
+ )
+
+///
+/// The PCIe DVSEC for Flex Bus Device
+///@{
+typedef union {
+ struct {
+ UINT16 CacheCapable : 1; // bit 0
+ UINT16 IoCapable : 1; // bit 1
+ UINT16 MemCapable : 1; // bit 2
+ UINT16 MemHwInitMode : 1; // bit 3
+ UINT16 HdmCount : 2; // bit 4..5
+ UINT16 Reserved1 : 8; // bit 6..13
+ UINT16 ViralCapable : 1; // bit 14
+ UINT16 Reserved2 : 1; // bit 15
+ } Bits;
+ UINT16 Uint16;
+} CXL_DVSEC_FLEX_BUS_DEVICE_CAPABILITY;
+
+typedef union {
+ struct {
+ UINT16 CacheEnable : 1; // bit 0
+ UINT16 IoEnable : 1; // bit 1
+ UINT16 MemEnable : 1; // bit 2
+ UINT16 CacheSfCoverage : 5; // bit 3..7
+ UINT16 CacheSfGranularity : 3; // bit 8..10
+ UINT16 CacheCleanEviction : 1; // bit 11
+ UINT16 Reserved1 : 2; // bit 12..13
+ UINT16 ViralEnable : 1; // bit 14
+ UINT16 Reserved2 : 1; // bit 15
+ } Bits;
+ UINT16 Uint16;
+} CXL_DVSEC_FLEX_BUS_DEVICE_CONTROL;
+
+typedef union {
+ struct {
+ UINT16 Reserved1 : 14; // bit 0..13
+ UINT16 ViralStatus : 1; // bit 14
+ UINT16 Reserved2 : 1; // bit 15
+ } Bits;
+ UINT16 Uint16;
+} CXL_DVSEC_FLEX_BUS_DEVICE_STATUS;
+
+typedef union {
+ struct {
+ UINT16 Reserved1 : 1; // bit 0
+ UINT16 Reserved2 : 1; // bit 1
+ UINT16 Reserved3 : 1; // bit 2
+ UINT16 Reserved4 : 13; // bit 3..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_1_1_DVSEC_FLEX_BUS_DEVICE_CONTROL2;
+
+typedef union {
+ struct {
+ UINT16 Reserved1 : 1; // bit 0
+ UINT16 Reserved2 : 1; // bit 1
+ UINT16 Reserved3 : 14; // bit 2..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_1_1_DVSEC_FLEX_BUS_DEVICE_STATUS2;
+
+typedef union {
+ struct {
+ UINT16 ConfigLock : 1; // bit 0
+ UINT16 Reserved1 : 15; // bit 1..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_DVSEC_FLEX_BUS_DEVICE_LOCK;
+
+typedef union {
+ struct {
+ UINT32 MemorySizeHigh : 32; // bit 0..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_SIZE_HIGH;
+
+typedef union {
+ struct {
+ UINT32 MemoryInfoValid : 1; // bit 0
+ UINT32 MemoryActive : 1; // bit 1
+ UINT32 MediaType : 3; // bit 2..4
+ UINT32 MemoryClass : 3; // bit 5..7
+ UINT32 DesiredInterleave : 3; // bit 8..10
+ UINT32 Reserved : 17; // bit 11..27
+ UINT32 MemorySizeLow : 4; // bit 28..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_SIZE_LOW;
+
+typedef union {
+ struct {
+ UINT32 MemoryBaseHigh : 32; // bit 0..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_BASE_HIGH;
+
+typedef union {
+ struct {
+ UINT32 Reserved : 28; // bit 0..27
+ UINT32 MemoryBaseLow : 4; // bit 28..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_BASE_LOW;
+
+
+typedef union {
+ struct {
+ UINT32 MemorySizeHigh : 32; // bit 0..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_SIZE_HIGH;
+
+typedef union {
+ struct {
+ UINT32 MemoryInfoValid : 1; // bit 0
+ UINT32 MemoryActive : 1; // bit 1
+ UINT32 MediaType : 3; // bit 2..4
+ UINT32 MemoryClass : 3; // bit 5..7
+ UINT32 DesiredInterleave : 3; // bit 8..10
+ UINT32 Reserved : 17; // bit 11..27
+ UINT32 MemorySizeLow : 4; // bit 28..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_SIZE_LOW;
+
+typedef union {
+ struct {
+ UINT32 MemoryBaseHigh : 32; // bit 0..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_BASE_HIGH;
+
+typedef union {
+ struct {
+ UINT32 Reserved : 28; // bit 0..27
+ UINT32 MemoryBaseLow : 4; // bit 28..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_BASE_LOW;
+
+//
+// Flex Bus Device DVSEC ID
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.1.1, Table 58
+//
+#define FLEX_BUS_DEVICE_DVSEC_ID 0
+
+//
+// PCIe DVSEC for Flex Bus Device
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.1.1, Figure 95
+//
+typedef struct {
+ PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; // offset 0
+ PCI_EXPRESS_DESIGNATED_VENDOR_SPECIFIC_HEADER_1 DesignatedVendorSpecificHeader1; // offset 4
+ PCI_EXPRESS_DESIGNATED_VENDOR_SPECIFIC_HEADER_2 DesignatedVendorSpecificHeader2; // offset 8
+ CXL_DVSEC_FLEX_BUS_DEVICE_CAPABILITY DeviceCapability; // offset 10
+ CXL_DVSEC_FLEX_BUS_DEVICE_CONTROL DeviceControl; // offset 12
+ CXL_DVSEC_FLEX_BUS_DEVICE_STATUS DeviceStatus; // offset 14
+ CXL_1_1_DVSEC_FLEX_BUS_DEVICE_CONTROL2 DeviceControl2; // offset 16
+ CXL_1_1_DVSEC_FLEX_BUS_DEVICE_STATUS2 DeviceStatus2; // offset 18
+ CXL_DVSEC_FLEX_BUS_DEVICE_LOCK DeviceLock; // offset 20
+ UINT16 Reserved; // offset 22
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_SIZE_HIGH DeviceRange1SizeHigh; // offset 24
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_SIZE_LOW DeviceRange1SizeLow; // offset 28
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_BASE_HIGH DeviceRange1BaseHigh; // offset 32
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE1_BASE_LOW DeviceRange1BaseLow; // offset 36
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_SIZE_HIGH DeviceRange2SizeHigh; // offset 40
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_SIZE_LOW DeviceRange2SizeLow; // offset 44
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_BASE_HIGH DeviceRange2BaseHigh; // offset 48
+ CXL_DVSEC_FLEX_BUS_DEVICE_RANGE2_BASE_LOW DeviceRange2BaseLow; // offset 52
+} CXL_1_1_DVSEC_FLEX_BUS_DEVICE;
+
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, Header , 0x00);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DesignatedVendorSpecificHeader1, 0x04);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DesignatedVendorSpecificHeader2, 0x08);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceCapability , 0x0A);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceControl , 0x0C);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceStatus , 0x0E);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceControl2 , 0x10);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceStatus2 , 0x12);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceLock , 0x14);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange1SizeHigh , 0x18);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange1SizeLow , 0x1C);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange1BaseHigh , 0x20);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange1BaseLow , 0x24);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange2SizeHigh , 0x28);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange2SizeLow , 0x2C);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange2BaseHigh , 0x30);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE, DeviceRange2BaseLow , 0x34);
+CXL_11_SIZE_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_DEVICE , 0x38);
+///@}
+
+///
+/// PCIe DVSEC for FLex Bus Port
+///@{
+typedef union {
+ struct {
+ UINT16 CacheCapable : 1; // bit 0
+ UINT16 IoCapable : 1; // bit 1
+ UINT16 MemCapable : 1; // bit 2
+ UINT16 Reserved : 13; // bit 3..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_1_1_DVSEC_FLEX_BUS_PORT_CAPABILITY;
+
+typedef union {
+ struct {
+ UINT16 CacheEnable : 1; // bit 0
+ UINT16 IoEnable : 1; // bit 1
+ UINT16 MemEnable : 1; // bit 2
+ UINT16 CxlSyncBypassEnable : 1; // bit 3
+ UINT16 DriftBufferEnable : 1; // bit 4
+ UINT16 Reserved : 3; // bit 5..7
+ UINT16 Retimer1Present : 1; // bit 8
+ UINT16 Retimer2Present : 1; // bit 9
+ UINT16 Reserved2 : 6; // bit 10..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_1_1_DVSEC_FLEX_BUS_PORT_CONTROL;
+
+typedef union {
+ struct {
+ UINT16 CacheEnable : 1; // bit 0
+ UINT16 IoEnable : 1; // bit 1
+ UINT16 MemEnable : 1; // bit 2
+ UINT16 CxlSyncBypassEnable : 1; // bit 3
+ UINT16 DriftBufferEnable : 1; // bit 4
+ UINT16 Reserved : 3; // bit 5..7
+ UINT16 CxlCorrectableProtocolIdFramingError : 1; // bit 8
+ UINT16 CxlUncorrectableProtocolIdFramingError : 1; // bit 9
+ UINT16 CxlUnexpectedProtocolIdDropped : 1; // bit 10
+ UINT16 Reserved2 : 5; // bit 11..15
+ } Bits;
+ UINT16 Uint16;
+} CXL_1_1_DVSEC_FLEX_BUS_PORT_STATUS;
+
+//
+// Flex Bus Port DVSEC ID
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.2.1.3, Table 62
+//
+#define FLEX_BUS_PORT_DVSEC_ID 7
+
+//
+// PCIe DVSEC for Flex Bus Port
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.2.1.3, Figure 99
+//
+typedef struct {
+ PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER Header; // offset 0
+ PCI_EXPRESS_DESIGNATED_VENDOR_SPECIFIC_HEADER_1 DesignatedVendorSpecificHeader1; // offset 4
+ PCI_EXPRESS_DESIGNATED_VENDOR_SPECIFIC_HEADER_2 DesignatedVendorSpecificHeader2; // offset 8
+ CXL_1_1_DVSEC_FLEX_BUS_PORT_CAPABILITY PortCapability; // offset 10
+ CXL_1_1_DVSEC_FLEX_BUS_PORT_CONTROL PortControl; // offset 12
+ CXL_1_1_DVSEC_FLEX_BUS_PORT_STATUS PortStatus; // offset 14
+} CXL_1_1_DVSEC_FLEX_BUS_PORT;
+
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT, Header , 0x00);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT, DesignatedVendorSpecificHeader1, 0x04);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT, DesignatedVendorSpecificHeader2, 0x08);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT, PortCapability , 0x0A);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT, PortControl , 0x0C);
+CXL_11_OFFSET_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT, PortStatus , 0x0E);
+CXL_11_SIZE_ASSERT (CXL_1_1_DVSEC_FLEX_BUS_PORT , 0x10);
+///@}
+
+///
+/// CXL 1.1 Upstream and Downstream Port Subsystem Component registers
+///
+
+/// The CXL.Cache and CXL.Memory Architectural register definitions
+/// Based on chapter 7.2.2 of Compute Express Link Specification Revision: 1.1
+///@{
+
+#define CXL_CAPABILITY_HEADER_OFFSET 0
+typedef union {
+ struct {
+ UINT32 CxlCapabilityId : 16; // bit 0..15
+ UINT32 CxlCapabilityVersion : 4; // bit 16..19
+ UINT32 CxlCacheMemVersion : 4; // bit 20..23
+ UINT32 ArraySize : 8; // bit 24..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CAPABILITY_HEADER;
+
+#define CXL_RAS_CAPABILITY_HEADER_OFFSET 4
+typedef union {
+ struct {
+ UINT32 CxlCapabilityId : 16; // bit 0..15
+ UINT32 CxlCapabilityVersion : 4; // bit 16..19
+ UINT32 CxlRasCapabilityPointer : 12; // bit 20..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_RAS_CAPABILITY_HEADER;
+
+#define CXL_SECURITY_CAPABILITY_HEADER_OFFSET 8
+typedef union {
+ struct {
+ UINT32 CxlCapabilityId : 16; // bit 0..15
+ UINT32 CxlCapabilityVersion : 4; // bit 16..19
+ UINT32 CxlSecurityCapabilityPointer : 12; // bit 20..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_SECURITY_CAPABILITY_HEADER;
+
+#define CXL_LINK_CAPABILITY_HEADER_OFFSET 0xC
+typedef union {
+ struct {
+ UINT32 CxlCapabilityId : 16; // bit 0..15
+ UINT32 CxlCapabilityVersion : 4; // bit 16..19
+ UINT32 CxlLinkCapabilityPointer : 12; // bit 20..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_LINK_CAPABILITY_HEADER;
+
+typedef union {
+ struct {
+ UINT32 CacheDataParity : 1; // bit 0..0
+ UINT32 CacheAddressParity : 1; // bit 1..1
+ UINT32 CacheByteEnableParity : 1; // bit 2..2
+ UINT32 CacheDataEcc : 1; // bit 3..3
+ UINT32 MemDataParity : 1; // bit 4..4
+ UINT32 MemAddressParity : 1; // bit 5..5
+ UINT32 MemByteEnableParity : 1; // bit 6..6
+ UINT32 MemDataEcc : 1; // bit 7..7
+ UINT32 ReInitThreshold : 1; // bit 8..8
+ UINT32 RsvdEncodingViolation : 1; // bit 9..9
+ UINT32 PoisonReceived : 1; // bit 10..10
+ UINT32 ReceiverOverflow : 1; // bit 11..11
+ UINT32 Reserved : 20; // bit 12..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_1_1_UNCORRECTABLE_ERROR_STATUS;
+
+typedef union {
+ struct {
+ UINT32 CacheDataParityMask : 1; // bit 0..0
+ UINT32 CacheAddressParityMask : 1; // bit 1..1
+ UINT32 CacheByteEnableParityMask : 1; // bit 2..2
+ UINT32 CacheDataEccMask : 1; // bit 3..3
+ UINT32 MemDataParityMask : 1; // bit 4..4
+ UINT32 MemAddressParityMask : 1; // bit 5..5
+ UINT32 MemByteEnableParityMask : 1; // bit 6..6
+ UINT32 MemDataEccMask : 1; // bit 7..7
+ UINT32 ReInitThresholdMask : 1; // bit 8..8
+ UINT32 RsvdEncodingViolationMask : 1; // bit 9..9
+ UINT32 PoisonReceivedMask : 1; // bit 10..10
+ UINT32 ReceiverOverflowMask : 1; // bit 11..11
+ UINT32 Reserved : 20; // bit 12..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_1_1_UNCORRECTABLE_ERROR_MASK;
+
+typedef union {
+ struct {
+ UINT32 CacheDataParitySeverity : 1; // bit 0..0
+ UINT32 CacheAddressParitySeverity : 1; // bit 1..1
+ UINT32 CacheByteEnableParitySeverity : 1; // bit 2..2
+ UINT32 CacheDataEccSeverity : 1; // bit 3..3
+ UINT32 MemDataParitySeverity : 1; // bit 4..4
+ UINT32 MemAddressParitySeverity : 1; // bit 5..5
+ UINT32 MemByteEnableParitySeverity : 1; // bit 6..6
+ UINT32 MemDataEccSeverity : 1; // bit 7..7
+ UINT32 ReInitThresholdSeverity : 1; // bit 8..8
+ UINT32 RsvdEncodingViolationSeverity : 1; // bit 9..9
+ UINT32 PoisonReceivedSeverity : 1; // bit 10..10
+ UINT32 ReceiverOverflowSeverity : 1; // bit 11..11
+ UINT32 Reserved : 20; // bit 12..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_1_1_UNCORRECTABLE_ERROR_SEVERITY;
+
+typedef union {
+ struct {
+ UINT32 CacheDataEcc : 1; // bit 0..0
+ UINT32 MemoryDataEcc : 1; // bit 1..1
+ UINT32 CrcThreshold : 1; // bit 2..2
+ UINT32 RetryThreshold : 1; // bit 3..3
+ UINT32 CachePoisonReceived : 1; // bit 4..4
+ UINT32 MemoryPoisonReceived : 1; // bit 5..5
+ UINT32 PhysicalLayerError : 1; // bit 6..6
+ UINT32 Reserved : 25; // bit 7..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CORRECTABLE_ERROR_STATUS;
+
+typedef union {
+ struct {
+ UINT32 CacheDataEccMask : 1; // bit 0..0
+ UINT32 MemoryDataEccMask : 1; // bit 1..1
+ UINT32 CrcThresholdMask : 1; // bit 2..2
+ UINT32 RetryThresholdMask : 1; // bit 3..3
+ UINT32 CachePoisonReceivedMask : 1; // bit 4..4
+ UINT32 MemoryPoisonReceivedMask : 1; // bit 5..5
+ UINT32 PhysicalLayerErrorMask : 1; // bit 6..6
+ UINT32 Reserved : 25; // bit 7..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CORRECTABLE_ERROR_MASK;
+
+typedef union {
+ struct {
+ UINT32 FirstErrorPointer : 4; // bit 0..3
+ UINT32 Reserved1 : 5; // bit 4..8
+ UINT32 MultipleHeaderRecordingCapability : 1; // bit 9..9
+ UINT32 Reserved2 : 3; // bit 10..12
+ UINT32 PoisonEnabled : 1; // bit 13..13
+ UINT32 Reserved3 : 18; // bit 14..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_ERROR_CAPABILITIES_AND_CONTROL;
+
+typedef struct {
+ CXL_1_1_UNCORRECTABLE_ERROR_STATUS UncorrectableErrorStatus;
+ CXL_1_1_UNCORRECTABLE_ERROR_MASK UncorrectableErrorMask;
+ CXL_1_1_UNCORRECTABLE_ERROR_SEVERITY UncorrectableErrorSeverity;
+ CXL_CORRECTABLE_ERROR_STATUS CorrectableErrorStatus;
+ CXL_CORRECTABLE_ERROR_MASK CorrectableErrorMask;
+ CXL_ERROR_CAPABILITIES_AND_CONTROL ErrorCapabilitiesAndControl;
+ UINT32 HeaderLog[16];
+} CXL_1_1_RAS_CAPABILITY_STRUCTURE;
+
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, UncorrectableErrorStatus , 0x00);
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, UncorrectableErrorMask , 0x04);
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, UncorrectableErrorSeverity , 0x08);
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, CorrectableErrorStatus , 0x0C);
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, CorrectableErrorMask , 0x10);
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, ErrorCapabilitiesAndControl, 0x14);
+CXL_11_OFFSET_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE, HeaderLog , 0x18);
+CXL_11_SIZE_ASSERT (CXL_1_1_RAS_CAPABILITY_STRUCTURE , 0x58);
+
+typedef union {
+ struct {
+ UINT32 DeviceTrustLevel : 2; // bit 0..1
+ UINT32 Reserved : 30; // bit 2..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_1_1_SECURITY_POLICY;
+
+typedef struct {
+ CXL_1_1_SECURITY_POLICY SecurityPolicy;
+} CXL_1_1_SECURITY_CAPABILITY_STRUCTURE;
+
+CXL_11_OFFSET_ASSERT (CXL_1_1_SECURITY_CAPABILITY_STRUCTURE, SecurityPolicy, 0x0);
+CXL_11_SIZE_ASSERT (CXL_1_1_SECURITY_CAPABILITY_STRUCTURE, 0x4);
+
+typedef union {
+ struct {
+ UINT64 CxlLinkVersionSupported : 4; // bit 0..3
+ UINT64 CxlLinkVersionReceived : 4; // bit 4..7
+ UINT64 LlrWrapValueSupported : 8; // bit 8..15
+ UINT64 LlrWrapValueReceived : 8; // bit 16..23
+ UINT64 NumRetryReceived : 5; // bit 24..28
+ UINT64 NumPhyReinitReceived : 5; // bit 29..33
+ UINT64 WrPtrReceived : 8; // bit 34..41
+ UINT64 EchoEseqReceived : 8; // bit 42..49
+ UINT64 NumFreeBufReceived : 8; // bit 50..57
+ UINT64 Reserved : 6; // bit 58..63
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_CAPABILITY;
+
+typedef union {
+ struct {
+ UINT16 LlReset : 1; // bit 0..0
+ UINT16 LlInitStall : 1; // bit 1..1
+ UINT16 LlCrdStall : 1; // bit 2..2
+ UINT16 InitState : 2; // bit 3..4
+ UINT16 LlRetryBufferConsumed : 8; // bit 5..12
+ UINT16 Reserved : 3; // bit 13..15
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_CONTROL_AND_STATUS;
+
+typedef union {
+ struct {
+ UINT64 CacheReqCredits : 10; // bit 0..9
+ UINT64 CacheRspCredits : 10; // bit 10..19
+ UINT64 CacheDataCredits : 10; // bit 20..29
+ UINT64 MemReqRspCredits : 10; // bit 30..39
+ UINT64 MemDataCredits : 10; // bit 40..49
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_RX_CREDIT_CONTROL;
+
+typedef union {
+ struct {
+ UINT64 CacheReqCredits : 10; // bit 0..9
+ UINT64 CacheRspCredits : 10; // bit 10..19
+ UINT64 CacheDataCredits : 10; // bit 20..29
+ UINT64 MemReqRspCredits : 10; // bit 30..39
+ UINT64 MemDataCredits : 10; // bit 40..49
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_RX_CREDIT_RETURN_STATUS;
+
+typedef union {
+ struct {
+ UINT64 CacheReqCredits : 10; // bit 0..9
+ UINT64 CacheRspCredits : 10; // bit 10..19
+ UINT64 CacheDataCredits : 10; // bit 20..29
+ UINT64 MemReqRspCredits : 10; // bit 30..39
+ UINT64 MemDataCredits : 10; // bit 40..49
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_TX_CREDIT_STATUS;
+
+typedef union {
+ struct {
+ UINT32 AckForceThreshold : 8; // bit 0..7
+ UINT32 AckFLushRetimer : 10; // bit 8..17
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_ACK_TIMER_CONTROL;
+
+typedef union {
+ struct {
+ UINT32 MdhDisable : 1; // bit 0..0
+ UINT32 Reserved : 31; // bit 1..31
+ } Bits;
+ UINT64 Uint64;
+} CXL_LINK_LAYER_DEFEATURE;
+
+typedef struct {
+ CXL_LINK_LAYER_CAPABILITY LinkLayerCapability;
+ CXL_LINK_LAYER_CONTROL_AND_STATUS LinkLayerControlStatus;
+ CXL_LINK_LAYER_RX_CREDIT_CONTROL LinkLayerRxCreditControl;
+ CXL_LINK_LAYER_RX_CREDIT_RETURN_STATUS LinkLayerRxCreditReturnStatus;
+ CXL_LINK_LAYER_TX_CREDIT_STATUS LinkLayerTxCreditStatus;
+ CXL_LINK_LAYER_ACK_TIMER_CONTROL LinkLayerAckTimerControl;
+ CXL_LINK_LAYER_DEFEATURE LinkLayerDefeature;
+} CXL_1_1_LINK_CAPABILITY_STRUCTURE;
+
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerCapability , 0x00);
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerControlStatus , 0x08);
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerRxCreditControl , 0x10);
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerRxCreditReturnStatus, 0x18);
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerTxCreditStatus , 0x20);
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerAckTimerControl , 0x28);
+CXL_11_OFFSET_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE, LinkLayerDefeature , 0x30);
+CXL_11_SIZE_ASSERT (CXL_1_1_LINK_CAPABILITY_STRUCTURE , 0x38);
+
+#define CXL_IO_ARBITRATION_CONTROL_OFFSET 0x180
+typedef union {
+ struct {
+ UINT32 Reserved1 : 4; // bit 0..3
+ UINT32 WeightedRoundRobinArbitrationWeight : 4; // bit 4..7
+ UINT32 Reserved2 : 24; // bit 8..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_IO_ARBITRATION_CONTROL;
+
+CXL_11_SIZE_ASSERT (CXL_IO_ARBITRATION_CONTROL, 0x4);
+
+#define CXL_CACHE_MEMORY_ARBITRATION_CONTROL_OFFSET 0x1C0
+typedef union {
+ struct {
+ UINT32 Reserved1 : 4; // bit 0..3
+ UINT32 WeightedRoundRobinArbitrationWeight : 4; // bit 4..7
+ UINT32 Reserved2 : 24; // bit 8..31
+ } Bits;
+ UINT32 Uint32;
+} CXL_CACHE_MEMORY_ARBITRATION_CONTROL;
+
+CXL_11_SIZE_ASSERT (CXL_CACHE_MEMORY_ARBITRATION_CONTROL, 0x4);
+
+///@}
+
+/// The CXL.RCRB base register definition
+/// Based on chapter 7.3 of Compute Express Link Specification Revision: 1.1
+///@{
+typedef union {
+ struct {
+ UINT64 RcrbEnable : 1; // bit 0..0
+ UINT64 Reserved : 12; // bit 1..12
+ UINT64 RcrbBaseAddress : 51; // bit 13..63
+ } Bits;
+ UINT64 Uint64;
+} CXL_RCRB_BASE;
+
+CXL_11_SIZE_ASSERT (CXL_RCRB_BASE, 0x8);
+
+///@}
+
+#pragma pack()
+
+//
+// CXL Downstream / Upstream Port RCRB space register offsets
+// Compute Express Link Specification Revision: 1.1 - Chapter 7.2.1.1 - Figure 97
+//
+#define CXL_PORT_RCRB_MEMBAR0_LOW_OFFSET 0x010
+#define CXL_PORT_RCRB_MEMBAR0_HIGH_OFFSET 0x014
+#define CXL_PORT_RCRB_EXTENDED_CAPABILITY_BASE_OFFSET 0x100
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h
index 3e5aadc4a83..a36df39b07d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/DmaRemappingReportingTable.h
@@ -2,13 +2,13 @@
DMA Remapping Reporting (DMAR) ACPI table definition from Intel(R)
Virtualization Technology for Directed I/O (VT-D) Architecture Specification.
- Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
- Intel(R) Virtualization Technology for Directed I/O (VT-D) Architecture
- Specification v2.5, Dated November 2017.
- http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/vt-directed-io-spec.pdf
+ Specification v3.2, Dated October 2020.
+ https://software.intel.com/content/dam/develop/external/us/en/documents/vt-directed-io-spec.pdf
@par Glossary:
- HPET - High Precision Event Timer
@@ -39,6 +39,7 @@
#define EFI_ACPI_DMAR_TYPE_ATSR 0x02
#define EFI_ACPI_DMAR_TYPE_RHSA 0x03
#define EFI_ACPI_DMAR_TYPE_ANDD 0x04
+#define EFI_ACPI_DMAR_TYPE_SATC 0x05
///@}
///
@@ -217,6 +218,32 @@ typedef struct {
} EFI_ACPI_DMAR_ANDD_HEADER;
/**
+ An SoC Integrated Address Translation Cache (SATC) reporting structure is
+ defined in section 8.8.
+**/
+typedef struct {
+ EFI_ACPI_DMAR_STRUCTURE_HEADER Header;
+ /**
+ - Bit[0]: ATC_REQUIRED:
+ - If Set, indicates that every SoC integrated device enumerated
+ in this table has a functional requirement to enable its ATC
+ (via the ATS capability) for device operation.
+ - If Clear, any device enumerated in this table can operate when
+ its respective ATC is not enabled (albeit with reduced
+ performance or functionality).
+ - Bits[7:1] Reserved.
+ **/
+ UINT8 Flags;
+ UINT8 Reserved;
+ ///
+ /// The PCI Segment associated with this SATC structure. All SoC integrated
+ /// devices within a PCI segment with same value for Flags field must be
+ /// enumerated in the same SATC structure.
+ ///
+ UINT16 SegmentNumber;
+} EFI_ACPI_DMAR_SATC_HEADER;
+
+/**
DMA Remapping Reporting Structure Header as defined in section 8.1
This header will be followed by list of Remapping Structures listed below
- DMA Remapping Hardware Unit Definition (DRHD)
@@ -224,6 +251,7 @@ typedef struct {
- Root Port ATS Capability Reporting (ATSR)
- Remapping Hardware Static Affinity (RHSA)
- ACPI Name-space Device Declaration (ANDD)
+ - SoC Integrated Address Translation Cache reporting (SATC)
These structure types must by reported in numerical order.
i.e., All remapping structures of type 0 (DRHD) enumerated before remapping
structures of type 1 (RMRR), and so forth.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Http11.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Http11.h
index 50a182634d0..79fbde66f59 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Http11.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Http11.h
@@ -146,7 +146,11 @@
/// is a property of the message, not of the entity.
///
#define HTTP_HEADER_TRANSFER_ENCODING "Transfer-Encoding"
-
+#define HTTP_HEADER_TRANSFER_ENCODING_CHUNKED "chunked"
+#define CHUNKED_TRANSFER_CODING_CR '\r'
+#define CHUNKED_TRANSFER_CODING_LF '\n'
+#define CHUNKED_TRANSFER_CODING_LAST_CHUNK '0'
+#define CHUNKED_TRANSFER_CODING_EXTENSION_SEPARATOR ';'
///
/// User Agent Request Header
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h
index 408971c019b..4bc163e1bfe 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h
@@ -10,6 +10,8 @@
#ifndef _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_
#define _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_
+#include <IndustryStandard/Acpi.h>
+
//
// Ensure proper structure formats
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Pci.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Pci.h
index ef5791ef568..2cd95d75a21 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Pci.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Pci.h
@@ -1,7 +1,7 @@
/** @file
Support for the latest PCI standard.
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -9,9 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef _PCI_H_
#define _PCI_H_
-#include <IndustryStandard/Pci30.h>
-#include <IndustryStandard/PciExpress21.h>
-#include <IndustryStandard/PciExpress30.h>
+#include <IndustryStandard/PciExpress50.h>
#include <IndustryStandard/PciCodeId.h>
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/PciExpress21.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/PciExpress21.h
index 4f1322310be..dbe6349dea6 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/PciExpress21.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/PciExpress21.h
@@ -1,7 +1,7 @@
/** @file
Support for the latest PCI standard.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -632,10 +632,30 @@ typedef struct {
#define PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID 0x0015
#define PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_VER1 0x1
+typedef union {
+ struct {
+ UINT32 Reserved:4;
+ UINT32 BarSizeCapability:28;
+ } Bits;
+ UINT32 Uint32;
+} PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY;
+
+
+typedef union {
+ struct {
+ UINT32 BarIndex:3;
+ UINT32 Reserved:2;
+ UINT32 ResizableBarNumber:3;
+ UINT32 BarSize:6;
+ UINT32 Reserved2:2;
+ UINT32 BarSizeCapability:16;
+ } Bits;
+ UINT32 Uint32;
+} PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL;
+
typedef struct {
- UINT32 ResizableBarCapability;
- UINT16 ResizableBarControl;
- UINT16 Reserved;
+ PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CAPABILITY ResizableBarCapability;
+ PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_CONTROL ResizableBarControl;
} PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY;
typedef struct {
@@ -643,7 +663,7 @@ typedef struct {
PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY Capability[1];
} PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR;
-#define GET_NUMBER_RESIZABLE_BARS(x) (((x->Capability[0].ResizableBarControl) & 0xE0) >> 5)
+#define GET_NUMBER_RESIZABLE_BARS(x) (x->Capability[0].ResizableBarControl.Bits.ResizableBarNumber)
#define PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_ID 0x000E
#define PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_VER1 0x1
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/SmBios.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/SmBios.h
index c04df502a46..39d855db837 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/SmBios.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/SmBios.h
@@ -862,18 +862,32 @@ typedef struct {
} PROCESSOR_FEATURE_FLAGS;
typedef struct {
- UINT32 ProcessorReserved1 :1;
- UINT32 ProcessorUnknown :1;
- UINT32 Processor64BitCapble :1;
- UINT32 ProcessorMultiCore :1;
- UINT32 ProcessorHardwareThread :1;
- UINT32 ProcessorExecuteProtection :1;
- UINT32 ProcessorEnhancedVirtulization :1;
- UINT32 ProcessorPowerPerformanceCtrl :1;
- UINT32 Processor128bitCapble :1;
- UINT32 ProcessorReserved2 :7;
+ UINT16 ProcessorReserved1 :1;
+ UINT16 ProcessorUnknown :1;
+ UINT16 Processor64BitCapable :1;
+ UINT16 ProcessorMultiCore :1;
+ UINT16 ProcessorHardwareThread :1;
+ UINT16 ProcessorExecuteProtection :1;
+ UINT16 ProcessorEnhancedVirtualization :1;
+ UINT16 ProcessorPowerPerformanceCtrl :1;
+ UINT16 Processor128BitCapable :1;
+ UINT16 ProcessorArm64SocId :1;
+ UINT16 ProcessorReserved2 :6;
} PROCESSOR_CHARACTERISTIC_FLAGS;
+///
+/// Processor Information - Status
+///
+typedef union {
+ struct {
+ UINT8 CpuStatus :3; ///< Indicates the status of the processor.
+ UINT8 Reserved1 :3; ///< Reserved for future use. Must be set to zero.
+ UINT8 SocketPopulated :1; ///< Indicates if the processor socket is populated or not.
+ UINT8 Reserved2 :1; ///< Reserved for future use. Must be set to zero.
+ } Bits;
+ UINT8 Data;
+} PROCESSOR_STATUS_DATA;
+
typedef struct {
PROCESSOR_SIGNATURE Signature;
PROCESSOR_FEATURE_FLAGS FeatureFlags;
@@ -893,7 +907,7 @@ typedef struct {
SMBIOS_TABLE_STRING Socket;
UINT8 ProcessorType; ///< The enumeration value from PROCESSOR_TYPE_DATA.
UINT8 ProcessorFamily; ///< The enumeration value from PROCESSOR_FAMILY_DATA.
- SMBIOS_TABLE_STRING ProcessorManufacture;
+ SMBIOS_TABLE_STRING ProcessorManufacturer;
PROCESSOR_ID_DATA ProcessorId;
SMBIOS_TABLE_STRING ProcessorVersion;
PROCESSOR_VOLTAGE Voltage;
@@ -1718,7 +1732,9 @@ typedef enum {
MemoryTypeLpddr4 = 0x1E,
MemoryTypeLogicalNonVolatileDevice = 0x1F,
MemoryTypeHBM = 0x20,
- MemoryTypeHBM2 = 0x21
+ MemoryTypeHBM2 = 0x21,
+ MemoryTypeDdr5 = 0x22,
+ MemoryTypeLpddr5 = 0x23
} MEMORY_DEVICE_TYPE;
///
@@ -1834,7 +1850,7 @@ typedef struct {
//
UINT8 MemoryTechnology; ///< The enumeration value from MEMORY_DEVICE_TECHNOLOGY
MEMORY_DEVICE_OPERATING_MODE_CAPABILITY MemoryOperatingModeCapability;
- SMBIOS_TABLE_STRING FirwareVersion;
+ SMBIOS_TABLE_STRING FirmwareVersion;
UINT16 ModuleManufacturerID;
UINT16 ModuleProductID;
UINT16 MemorySubsystemControllerManufacturerID;
@@ -2504,6 +2520,15 @@ typedef struct {
} SMBIOS_TABLE_TYPE41;
///
+/// Management Controller Host Interface - Protocol Record Data Format.
+///
+typedef struct {
+ UINT8 ProtocolType;
+ UINT8 ProtocolTypeDataLen;
+ UINT8 ProtocolTypeData[1];
+} MC_HOST_INTERFACE_PROTOCOL_RECORD;
+
+///
/// Management Controller Host Interface - Interface Types.
/// 00h - 3Fh: MCTP Host Interfaces
///
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Tpm2Acpi.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Tpm2Acpi.h
index f52b7c7fd47..e6d0bda36ab 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Tpm2Acpi.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/IndustryStandard/Tpm2Acpi.h
@@ -2,6 +2,7 @@
TPM2 ACPI table definition.
Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved. <BR>
+Copyright (c) 2021, Ampere Computing LLC. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -48,6 +49,18 @@ typedef struct {
UINT64 Response;
} EFI_TPM2_ACPI_CONTROL_AREA;
+//
+// Start Method Specific Parameters for ARM SMC Start Method (11)
+// Refer to Table 9: Start Method Specific Parameters for ARM SMC
+//
+typedef struct {
+ UINT32 Interrupt;
+ UINT8 Flags;
+ UINT8 OperationFlags;
+ UINT8 Reserved[2];
+ UINT32 SmcFunctionId;
+} EFI_TPM2_ACPI_START_METHOD_SPECIFIC_PARAMETERS_ARM_SMC;
+
#pragma pack ()
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/BaseLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/BaseLib.h
index 762cb9ac3ab..679649a03b2 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/BaseLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/BaseLib.h
@@ -2,7 +2,7 @@
Provides string functions, linked list functions, math functions, synchronization
functions, file path functions, and CPU architecture-specific functions.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) Microsoft Corporation.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -962,82 +962,6 @@ AsciiStrHexToUint64S (
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Copies one Null-terminated Unicode string to another Null-terminated Unicode
- string and returns the new Unicode string.
-
- This function copies the contents of the Unicode string Source to the Unicode
- string Destination, and returns Destination. If Source and Destination
- overlap, then the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters not including the
- Null-terminator, then ASSERT().
-
- @param Destination The pointer to a Null-terminated Unicode string.
- @param Source The pointer to a Null-terminated Unicode string.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrCpy (
- OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source
- );
-
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Copies up to a specified length from one Null-terminated Unicode string to
- another Null-terminated Unicode string and returns the new Unicode string.
-
- This function copies the contents of the Unicode string Source to the Unicode
- string Destination, and returns Destination. At most, Length Unicode
- characters are copied from Source to Destination. If Length is 0, then
- Destination is returned unmodified. If Length is greater that the number of
- Unicode characters in Source, then Destination is padded with Null Unicode
- characters. If Source and Destination overlap, then the results are
- undefined.
-
- If Length > 0 and Destination is NULL, then ASSERT().
- If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Length > 0 and Source is NULL, then ASSERT().
- If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
- PcdMaximumUnicodeStringLength, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
- then ASSERT().
-
- @param Destination The pointer to a Null-terminated Unicode string.
- @param Source The pointer to a Null-terminated Unicode string.
- @param Length The maximum number of Unicode characters to copy.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrnCpy (
- OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source,
- IN UINTN Length
- );
-#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES)
-
/**
Returns the length of a Null-terminated Unicode string.
@@ -1164,99 +1088,6 @@ StrnCmp (
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Concatenates one Null-terminated Unicode string to another Null-terminated
- Unicode string, and returns the concatenated Unicode string.
-
- This function concatenates two Null-terminated Unicode strings. The contents
- of Null-terminated Unicode string Source are concatenated to the end of
- Null-terminated Unicode string Destination. The Null-terminated concatenated
- Unicode String is returned. If Source and Destination overlap, then the
- results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Destination contains more
- than PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination
- and Source results in a Unicode string with more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- @param Destination The pointer to a Null-terminated Unicode string.
- @param Source The pointer to a Null-terminated Unicode string.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrCat (
- IN OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source
- );
-
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Concatenates up to a specified length one Null-terminated Unicode to the end
- of another Null-terminated Unicode string, and returns the concatenated
- Unicode string.
-
- This function concatenates two Null-terminated Unicode strings. The contents
- of Null-terminated Unicode string Source are concatenated to the end of
- Null-terminated Unicode string Destination, and Destination is returned. At
- most, Length Unicode characters are concatenated from Source to the end of
- Destination, and Destination is always Null-terminated. If Length is 0, then
- Destination is returned unmodified. If Source and Destination overlap, then
- the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Length > 0 and Source is NULL, then ASSERT().
- If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
- PcdMaximumUnicodeStringLength, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Destination contains more
- than PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination
- and Source results in a Unicode string with more than PcdMaximumUnicodeStringLength
- Unicode characters, not including the Null-terminator, then ASSERT().
-
- @param Destination The pointer to a Null-terminated Unicode string.
- @param Source The pointer to a Null-terminated Unicode string.
- @param Length The maximum number of Unicode characters to concatenate from
- Source.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrnCat (
- IN OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source,
- IN UINTN Length
- );
-#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES)
-
/**
Returns the first occurrence of a Null-terminated Unicode sub-string
in a Null-terminated Unicode string.
@@ -1655,51 +1486,6 @@ StrHexToBytes (
IN UINTN MaxBufferSize
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Convert a Null-terminated Unicode string to a Null-terminated
- ASCII string and returns the ASCII string.
-
- This function converts the content of the Unicode string Source
- to the ASCII string Destination by copying the lower 8 bits of
- each Unicode character. It returns Destination.
-
- The caller is responsible to make sure Destination points to a buffer with size
- equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes.
-
- If any Unicode characters in Source contain non-zero value in
- the upper 8 bits, then ASSERT().
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
-
- If PcdMaximumUnicodeStringLength is not zero, and Source contains
- more than PcdMaximumUnicodeStringLength Unicode characters not including
- the Null-terminator, then ASSERT().
-
- If PcdMaximumAsciiStringLength is not zero, and Source contains more
- than PcdMaximumAsciiStringLength Unicode characters not including the
- Null-terminator, then ASSERT().
-
- @param Source The pointer to a Null-terminated Unicode string.
- @param Destination The pointer to a Null-terminated ASCII string.
-
- @return Destination.
-
-**/
-CHAR8 *
-EFIAPI
-UnicodeStrToAsciiStr (
- IN CONST CHAR16 *Source,
- OUT CHAR8 *Destination
- );
-
-#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES)
/**
Convert a Null-terminated Unicode string to a Null-terminated
@@ -1802,76 +1588,6 @@ UnicodeStrnToAsciiStrS (
OUT UINTN *DestinationLength
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Copies one Null-terminated ASCII string to another Null-terminated ASCII
- string and returns the new ASCII string.
-
- This function copies the contents of the ASCII string Source to the ASCII
- string Destination, and returns Destination. If Source and Destination
- overlap, then the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
- then ASSERT().
-
- @param Destination The pointer to a Null-terminated ASCII string.
- @param Source The pointer to a Null-terminated ASCII string.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrCpy (
- OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source
- );
-
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Copies up to a specified length one Null-terminated ASCII string to another
- Null-terminated ASCII string and returns the new ASCII string.
-
- This function copies the contents of the ASCII string Source to the ASCII
- string Destination, and returns Destination. At most, Length ASCII characters
- are copied from Source to Destination. If Length is 0, then Destination is
- returned unmodified. If Length is greater that the number of ASCII characters
- in Source, then Destination is padded with Null ASCII characters. If Source
- and Destination overlap, then the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Length is greater than
- PcdMaximumAsciiStringLength, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
-
- @param Destination The pointer to a Null-terminated ASCII string.
- @param Source The pointer to a Null-terminated ASCII string.
- @param Length The maximum number of ASCII characters to copy.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrnCpy (
- OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source,
- IN UINTN Length
- );
-#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES)
/**
Returns the length of a Null-terminated ASCII string.
@@ -2031,92 +1747,6 @@ AsciiStrnCmp (
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Concatenates one Null-terminated ASCII string to another Null-terminated
- ASCII string, and returns the concatenated ASCII string.
-
- This function concatenates two Null-terminated ASCII strings. The contents of
- Null-terminated ASCII string Source are concatenated to the end of Null-
- terminated ASCII string Destination. The Null-terminated concatenated ASCII
- String is returned.
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and Destination contains more than
- PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and concatenating Destination and
- Source results in a ASCII string with more than PcdMaximumAsciiStringLength
- ASCII characters, then ASSERT().
-
- @param Destination The pointer to a Null-terminated ASCII string.
- @param Source The pointer to a Null-terminated ASCII string.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrCat (
- IN OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source
- );
-
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Concatenates up to a specified length one Null-terminated ASCII string to
- the end of another Null-terminated ASCII string, and returns the
- concatenated ASCII string.
-
- This function concatenates two Null-terminated ASCII strings. The contents
- of Null-terminated ASCII string Source are concatenated to the end of Null-
- terminated ASCII string Destination, and Destination is returned. At most,
- Length ASCII characters are concatenated from Source to the end of
- Destination, and Destination is always Null-terminated. If Length is 0, then
- Destination is returned unmodified. If Source and Destination overlap, then
- the results are undefined.
-
- If Length > 0 and Destination is NULL, then ASSERT().
- If Length > 0 and Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Length is greater than
- PcdMaximumAsciiStringLength, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Destination contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and
- Source results in a ASCII string with more than PcdMaximumAsciiStringLength
- ASCII characters, not including the Null-terminator, then ASSERT().
-
- @param Destination The pointer to a Null-terminated ASCII string.
- @param Source The pointer to a Null-terminated ASCII string.
- @param Length The maximum number of ASCII characters to concatenate from
- Source.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrnCat (
- IN OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source,
- IN UINTN Length
- );
-#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES)
-
/**
Returns the first occurrence of a Null-terminated ASCII sub-string
in a Null-terminated ASCII string.
@@ -2496,45 +2126,6 @@ AsciiStrHexToBytes (
IN UINTN MaxBufferSize
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Convert one Null-terminated ASCII string to a Null-terminated
- Unicode string and returns the Unicode string.
-
- This function converts the contents of the ASCII string Source to the Unicode
- string Destination, and returns Destination. The function terminates the
- Unicode string Destination by appending a Null-terminator character at the end.
- The caller is responsible to make sure Destination points to a buffer with size
- equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes.
-
- If Destination is NULL, then ASSERT().
- If Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
- then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength ASCII characters not including the
- Null-terminator, then ASSERT().
-
- @param Source The pointer to a Null-terminated ASCII string.
- @param Destination The pointer to a Null-terminated Unicode string.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-AsciiStrToUnicodeStr (
- IN CONST CHAR8 *Source,
- OUT CHAR16 *Destination
- );
-
-#endif // !defined (DISABLE_NEW_DEPRECATED_INTERFACES)
/**
Convert one Null-terminated ASCII string to a Null-terminated
@@ -7832,6 +7423,60 @@ AsmLfence (
);
/**
+ Executes a XGETBV instruction
+
+ Executes a XGETBV instruction. This function is only available on IA-32 and
+ x64.
+
+ @param[in] Index Extended control register index
+
+ @return The current value of the extended control register
+**/
+UINT64
+EFIAPI
+AsmXGetBv (
+ IN UINT32 Index
+ );
+
+/**
+ Executes a XSETBV instruction to write a 64-bit value to a Extended Control
+ Register(XCR), and returns the value.
+
+ Writes the 64-bit value specified by Value to the XCR specified by Index. The
+ 64-bit value written to the XCR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and x64.
+
+ @param Index The 32-bit XCR index to write.
+ @param Value The 64-bit value to write to the XCR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+AsmXSetBv (
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+/**
+ Executes a VMGEXIT instruction (VMMCALL with a REP prefix)
+
+ Executes a VMGEXIT instruction. This function is only available on IA-32 and
+ x64.
+
+**/
+VOID
+EFIAPI
+AsmVmgExit (
+ VOID
+ );
+
+
+/**
Patch the immediate operand of an IA32 or X64 instruction such that the byte,
word, dword or qword operand is encoded at the end of the instruction's
binary representation.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/DebugLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/DebugLib.h
index c70fd481276..37fd081e6ac 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/DebugLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/DebugLib.h
@@ -289,12 +289,38 @@ DebugPrintLevelEnabled (
@param Expression Boolean expression that evaluated to FALSE
**/
+#if defined (EDKII_UNIT_TEST_FRAMEWORK_ENABLED)
+/**
+ Unit test library replacement for DebugAssert() in DebugLib.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+ @param FileName The pointer to the name of the source file that generated the assert condition.
+ @param LineNumber The line number in the source file that generated the assert condition
+ @param Description The pointer to the description of the assert condition.
+
+**/
+VOID
+EFIAPI
+UnitTestDebugAssert (
+ IN CONST CHAR8 *FileName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *Description
+ );
+
+#if defined(__clang__) && defined(__FILE_NAME__)
+#define _ASSERT(Expression) UnitTestDebugAssert (__FILE_NAME__, __LINE__, #Expression)
+#else
+#define _ASSERT(Expression) UnitTestDebugAssert (__FILE__, __LINE__, #Expression)
+#endif
+#else
#if defined(__clang__) && defined(__FILE_NAME__)
#define _ASSERT(Expression) DebugAssert (__FILE_NAME__, __LINE__, #Expression)
#else
#define _ASSERT(Expression) DebugAssert (__FILE__, __LINE__, #Expression)
#endif
-
+#endif
/**
Internal worker macro that calls DebugPrint().
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/MmUnblockMemoryLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/MmUnblockMemoryLib.h
new file mode 100644
index 00000000000..cf6b52c7c27
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/MmUnblockMemoryLib.h
@@ -0,0 +1,44 @@
+/** @file
+ MM Unblock Memory Library Interface.
+
+ This library provides an interface to request non-MMRAM pages to be mapped/unblocked
+ from inside MM environment.
+
+ For MM modules that need to access regions outside of MMRAMs, the agents that set up
+ these regions are responsible for invoking this API in order for these memory areas
+ to be accessed from inside MM.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MM_UNBLOCK_MEMORY_LIB_H_
+#define MM_UNBLOCK_MEMORY_LIB_H_
+
+/**
+ This API provides a way to unblock certain data pages to be accessible inside MM environment.
+
+ @param UnblockAddress The address of buffer caller requests to unblock, the address
+ has to be page aligned.
+ @param NumberOfPages The number of pages requested to be unblocked from MM
+ environment.
+
+ @retval RETURN_SUCCESS The request goes through successfully.
+ @retval RETURN_NOT_AVAILABLE_YET The requested functionality is not produced yet.
+ @retval RETURN_UNSUPPORTED The requested functionality is not supported on current platform.
+ @retval RETURN_SECURITY_VIOLATION The requested address failed to pass security check for
+ unblocking.
+ @retval RETURN_INVALID_PARAMETER Input address either NULL pointer or not page aligned.
+ @retval RETURN_ACCESS_DENIED The request is rejected due to system has passed certain boot
+ phase.
+
+**/
+RETURN_STATUS
+EFIAPI
+MmUnblockMemoryRequest (
+ IN PHYSICAL_ADDRESS UnblockAddress,
+ IN UINT64 NumberOfPages
+);
+
+#endif // MM_UNBLOCK_MEMORY_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PcdLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PcdLib.h
index 7a4a1bdaa3d..9a8cb70cd45 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PcdLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PcdLib.h
@@ -481,106 +481,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#define PcdGetExSize(Guid, TokenName) LibPcdGetExSize ((Guid), PcdTokenEx(Guid,TokenName))
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-/**
- Sets an 8-bit PCD token value based on a token name.
-
- Sets the 8-bit value for the token specified by TokenName. Value is returned.
- If TokenName is not a valid token in the token space, then the module will not build.
-
- @param TokenName The name of the PCD token to retrieve a current value for.
- @param Value The 8-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSet8(TokenName, Value) _PCD_SET_MODE_8_##TokenName ((Value))
-
-
-/**
- Sets a 16-bit PCD token value based on a token name.
-
- Sets the 16-bit value for the token specified by TokenName. Value is returned.
- If TokenName is not a valid token in the token space, then the module will not build.
-
- @param TokenName The name of the PCD token to retrieve a current value for.
- @param Value The 16-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSet16(TokenName, Value) _PCD_SET_MODE_16_##TokenName ((Value))
-
-
-/**
- Sets a 32-bit PCD token value based on a token name.
-
- Sets the 32-bit value for the token specified by TokenName. Value is returned.
- If TokenName is not a valid token in the token space, then the module will not build.
-
- @param TokenName The name of the PCD token to retrieve a current value for.
- @param Value The 32-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSet32(TokenName, Value) _PCD_SET_MODE_32_##TokenName ((Value))
-
-
-/**
- Sets a 64-bit PCD token value based on a token name.
-
- Sets the 64-bit value for the token specified by TokenName. Value is returned.
- If TokenName is not a valid token in the token space, then the module will not build.
-
- @param TokenName The name of the PCD token to retrieve a current value for.
- @param Value The 64-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSet64(TokenName, Value) _PCD_SET_MODE_64_##TokenName ((Value))
-
-
-/**
- Sets a pointer to a PCD token buffer based on a token name.
-
- Sets the buffer for the token specified by TokenName. Buffer is returned.
- If SizeOfBuffer is greater than the maximum size supported by TokenName,
- then set SizeOfBuffer to the maximum size supported by TokenName and return NULL
- to indicate that the set operation was not actually performed. If SizeOfBuffer
- is set to MAX_ADDRESS, then SizeOfBuffer must be set to the maximum size supported
- by TokenName and NULL must be returned.
- If TokenName is not a valid token in the token space, then the module will not build.
-
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param TokenName The name of the PCD token to set the current value for.
- @param SizeOfBuffer A pointer to the size, in bytes, of Buffer.
- @param Buffer A pointer to the buffer to set.
-
- @return Return the pointer to the Buffer that was set.
-
-**/
-#define PcdSetPtr(TokenName, SizeOfBuffer, Buffer) \
- _PCD_SET_MODE_PTR_##TokenName ((SizeOfBuffer), (Buffer))
-
-/**
- Sets a Boolean PCD token value based on a token name.
-
- Sets the Boolean value for the token specified by TokenName. Value is returned.
- If TokenName is not a valid token in the token space, then the module will not build.
-
- @param TokenName The name of the PCD token to set the current value for.
- @param Buffer The Boolean value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSetBool(TokenName, Value) _PCD_SET_MODE_BOOL_##TokenName ((Value))
-#endif
-
/**
Sets a 8-bit PCD token value based on a token name.
@@ -806,137 +706,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-/**
- Sets an 8-bit PCD token value based on a GUID and a token name.
-
- Sets the 8-bit value for the token specified by Guid and TokenName. Value is returned.
- If TokenName is not a valid token in the token space specified by Guid,
- then the module will not build.
-
- If Guid is NULL, then ASSERT().
-
- @param Guid Pointer to a 128-bit unique value that designates
- which namespace to retrieve a value from.
- @param TokenName The name of the PCD token to set the current value for.
- @param Value The 8-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSetEx8(Guid, TokenName, Value) LibPcdSetEx8 ((Guid), PcdTokenEx(Guid,TokenName), (Value))
-
-
-/**
- Sets a 16-bit PCD token value based on a GUID and a token name.
-
- Sets the 16-bit value for the token specified by Guid and TokenName. Value is returned.
- If TokenName is not a valid token in the token space specified by Guid,
- then the module will not build.
-
- If Guid is NULL, then ASSERT().
-
- @param Guid Pointer to a 128-bit unique value that designates
- which namespace to retrieve a value from.
- @param TokenName The name of the PCD token to set the current value for.
- @param Value The 16-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSetEx16(Guid, TokenName, Value) LibPcdSetEx16 ((Guid), PcdTokenEx(Guid,TokenName), (Value))
-
-
-/**
- Sets a 32-bit PCD token value based on a GUID and a token name.
-
- Sets the 32-bit value for the token specified by Guid and TokenName. Value is returned.
- If TokenName is not a valid token in the token space specified by Guid,
- then the module will not build.
-
- If Guid is NULL, then ASSERT().
-
- @param Guid Pointer to a 128-bit unique value that designates
- which namespace to retrieve a value from.
- @param TokenName The name of the PCD token to set the current value for.
- @param Value The 32-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSetEx32(Guid, TokenName, Value) LibPcdSetEx32 ((Guid), PcdTokenEx(Guid,TokenName), (Value))
-
-
-/**
- Sets a 64-bit PCD token value based on a GUID and a token name.
-
- Sets the 64-bit value for the token specified by Guid and TokenName. Value is returned.
- If TokenName is not a valid token in the token space specified by Guid,
- then the module will not build.
-
- If Guid is NULL, then ASSERT().
-
- @param Guid Pointer to a 128-bit unique value that designates
- which namespace to retrieve a value from.
- @param TokenName The name of the PCD token to set the current value for.
- @param Value The 64-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSetEx64(Guid, TokenName, Value) LibPcdSetEx64 ((Guid), PcdTokenEx(Guid,TokenName), (Value))
-
-
-/**
- Sets a pointer to a PCD token buffer based on a GUID and a token name.
-
- Sets the buffer for the token specified by Guid and TokenName. Buffer is returned.
- If SizeOfBuffer is greater than the maximum size supported by Guid and TokenName,
- then set SizeOfBuffer to the maximum size supported by Guid and TokenName and return
- NULL to indicate that the set operation was not actually performed. If SizeOfBuffer
- is set to MAX_ADDRESS, then SizeOfBuffer must be set to the maximum size supported by
- Guid and TokenName and NULL must be returned.
- If TokenName is not a valid token in the token space specified by Guid,
- then the module will not build.
-
- If Guid is NULL, then ASSERT().
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param Guid Pointer to a 128-bit unique value that designates
- which namespace to retrieve a value from.
- @param TokenName The name of the PCD token to set the current value for.
- @param SizeOfBuffer A pointer to the size, in bytes, of Buffer.
- @param Buffer Pointer to the buffer to set.
-
- @return Return the pointer to the Buffer that was set.
-
-**/
-#define PcdSetExPtr(Guid, TokenName, SizeOfBuffer, Buffer) \
- LibPcdSetExPtr ((Guid), PcdTokenEx(Guid,TokenName), (SizeOfBuffer), (Buffer))
-
-
-/**
- Sets a Boolean PCD token value based on a GUID and a token name.
-
- Sets the Boolean value for the token specified by Guid and TokenName. Value is returned.
- If TokenName is not a valid token in the token space specified by Guid,
- then the module will not build.
-
- If Guid is NULL, then ASSERT().
-
- @param Guid Pointer to a 128-bit unique value that designates
- which namespace to retrieve a value from.
- @param TokenName The name of the PCD token to set the current value for.
- @param Value The Boolean value to set.
-
- @return Return the Value that was set.
-
-**/
-#define PcdSetExBool(Guid, TokenName, Value) \
- LibPcdSetExBool((Guid), PcdTokenEx(Guid,TokenName), (Value))
-#endif
-
/**
Sets an 8-bit PCD token value based on a GUID and a token name.
@@ -1348,295 +1117,6 @@ LibPcdGetExSize (
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSet8 (
- IN UINTN TokenNumber,
- IN UINT8 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSet16 (
- IN UINTN TokenNumber,
- IN UINT16 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSet32 (
- IN UINTN TokenNumber,
- IN UINT32 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSet64 (
- IN UINTN TokenNumber,
- IN UINT64 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value
- specified by Buffer and SizeOfBuffer. Buffer is returned.
- If SizeOfBuffer is greater than the maximum size support by TokenNumber,
- then set SizeOfBuffer to the maximum size supported by TokenNumber and
- return NULL to indicate that the set operation was not actually performed.
-
- If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the
- maximum size supported by TokenName and NULL must be returned.
-
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pointer for the Buffer that was set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetPtr (
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN CONST VOID *Buffer
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The boolean value to set.
-
- @return Return the Value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetBool (
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid Pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSetEx8 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT8 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid Pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSetEx16 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT16 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid Pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSetEx32 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT32 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid Pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the Value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSetEx64 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT64 Value
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value specified by
- Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than
- the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size
- supported by TokenNumber and return NULL to indicate that the set operation
- was not actually performed.
-
- If Guid is NULL, then ASSERT().
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] Guid Pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pointer to the Buffer that was set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetExPtr (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN VOID *Buffer
- );
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid Pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The Boolean value to set.
-
- @return Return the Value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetExBool (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- );
-#endif
-
/**
This function provides a means by which to set a value for a given PCD token.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciExpressLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciExpressLib.h
index 59bb8100e2d..9d453c24eb6 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciExpressLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciExpressLib.h
@@ -2,8 +2,9 @@
Provides services to access PCI Configuration Space using the MMIO PCI Express window.
This library is identical to the PCI Library, except the access method for performing PCI
- configuration cycles must be through the 256 MB PCI Express MMIO window whose base address
- is defined by PcdPciExpressBaseAddress.
+ configuration cycles must be through the PCI Express MMIO window whose base address
+ is defined by PcdPciExpressBaseAddress and size defined by PcdPciExpressBaseSize.
+
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciSegmentInfoLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciSegmentInfoLib.h
index 228d75793b1..20a3eceeb80 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciSegmentInfoLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PciSegmentInfoLib.h
@@ -3,7 +3,7 @@
This library is consumed by PciSegmentLib to support multiple segment PCI configuration access.
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -28,6 +28,7 @@ typedef struct {
@retval A callee owned array holding the segment information.
**/
PCI_SEGMENT_INFO *
+EFIAPI
GetPciSegmentInfo (
UINTN *Count
);
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PrintLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PrintLib.h
index 8548e1ce5b6..59cd89cc533 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PrintLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/PrintLib.h
@@ -485,62 +485,6 @@ UnicodeSPrintAsciiFormat (
...
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Converts a decimal value to a Null-terminated Unicode string.
-
- Converts the decimal number specified by Value to a Null-terminated Unicode
- string specified by Buffer containing at most Width characters. No padding of spaces
- is ever performed. If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
- The number of Unicode characters in Buffer is returned, not including the Null-terminator.
- If the conversion contains more than Width characters, then only the first
- Width characters are returned, and the total number of characters
- required to perform the conversion is returned.
- Additional conversion parameters are specified in Flags.
-
- The Flags bit LEFT_JUSTIFY is always ignored.
- All conversions are left justified in Buffer.
- If Width is 0, PREFIX_ZERO is ignored in Flags.
- If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
- are inserted every 3rd digit starting from the right.
- If RADIX_HEX is set in Flags, then the output buffer will be
- formatted in hexadecimal format.
- If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
- then Buffer is padded with '0' characters so the combination of the optional '-'
- sign character, '0' characters, digit characters for Value, and the Null-terminator
- add up to Width characters.
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Buffer is NULL, then ASSERT().
- If Buffer is not aligned on a 16-bit boundary, then ASSERT().
- If unsupported bits are set in Flags, then ASSERT().
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
-
- @param Buffer The pointer to the output buffer for the produced Null-terminated
- Unicode string.
- @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
- @param Value The 64-bit signed value to convert to a string.
- @param Width The maximum number of Unicode characters to place in Buffer, not including
- the Null-terminator.
-
- @return The number of Unicode characters in Buffer, not including the Null-terminator.
-
-**/
-UINTN
-EFIAPI
-UnicodeValueToString (
- IN OUT CHAR16 *Buffer,
- IN UINTN Flags,
- IN INT64 Value,
- IN UINTN Width
- );
-
-#endif
-
/**
Converts a decimal value to a Null-terminated Unicode string.
@@ -882,60 +826,6 @@ AsciiSPrintUnicodeFormat (
...
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Converts a decimal value to a Null-terminated ASCII string.
-
- Converts the decimal number specified by Value to a Null-terminated ASCII string
- specified by Buffer containing at most Width characters. No padding of spaces
- is ever performed.
- If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
- The number of ASCII characters in Buffer is returned, not including the Null-terminator.
- If the conversion contains more than Width characters, then only the first Width
- characters are returned, and the total number of characters required to perform
- the conversion is returned.
- Additional conversion parameters are specified in Flags.
- The Flags bit LEFT_JUSTIFY is always ignored.
- All conversions are left justified in Buffer.
- If Width is 0, PREFIX_ZERO is ignored in Flags.
- If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
- are inserted every 3rd digit starting from the right.
- If RADIX_HEX is set in Flags, then the output buffer will be
- formatted in hexadecimal format.
- If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
- then Buffer is padded with '0' characters so the combination of the optional '-'
- sign character, '0' characters, digit characters for Value, and the Null-terminator
- add up to Width characters.
-
- If Buffer is NULL, then ASSERT().
- If unsupported bits are set in Flags, then ASSERT().
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
-
- @param Buffer A pointer to the output buffer for the produced Null-terminated
- ASCII string.
- @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
- @param Value The 64-bit signed value to convert to a string.
- @param Width The maximum number of ASCII characters to place in Buffer, not including
- the Null-terminator.
-
- @return The number of ASCII characters in Buffer, not including the Null-terminator.
-
-**/
-UINTN
-EFIAPI
-AsciiValueToString (
- OUT CHAR8 *Buffer,
- IN UINTN Flags,
- IN INT64 Value,
- IN UINTN Width
- );
-
-#endif
/**
Converts a decimal value to a Null-terminated Ascii string.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/RegisterFilterLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/RegisterFilterLib.h
new file mode 100644
index 00000000000..5c28715a467
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/RegisterFilterLib.h
@@ -0,0 +1,243 @@
+/** @file
+ Public include file for the Port IO/MMIO/MSR RegisterFilterLib.
+
+Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REGISTER_FILTER_LIB_H_
+#define REGISTER_FILTER_LIB_H_
+
+typedef enum {
+ FilterWidth8,
+ FilterWidth16,
+ FilterWidth32,
+ FilterWidth64
+} FILTER_IO_WIDTH;
+
+/**
+ Filter IO read operation before read IO port.
+ It is used to filter IO read operation.
+
+ It will return the flag to decide whether require read real IO port.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The destination buffer to store the results.
+
+ @retval TRUE Need to excute the IO read.
+ @retval FALSE Skip the IO read.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Trace IO read operation after read IO port.
+ It is used to trace IO operation.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The destination buffer to store the results.
+
+**/
+VOID
+EFIAPI
+FilterAfterIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ );
+/**
+ Filter IO Write operation before wirte IO port.
+ It is used to filter IO operation.
+
+ It will return the flag to decide whether require read write IO port.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The source buffer from which to BeforeWrite data.
+
+ @retval TRUE Need to excute the IO write.
+ @retval FALSE Skip the IO write.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ );
+
+ /**
+ Trace IO Write operation after wirte IO port.
+ It is used to trace IO operation.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The source buffer from which to BeforeWrite data.
+
+**/
+VOID
+EFIAPI
+FilterAfterIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ );
+
+/**
+ Filter memory IO before Read operation.
+
+ It will return the flag to decide whether require read real MMIO.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The destination buffer to store the results.
+
+ @retval TRUE Need to excute the MMIO read.
+ @retval FALSE Skip the MMIO read.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMmIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Tracer memory IO after read operation
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The destination buffer to store the results.
+
+**/
+VOID
+EFIAPI
+FilterAfterMmIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ );
+
+/**
+ Filter memory IO before write operation
+
+ It will return the flag to decide whether require wirte real MMIO.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The source buffer from which to BeforeWrite data.
+
+ @retval TRUE Need to excute the MMIO write.
+ @retval FALSE Skip the MMIO write.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMmIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ );
+
+/**
+ Tracer memory IO after write operation
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The source buffer from which to BeforeWrite data.
+
+**/
+VOID
+EFIAPI
+FilterAfterMmIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ );
+
+/**
+ Filter MSR before read operation.
+
+ It will return the flag to decide whether require read real MSR.
+ It can be used for emulation environment.
+
+ @param Index The 8-bit Machine Specific Register index to BeforeWrite.
+ @param Value The 64-bit value to BeforeRead from the Machine Specific Register.
+
+ @retval TRUE Need to excute the MSR read.
+ @retval FALSE Skip the MSR read.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMsrRead (
+ IN UINT32 Index,
+ IN OUT UINT64 *Value
+ );
+
+/**
+ Trace MSR after read operation
+
+ @param Index The 8-bit Machine Specific Register index to BeforeWrite.
+ @param Value The 64-bit value to BeforeRead from the Machine Specific Register.
+
+**/
+VOID
+EFIAPI
+FilterAfterMsrRead (
+ IN UINT32 Index,
+ IN UINT64 *Value
+ );
+
+/**
+ Filter MSR before write operation
+
+ It will return the flag to decide whether require write real MSR.
+ It can be used for emulation environment.
+
+ @param Index The 8-bit Machine Specific Register index to BeforeWrite.
+ @param Value The 64-bit value to BeforeWrite to the Machine Specific Register.
+
+ @retval TRUE Need to excute the MSR write.
+ @retval FALSE Skip the MSR write.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMsrWrite (
+ IN UINT32 Index,
+ IN UINT64 *Value
+ );
+
+/**
+ Trace MSR after write operation
+
+ @param Index The 8-bit Machine Specific Register index to BeforeWrite.
+ @param Value The 64-bit value to BeforeWrite to the Machine Specific Register.
+
+**/
+VOID
+EFIAPI
+FilterAfterMsrWrite (
+ IN UINT32 Index,
+ IN UINT64 *Value
+ );
+
+#endif // REGISTER_FILTER_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h
index 9de5f362837..a26fdcca63a 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/StandaloneMmDriverEntryPoint.h
@@ -18,6 +18,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
///
extern CONST UINT32 _gMmRevision;
+///
+/// Declare the number of unload handler in the image.
+///
+extern CONST UINT8 _gDriverUnloadImageCount;
+
/**
The entry point of PE/COFF Image for a Standalone MM Driver.
@@ -122,4 +127,24 @@ ProcessModuleEntryPointList (
IN EFI_MM_SYSTEM_TABLE *MmSystemTable
);
+/**
+ Autogenerated function that calls a set of module unload handlers.
+
+ This function must be called from the unload handler registered by _ModuleEntryPoint().
+ This function calls the set of module unload handlers.
+ This function is autogenerated by build tools and those build tools are responsible
+ for collecting the module unload handlers and calling them in a specified order.
+
+ @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, DXE SMM Driver, or UEFI Driver.
+
+ @retval EFI_SUCCESS The unload handlers executed normally.
+ @retval !EFI_SUCCESS The unload handlers failed to execute normally.
+
+**/
+EFI_STATUS
+EFIAPI
+ProcessModuleUnloadList (
+ IN EFI_HANDLE ImageHandle
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UefiLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UefiLib.h
index fb39f5f0d48..264287fb6bc 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UefiLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UefiLib.h
@@ -680,59 +680,6 @@ FreeUnicodeStringTable (
IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable
);
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Returns a pointer to an allocated buffer that contains the contents of a
- variable retrieved through the UEFI Runtime Service GetVariable(). The
- returned buffer is allocated using AllocatePool(). The caller is responsible
- for freeing this buffer with FreePool().
-
- If Name is NULL, then ASSERT().
- If Guid is NULL, then ASSERT().
-
- @param[in] Name The pointer to a Null-terminated Unicode string.
- @param[in] Guid The pointer to an EFI_GUID structure.
-
- @retval NULL The variable could not be retrieved.
- @retval NULL There are not enough resources available for the variable contents.
- @retval Other A pointer to allocated buffer containing the variable contents.
-
-**/
-VOID *
-EFIAPI
-GetVariable (
- IN CONST CHAR16 *Name,
- IN CONST EFI_GUID *Guid
- );
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Returns a pointer to an allocated buffer that contains the contents of a
- variable retrieved through the UEFI Runtime Service GetVariable(). This
- function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables.
- The returned buffer is allocated using AllocatePool(). The caller is
- responsible for freeing this buffer with FreePool().
-
- If Name is NULL, then ASSERT().
-
- @param[in] Name The pointer to a Null-terminated Unicode string.
-
- @retval NULL The variable could not be retrieved.
- @retval NULL There are not enough resources available for the variable contents.
- @retval Other A pointer to allocated buffer containing the variable contents.
-
-**/
-VOID *
-EFIAPI
-GetEfiGlobalVariable (
- IN CONST CHAR16 *Name
- );
-#endif
-
/**
Returns the status whether get the variable success. The function retrieves
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UnitTestLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UnitTestLib.h
index b176a955633..46ba40d5006 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UnitTestLib.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Library/UnitTestLib.h
@@ -313,11 +313,9 @@ FreeUnitTestFramework (
at least the current execution count) which will be saved by the framework and
passed to the test case upon resume.
- Generally called from within a test case prior to quitting or rebooting.
+ This should be called while the current test framework is valid and active. It is
+ generally called from within a test case prior to quitting or rebooting.
- @param[in] FrameworkHandle A handle to the current running framework that
- dispatched the test. Necessary for recording
- certain test events with the framework.
@param[in] ContextToSave A buffer of test case-specific data to be saved
along with framework state. Will be passed as
"Context" to the test case upon resume. This
@@ -325,7 +323,7 @@ FreeUnitTestFramework (
@param[in] ContextToSaveSize Size of the ContextToSave buffer.
@retval EFI_SUCCESS The framework state and context were saved.
- @retval EFI_INVALID_PARAMETER FrameworkHandle is NULL.
+ @retval EFI_NOT_FOUND An active framework handle was not found.
@retval EFI_INVALID_PARAMETER ContextToSave is not NULL and
ContextToSaveSize is 0.
@retval EFI_INVALID_PARAMETER ContextToSave is >= 4GB.
@@ -338,7 +336,6 @@ FreeUnitTestFramework (
EFI_STATUS
EFIAPI
SaveFrameworkState (
- IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle,
IN UNIT_TEST_CONTEXT ContextToSave OPTIONAL,
IN UINTN ContextToSaveSize
);
@@ -445,6 +442,56 @@ SaveFrameworkState (
}
/**
+ This macro uses the framework assertion logic to check whether a function call
+ triggers an ASSERT() condition. The BaseLib SetJump()/LongJump() services
+ are used to establish a safe return point when an ASSERT() is triggered.
+ If an ASSERT() is triggered, unit test execution continues and Status is set
+ to UNIT_TEST_PASSED. Otherwise, a unit test case failure is raised and
+ Status is set to UNIT_TEST_ERROR_TEST_FAILED.
+
+ If ASSERT() macros are disabled, then the test case is skipped and a warning
+ message is added to the unit test log. Status is set to UNIT_TEST_SKIPPED.
+
+ @param[in] FunctionCall Function call that is expected to trigger ASSERT().
+ @param[out] Status Pointer to a UNIT_TEST_STATUS return value. This
+ is an optional parameter that may be NULL.
+**/
+#if defined (EDKII_UNIT_TEST_FRAMEWORK_ENABLED)
+ #include <Library/BaseLib.h>
+
+ ///
+ /// Pointer to jump buffer used with SetJump()/LongJump() to test if a
+ /// function under test generates an expected ASSERT() condition.
+ ///
+ extern BASE_LIBRARY_JUMP_BUFFER *gUnitTestExpectAssertFailureJumpBuffer;
+
+ #define UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status) \
+ do { \
+ UNIT_TEST_STATUS UnitTestJumpStatus; \
+ BASE_LIBRARY_JUMP_BUFFER UnitTestJumpBuffer; \
+ UnitTestJumpStatus = UNIT_TEST_SKIPPED; \
+ if (DebugAssertEnabled ()) { \
+ gUnitTestExpectAssertFailureJumpBuffer = &UnitTestJumpBuffer; \
+ if (SetJump (gUnitTestExpectAssertFailureJumpBuffer) == 0) { \
+ FunctionCall; \
+ UnitTestJumpStatus = UNIT_TEST_ERROR_TEST_FAILED; \
+ } else { \
+ UnitTestJumpStatus = UNIT_TEST_PASSED; \
+ } \
+ gUnitTestExpectAssertFailureJumpBuffer = NULL; \
+ } \
+ if (!UnitTestExpectAssertFailure ( \
+ UnitTestJumpStatus, \
+ __FUNCTION__, __LINE__, __FILE__, \
+ #FunctionCall, Status)) { \
+ return UNIT_TEST_ERROR_TEST_FAILED; \
+ } \
+ } while (FALSE)
+#else
+ #define UT_EXPECT_ASSERT_FAILURE(FunctionCall, Status) FunctionCall;
+#endif
+
+/**
If Expression is TRUE, then TRUE is returned.
If Expression is FALSE, then an assert is triggered and the location of the
assert provided by FunctionName, LineNumber, FileName, and Description are
@@ -694,6 +741,46 @@ UnitTestAssertNotNull (
);
/**
+ If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return
+ TRUE because an ASSERT() was expected when FunctionCall was executed and an
+ ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a
+ warning message and return TRUE because ASSERT() macros are disabled. If
+ UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and
+ return FALSE because an ASSERT() was expected when FunctionCall was executed,
+ but no ASSERT() conditions were triggered. The log messages contain
+ FunctionName, LineNumber, and FileName strings to provide the location of the
+ UT_EXPECT_ASSERT_FAILURE() macro.
+
+ @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that
+ is either pass, skipped, or failed.
+ @param[in] FunctionName Null-terminated ASCII string of the function
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] LineNumber The source file line number of the the function
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] FileName Null-terminated ASCII string of the filename
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] FunctionCall Null-terminated ASCII string of the function call
+ executed by the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[out] ResultStatus Used to return the UnitTestStatus value to the
+ caller of UT_EXPECT_ASSERT_FAILURE(). This is
+ optional parameter that may be NULL.
+
+ @retval TRUE UnitTestStatus is UNIT_TEST_PASSED.
+ @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED.
+ @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.
+**/
+BOOLEAN
+EFIAPI
+UnitTestExpectAssertFailure (
+ IN UNIT_TEST_STATUS UnitTestStatus,
+ IN CONST CHAR8 *FunctionName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *FileName,
+ IN CONST CHAR8 *FunctionCall,
+ OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL
+ );
+
+/**
Test logging macro that records an ERROR message in the test framework log.
Record is associated with the currently executing test case.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/BlockIo.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/BlockIo.h
index 460b616fdd8..107ea920827 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/BlockIo.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/BlockIo.h
@@ -201,7 +201,7 @@ typedef struct {
#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000
#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
-#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x00020031
+#define EFI_BLOCK_IO_PROTOCOL_REVISION3 0x0002001F
///
/// Revision defined in EFI1.1.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/HiiPopup.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/HiiPopup.h
index 8924a3a5704..a0e17b63a03 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/HiiPopup.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/HiiPopup.h
@@ -2,7 +2,7 @@
This protocol provides services to display a popup window.
The protocol is typically produced by the forms browser and consumed by a driver callback handler.
- Copyright (c) 2017-2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017-2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
@@ -67,10 +67,10 @@ EFI_STATUS
OUT EFI_HII_POPUP_SELECTION *UserSelection OPTIONAL
);
-typedef struct _EFI_HII_POPUP_PROTOCOL {
+struct _EFI_HII_POPUP_PROTOCOL {
UINT64 Revision;
EFI_HII_CREATE_POPUP CreatePopup;
-} EFI_HII_POPUP_PROTOCOL;
+};
extern EFI_GUID gEfiHiiPopupProtocolGuid;
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RedfishDiscover.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RedfishDiscover.h
new file mode 100644
index 00000000000..284e4a3b012
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RedfishDiscover.h
@@ -0,0 +1,193 @@
+/** @file
+ This file defines the EFI Redfish Discover Protocol interface.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ - Some corrections and revises are added to UEFI Specification 2.9.
+ - This Protocol is introduced in UEFI Specification 2.8.
+
+**/
+
+#ifndef EFI_REDFISH_DISCOVER_PROTOCOL_H_
+#define EFI_REDFISH_DISCOVER_PROTOCOL_H_
+
+//
+// GUID definitions
+//
+#define EFI_REDFISH_DISCOVER_PROTOCOL_GUID \
+ { \
+ 0x5db12509, 0x4550, 0x4347, { 0x96, 0xb3, 0x73, 0xc0, 0xff, 0x6e, 0x86, 0x9f } \
+ }
+
+#define REDFISH_DISCOVER_TOKEN_SIGNATURE SIGNATURE_32 ('R', 'F', 'T', 'S')
+
+typedef UINT32 EFI_REDFISH_DISCOVER_FLAG;
+#define EFI_REDFISH_DISCOVER_HOST_INTERFACE 0x00000001 ///< Discover Redfish server reported in SMBIOS 42h.
+#define EFI_REDFISH_DISCOVER_SSDP 0x00000002 ///< Discover Redfish server using UPnP Http search method.
+#define EFI_REDFISH_DISCOVER_SSDP_UDP6 0x00000004 ///< Use UDP version 6.
+#define EFI_REDFISH_DISCOVER_KEEP_ALIVE 0x00000008 ///< Keep to send UPnP Search in the duration indicated in
+ ///< EFI_REDFISH_DISCOVER_DURATION_MASK.
+#define EFI_REDFISH_DISCOVER_RENEW 0x00000010 ///< Set this bit to indicate this function to notify the caller
+ ///< a list of all Redfish servers it found. Otherwise, this fucntion
+ ///< just notify the caller new found Redfish servers.
+ ///<
+#define EFI_REDFISH_DISCOVER_VALIDATION 0x80000000 ///< Validate Redfish service for host interface instance.
+#define EFI_REDFISH_DISCOVER_DURATION_MASK 0x0f000000 ///< 2 to the Power of Duration. The valid value of duration is between
+ ///< 3 to 15. The corresponding duration is 8 to 2^15 seconds.
+ ///< Duration is only valid when EFI_REDFISH_DISCOVER_KEEP_ALIVE
+ ///< is set to 1.
+typedef struct _EFI_REDFISH_DISCOVER_PROTOCOL EFI_REDFISH_DISCOVER_PROTOCOL;
+
+typedef struct {
+ EFI_HANDLE RedfishRestExHandle; ///< REST EX EFI handle associated with this Redfish service.
+ BOOLEAN IsUdp6; ///< Indicates it's IP versino 6.
+ EFI_IP_ADDRESS RedfishHostIpAddress; ///< IP address of Redfish service.
+ UINTN RedfishVersion; ///< Redfish service version.
+ CHAR16 *Location; ///< Redfish service location.
+ CHAR16 *Uuid; ///< Redfish service UUID.
+ CHAR16 *Os; ///< Redfish service OS.
+ CHAR16 *OsVersion; ///< Redfish service OS version.
+ CHAR16 *Product; ///< Redfish service product name.
+ CHAR16 *ProductVer; ///< Redfish service product version.
+ BOOLEAN UseHttps; ///< Using HTTPS.
+} EFI_REDFISH_DISCOVERED_INFORMATION;
+
+typedef struct {
+ EFI_STATUS Status; ///< Status of Redfish service discovery.
+ EFI_REDFISH_DISCOVERED_INFORMATION Information; ///< Redfish service discovered.
+} EFI_REDFISH_DISCOVERED_INSTANCE;
+
+typedef struct {
+ UINTN NumberOfServiceFound; ///< Must be 0 when pass to Acquire ().
+ EFI_REDFISH_DISCOVERED_INSTANCE *RedfishInstances; ///< Must be NULL when pass to Acquire ().
+} EFI_REDFISH_DISCOVERED_LIST;
+
+typedef struct {
+ EFI_MAC_ADDRESS MacAddress; ///< MAC address of network interfase to discover Redfish service.
+ BOOLEAN IsIpv6; ///< Indicates it's IP versino 6.
+ EFI_IP_ADDRESS SubnetId; ///< Subnet ID.
+ UINT8 SubnetPrefixLength; ///< Subnet prefix-length for IPv4 and IPv6.
+ UINT16 VlanId; ///< VLAN ID.
+} EFI_REDFISH_DISCOVER_NETWORK_INTERFACE;
+
+typedef struct {
+ UINT32 Signature; ///< Token signature.
+ EFI_REDFISH_DISCOVERED_LIST DiscoverList; ///< The memory of EFI_REDFISH_DISCOVERED_LIST is
+ ///< allocated by Acquire() and freed when caller invoke Release().
+ EFI_EVENT Event; ///< The TPL_CALLBACK event to be notified when Redfish services
+ ///< are discovered or any errors occurred during discovery.
+ UINTN Timeout; ///< The timeout value declared in EFI_REDFISH_DISCOVERED_TOKEN
+ ///< determines the seconds to drop discover process.
+ ///< Basically, the nearby Redfish services must response in >=1
+ ///< and <= 5 seconds. The valid timeout value used to have
+ ///< asynchronous discovery is >= 1 and <= 5 seconds. Set the
+ ///< timeout to zero means to discover Redfish service synchronously.
+ ///< Event in token is created by caller to listen the Reefish services
+ ///< found by Acquire().
+} EFI_REDFISH_DISCOVERED_TOKEN;
+
+/**
+ This function gets the NIC list which Redfish discover protocol
+ can discover Redfish service on it.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI Image handle request the NIC list,
+ @param[out] NumberOfNetworkInterfaces Number of NICs can do Redfish service discovery.
+ @param[out] NetworkInterfaces NIC instances. It's an array of instance. The number of entries
+ in array is indicated by NumberOfNetworkInterfaces.
+ Caller has to release the memory
+ allocated by Redfish discover protocol.
+
+ @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
+ @retval Others Fail to remove the entry
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REDFISH_DISCOVER_NETWORK_LIST)(
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *NumberOfNetworkInterfaces,
+ OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE **NetworkInterfaces
+);
+
+/**
+ This function acquires Redfish services by discovering static Redfish setting
+ according to Redfish Host Interface or through SSDP. Returns a list of EFI
+ handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
+ EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
+ created through EFI REST EX serivce protoocl for communicating with specific
+ Redfish service.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI image owns these Redfish service instances.
+ @param[in] TargetNetworkInterface Target NIC to do the discovery.
+ NULL means discover Redfish service on all NICs on platform.
+ @param[in] Flags Redfish service discover flags.
+ @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
+ The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
+ EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
+ and must be freed when caller invoke Release().
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
+ or Token->Event == NULL.
+ @retval Others Fail acquire Redfish services.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REDFISH_DISCOVER_ACQUIRE_SERVICE)(
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface OPTIONAL,
+ IN EFI_REDFISH_DISCOVER_FLAG Flags,
+ IN EFI_REDFISH_DISCOVERED_TOKEN *Token
+);
+
+/**
+ This function aborts Redfish service discovery on the given network interface.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] TargetNetworkInterface Target NIC to do the discovery.
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval Others Fail to abort Redfish service discovery.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REDFISH_DISCOVER_ABORT_ACQUIRE)(
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface OPTIONAL
+);
+
+/**
+ This function releases Redfish services found by RedfishServiceAcquire().
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] List The Redfish service to release.
+
+ @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
+ @retval Others Fail to remove the entry
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REDFISH_DISCOVER_RELEASE_SERVICE)(
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_REDFISH_DISCOVERED_LIST *List
+);
+
+struct _EFI_REDFISH_DISCOVER_PROTOCOL {
+ EFI_REDFISH_DISCOVER_NETWORK_LIST GetNetworkInterfaceList;
+ EFI_REDFISH_DISCOVER_ACQUIRE_SERVICE AcquireRedfishService;
+ EFI_REDFISH_DISCOVER_ABORT_ACQUIRE AbortAcquireRedfishService;
+ EFI_REDFISH_DISCOVER_RELEASE_SERVICE ReleaseRedfishService;
+};
+
+extern EFI_GUID gEfiRedfishDiscoverProtocolGuid;
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/ResetNotification.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/ResetNotification.h
index 23cb6fac5b3..171fca8042e 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/ResetNotification.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/ResetNotification.h
@@ -2,7 +2,7 @@
EFI Reset Notification Protocol as defined in UEFI 2.7.
This protocol provides services to register for a notification when ResetSystem is called.
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Revision Reference:
@@ -68,10 +68,10 @@ EFI_STATUS
IN EFI_RESET_SYSTEM ResetFunction
);
-typedef struct _EFI_RESET_NOTIFICATION_PROTOCOL {
+struct _EFI_RESET_NOTIFICATION_PROTOCOL {
EFI_REGISTER_RESET_NOTIFY RegisterResetNotify;
EFI_UNREGISTER_RESET_NOTIFY UnregisterResetNotify;
-} EFI_RESET_NOTIFICATION_PROTOCOL;
+};
extern EFI_GUID gEfiResetNotificationProtocolGuid;
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestEx.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestEx.h
new file mode 100644
index 00000000000..c0cdde3cb06
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestEx.h
@@ -0,0 +1,390 @@
+/** @file
+ This file defines the EFI REST EX Protocol interface. It is
+ split into the following two main sections.
+
+ - REST EX Service Binding Protocol
+ - REST EX Protocol
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.8
+
+**/
+
+#ifndef EFI_REST_EX_PROTOCOL_H_
+#define EFI_REST_EX_PROTOCOL_H_
+
+#include <Protocol/Http.h>
+
+//
+//GUID definitions
+//
+#define EFI_REST_EX_SERVICE_BINDING_PROTOCOL_GUID \
+ { \
+ 0x456bbe01, 0x99d0, 0x45ea, {0xbb, 0x5f, 0x16, 0xd8, 0x4b, 0xed, 0xc5, 0x59 } \
+ }
+
+#define EFI_REST_EX_PROTOCOL_GUID \
+ { \
+ 0x55648b91, 0xe7d, 0x40a3, {0xa9, 0xb3, 0xa8, 0x15, 0xd7, 0xea, 0xdf, 0x97 } \
+ }
+
+typedef struct _EFI_REST_EX_PROTOCOL EFI_REST_EX_PROTOCOL;
+
+//*******************************************************
+//EFI_REST_EX_SERVICE_INFO_VER
+//*******************************************************
+typedef struct {
+ UINT8 Major;
+ UINT8 Minor;
+} EFI_REST_EX_SERVICE_INFO_VER;
+
+//*******************************************************
+//EFI_REST_EX_SERVICE_INFO_HEADER
+//*******************************************************
+typedef struct {
+ UINT32 Length;
+ EFI_REST_EX_SERVICE_INFO_VER RestServiceInfoVer;
+} EFI_REST_EX_SERVICE_INFO_HEADER;
+
+//*******************************************************
+// EFI_REST_EX_SERVICE_TYPE
+//*******************************************************
+typedef enum {
+ EfiRestExServiceUnspecific = 1,
+ EfiRestExServiceRedfish,
+ EfiRestExServiceOdata,
+ EfiRestExServiceVendorSpecific = 0xff,
+ EfiRestExServiceTypeMax
+} EFI_REST_EX_SERVICE_TYPE;
+
+//*******************************************************
+// EFI_REST_EX_SERVICE_ACCESS_MODE
+//*******************************************************
+typedef enum {
+ EfiRestExServiceInBandAccess = 1,
+ EfiRestExServiceOutOfBandAccess = 2,
+ EfiRestExServiceModeMax
+} EFI_REST_EX_SERVICE_ACCESS_MODE;
+
+//*******************************************************
+// EFI_REST_EX_CONFIG_TYPE
+//*******************************************************
+typedef enum {
+ EfiRestExConfigHttp,
+ EfiRestExConfigUnspecific,
+ EfiRestExConfigTypeMax
+} EFI_REST_EX_CONFIG_TYPE;
+
+//*******************************************************
+//EFI_REST_EX_SERVICE_INFO v1.0
+//*******************************************************
+typedef struct {
+ EFI_REST_EX_SERVICE_INFO_HEADER EfiRestExServiceInfoHeader;
+ EFI_REST_EX_SERVICE_TYPE RestServiceType;
+ EFI_REST_EX_SERVICE_ACCESS_MODE RestServiceAccessMode;
+ EFI_GUID VendorRestServiceName;
+ UINT32 VendorSpecificDataLength;
+ UINT8 *VendorSpecifcData;
+ EFI_REST_EX_CONFIG_TYPE RestExConfigType;
+ UINT8 RestExConfigDataLength;
+} EFI_REST_EX_SERVICE_INFO_V_1_0;
+
+//*******************************************************
+//EFI_REST_EX_SERVICE_INFO
+//*******************************************************
+typedef union {
+ EFI_REST_EX_SERVICE_INFO_HEADER EfiRestExServiceInfoHeader;
+ EFI_REST_EX_SERVICE_INFO_V_1_0 EfiRestExServiceInfoV10;
+} EFI_REST_EX_SERVICE_INFO;
+
+//*******************************************************
+// EFI_REST_EX_HTTP_CONFIG_DATA
+//*******************************************************
+typedef struct {
+ EFI_HTTP_CONFIG_DATA HttpConfigData;
+ UINT32 SendReceiveTimeout;
+} EFI_REST_EX_HTTP_CONFIG_DATA;
+
+//*******************************************************
+//EFI_REST_EX_CONFIG_DATA
+//*******************************************************
+typedef UINT8 *EFI_REST_EX_CONFIG_DATA;
+
+//*******************************************************
+//EFI_REST_EX_TOKEN
+//*******************************************************
+typedef struct {
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+ EFI_HTTP_MESSAGE *ResponseMessage;
+} EFI_REST_EX_TOKEN;
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_SEND_RECEIVE)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_GET_TIME)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_EX_GET_SERVICE)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_EX_GET_MODE_DATA)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_EX_CONFIGURE)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_EX_ASYNC_SEND_RECEIVE)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_EX_EVENT_SERVICE)(
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+);
+
+///
+/// EFI REST(EX) protocols are designed to support REST communication between EFI REST client
+/// applications/drivers and REST services. EFI REST client tool uses EFI REST(EX) protocols
+/// to send/receive resources to/from REST service to manage systems, configure systems or
+/// manipulate resources on REST service. Due to HTTP protocol is commonly used to communicate
+/// with REST service in practice, EFI REST(EX) protocols adopt HTTP as the message format to
+/// send and receive REST service resource. EFI REST(EX) driver instance abstracts EFI REST
+/// client functionality and provides underlying interface to communicate with REST service.
+/// EFI REST(EX) driver instance knows how to communicate with REST service through certain
+/// interface after the corresponding configuration is initialized.
+///
+struct _EFI_REST_EX_PROTOCOL {
+ EFI_REST_SEND_RECEIVE SendReceive;
+ EFI_REST_GET_TIME GetServiceTime;
+ EFI_REST_EX_GET_SERVICE GetService;
+ EFI_REST_EX_GET_MODE_DATA GetModeData;
+ EFI_REST_EX_CONFIGURE Configure;
+ EFI_REST_EX_ASYNC_SEND_RECEIVE AyncSendReceive;
+ EFI_REST_EX_EVENT_SERVICE EventService;
+};
+
+extern EFI_GUID gEfiRestExServiceBindingProtocolGuid;
+extern EFI_GUID gEfiRestExProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestJsonStructure.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestJsonStructure.h
new file mode 100644
index 00000000000..7d37489b41e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/RestJsonStructure.h
@@ -0,0 +1,161 @@
+/** @file
+ This file defines the EFI REST JSON Structure Protocol interface.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This Protocol is introduced in UEFI Specification 2.8
+
+**/
+
+#ifndef EFI_REST_JSON_STRUCTURE_PROTOCOL_H_
+#define EFI_REST_JSON_STRUCTURE_PROTOCOL_H_
+
+///
+/// GUID definitions
+///
+#define EFI_REST_JSON_STRUCTURE_PROTOCOL_GUID \
+ { \
+ 0xa9a048f6, 0x48a0, 0x4714, {0xb7, 0xda, 0xa9, 0xad,0x87, 0xd4, 0xda, 0xc9 } \
+ }
+
+typedef struct _EFI_REST_JSON_STRUCTURE_PROTOCOL EFI_REST_JSON_STRUCTURE_PROTOCOL;
+typedef CHAR8 * EFI_REST_JSON_RESOURCE_TYPE_DATATYPE;
+
+///
+/// Structure defintions of resource name space.
+///
+/// The fields declared in this structure define the
+/// name and revision of payload delievered throught
+/// REST API.
+///
+typedef struct _EFI_REST_JSON_RESOURCE_TYPE_NAMESPACE {
+ CHAR8 *ResourceTypeName; ///< Resource type name
+ CHAR8 *MajorVersion; ///< Resource major version
+ CHAR8 *MinorVersion; ///< Resource minor version
+ CHAR8 *ErrataVersion; ///< Resource errata version
+} EFI_REST_JSON_RESOURCE_TYPE_NAMESPACE;
+
+///
+/// REST resource type identifier
+///
+/// REST resource type consists of name space and data type.
+///
+typedef struct _EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER {
+ EFI_REST_JSON_RESOURCE_TYPE_NAMESPACE NameSpace; ///< Namespace of this resource type.
+ EFI_REST_JSON_RESOURCE_TYPE_DATATYPE DataType; ///< Name of data type declared in this
+ ///< resource type.
+} EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER;
+
+///
+/// List of JSON to C structure conversions which this convertor supports.
+///
+typedef struct _EFI_REST_JSON_STRUCTURE_SUPPORTED {
+ LIST_ENTRY NextSupportedRsrcInterp; ///< Linklist to next supported conversion.
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER RestResourceInterp; ///< JSON resource type this convertor supports.
+} EFI_REST_JSON_STRUCTURE_SUPPORTED;
+
+///
+/// The header file of JSON C structure
+///
+typedef struct _EFI_REST_JSON_STRUCTURE_HEADER {
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER JsonRsrcIdentifier; ///< Resource identifier which use to
+ ///< choice the proper interpreter.
+ ///< Follow by a pointer points to JSON structure, the content in the
+ ///< JSON structure is implementation-specific according to converter producer.
+ VOID *JsonStructurePointer;
+} EFI_REST_JSON_STRUCTURE_HEADER;
+
+/**
+ JSON-IN C Structure-OUT function. Convert the given REST JSON resource into structure.
+
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] JsonRsrcIdentifier This indicates the resource type and version is given in
+ ResourceJsonText.
+ @param[in] ResourceJsonText REST JSON resource in text format.
+ @param[out] JsonStructure Pointer to receive the pointer to EFI_REST_JSON_STRUCTURE_HEADER
+
+ @retval EFI_SUCCESS
+ @retval Others
+--*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_JSON_STRUCTURE_TO_STRUCTURE)(
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *JsonRsrcIdentifier OPTIONAL,
+ IN CHAR8 *ResourceJsonText,
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **JsonStructure
+);
+
+/**
+ Convert the given REST JSON structure into JSON text.
+
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] JsonStructureHeader The point to EFI_REST_JSON_STRUCTURE_HEADER structure.
+ @param[out] ResourceJsonText Pointer to receive REST JSON resource in text format.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+--*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_JSON_STRUCTURE_TO_JSON)(
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *JsonStructureHeader,
+ OUT CHAR8 **ResourceJsonText
+);
+
+/**
+ This function destroys the REST JSON structure.
+
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] JsonStructureHeader JSON structure to destroy.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+--*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE)(
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *JsonStructureHeader
+);
+/**
+ This function provides REST JSON resource to structure converter registration.
+
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] JsonStructureSupported The type and version of REST JSON resource which this converter
+ supports.
+ @param[in] ToStructure The function to convert REST JSON resource to structure.
+ @param[in] ToJson The function to convert REST JSON structure to JSON in text format.
+ @param[in] DestroyStructure Destroy REST JSON structure returned in ToStructure() function.
+
+ @retval EFI_SUCCESS Register successfully.
+ @retval Others Fail to register.
+
+--*/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REST_JSON_STRUCTURE_REGISTER)(
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_SUPPORTED *JsonStructureSupported,
+ IN EFI_REST_JSON_STRUCTURE_TO_STRUCTURE ToStructure,
+ IN EFI_REST_JSON_STRUCTURE_TO_JSON ToJson,
+ IN EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure
+);
+
+///
+/// EFI REST JSON to C structure protocol definition.
+///
+struct _EFI_REST_JSON_STRUCTURE_PROTOCOL {
+ EFI_REST_JSON_STRUCTURE_REGISTER Register; ///< Register JSON to C structure convertor
+ EFI_REST_JSON_STRUCTURE_TO_STRUCTURE ToStructure; ///< The function to convert JSON to C structure
+ EFI_REST_JSON_STRUCTURE_TO_JSON ToJson; ///< The function to convert C structure to JSON
+ EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestoryStructure; ///< Destory C structure.
+};
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SerialIo.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SerialIo.h
index 8d788306e54..3a726537337 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SerialIo.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SerialIo.h
@@ -17,6 +17,11 @@
0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD } \
}
+#define EFI_SERIAL_TERMINAL_DEVICE_TYPE_GUID \
+ { \
+ 0X6AD9A60F, 0X5815, 0X4C7C, { 0X8A, 0X10, 0X50, 0X53, 0XD2, 0XBF, 0X7A, 0X1B } \
+ }
+
///
/// Protocol GUID defined in EFI1.1.
///
@@ -299,5 +304,6 @@ struct _EFI_SERIAL_IO_PROTOCOL {
};
extern EFI_GUID gEfiSerialIoProtocolGuid;
+extern EFI_GUID gEfiSerialTerminalDeviceTypeGuid;
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SimpleTextOut.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SimpleTextOut.h
index 18438d3533e..0653bc199ab 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SimpleTextOut.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/SimpleTextOut.h
@@ -32,7 +32,7 @@ typedef struct _EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE;
//
-// Define's for required EFI Unicode Box Draw characters
+// Defines for required EFI Unicode Box Draw characters
//
#define BOXDRAW_HORIZONTAL 0x2500
#define BOXDRAW_VERTICAL 0x2502
@@ -151,7 +151,7 @@ typedef EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SIMPLE_TEXT_OUTPUT_INTERFACE;
#define EFI_WIDE_ATTRIBUTE 0x80
/**
- Reset the text output device hardware and optionaly run diagnostics
+ Reset the text output device hardware and optionally run diagnostics
@param This The protocol instance pointer.
@param ExtendedVerification Driver may perform more exhaustive verification
@@ -373,7 +373,7 @@ typedef struct {
///
INT32 CursorRow;
///
- /// The cursor is currently visbile or not.
+ /// The cursor is currently visible or not.
///
BOOLEAN CursorVisible;
} EFI_SIMPLE_TEXT_OUTPUT_MODE;
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/UgaDraw.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/UgaDraw.h
index 1b2bd17b4c9..472ceeaaf05 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/UgaDraw.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Protocol/UgaDraw.h
@@ -127,7 +127,7 @@ typedef enum {
@retval EFI_SUCCESS - The Blt operation completed.
@retval EFI_INVALID_PARAMETER - BltOperation is not valid.
- @retval EFI_DEVICE_ERROR - A hardware error occured writting to the video buffer.
+ @retval EFI_DEVICE_ERROR - A hardware error occurred writting to the video buffer.
**/
typedef
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Fam17Msr.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Fam17Msr.h
index 4325477eef6..5be1db4f668 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Fam17Msr.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Fam17Msr.h
@@ -18,6 +18,52 @@
#define __FAM17_MSR_H__
/**
+ Secure Encrypted Virtualization - Encrypted State (SEV-ES) GHCB register
+
+**/
+#define MSR_SEV_ES_GHCB 0xc0010130
+
+/**
+ MSR information returned for #MSR_SEV_ES_GHCB
+**/
+typedef union {
+ struct {
+ UINT32 Function:12;
+ UINT32 Reserved1:20;
+ UINT32 Reserved2:32;
+ } GhcbInfo;
+
+ struct {
+ UINT8 Reserved[3];
+ UINT8 SevEncryptionBitPos;
+ UINT16 SevEsProtocolMin;
+ UINT16 SevEsProtocolMax;
+ } GhcbProtocol;
+
+ struct {
+ UINT32 Function:12;
+ UINT32 ReasonCodeSet:4;
+ UINT32 ReasonCode:8;
+ UINT32 Reserved1:8;
+ UINT32 Reserved2:32;
+ } GhcbTerminate;
+
+ VOID *Ghcb;
+
+ UINT64 GhcbPhysicalAddress;
+} MSR_SEV_ES_GHCB_REGISTER;
+
+#define GHCB_INFO_SEV_INFO 1
+#define GHCB_INFO_SEV_INFO_GET 2
+#define GHCB_INFO_CPUID_REQUEST 4
+#define GHCB_INFO_CPUID_RESPONSE 5
+#define GHCB_INFO_TERMINATE_REQUEST 256
+
+#define GHCB_TERMINATE_GHCB 0
+#define GHCB_TERMINATE_GHCB_GENERAL 0
+#define GHCB_TERMINATE_GHCB_PROTOCOL 1
+
+/**
Secure Encrypted Virtualization (SEV) status register
**/
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Ghcb.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Ghcb.h
new file mode 100644
index 00000000000..8ba2989d680
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Amd/Ghcb.h
@@ -0,0 +1,157 @@
+/** @file
+ Guest-Hypervisor Communication Block (GHCB) Definition.
+
+ Provides data types allowing an SEV-ES guest to interact with the hypervisor
+ using the GHCB protocol.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Specification Reference:
+ SEV-ES Guest-Hypervisor Communication Block Standardization
+
+**/
+
+#ifndef __GHCB_H__
+#define __GHCB_H__
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#define UD_EXCEPTION 6
+#define GP_EXCEPTION 13
+#define VC_EXCEPTION 29
+
+#define GHCB_VERSION_MIN 1
+#define GHCB_VERSION_MAX 1
+
+#define GHCB_STANDARD_USAGE 0
+
+//
+// SVM Exit Codes
+//
+#define SVM_EXIT_DR7_READ 0x27ULL
+#define SVM_EXIT_DR7_WRITE 0x37ULL
+#define SVM_EXIT_RDTSC 0x6EULL
+#define SVM_EXIT_RDPMC 0x6FULL
+#define SVM_EXIT_CPUID 0x72ULL
+#define SVM_EXIT_INVD 0x76ULL
+#define SVM_EXIT_IOIO_PROT 0x7BULL
+#define SVM_EXIT_MSR 0x7CULL
+#define SVM_EXIT_VMMCALL 0x81ULL
+#define SVM_EXIT_RDTSCP 0x87ULL
+#define SVM_EXIT_WBINVD 0x89ULL
+#define SVM_EXIT_MONITOR 0x8AULL
+#define SVM_EXIT_MWAIT 0x8BULL
+#define SVM_EXIT_NPF 0x400ULL
+
+//
+// VMG Special Exit Codes
+//
+#define SVM_EXIT_MMIO_READ 0x80000001ULL
+#define SVM_EXIT_MMIO_WRITE 0x80000002ULL
+#define SVM_EXIT_NMI_COMPLETE 0x80000003ULL
+#define SVM_EXIT_AP_RESET_HOLD 0x80000004ULL
+#define SVM_EXIT_AP_JUMP_TABLE 0x80000005ULL
+#define SVM_EXIT_UNSUPPORTED 0x8000FFFFULL
+
+//
+// IOIO Exit Information
+//
+#define IOIO_TYPE_STR BIT2
+#define IOIO_TYPE_IN 1
+#define IOIO_TYPE_INS (IOIO_TYPE_IN | IOIO_TYPE_STR)
+#define IOIO_TYPE_OUT 0
+#define IOIO_TYPE_OUTS (IOIO_TYPE_OUT | IOIO_TYPE_STR)
+
+#define IOIO_REP BIT3
+
+#define IOIO_ADDR_64 BIT9
+#define IOIO_ADDR_32 BIT8
+#define IOIO_ADDR_16 BIT7
+
+#define IOIO_DATA_32 BIT6
+#define IOIO_DATA_16 BIT5
+#define IOIO_DATA_8 BIT4
+#define IOIO_DATA_MASK (BIT6 | BIT5 | BIT4)
+#define IOIO_DATA_OFFSET 4
+#define IOIO_DATA_BYTES(x) (((x) & IOIO_DATA_MASK) >> IOIO_DATA_OFFSET)
+
+#define IOIO_SEG_ES 0
+#define IOIO_SEG_DS (BIT11 | BIT10)
+
+
+typedef PACKED struct {
+ UINT8 Reserved1[203];
+ UINT8 Cpl;
+ UINT8 Reserved8[300];
+ UINT64 Rax;
+ UINT8 Reserved4[264];
+ UINT64 Rcx;
+ UINT64 Rdx;
+ UINT64 Rbx;
+ UINT8 Reserved5[112];
+ UINT64 SwExitCode;
+ UINT64 SwExitInfo1;
+ UINT64 SwExitInfo2;
+ UINT64 SwScratch;
+ UINT8 Reserved6[56];
+ UINT64 XCr0;
+ UINT8 ValidBitmap[16];
+ UINT64 X87StateGpa;
+ UINT8 Reserved7[1016];
+} GHCB_SAVE_AREA;
+
+typedef PACKED struct {
+ GHCB_SAVE_AREA SaveArea;
+ UINT8 SharedBuffer[2032];
+ UINT8 Reserved1[10];
+ UINT16 ProtocolVersion;
+ UINT32 GhcbUsage;
+} GHCB;
+
+#define GHCB_SAVE_AREA_QWORD_OFFSET(RegisterField) \
+ (OFFSET_OF (GHCB, SaveArea.RegisterField) / sizeof (UINT64))
+
+typedef enum {
+ GhcbCpl = GHCB_SAVE_AREA_QWORD_OFFSET (Cpl),
+ GhcbRax = GHCB_SAVE_AREA_QWORD_OFFSET (Rax),
+ GhcbRbx = GHCB_SAVE_AREA_QWORD_OFFSET (Rbx),
+ GhcbRcx = GHCB_SAVE_AREA_QWORD_OFFSET (Rcx),
+ GhcbRdx = GHCB_SAVE_AREA_QWORD_OFFSET (Rdx),
+ GhcbXCr0 = GHCB_SAVE_AREA_QWORD_OFFSET (XCr0),
+ GhcbSwExitCode = GHCB_SAVE_AREA_QWORD_OFFSET (SwExitCode),
+ GhcbSwExitInfo1 = GHCB_SAVE_AREA_QWORD_OFFSET (SwExitInfo1),
+ GhcbSwExitInfo2 = GHCB_SAVE_AREA_QWORD_OFFSET (SwExitInfo2),
+ GhcbSwScratch = GHCB_SAVE_AREA_QWORD_OFFSET (SwScratch),
+} GHCB_REGISTER;
+
+typedef union {
+ struct {
+ UINT32 Lower32Bits;
+ UINT32 Upper32Bits;
+ } Elements;
+
+ UINT64 Uint64;
+} GHCB_EXIT_INFO;
+
+typedef union {
+ struct {
+ UINT32 Vector:8;
+ UINT32 Type:3;
+ UINT32 ErrorCodeValid:1;
+ UINT32 Rsvd:19;
+ UINT32 Valid:1;
+ UINT32 ErrorCode;
+ } Elements;
+
+ UINT64 Uint64;
+} GHCB_EVENT_INJECTION;
+
+#define GHCB_EVENT_INJECTION_TYPE_INT 0
+#define GHCB_EVENT_INJECTION_TYPE_NMI 2
+#define GHCB_EVENT_INJECTION_TYPE_EXCEPTION 3
+#define GHCB_EVENT_INJECTION_TYPE_SOFT_INT 4
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Intel/Cpuid.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Intel/Cpuid.h
index 47a694fdf8b..eeb23e152ff 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Intel/Cpuid.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Register/Intel/Cpuid.h
@@ -6,7 +6,7 @@
If a register returned is a single 32-bit value, then a data structure is
not provided for that register.
- Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Specification Reference:
@@ -1278,7 +1278,7 @@ typedef union {
@retval EAX The maximum input value for ECX to retrieve sub-leaf information.
@retval EBX Structured Extended Feature Flags described by the type
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_EBX.
- @retval EBX Structured Extended Feature Flags described by the type
+ @retval ECX Structured Extended Feature Flags described by the type
CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX.
@retval EDX Reserved.
@@ -1550,9 +1550,17 @@ typedef union {
///
UINT32 AVX512_4FMAPS:1;
///
- /// [Bit 25:4] Reserved.
+ /// [Bit 14:4] Reserved.
+ ///
+ UINT32 Reserved4:11;
+ ///
+ /// [Bit 15] Hybrid. If 1, the processor is identified as a hybrid part.
+ ///
+ UINT32 Hybrid:1;
///
- UINT32 Reserved2:22;
+ /// [Bit 25:16] Reserved.
+ ///
+ UINT32 Reserved5:10;
///
/// [Bit 26] Enumerates support for indirect branch restricted speculation
/// (IBRS) and the indirect branch pre-dictor barrier (IBPB). Processors
@@ -3598,6 +3606,76 @@ typedef union {
/**
+ CPUID Hybrid Information Enumeration Leaf
+
+ @param EAX CPUID_HYBRID_INFORMATION (0x1A)
+ @param ECX CPUID_HYBRID_INFORMATION_MAIN_LEAF (0x00).
+
+ @retval EAX Enumerates the native model ID and core type described
+ by the type CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX
+ @retval EBX Reserved.
+ @retval ECX Reserved.
+ @retval EDX Reserved.
+
+ <b>Example usage</b>
+ @code
+ CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX Eax;
+
+ AsmCpuidEx (
+ CPUID_HYBRID_INFORMATION,
+ CPUID_HYBRID_INFORMATION_MAIN_LEAF,
+ &Eax, NULL, NULL, NULL
+ );
+ @endcode
+
+**/
+#define CPUID_HYBRID_INFORMATION 0x1A
+
+///
+/// CPUID Hybrid Information Enumeration main leaf
+///
+#define CPUID_HYBRID_INFORMATION_MAIN_LEAF 0x00
+
+/**
+ CPUID Hybrid Information EAX for CPUID leaf #CPUID_HYBRID_INFORMATION,
+ main leaf #CPUID_HYBRID_INFORMATION_MAIN_LEAF.
+**/
+typedef union {
+ ///
+ /// Individual bit fields
+ ///
+ struct {
+ ///
+ /// [Bit 23:0] Native model ID of the core.
+ ///
+ /// The core-type and native mode ID can be used to uniquely identify
+ /// the microarchitecture of the core.This native model ID is not unique
+ /// across core types, and not related to the model ID reported in CPUID
+ /// leaf 01H, and does not identify the SOC.
+ ///
+ UINT32 NativeModelId:24;
+ ///
+ /// [Bit 31:24] Core type
+ ///
+ UINT32 CoreType:8;
+ } Bits;
+ ///
+ /// All bit fields as a 32-bit value
+ ///
+ UINT32 Uint32;
+} CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX;
+
+///
+/// @{ Define value for CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX.CoreType
+///
+#define CPUID_CORE_TYPE_INTEL_ATOM 0x20
+#define CPUID_CORE_TYPE_INTEL_CORE 0x40
+///
+/// @}
+///
+
+
+/**
CPUID V2 Extended Topology Enumeration Leaf
@note
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiBaseType.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiBaseType.h
index 6a2f3303937..b9183fda483 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiBaseType.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiBaseType.h
@@ -1,7 +1,7 @@
/** @file
Defines data types and constants introduced in UEFI.
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.<BR>
Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -248,6 +248,7 @@ typedef union {
#define EFI_IMAGE_MACHINE_RISCV64 0x5064
#define EFI_IMAGE_MACHINE_RISCV128 0x5128
+#if !defined(EFI_IMAGE_MACHINE_TYPE_VALUE) && !defined(EFI_IMAGE_MACHINE_CROSS_TYPE_VALUE)
#if defined (MDE_CPU_IA32)
#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \
@@ -294,5 +295,17 @@ typedef union {
#else
#error Unknown Processor Type
#endif
+#else
+#if defined (EFI_IMAGE_MACHINE_TYPE_VALUE)
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_TYPE_VALUE)
+#else
+#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) (FALSE)
+#endif
+#if defined (EFI_IMAGE_MACHINE_CROSS_TYPE_VALUE)
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_CROSS_TYPE_VALUE)
+#else
+#define EFI_IMAGE_MACHINE_CROSS_TYPE_SUPPORTED(Machine) (FALSE)
+#endif
+#endif
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiSpec.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiSpec.h
index 71b10fbba4c..64047eaff9d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiSpec.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/Uefi/UefiSpec.h
@@ -5,7 +5,7 @@
If a code construct is defined in the UEFI 2.7 specification it must be included
by this include file.
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -96,9 +96,9 @@ typedef enum {
#define EFI_MEMORY_SP 0x0000000000040000ULL
//
// If this flag is set, the memory region is capable of being
-// protected with the CPU?s memory cryptographic
+// protected with the CPU's memory cryptographic
// capabilities. If this flag is clear, the memory region is not
-// capable of being protected with the CPU?s memory
+// capable of being protected with the CPU's memory
// cryptographic capabilities or the CPU does not support CPU
// memory cryptographic capabilities.
//
@@ -109,6 +109,13 @@ typedef enum {
//
#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL
+//
+// Attributes bitmasks, grouped by type
+//
+#define EFI_CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)
+#define EFI_MEMORY_ACCESS_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)
+#define EFI_MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_ACCESS_MASK | EFI_MEMORY_SP | EFI_MEMORY_CPU_CRYPTO)
+
///
/// Memory descriptor version number.
///
@@ -2218,6 +2225,7 @@ typedef struct {
#define EFI_REMOVABLE_MEDIA_FILE_NAME_AARCH64 L"\\EFI\\BOOT\\BOOTAA64.EFI"
#define EFI_REMOVABLE_MEDIA_FILE_NAME_RISCV64 L"\\EFI\\BOOT\\BOOTRISCV64.EFI"
+#if !defined(EFI_REMOVABLE_MEDIA_FILE_NAME)
#if defined (MDE_CPU_IA32)
#define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA32
#elif defined (MDE_CPU_X64)
@@ -2232,6 +2240,7 @@ typedef struct {
#else
#error Unknown Processor Type
#endif
+#endif
//
// The directory within the active EFI System Partition defined for delivery of capsule to firmware
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/X64/Nasm.inc b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/X64/Nasm.inc
index 2d85a877083..2b6e03803d6 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Include/X64/Nasm.inc
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Include/X64/Nasm.inc
@@ -1,6 +1,6 @@
;------------------------------------------------------------------------------
;
-; Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Abstract:
@@ -9,6 +9,18 @@
;
;------------------------------------------------------------------------------
+%macro SAVEPREVSSP 0
+ DB 0xF3, 0x0F, 0x01, 0xEA
+%endmacro
+
+%macro CLRSSBSY_RAX 0
+ DB 0xF3, 0x0F, 0xAE, 0x30
+%endmacro
+
+%macro RSTORSSP_RAX 0
+ DB 0xF3, 0x0F, 0x01, 0x28
+%endmacro
+
%macro SETSSBSY 0
DB 0xF3, 0x0F, 0x01, 0xE8
%endmacro
@@ -20,3 +32,41 @@
%macro INCSSP_RAX 0
DB 0xF3, 0x48, 0x0F, 0xAE, 0xE8
%endmacro
+
+; NASM provides built-in macros STRUC and ENDSTRUC for structure definition.
+; For example, to define a structure called mytype containing a longword,
+; a word, a byte and a string of bytes, you might code
+;
+; struc mytype
+;
+; mt_long: resd 1
+; mt_word: resw 1
+; mt_byte: resb 1
+; mt_str: resb 32
+;
+; endstruc
+;
+; Below macros are help to map the C types and the RESB family of pseudo-instructions.
+; So that the above structure definition can be coded as
+;
+; struc mytype
+;
+; mt_long: CTYPE_UINT32 1
+; mt_word: CTYPE_UINT16 1
+; mt_byte: CTYPE_UINT8 1
+; mt_str: CTYPE_CHAR8 32
+;
+; endstruc
+%define CTYPE_UINT64 resq
+%define CTYPE_INT64 resq
+%define CTYPE_UINT32 resd
+%define CTYPE_INT32 resd
+%define CTYPE_UINT16 resw
+%define CTYPE_INT16 resw
+%define CTYPE_BOOLEAN resb
+%define CTYPE_UINT8 resb
+%define CTYPE_CHAR8 resb
+%define CTYPE_INT8 resb
+
+%define CTYPE_UINTN resq
+%define CTYPE_INTN resq
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c
new file mode 100644
index 00000000000..f7d14252389
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.c
@@ -0,0 +1,225 @@
+/** @file
+ Null Cache Maintenance Librfary implementation.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/DebugLib.h>
+
+/**
+ Invalidates the entire instruction cache in cache coherency domain of the
+ calling CPU.
+
+**/
+VOID
+EFIAPI
+InvalidateInstructionCache (
+ VOID
+ )
+{
+}
+
+/**
+ Invalidates a range of instruction cache lines in the cache coherency domain
+ of the calling CPU.
+
+ Invalidates the instruction cache lines specified by Address and Length. If
+ Address is not aligned on a cache line boundary, then entire instruction
+ cache line containing Address is invalidated. If Address + Length is not
+ aligned on a cache line boundary, then the entire instruction cache line
+ containing Address + Length -1 is invalidated. This function may choose to
+ invalidate the entire instruction cache if that is more efficient than
+ invalidating the specified range. If Length is 0, then no instruction cache
+ lines are invalidated. Address is returned.
+
+ If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
+
+ @param Address The base address of the instruction cache lines to
+ invalidate. If the CPU is in a physical addressing mode, then
+ Address is a physical address. If the CPU is in a virtual
+ addressing mode, then Address is a virtual address.
+
+ @param Length The number of bytes to invalidate from the instruction cache.
+
+ @return Address.
+
+**/
+VOID *
+EFIAPI
+InvalidateInstructionCacheRange (
+ IN VOID *Address,
+ IN UINTN Length
+ )
+{
+ ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1);
+ return Address;
+}
+
+/**
+ Writes back and invalidates the entire data cache in cache coherency domain
+ of the calling CPU.
+
+ Writes back and invalidates the entire data cache in cache coherency domain
+ of the calling CPU. This function guarantees that all dirty cache lines are
+ written back to system memory, and also invalidates all the data cache lines
+ in the cache coherency domain of the calling CPU.
+
+**/
+VOID
+EFIAPI
+WriteBackInvalidateDataCache (
+ VOID
+ )
+{
+}
+
+/**
+ Writes back and invalidates a range of data cache lines in the cache
+ coherency domain of the calling CPU.
+
+ Writes Back and Invalidate the data cache lines specified by Address and
+ Length. If Address is not aligned on a cache line boundary, then entire data
+ cache line containing Address is written back and invalidated. If Address +
+ Length is not aligned on a cache line boundary, then the entire data cache
+ line containing Address + Length -1 is written back and invalidated. This
+ function may choose to write back and invalidate the entire data cache if
+ that is more efficient than writing back and invalidating the specified
+ range. If Length is 0, then no data cache lines are written back and
+ invalidated. Address is returned.
+
+ If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
+
+ @param Address The base address of the data cache lines to write back and
+ invalidate. If the CPU is in a physical addressing mode, then
+ Address is a physical address. If the CPU is in a virtual
+ addressing mode, then Address is a virtual address.
+ @param Length The number of bytes to write back and invalidate from the
+ data cache.
+
+ @return Address of cache invalidation.
+
+**/
+VOID *
+EFIAPI
+WriteBackInvalidateDataCacheRange (
+ IN VOID *Address,
+ IN UINTN Length
+ )
+{
+ ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1);
+ return Address;
+}
+
+/**
+ Writes back the entire data cache in cache coherency domain of the calling
+ CPU.
+
+ Writes back the entire data cache in cache coherency domain of the calling
+ CPU. This function guarantees that all dirty cache lines are written back to
+ system memory. This function may also invalidate all the data cache lines in
+ the cache coherency domain of the calling CPU.
+
+**/
+VOID
+EFIAPI
+WriteBackDataCache (
+ VOID
+ )
+{
+}
+
+/**
+ Writes back a range of data cache lines in the cache coherency domain of the
+ calling CPU.
+
+ Writes back the data cache lines specified by Address and Length. If Address
+ is not aligned on a cache line boundary, then entire data cache line
+ containing Address is written back. If Address + Length is not aligned on a
+ cache line boundary, then the entire data cache line containing Address +
+ Length -1 is written back. This function may choose to write back the entire
+ data cache if that is more efficient than writing back the specified range.
+ If Length is 0, then no data cache lines are written back. This function may
+ also invalidate all the data cache lines in the specified range of the cache
+ coherency domain of the calling CPU. Address is returned.
+
+ If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
+
+ @param Address The base address of the data cache lines to write back. If
+ the CPU is in a physical addressing mode, then Address is a
+ physical address. If the CPU is in a virtual addressing
+ mode, then Address is a virtual address.
+ @param Length The number of bytes to write back from the data cache.
+
+ @return Address of cache written in main memory.
+
+**/
+VOID *
+EFIAPI
+WriteBackDataCacheRange (
+ IN VOID *Address,
+ IN UINTN Length
+ )
+{
+ ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1);
+ return Address;
+}
+
+/**
+ Invalidates the entire data cache in cache coherency domain of the calling
+ CPU.
+
+ Invalidates the entire data cache in cache coherency domain of the calling
+ CPU. This function must be used with care because dirty cache lines are not
+ written back to system memory. It is typically used for cache diagnostics. If
+ the CPU does not support invalidation of the entire data cache, then a write
+ back and invalidate operation should be performed on the entire data cache.
+
+**/
+VOID
+EFIAPI
+InvalidateDataCache (
+ VOID
+ )
+{
+}
+
+/**
+ Invalidates a range of data cache lines in the cache coherency domain of the
+ calling CPU.
+
+ Invalidates the data cache lines specified by Address and Length. If Address
+ is not aligned on a cache line boundary, then entire data cache line
+ containing Address is invalidated. If Address + Length is not aligned on a
+ cache line boundary, then the entire data cache line containing Address +
+ Length -1 is invalidated. This function must never invalidate any cache lines
+ outside the specified range. If Length is 0, then no data cache lines are
+ invalidated. Address is returned. This function must be used with care
+ because dirty cache lines are not written back to system memory. It is
+ typically used for cache diagnostics. If the CPU does not support
+ invalidation of a data cache range, then a write back and invalidate
+ operation should be performed on the data cache range.
+
+ If Length is greater than (MAX_ADDRESS - Address + 1), then ASSERT().
+
+ @param Address The base address of the data cache lines to invalidate. If
+ the CPU is in a physical addressing mode, then Address is a
+ physical address. If the CPU is in a virtual addressing mode,
+ then Address is a virtual address.
+ @param Length The number of bytes to invalidate from the data cache.
+
+ @return Address.
+
+**/
+VOID *
+EFIAPI
+InvalidateDataCacheRange (
+ IN VOID *Address,
+ IN UINTN Length
+ )
+{
+ ASSERT (Length <= MAX_ADDRESS - (UINTN)Address + 1);
+ return Address;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf
new file mode 100644
index 00000000000..0c343bfc82c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf
@@ -0,0 +1,29 @@
+## @file
+# Null Cache Maintenance Library implementation.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCacheMaintenanceLibNull
+ MODULE_UNI_FILE = BaseCacheMaintenanceLibNull.uni
+ FILE_GUID = 13F13249-AC31-4373-8B2B-AFC5755A6FCD
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = CacheMaintenanceLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64
+#
+
+[Sources]
+ BaseCacheMaintenanceLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DebugLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni
new file mode 100644
index 00000000000..260c7561901
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.uni
@@ -0,0 +1,12 @@
+// /** @file
+// Null Cache Maintenance Library implementation.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "Null instance of Cache Maintenance Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Null instance of the Cache Maintenance Library."
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c
new file mode 100644
index 00000000000..c45e24a7a50
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.c
@@ -0,0 +1,37 @@
+/** @file
+ Null instance of CPU Library.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+/**
+ Places the CPU in a sleep state until an interrupt is received.
+
+ Places the CPU in a sleep state until an interrupt is received. If interrupts
+ are disabled prior to calling this function, then the CPU will be placed in a
+ sleep state indefinitely.
+
+**/
+VOID
+EFIAPI
+CpuSleep (
+ VOID
+ )
+{
+}
+
+/**
+ Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU.
+
+ Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU.
+
+**/
+VOID
+EFIAPI
+CpuFlushTlb (
+ VOID
+ )
+{
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
new file mode 100644
index 00000000000..9aba4b5ae76
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
@@ -0,0 +1,26 @@
+## @file
+# Null instance of CPU Library.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = BaseCpuLibNull
+ MODULE_UNI_FILE = BaseCpuLibNull.uni
+ FILE_GUID = 8A29AAA5-0FB7-44CC-8709-1344FE89B878
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64
+#
+
+[Sources]
+ BaseCpuLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni
new file mode 100644
index 00000000000..1030221d5ca
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.uni
@@ -0,0 +1,11 @@
+// /** @file
+// Null instance of CPU Library.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "Null Instance of CPU Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Null instance of CPU Library."
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
index ede0e8e6ae0..33d2672e758 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
@@ -7,7 +7,7 @@
# ASSERT(). For ARM, AARCH64 and RISCV64, this I/O library only provides non I/O
# read and write.
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
# Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -66,4 +66,5 @@
[LibraryClasses]
DebugLib
BaseLib
+ RegisterFilterLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
index d97050df163..6beaabec8cf 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicArmVirt.inf
@@ -1,7 +1,7 @@
## @file
# Instance of I/O Library using KVM/ARM safe assembler routines
#
-# Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
# Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
@@ -44,3 +44,4 @@
[LibraryClasses]
DebugLib
BaseLib
+ RegisterFilterLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h
index 1e709ce3e9c..8b10be6f551 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicInternal.h
@@ -3,7 +3,7 @@
This file includes package header files, dependent library classes.
- Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -17,5 +17,6 @@
#include <Library/IoLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
+#include <Library/RegisterFilterLib.h>
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
index 84fdf6adb79..b3ea6b7b2fa 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
@@ -4,7 +4,7 @@
# I/O Library that uses compiler intrinsics to perform IN and OUT instructions
# for IA-32 and x64.
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
#
@@ -49,4 +49,5 @@
[LibraryClasses]
DebugLib
BaseLib
+ RegisterFilterLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c
index f55b328d5a7..73160f39287 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c
@@ -1,7 +1,7 @@
/** @file
Common I/O Library routines.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -82,10 +82,15 @@ MmioRead8 (
)
{
UINT8 Value;
+ BOOLEAN Flag;
- MemoryFence ();
- Value = *(volatile UINT8*)Address;
- MemoryFence ();
+ Flag = FilterBeforeMmIoRead (FilterWidth8, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ Value = *(volatile UINT8*)Address;
+ MemoryFence ();
+ }
+ FilterAfterMmIoRead (FilterWidth8, Address, &Value);
return Value;
}
@@ -112,9 +117,15 @@ MmioWrite8 (
IN UINT8 Value
)
{
- MemoryFence ();
- *(volatile UINT8*)Address = Value;
- MemoryFence ();
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMmIoWrite (FilterWidth8, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ *(volatile UINT8*)Address = Value;
+ MemoryFence ();
+ }
+ FilterAfterMmIoWrite (FilterWidth8, Address, &Value);
return Value;
}
@@ -141,12 +152,16 @@ MmioRead16 (
)
{
UINT16 Value;
+ BOOLEAN Flag;
ASSERT ((Address & 1) == 0);
-
- MemoryFence ();
- Value = *(volatile UINT16*)Address;
- MemoryFence ();
+ Flag = FilterBeforeMmIoRead (FilterWidth16, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ Value = *(volatile UINT16*)Address;
+ MemoryFence ();
+ }
+ FilterAfterMmIoRead (FilterWidth16, Address, &Value);
return Value;
}
@@ -174,11 +189,17 @@ MmioWrite16 (
IN UINT16 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 1) == 0);
- MemoryFence ();
- *(volatile UINT16*)Address = Value;
- MemoryFence ();
+ Flag = FilterBeforeMmIoWrite (FilterWidth16, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ *(volatile UINT16*)Address = Value;
+ MemoryFence ();
+ }
+ FilterAfterMmIoWrite (FilterWidth16, Address, &Value);
return Value;
}
@@ -205,12 +226,17 @@ MmioRead32 (
)
{
UINT32 Value;
+ BOOLEAN Flag;
ASSERT ((Address & 3) == 0);
- MemoryFence ();
- Value = *(volatile UINT32*)Address;
- MemoryFence ();
+ Flag = FilterBeforeMmIoRead (FilterWidth32, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ Value = *(volatile UINT32*)Address;
+ MemoryFence ();
+ }
+ FilterAfterMmIoRead (FilterWidth32, Address, &Value);
return Value;
}
@@ -238,11 +264,17 @@ MmioWrite32 (
IN UINT32 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 3) == 0);
- MemoryFence ();
- *(volatile UINT32*)Address = Value;
- MemoryFence ();
+ Flag = FilterBeforeMmIoWrite (FilterWidth32, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ *(volatile UINT32*)Address = Value;
+ MemoryFence ();
+ }
+ FilterAfterMmIoWrite (FilterWidth32, Address, &Value);
return Value;
}
@@ -269,12 +301,17 @@ MmioRead64 (
)
{
UINT64 Value;
+ BOOLEAN Flag;
ASSERT ((Address & 7) == 0);
- MemoryFence ();
- Value = *(volatile UINT64*)Address;
- MemoryFence ();
+ Flag = FilterBeforeMmIoRead (FilterWidth64, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ Value = *(volatile UINT64*)Address;
+ MemoryFence ();
+ }
+ FilterAfterMmIoRead (FilterWidth64, Address, &Value);
return Value;
}
@@ -300,11 +337,17 @@ MmioWrite64 (
IN UINT64 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 7) == 0);
- MemoryFence ();
- *(volatile UINT64*)Address = Value;
- MemoryFence ();
+ Flag = FilterBeforeMmIoWrite (FilterWidth64, Address, &Value);
+ if (Flag) {
+ MemoryFence ();
+ *(volatile UINT64*)Address = Value;
+ MemoryFence ();
+ }
+ FilterAfterMmIoWrite (FilterWidth64, Address, &Value);
return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c
index 763441e0709..9fc5c6bc15d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibArmVirt.c
@@ -1,7 +1,7 @@
/** @file
I/O Library for ARM.
- Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
@@ -546,7 +546,16 @@ MmioRead8 (
IN UINTN Address
)
{
- return MmioRead8Internal (Address);
+ UINT8 Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMmIoRead (FilterWidth8, Address, &Value);
+ if (Flag) {
+ Value = MmioRead8Internal (Address);
+ }
+ FilterAfterMmIoRead (FilterWidth8, Address, &Value);
+
+ return Value;
}
/**
@@ -569,7 +578,14 @@ MmioWrite8 (
IN UINT8 Value
)
{
- MmioWrite8Internal (Address, Value);
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMmIoWrite (FilterWidth8, Address, &Value);
+ if (Flag) {
+ MmioWrite8Internal (Address, Value);
+ }
+ FilterAfterMmIoWrite (FilterWidth8, Address, &Value);
+
return Value;
}
@@ -593,9 +609,18 @@ MmioRead16 (
IN UINTN Address
)
{
+ BOOLEAN Flag;
+ UINT16 Value;
+
ASSERT ((Address & 1) == 0);
- return MmioRead16Internal (Address);
+ Flag = FilterBeforeMmIoRead (FilterWidth16, Address, &Value);
+ if (Flag) {
+ Value = MmioRead16Internal (Address);
+ }
+ FilterAfterMmIoRead (FilterWidth16, Address, &Value);
+
+ return Value;
}
/**
@@ -618,9 +643,16 @@ MmioWrite16 (
IN UINT16 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 1) == 0);
- MmioWrite16Internal (Address, Value);
+ Flag = FilterBeforeMmIoWrite (FilterWidth16, Address, &Value);
+ if (Flag) {
+ MmioWrite16Internal (Address, Value);
+ }
+ FilterAfterMmIoWrite (FilterWidth16, Address, &Value);
+
return Value;
}
@@ -644,9 +676,18 @@ MmioRead32 (
IN UINTN Address
)
{
+ BOOLEAN Flag;
+ UINT32 Value;
+
ASSERT ((Address & 3) == 0);
- return MmioRead32Internal (Address);
+ Flag = FilterBeforeMmIoRead (FilterWidth32, Address, &Value);
+ if (Flag) {
+ Value = MmioRead32Internal (Address);
+ }
+ FilterAfterMmIoRead (FilterWidth32, Address, &Value);
+
+ return Value;
}
/**
@@ -669,9 +710,16 @@ MmioWrite32 (
IN UINT32 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 3) == 0);
- MmioWrite32Internal (Address, Value);
+ Flag = FilterBeforeMmIoWrite (FilterWidth32, Address, &Value);
+ if (Flag) {
+ MmioWrite32Internal (Address, Value);
+ }
+ FilterAfterMmIoWrite (FilterWidth32, Address, &Value);
+
return Value;
}
@@ -695,9 +743,18 @@ MmioRead64 (
IN UINTN Address
)
{
+ BOOLEAN Flag;
+ UINT64 Value;
+
ASSERT ((Address & 7) == 0);
- return MmioRead64Internal (Address);
+ Flag = FilterBeforeMmIoRead (FilterWidth64, Address, &Value);
+ if (Flag) {
+ Value = MmioRead64Internal (Address);
+ }
+ FilterAfterMmIoRead (FilterWidth64, Address, &Value);
+
+ return Value;
}
/**
@@ -720,8 +777,15 @@ MmioWrite64 (
IN UINT64 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 7) == 0);
- MmioWrite64Internal (Address, Value);
+ Flag = FilterBeforeMmIoWrite (FilterWidth64, Address, &Value);
+ if (Flag) {
+ MmioWrite64Internal (Address, Value);
+ }
+ FilterAfterMmIoWrite (FilterWidth64, Address, &Value);
+
return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c
index 313a38e3d80..e7502822290 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c
@@ -10,7 +10,7 @@
We don't advocate putting compiler specifics in libraries or drivers but there
is no other way to make this work.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -39,8 +39,14 @@ IoRead8 (
)
{
UINT8 Data;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeIoRead (FilterWidth8, Port, &Data);
+ if (Flag) {
+ __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port));
+ }
+ FilterAfterIoRead (FilterWidth8, Port, &Data);
- __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port));
return Data;
}
@@ -66,7 +72,14 @@ IoWrite8 (
IN UINT8 Value
)
{
- __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeIoWrite (FilterWidth8, Port, &Value);
+ if (Flag) {
+ __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+ }
+ FilterAfterIoWrite (FilterWidth8, Port, &Value);
+
return Value;;
}
@@ -92,9 +105,16 @@ IoRead16 (
)
{
UINT16 Data;
+ BOOLEAN Flag;
ASSERT ((Port & 1) == 0);
- __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port));
+
+ Flag = FilterBeforeIoRead (FilterWidth16, Port, &Data);
+ if (Flag) {
+ __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port));
+ }
+ FilterAfterIoRead (FilterWidth16, Port, &Data);
+
return Data;
}
@@ -121,8 +141,17 @@ IoWrite16 (
IN UINT16 Value
)
{
+
+ BOOLEAN Flag;
+
ASSERT ((Port & 1) == 0);
- __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+
+ Flag = FilterBeforeIoWrite (FilterWidth16, Port, &Value);
+ if (Flag) {
+ __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+ }
+ FilterAfterIoWrite (FilterWidth16, Port, &Value);
+
return Value;;
}
@@ -148,9 +177,16 @@ IoRead32 (
)
{
UINT32 Data;
+ BOOLEAN Flag;
ASSERT ((Port & 3) == 0);
- __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port));
+
+ Flag = FilterBeforeIoRead (FilterWidth32, Port, &Data);
+ if (Flag) {
+ __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port));
+ }
+ FilterAfterIoRead (FilterWidth32, Port, &Data);
+
return Data;
}
@@ -177,8 +213,16 @@ IoWrite32 (
IN UINT32 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Port & 3) == 0);
- __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+
+ Flag = FilterBeforeIoWrite (FilterWidth32, Port, &Value);
+ if (Flag) {
+ __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port));
+ }
+ FilterAfterIoWrite (FilterWidth32, Port, &Value);
+
return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c
index 01aa48edc4d..339711a7a03 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c
@@ -8,7 +8,7 @@
We don't advocate putting compiler specifics in libraries or drivers but there
is no other way to make this work.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -66,10 +66,16 @@ IoRead8 (
)
{
UINT8 Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeIoRead (FilterWidth8, Port, &Value);
+ if (Flag) {
+ _ReadWriteBarrier ();
+ Value = (UINT8)_inp ((UINT16)Port);
+ _ReadWriteBarrier ();
+ }
+ FilterAfterIoRead (FilterWidth8, Port, &Value);
- _ReadWriteBarrier ();
- Value = (UINT8)_inp ((UINT16)Port);
- _ReadWriteBarrier ();
return Value;
}
@@ -95,9 +101,16 @@ IoWrite8 (
IN UINT8 Value
)
{
- _ReadWriteBarrier ();
- (UINT8)_outp ((UINT16)Port, Value);
- _ReadWriteBarrier ();
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeIoWrite(FilterWidth8, Port, &Value);
+ if (Flag) {
+ _ReadWriteBarrier ();
+ (UINT8)_outp ((UINT16)Port, Value);
+ _ReadWriteBarrier ();
+ }
+ FilterAfterIoWrite (FilterWidth8, Port, &Value);
+
return Value;
}
@@ -123,11 +136,18 @@ IoRead16 (
)
{
UINT16 Value;
+ BOOLEAN Flag;
ASSERT ((Port & 1) == 0);
- _ReadWriteBarrier ();
- Value = _inpw ((UINT16)Port);
- _ReadWriteBarrier ();
+
+ Flag = FilterBeforeIoRead (FilterWidth16, Port, &Value);
+ if (Flag) {
+ _ReadWriteBarrier ();
+ Value = _inpw ((UINT16)Port);
+ _ReadWriteBarrier ();
+ }
+ FilterBeforeIoRead (FilterWidth16, Port, &Value);
+
return Value;
}
@@ -154,10 +174,18 @@ IoWrite16 (
IN UINT16 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Port & 1) == 0);
- _ReadWriteBarrier ();
- _outpw ((UINT16)Port, Value);
- _ReadWriteBarrier ();
+
+ Flag = FilterBeforeIoWrite(FilterWidth16, Port, &Value);
+ if (Flag) {
+ _ReadWriteBarrier ();
+ _outpw ((UINT16)Port, Value);
+ _ReadWriteBarrier ();
+ }
+ FilterAfterIoWrite (FilterWidth16, Port, &Value);
+
return Value;
}
@@ -183,11 +211,18 @@ IoRead32 (
)
{
UINT32 Value;
+ BOOLEAN Flag;
ASSERT ((Port & 3) == 0);
- _ReadWriteBarrier ();
- Value = _inpd ((UINT16)Port);
- _ReadWriteBarrier ();
+
+ Flag = FilterBeforeIoRead(FilterWidth32, Port, &Value);
+ if (Flag) {
+ _ReadWriteBarrier ();
+ Value = _inpd ((UINT16)Port);
+ _ReadWriteBarrier ();
+ }
+ FilterAfterIoRead (FilterWidth32, Port, &Value);
+
return Value;
}
@@ -214,9 +249,17 @@ IoWrite32 (
IN UINT32 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Port & 3) == 0);
- _ReadWriteBarrier ();
- _outpd ((UINT16)Port, Value);
- _ReadWriteBarrier ();
+
+ Flag = FilterBeforeIoWrite(FilterWidth32, Port, &Value);
+ if (Flag) {
+ _ReadWriteBarrier ();
+ _outpd ((UINT16)Port, Value);
+ _ReadWriteBarrier ();
+ }
+ FilterAfterIoWrite (FilterWidth32, Port, &Value);
+
return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c
index fd43d809de8..4ebb67deada 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseIoLibIntrinsic/IoLibNoIo.c
@@ -2,7 +2,7 @@
I/O library for non I/O read and write access (memory map I/O read and
write only) architecture, such as ARM and RISC-V processor.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -408,8 +408,14 @@ MmioRead8 (
)
{
UINT8 Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMmIoRead (FilterWidth8, Address, &Value);
+ if (Flag) {
+ Value = *(volatile UINT8*)Address;
+ }
+ FilterAfterMmIoRead (FilterWidth8, Address, &Value);
- Value = *(volatile UINT8*)Address;
return Value;
}
@@ -433,7 +439,14 @@ MmioWrite8 (
IN UINT8 Value
)
{
- *(volatile UINT8*)Address = Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMmIoWrite (FilterWidth8, Address, &Value);
+ if (Flag) {
+ *(volatile UINT8*)Address = Value;
+ }
+ FilterAfterMmIoWrite (FilterWidth8, Address, &Value);
+
return Value;
}
@@ -458,9 +471,16 @@ MmioRead16 (
)
{
UINT16 Value;
+ BOOLEAN Flag;
ASSERT ((Address & 1) == 0);
- Value = *(volatile UINT16*)Address;
+
+ Flag = FilterBeforeMmIoRead (FilterWidth16, Address, &Value);
+ if (Flag) {
+ Value = *(volatile UINT16*)Address;
+ }
+ FilterAfterMmIoRead (FilterWidth16, Address, &Value);
+
return Value;
}
@@ -484,8 +504,16 @@ MmioWrite16 (
IN UINT16 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 1) == 0);
- *(volatile UINT16*)Address = Value;
+
+ Flag = FilterBeforeMmIoWrite (FilterWidth16, Address, &Value);
+ if (Flag) {
+ *(volatile UINT16*)Address = Value;
+ }
+ FilterAfterMmIoWrite (FilterWidth16, Address, &Value);
+
return Value;
}
@@ -510,9 +538,16 @@ MmioRead32 (
)
{
UINT32 Value;
+ BOOLEAN Flag;
ASSERT ((Address & 3) == 0);
- Value = *(volatile UINT32*)Address;
+
+ Flag = FilterBeforeMmIoRead (FilterWidth32, Address, &Value);
+ if (Flag) {
+ Value = *(volatile UINT32*)Address;
+ }
+ FilterAfterMmIoRead (FilterWidth32, Address, &Value);
+
return Value;
}
@@ -536,8 +571,16 @@ MmioWrite32 (
IN UINT32 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 3) == 0);
+
+ Flag = FilterBeforeMmIoWrite (FilterWidth32, Address, &Value);
+ if (Flag) {
*(volatile UINT32*)Address = Value;
+ }
+ FilterAfterMmIoWrite (FilterWidth32, Address, &Value);
+
return Value;
}
@@ -562,9 +605,16 @@ MmioRead64 (
)
{
UINT64 Value;
+ BOOLEAN Flag;
ASSERT ((Address & 7) == 0);
- Value = *(volatile UINT64*)Address;
+
+ Flag = FilterBeforeMmIoRead (FilterWidth64, Address, &Value);
+ if (Flag) {
+ Value = *(volatile UINT64*)Address;
+ }
+ FilterAfterMmIoRead (FilterWidth64, Address, &Value);
+
return Value;
}
@@ -588,8 +638,16 @@ MmioWrite64 (
IN UINT64 Value
)
{
+ BOOLEAN Flag;
+
ASSERT ((Address & 7) == 0);
- *(volatile UINT64*)Address = Value;
+
+ Flag = FilterBeforeMmIoWrite (FilterWidth64, Address, &Value);
+ if (Flag) {
+ *(volatile UINT64*)Address = Value;
+ }
+ FilterAfterMmIoWrite (FilterWidth64, Address, &Value);
+
return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S
index ac70acf586f..6b52a77d54f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S
@@ -20,10 +20,10 @@ GCC_ASM_EXPORT(InternalLongJump)
REG_ONE (x16, 96) /*IP0*/
#define FPR_LAYOUT \
- REG_PAIR ( d8, d9, 112); \
- REG_PAIR (d10, d11, 128); \
- REG_PAIR (d12, d13, 144); \
- REG_PAIR (d14, d15, 160);
+ REG_PAIR ( d8, d9, 104); \
+ REG_PAIR (d10, d11, 120); \
+ REG_PAIR (d12, d13, 136); \
+ REG_PAIR (d14, d15, 152);
#/**
# Saves the current CPU context that can be restored with a call to LongJump() and returns 0.#
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm
index 84c8053fc4e..c7d616377d0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm
@@ -19,10 +19,10 @@
REG_ONE (x16, #96) /*IP0*/
#define FPR_LAYOUT \
- REG_PAIR ( d8, d9, #112); \
- REG_PAIR (d10, d11, #128); \
- REG_PAIR (d12, d13, #144); \
- REG_PAIR (d14, d15, #160);
+ REG_PAIR ( d8, d9, #104); \
+ REG_PAIR (d10, d11, #120); \
+ REG_PAIR (d12, d13, #136); \
+ REG_PAIR (d14, d15, #152);
;/**
; Saves the current CPU context that can be restored with a call to LongJump() and returns 0.#
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/BaseLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/BaseLib.inf
index 8a14c2d5494..28fc47fe67e 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/BaseLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/BaseLib.inf
@@ -1,7 +1,7 @@
## @file
# Base Library implementation.
#
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
@@ -156,6 +156,7 @@
Ia32/GccInline.c | GCC
+ Ia32/GccInlinePriv.c | GCC
Ia32/Thunk16.nasm
Ia32/EnableDisableInterrupts.nasm| GCC
Ia32/EnablePaging64.nasm
@@ -182,6 +183,9 @@
Ia32/EnableCache.nasm| GCC
Ia32/DisableCache.nasm| GCC
Ia32/RdRand.nasm
+ Ia32/XGetBv.nasm
+ Ia32/XSetBv.nasm
+ Ia32/VmgExit.nasm
Ia32/DivS64x64Remainder.c
Ia32/InternalSwitchStack.c | MSFT
@@ -323,9 +327,13 @@
X86PatchInstruction.c
X86SpeculationBarrier.c
X64/GccInline.c | GCC
+ X64/GccInlinePriv.c | GCC
X64/EnableDisableInterrupts.nasm
X64/DisablePaging64.nasm
X64/RdRand.nasm
+ X64/XGetBv.nasm
+ X64/XSetBv.nasm
+ X64/VmgExit.nasm
ChkStkGcc.c | GCC
[Sources.EBC]
@@ -418,6 +426,9 @@
DebugLib
BaseMemoryLib
+[LibraryClasses.X64, LibraryClasses.IA32]
+ RegisterFilterLib
+
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength ## SOMETIMES_CONSUMES
gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/CpuDeadLoop.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/CpuDeadLoop.c
index 5df4fa0f098..419fa173256 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/CpuDeadLoop.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/CpuDeadLoop.c
@@ -28,5 +28,7 @@ CpuDeadLoop (
{
volatile UINTN Index;
- for (Index = 0; Index == 0;);
+ for (Index = 0; Index == 0;) {
+ CpuPause();
+ }
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/FilePaths.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/FilePaths.c
index 8f02ee8d6ca..77b3fc32abb 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/FilePaths.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/FilePaths.c
@@ -57,7 +57,7 @@ PathRemoveLastItem(
@param[in] Path The pointer to the string containing the path.
- @return Returns Path, otherwise returns NULL to indicate that an error has occured.
+ @return Returns Path, otherwise returns NULL to indicate that an error has occurred.
**/
CHAR16*
EFIAPI
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInline.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInline.c
index 6227c64ca8f..5bf3e42c09f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInline.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInline.c
@@ -1,7 +1,7 @@
/** @file
GCC inline implementation of BaseLib processor specific functions.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,8 +10,6 @@
#include "BaseLibInternals.h"
-
-
/**
Used to serialize load and store operations.
@@ -31,41 +29,6 @@ MemoryFence (
__asm__ __volatile__ ("":::"memory");
}
-
-/**
- Enables CPU interrupts.
-
- Enables CPU interrupts.
-
-**/
-VOID
-EFIAPI
-EnableInterrupts (
- VOID
- )
-{
- __asm__ __volatile__ ("sti"::: "memory");
-}
-
-
-/**
- Disables CPU interrupts.
-
- Disables CPU interrupts.
-
-**/
-VOID
-EFIAPI
-DisableInterrupts (
- VOID
- )
-{
- __asm__ __volatile__ ("cli"::: "memory");
-}
-
-
-
-
/**
Requests CPU to pause for a short period of time.
@@ -82,7 +45,6 @@ CpuPause (
__asm__ __volatile__ ("pause");
}
-
/**
Generates a breakpoint on the CPU.
@@ -99,75 +61,6 @@ CpuBreakpoint (
__asm__ __volatile__ ("int $3");
}
-
-
-/**
- Returns a 64-bit Machine Specific Register(MSR).
-
- Reads and returns the 64-bit MSR specified by Index. No parameter checking is
- performed on Index, and some Index values may cause CPU exceptions. The
- caller must either guarantee that Index is valid, or the caller must set up
- exception handlers to catch the exceptions. This function is only available
- on IA-32 and X64.
-
- @param Index The 32-bit MSR index to read.
-
- @return The value of the MSR identified by Index.
-
-**/
-UINT64
-EFIAPI
-AsmReadMsr64 (
- IN UINT32 Index
- )
-{
- UINT64 Data;
-
- __asm__ __volatile__ (
- "rdmsr"
- : "=A" (Data) // %0
- : "c" (Index) // %1
- );
-
- return Data;
-}
-
-/**
- Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
- value.
-
- Writes the 64-bit value specified by Value to the MSR specified by Index. The
- 64-bit value written to the MSR is returned. No parameter checking is
- performed on Index or Value, and some of these may cause CPU exceptions. The
- caller must either guarantee that Index and Value are valid, or the caller
- must establish proper exception handlers. This function is only available on
- IA-32 and X64.
-
- @param Index The 32-bit MSR index to write.
- @param Value The 64-bit value to write to the MSR.
-
- @return Value
-
-**/
-UINT64
-EFIAPI
-AsmWriteMsr64 (
- IN UINT32 Index,
- IN UINT64 Value
- )
-{
- __asm__ __volatile__ (
- "wrmsr"
- :
- : "c" (Index),
- "A" (Value)
- );
-
- return Value;
-}
-
-
-
/**
Reads the current value of the EFLAGS register.
@@ -195,965 +88,6 @@ AsmReadEflags (
return Eflags;
}
-
-
-/**
- Reads the current value of the Control Register 0 (CR0).
-
- Reads and returns the current value of CR0. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 0 (CR0).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr0 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%cr0,%0"
- : "=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of the Control Register 2 (CR2).
-
- Reads and returns the current value of CR2. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 2 (CR2).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr2 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%cr2, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-/**
- Reads the current value of the Control Register 3 (CR3).
-
- Reads and returns the current value of CR3. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 3 (CR3).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr3 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%cr3, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of the Control Register 4 (CR4).
-
- Reads and returns the current value of CR4. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 4 (CR4).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr4 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%cr4, %0"
- : "=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Writes a value to Control Register 0 (CR0).
-
- Writes and returns a new value to CR0. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr0 The value to write to CR0.
-
- @return The value written to CR0.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr0 (
- UINTN Cr0
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%cr0"
- :
- : "r" (Cr0)
- );
- return Cr0;
-}
-
-
-/**
- Writes a value to Control Register 2 (CR2).
-
- Writes and returns a new value to CR2. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr2 The value to write to CR2.
-
- @return The value written to CR2.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr2 (
- UINTN Cr2
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%cr2"
- :
- : "r" (Cr2)
- );
- return Cr2;
-}
-
-
-/**
- Writes a value to Control Register 3 (CR3).
-
- Writes and returns a new value to CR3. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr3 The value to write to CR3.
-
- @return The value written to CR3.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr3 (
- UINTN Cr3
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%cr3"
- :
- : "r" (Cr3)
- );
- return Cr3;
-}
-
-
-/**
- Writes a value to Control Register 4 (CR4).
-
- Writes and returns a new value to CR4. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr4 The value to write to CR4.
-
- @return The value written to CR4.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr4 (
- UINTN Cr4
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%cr4"
- :
- : "r" (Cr4)
- );
- return Cr4;
-}
-
-
-/**
- Reads the current value of Debug Register 0 (DR0).
-
- Reads and returns the current value of DR0. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 0 (DR0).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr0 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr0, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 1 (DR1).
-
- Reads and returns the current value of DR1. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 1 (DR1).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr1 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr1, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 2 (DR2).
-
- Reads and returns the current value of DR2. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 2 (DR2).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr2 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr2, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 3 (DR3).
-
- Reads and returns the current value of DR3. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 3 (DR3).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr3 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr3, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 4 (DR4).
-
- Reads and returns the current value of DR4. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 4 (DR4).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr4 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr4, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 5 (DR5).
-
- Reads and returns the current value of DR5. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 5 (DR5).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr5 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr5, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 6 (DR6).
-
- Reads and returns the current value of DR6. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 6 (DR6).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr6 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr6, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 7 (DR7).
-
- Reads and returns the current value of DR7. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 7 (DR7).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr7 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "movl %%dr7, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Writes a value to Debug Register 0 (DR0).
-
- Writes and returns a new value to DR0. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr0 The value to write to Dr0.
-
- @return The value written to Debug Register 0 (DR0).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr0 (
- UINTN Dr0
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr0"
- :
- : "r" (Dr0)
- );
- return Dr0;
-}
-
-
-/**
- Writes a value to Debug Register 1 (DR1).
-
- Writes and returns a new value to DR1. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr1 The value to write to Dr1.
-
- @return The value written to Debug Register 1 (DR1).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr1 (
- UINTN Dr1
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr1"
- :
- : "r" (Dr1)
- );
- return Dr1;
-}
-
-
-/**
- Writes a value to Debug Register 2 (DR2).
-
- Writes and returns a new value to DR2. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr2 The value to write to Dr2.
-
- @return The value written to Debug Register 2 (DR2).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr2 (
- UINTN Dr2
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr2"
- :
- : "r" (Dr2)
- );
- return Dr2;
-}
-
-
-/**
- Writes a value to Debug Register 3 (DR3).
-
- Writes and returns a new value to DR3. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr3 The value to write to Dr3.
-
- @return The value written to Debug Register 3 (DR3).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr3 (
- UINTN Dr3
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr3"
- :
- : "r" (Dr3)
- );
- return Dr3;
-}
-
-
-/**
- Writes a value to Debug Register 4 (DR4).
-
- Writes and returns a new value to DR4. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr4 The value to write to Dr4.
-
- @return The value written to Debug Register 4 (DR4).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr4 (
- UINTN Dr4
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr4"
- :
- : "r" (Dr4)
- );
- return Dr4;
-}
-
-
-/**
- Writes a value to Debug Register 5 (DR5).
-
- Writes and returns a new value to DR5. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr5 The value to write to Dr5.
-
- @return The value written to Debug Register 5 (DR5).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr5 (
- UINTN Dr5
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr5"
- :
- : "r" (Dr5)
- );
- return Dr5;
-}
-
-
-/**
- Writes a value to Debug Register 6 (DR6).
-
- Writes and returns a new value to DR6. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr6 The value to write to Dr6.
-
- @return The value written to Debug Register 6 (DR6).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr6 (
- UINTN Dr6
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr6"
- :
- : "r" (Dr6)
- );
- return Dr6;
-}
-
-
-/**
- Writes a value to Debug Register 7 (DR7).
-
- Writes and returns a new value to DR7. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr7 The value to write to Dr7.
-
- @return The value written to Debug Register 7 (DR7).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr7 (
- UINTN Dr7
- )
-{
- __asm__ __volatile__ (
- "movl %0, %%dr7"
- :
- : "r" (Dr7)
- );
- return Dr7;
-}
-
-
-/**
- Reads the current value of Code Segment Register (CS).
-
- Reads and returns the current value of CS. This function is only available on
- IA-32 and X64.
-
- @return The current value of CS.
-
-**/
-UINT16
-EFIAPI
-AsmReadCs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%cs, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Data Segment Register (DS).
-
- Reads and returns the current value of DS. This function is only available on
- IA-32 and X64.
-
- @return The current value of DS.
-
-**/
-UINT16
-EFIAPI
-AsmReadDs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%ds, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Extra Segment Register (ES).
-
- Reads and returns the current value of ES. This function is only available on
- IA-32 and X64.
-
- @return The current value of ES.
-
-**/
-UINT16
-EFIAPI
-AsmReadEs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%es, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of FS Data Segment Register (FS).
-
- Reads and returns the current value of FS. This function is only available on
- IA-32 and X64.
-
- @return The current value of FS.
-
-**/
-UINT16
-EFIAPI
-AsmReadFs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%fs, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of GS Data Segment Register (GS).
-
- Reads and returns the current value of GS. This function is only available on
- IA-32 and X64.
-
- @return The current value of GS.
-
-**/
-UINT16
-EFIAPI
-AsmReadGs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%gs, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Stack Segment Register (SS).
-
- Reads and returns the current value of SS. This function is only available on
- IA-32 and X64.
-
- @return The current value of SS.
-
-**/
-UINT16
-EFIAPI
-AsmReadSs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%ds, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Task Register (TR).
-
- Reads and returns the current value of TR. This function is only available on
- IA-32 and X64.
-
- @return The current value of TR.
-
-**/
-UINT16
-EFIAPI
-AsmReadTr (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "str %0"
- : "=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current Global Descriptor Table Register(GDTR) descriptor.
-
- Reads and returns the current GDTR descriptor and returns it in Gdtr. This
- function is only available on IA-32 and X64.
-
- @param Gdtr The pointer to a GDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86ReadGdtr (
- OUT IA32_DESCRIPTOR *Gdtr
- )
-{
- __asm__ __volatile__ (
- "sgdt %0"
- : "=m" (*Gdtr)
- );
-}
-
-
-/**
- Writes the current Global Descriptor Table Register (GDTR) descriptor.
-
- Writes and the current GDTR descriptor specified by Gdtr. This function is
- only available on IA-32 and X64.
-
- @param Gdtr The pointer to a GDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86WriteGdtr (
- IN CONST IA32_DESCRIPTOR *Gdtr
- )
-{
- __asm__ __volatile__ (
- "lgdt %0"
- :
- : "m" (*Gdtr)
- );
-
-}
-
-
-/**
- Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
-
- Reads and returns the current IDTR descriptor and returns it in Idtr. This
- function is only available on IA-32 and X64.
-
- @param Idtr The pointer to a IDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86ReadIdtr (
- OUT IA32_DESCRIPTOR *Idtr
- )
-{
- __asm__ __volatile__ (
- "sidt %0"
- : "=m" (*Idtr)
- );
-}
-
-
-/**
- Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
-
- Writes the current IDTR descriptor and returns it in Idtr. This function is
- only available on IA-32 and X64.
-
- @param Idtr The pointer to a IDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86WriteIdtr (
- IN CONST IA32_DESCRIPTOR *Idtr
- )
-{
- __asm__ __volatile__ (
- "lidt %0"
- :
- : "m" (*Idtr)
- );
-}
-
-
-/**
- Reads the current Local Descriptor Table Register(LDTR) selector.
-
- Reads and returns the current 16-bit LDTR descriptor value. This function is
- only available on IA-32 and X64.
-
- @return The current selector of LDT.
-
-**/
-UINT16
-EFIAPI
-AsmReadLdtr (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "sldt %0"
- : "=g" (Data) // %0
- );
-
- return Data;
-}
-
-
-/**
- Writes the current Local Descriptor Table Register (GDTR) selector.
-
- Writes and the current LDTR descriptor specified by Ldtr. This function is
- only available on IA-32 and X64.
-
- @param Ldtr 16-bit LDTR selector value.
-
-**/
-VOID
-EFIAPI
-AsmWriteLdtr (
- IN UINT16 Ldtr
- )
-{
- __asm__ __volatile__ (
- "lldtw %0"
- :
- : "g" (Ldtr) // %0
- );
-}
-
-
/**
Save the current floating point/SSE/SSE2 context to a buffer.
@@ -1650,116 +584,3 @@ AsmReadTsc (
return Data;
}
-
-
-/**
- Reads the current value of a Performance Counter (PMC).
-
- Reads and returns the current value of performance counter specified by
- Index. This function is only available on IA-32 and X64.
-
- @param Index The 32-bit Performance Counter index to read.
-
- @return The value of the PMC specified by Index.
-
-**/
-UINT64
-EFIAPI
-AsmReadPmc (
- IN UINT32 Index
- )
-{
- UINT64 Data;
-
- __asm__ __volatile__ (
- "rdpmc"
- : "=A" (Data)
- : "c" (Index)
- );
-
- return Data;
-}
-
-
-
-
-/**
- Executes a WBINVD instruction.
-
- Executes a WBINVD instruction. This function is only available on IA-32 and
- X64.
-
-**/
-VOID
-EFIAPI
-AsmWbinvd (
- VOID
- )
-{
- __asm__ __volatile__ ("wbinvd":::"memory");
-}
-
-
-/**
- Executes a INVD instruction.
-
- Executes a INVD instruction. This function is only available on IA-32 and
- X64.
-
-**/
-VOID
-EFIAPI
-AsmInvd (
- VOID
- )
-{
- __asm__ __volatile__ ("invd":::"memory");
-
-}
-
-
-/**
- Flushes a cache line from all the instruction and data caches within the
- coherency domain of the CPU.
-
- Flushed the cache line specified by LinearAddress, and returns LinearAddress.
- This function is only available on IA-32 and X64.
-
- @param LinearAddress The address of the cache line to flush. If the CPU is
- in a physical addressing mode, then LinearAddress is a
- physical address. If the CPU is in a virtual
- addressing mode, then LinearAddress is a virtual
- address.
-
- @return LinearAddress
-**/
-VOID *
-EFIAPI
-AsmFlushCacheLine (
- IN VOID *LinearAddress
- )
-{
- UINT32 RegEdx;
-
- //
- // If the CPU does not support CLFLUSH instruction,
- // then promote flush range to flush entire cache.
- //
- AsmCpuid (0x01, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT19) == 0) {
- __asm__ __volatile__ ("wbinvd":::"memory");
- return LinearAddress;
- }
-
-
- __asm__ __volatile__ (
- "clflush (%0)"
- : "+a" (LinearAddress)
- :
- : "memory"
- );
-
- return LinearAddress;
-}
-
-
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c
new file mode 100644
index 00000000000..f5314bf0ad5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/GccInlinePriv.c
@@ -0,0 +1,1182 @@
+/** @file
+ GCC inline implementation of BaseLib processor specific functions that use
+ privlidged instructions.
+
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "BaseLibInternals.h"
+#include <Library/RegisterFilterLib.h>
+
+/**
+ Enables CPU interrupts.
+
+ Enables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+EnableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("sti"::: "memory");
+}
+
+
+/**
+ Disables CPU interrupts.
+
+ Disables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+DisableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("cli"::: "memory");
+}
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and X64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadMsr64 (
+ IN UINT32 Index
+ )
+{
+ UINT64 Data;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrRead (Index, &Data);
+ if (Flag) {
+ __asm__ __volatile__ (
+ "rdmsr"
+ : "=A" (Data) // %0
+ : "c" (Index) // %1
+ );
+ }
+ FilterAfterMsrRead (Index, &Data);
+
+ return Data;
+}
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and X64.
+
+ @param Index The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+AsmWriteMsr64 (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrWrite (Index, &Value);
+ if (Flag) {
+ __asm__ __volatile__ (
+ "wrmsr"
+ :
+ : "c" (Index),
+ "A" (Value)
+ );
+ }
+ FilterAfterMsrWrite (Index, &Value);
+
+ return Value;
+}
+
+/**
+ Reads the current value of the Control Register 0 (CR0).
+
+ Reads and returns the current value of CR0. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 0 (CR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr0 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr0,%0"
+ : "=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of the Control Register 2 (CR2).
+
+ Reads and returns the current value of CR2. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 2 (CR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr2 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr2, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+/**
+ Reads the current value of the Control Register 3 (CR3).
+
+ Reads and returns the current value of CR3. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 3 (CR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr3 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr3, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of the Control Register 4 (CR4).
+
+ Reads and returns the current value of CR4. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 4 (CR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr4 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%cr4, %0"
+ : "=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes a value to Control Register 0 (CR0).
+
+ Writes and returns a new value to CR0. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr0 The value to write to CR0.
+
+ @return The value written to CR0.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr0 (
+ UINTN Cr0
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr0"
+ :
+ : "r" (Cr0)
+ );
+ return Cr0;
+}
+
+
+/**
+ Writes a value to Control Register 2 (CR2).
+
+ Writes and returns a new value to CR2. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr2 The value to write to CR2.
+
+ @return The value written to CR2.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr2 (
+ UINTN Cr2
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr2"
+ :
+ : "r" (Cr2)
+ );
+ return Cr2;
+}
+
+
+/**
+ Writes a value to Control Register 3 (CR3).
+
+ Writes and returns a new value to CR3. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr3 The value to write to CR3.
+
+ @return The value written to CR3.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr3 (
+ UINTN Cr3
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr3"
+ :
+ : "r" (Cr3)
+ );
+ return Cr3;
+}
+
+
+/**
+ Writes a value to Control Register 4 (CR4).
+
+ Writes and returns a new value to CR4. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr4 The value to write to CR4.
+
+ @return The value written to CR4.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr4 (
+ UINTN Cr4
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%cr4"
+ :
+ : "r" (Cr4)
+ );
+ return Cr4;
+}
+
+
+/**
+ Reads the current value of Debug Register 0 (DR0).
+
+ Reads and returns the current value of DR0. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr0 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr0, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 1 (DR1).
+
+ Reads and returns the current value of DR1. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr1 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr1, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 2 (DR2).
+
+ Reads and returns the current value of DR2. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr2 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr2, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 3 (DR3).
+
+ Reads and returns the current value of DR3. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr3 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr3, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 4 (DR4).
+
+ Reads and returns the current value of DR4. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr4 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr4, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 5 (DR5).
+
+ Reads and returns the current value of DR5. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr5 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr5, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 6 (DR6).
+
+ Reads and returns the current value of DR6. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr6 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr6, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 7 (DR7).
+
+ Reads and returns the current value of DR7. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr7 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "movl %%dr7, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes a value to Debug Register 0 (DR0).
+
+ Writes and returns a new value to DR0. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr0 The value to write to Dr0.
+
+ @return The value written to Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr0 (
+ UINTN Dr0
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr0"
+ :
+ : "r" (Dr0)
+ );
+ return Dr0;
+}
+
+
+/**
+ Writes a value to Debug Register 1 (DR1).
+
+ Writes and returns a new value to DR1. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr1 The value to write to Dr1.
+
+ @return The value written to Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr1 (
+ UINTN Dr1
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr1"
+ :
+ : "r" (Dr1)
+ );
+ return Dr1;
+}
+
+
+/**
+ Writes a value to Debug Register 2 (DR2).
+
+ Writes and returns a new value to DR2. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr2 The value to write to Dr2.
+
+ @return The value written to Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr2 (
+ UINTN Dr2
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr2"
+ :
+ : "r" (Dr2)
+ );
+ return Dr2;
+}
+
+
+/**
+ Writes a value to Debug Register 3 (DR3).
+
+ Writes and returns a new value to DR3. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr3 The value to write to Dr3.
+
+ @return The value written to Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr3 (
+ UINTN Dr3
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr3"
+ :
+ : "r" (Dr3)
+ );
+ return Dr3;
+}
+
+
+/**
+ Writes a value to Debug Register 4 (DR4).
+
+ Writes and returns a new value to DR4. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr4 The value to write to Dr4.
+
+ @return The value written to Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr4 (
+ UINTN Dr4
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr4"
+ :
+ : "r" (Dr4)
+ );
+ return Dr4;
+}
+
+
+/**
+ Writes a value to Debug Register 5 (DR5).
+
+ Writes and returns a new value to DR5. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr5 The value to write to Dr5.
+
+ @return The value written to Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr5 (
+ UINTN Dr5
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr5"
+ :
+ : "r" (Dr5)
+ );
+ return Dr5;
+}
+
+
+/**
+ Writes a value to Debug Register 6 (DR6).
+
+ Writes and returns a new value to DR6. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr6 The value to write to Dr6.
+
+ @return The value written to Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr6 (
+ UINTN Dr6
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr6"
+ :
+ : "r" (Dr6)
+ );
+ return Dr6;
+}
+
+
+/**
+ Writes a value to Debug Register 7 (DR7).
+
+ Writes and returns a new value to DR7. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr7 The value to write to Dr7.
+
+ @return The value written to Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr7 (
+ UINTN Dr7
+ )
+{
+ __asm__ __volatile__ (
+ "movl %0, %%dr7"
+ :
+ : "r" (Dr7)
+ );
+ return Dr7;
+}
+
+
+/**
+ Reads the current value of Code Segment Register (CS).
+
+ Reads and returns the current value of CS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of CS.
+
+**/
+UINT16
+EFIAPI
+AsmReadCs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%cs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Data Segment Register (DS).
+
+ Reads and returns the current value of DS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of DS.
+
+**/
+UINT16
+EFIAPI
+AsmReadDs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%ds, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Extra Segment Register (ES).
+
+ Reads and returns the current value of ES. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of ES.
+
+**/
+UINT16
+EFIAPI
+AsmReadEs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%es, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of FS Data Segment Register (FS).
+
+ Reads and returns the current value of FS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of FS.
+
+**/
+UINT16
+EFIAPI
+AsmReadFs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%fs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of GS Data Segment Register (GS).
+
+ Reads and returns the current value of GS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of GS.
+
+**/
+UINT16
+EFIAPI
+AsmReadGs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%gs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Stack Segment Register (SS).
+
+ Reads and returns the current value of SS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of SS.
+
+**/
+UINT16
+EFIAPI
+AsmReadSs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%ds, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Task Register (TR).
+
+ Reads and returns the current value of TR. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of TR.
+
+**/
+UINT16
+EFIAPI
+AsmReadTr (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "str %0"
+ : "=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current Global Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current GDTR descriptor and returns it in Gdtr. This
+ function is only available on IA-32 and X64.
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86ReadGdtr (
+ OUT IA32_DESCRIPTOR *Gdtr
+ )
+{
+ __asm__ __volatile__ (
+ "sgdt %0"
+ : "=m" (*Gdtr)
+ );
+}
+
+
+/**
+ Writes the current Global Descriptor Table Register (GDTR) descriptor.
+
+ Writes and the current GDTR descriptor specified by Gdtr. This function is
+ only available on IA-32 and X64.
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86WriteGdtr (
+ IN CONST IA32_DESCRIPTOR *Gdtr
+ )
+{
+ __asm__ __volatile__ (
+ "lgdt %0"
+ :
+ : "m" (*Gdtr)
+ );
+
+}
+
+
+/**
+ Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current IDTR descriptor and returns it in Idtr. This
+ function is only available on IA-32 and X64.
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86ReadIdtr (
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "sidt %0"
+ : "=m" (*Idtr)
+ );
+}
+
+
+/**
+ Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
+
+ Writes the current IDTR descriptor and returns it in Idtr. This function is
+ only available on IA-32 and X64.
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86WriteIdtr (
+ IN CONST IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "lidt %0"
+ :
+ : "m" (*Idtr)
+ );
+}
+
+
+/**
+ Reads the current Local Descriptor Table Register(LDTR) selector.
+
+ Reads and returns the current 16-bit LDTR descriptor value. This function is
+ only available on IA-32 and X64.
+
+ @return The current selector of LDT.
+
+**/
+UINT16
+EFIAPI
+AsmReadLdtr (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "sldt %0"
+ : "=g" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes the current Local Descriptor Table Register (GDTR) selector.
+
+ Writes and the current LDTR descriptor specified by Ldtr. This function is
+ only available on IA-32 and X64.
+
+ @param Ldtr 16-bit LDTR selector value.
+
+**/
+VOID
+EFIAPI
+AsmWriteLdtr (
+ IN UINT16 Ldtr
+ )
+{
+ __asm__ __volatile__ (
+ "lldtw %0"
+ :
+ : "g" (Ldtr) // %0
+ );
+}
+
+/**
+ Reads the current value of a Performance Counter (PMC).
+
+ Reads and returns the current value of performance counter specified by
+ Index. This function is only available on IA-32 and X64.
+
+ @param Index The 32-bit Performance Counter index to read.
+
+ @return The value of the PMC specified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadPmc (
+ IN UINT32 Index
+ )
+{
+ UINT64 Data;
+
+ __asm__ __volatile__ (
+ "rdpmc"
+ : "=A" (Data)
+ : "c" (Index)
+ );
+
+ return Data;
+}
+
+/**
+ Executes a WBINVD instruction.
+
+ Executes a WBINVD instruction. This function is only available on IA-32 and
+ X64.
+
+**/
+VOID
+EFIAPI
+AsmWbinvd (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("wbinvd":::"memory");
+}
+
+/**
+ Executes a INVD instruction.
+
+ Executes a INVD instruction. This function is only available on IA-32 and
+ X64.
+
+**/
+VOID
+EFIAPI
+AsmInvd (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("invd":::"memory");
+
+}
+
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and X64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress
+**/
+VOID *
+EFIAPI
+AsmFlushCacheLine (
+ IN VOID *LinearAddress
+ )
+{
+ UINT32 RegEdx;
+
+ //
+ // If the CPU does not support CLFLUSH instruction,
+ // then promote flush range to flush entire cache.
+ //
+ AsmCpuid (0x01, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT19) == 0) {
+ __asm__ __volatile__ ("wbinvd":::"memory");
+ return LinearAddress;
+ }
+
+
+ __asm__ __volatile__ (
+ "clflush (%0)"
+ : "+a" (LinearAddress)
+ :
+ : "memory"
+ );
+
+ return LinearAddress;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c
index e64db921793..f3f6b0f3a48 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/ReadMsr64.c
@@ -1,13 +1,13 @@
/** @file
AsmReadMsr64 function
- Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-
+#include <Library/RegisterFilterLib.h>
/**
Returns a 64-bit Machine Specific Register(MSR).
@@ -24,8 +24,7 @@
**/
UINT64
-EFIAPI
-AsmReadMsr64 (
+AsmReadMsr64Internal (
IN UINT32 Index
)
{
@@ -35,3 +34,34 @@ AsmReadMsr64 (
}
}
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and x64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadMsr64 (
+ IN UINT32 Index
+ )
+{
+ UINT64 Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrRead (Index, &Value);
+ if (Flag) {
+ Value = AsmReadMsr64Internal (Index);
+ }
+ FilterAfterMsrRead (Index, &Value);
+
+ return Value;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm
new file mode 100644
index 00000000000..c02d7a98aec
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/VmgExit.nasm
@@ -0,0 +1,38 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; VmgExit.Asm
+;
+; Abstract:
+;
+; AsmVmgExit function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmVmgExit (
+; VOID
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmVmgExit)
+ASM_PFX(AsmVmgExit):
+;
+; NASM doesn't support the vmmcall instruction in 32-bit mode and NASM versions
+; before 2.12 cannot translate the 64-bit "rep vmmcall" instruction into elf32
+; format. Given that VMGEXIT does not make sense on IA32, provide a stub
+; implementation that is identical to CpuBreakpoint(). In practice, AsmVmgExit()
+; should never be called on IA32.
+;
+ int 3
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c
index d045d3cde5e..c94a79c8815 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/WriteMsr64.c
@@ -1,13 +1,13 @@
/** @file
AsmWriteMsr64 function
- Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-
+#include <Library/RegisterFilterLib.h>
/**
Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
@@ -33,11 +33,19 @@ AsmWriteMsr64 (
IN UINT64 Value
)
{
- _asm {
- mov edx, dword ptr [Value + 4]
- mov eax, dword ptr [Value + 0]
- mov ecx, Index
- wrmsr
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrWrite (Index, &Value);
+ if (Flag) {
+ _asm {
+ mov edx, dword ptr [Value + 4]
+ mov eax, dword ptr [Value + 0]
+ mov ecx, Index
+ wrmsr
+ }
}
+ FilterAfterMsrWrite (Index, &Value);
+
+ return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm
new file mode 100644
index 00000000000..5a3d98a04b1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XGetBv.nasm
@@ -0,0 +1,31 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; XGetBv.Asm
+;
+; Abstract:
+;
+; AsmXgetBv function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmXGetBv (
+; IN UINT32 Index
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmXGetBv)
+ASM_PFX(AsmXGetBv):
+ mov ecx, [esp + 4]
+ xgetbv
+ ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XSetBv.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XSetBv.nasm
new file mode 100644
index 00000000000..32f8d7a51d0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/Ia32/XSetBv.nasm
@@ -0,0 +1,34 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; XSetBv.nasm
+;
+; Abstract:
+;
+; AsmXSetBv function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmXSetBv (
+; IN UINT32 Index,
+; IN UINT64 Value
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmXSetBv)
+ASM_PFX(AsmXSetBv):
+ mov edx, [esp + 12]
+ mov eax, [esp + 8]
+ mov ecx, [esp + 4]
+ xsetbv
+ ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S
index 025b3e3c1d5..a82384bc2ce 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/RiscV64/RiscVInterrupt.S
@@ -12,21 +12,52 @@ ASM_GLOBAL ASM_PFX(RiscVDisableSupervisorModeInterrupts)
ASM_GLOBAL ASM_PFX(RiscVEnableSupervisorModeInterrupt)
ASM_GLOBAL ASM_PFX(RiscVGetSupervisorModeInterrupts)
-# define MSTATUS_SIE 0x00000002
-# define CSR_SSTATUS 0x100
+#define SSTATUS_SIE 0x00000002
+#define CSR_SSTATUS 0x100
+ #define SSTATUS_SPP_BIT_POSITION 8
+//
+// This routine disables supervisor mode interrupt
+//
ASM_PFX(RiscVDisableSupervisorModeInterrupts):
- li a1, MSTATUS_SIE
- csrc CSR_SSTATUS, a1
+ add sp, sp, -(__SIZEOF_POINTER__)
+ sd a1, (sp)
+ li a1, SSTATUS_SIE
+ csrc CSR_SSTATUS, a1
+ ld a1, (sp)
+ add sp, sp, (__SIZEOF_POINTER__)
ret
+//
+// This routine enables supervisor mode interrupt
+//
ASM_PFX(RiscVEnableSupervisorModeInterrupt):
- li a1, MSTATUS_SIE
- csrs CSR_SSTATUS, a1
+ add sp, sp, -2*(__SIZEOF_POINTER__)
+ sd a0, (0*__SIZEOF_POINTER__)(sp)
+ sd a1, (1*__SIZEOF_POINTER__)(sp)
+
+ csrr a0, CSR_SSTATUS
+ and a0, a0, (1 << SSTATUS_SPP_BIT_POSITION)
+ bnez a0, InTrap // We are in supervisor mode (SMode)
+ // trap handler.
+ // Skip enabling SIE becasue SIE
+ // is set to disabled by RISC-V hart
+ // when the trap takes hart to SMode.
+
+ li a1, SSTATUS_SIE
+ csrs CSR_SSTATUS, a1
+InTrap:
+ ld a0, (0*__SIZEOF_POINTER__)(sp)
+ ld a1, (1*__SIZEOF_POINTER__)(sp)
+ add sp, sp, 2*(__SIZEOF_POINTER__)
ret
+//
+// This routine returns supervisor mode interrupt
+// status.
+//
ASM_PFX(RiscVGetSupervisorModeInterrupts):
csrr a0, CSR_SSTATUS
- andi a0, a0, MSTATUS_SIE
+ andi a0, a0, SSTATUS_SIE
ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/String.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/String.c
index a9ad94b9380..08c8d40c9aa 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/String.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/String.c
@@ -8,135 +8,6 @@
#include "BaseLibInternals.h"
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Copies one Null-terminated Unicode string to another Null-terminated Unicode
- string and returns the new Unicode string.
-
- This function copies the contents of the Unicode string Source to the Unicode
- string Destination, and returns Destination. If Source and Destination
- overlap, then the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- @param Destination A pointer to a Null-terminated Unicode string.
- @param Source A pointer to a Null-terminated Unicode string.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrCpy (
- OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source
- )
-{
- CHAR16 *ReturnValue;
-
- //
- // Destination cannot be NULL
- //
- ASSERT (Destination != NULL);
- ASSERT (((UINTN) Destination & BIT0) == 0);
-
- //
- // Destination and source cannot overlap
- //
- ASSERT ((UINTN)(Destination - Source) > StrLen (Source));
- ASSERT ((UINTN)(Source - Destination) > StrLen (Source));
-
- ReturnValue = Destination;
- while (*Source != 0) {
- *(Destination++) = *(Source++);
- }
- *Destination = 0;
- return ReturnValue;
-}
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Copies up to a specified length from one Null-terminated Unicode string to
- another Null-terminated Unicode string and returns the new Unicode string.
-
- This function copies the contents of the Unicode string Source to the Unicode
- string Destination, and returns Destination. At most, Length Unicode
- characters are copied from Source to Destination. If Length is 0, then
- Destination is returned unmodified. If Length is greater that the number of
- Unicode characters in Source, then Destination is padded with Null Unicode
- characters. If Source and Destination overlap, then the results are
- undefined.
-
- If Length > 0 and Destination is NULL, then ASSERT().
- If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Length > 0 and Source is NULL, then ASSERT().
- If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
- PcdMaximumUnicodeStringLength, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator,
- then ASSERT().
-
- @param Destination A pointer to a Null-terminated Unicode string.
- @param Source A pointer to a Null-terminated Unicode string.
- @param Length The maximum number of Unicode characters to copy.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrnCpy (
- OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source,
- IN UINTN Length
- )
-{
- CHAR16 *ReturnValue;
-
- if (Length == 0) {
- return Destination;
- }
-
- //
- // Destination cannot be NULL if Length is not zero
- //
- ASSERT (Destination != NULL);
- ASSERT (((UINTN) Destination & BIT0) == 0);
-
- //
- // Destination and source cannot overlap
- //
- ASSERT ((UINTN)(Destination - Source) > StrLen (Source));
- ASSERT ((UINTN)(Source - Destination) >= Length);
-
- if (PcdGet32 (PcdMaximumUnicodeStringLength) != 0) {
- ASSERT (Length <= PcdGet32 (PcdMaximumUnicodeStringLength));
- }
-
- ReturnValue = Destination;
-
- while ((*Source != L'\0') && (Length > 0)) {
- *(Destination++) = *(Source++);
- Length--;
- }
-
- ZeroMem (Destination, Length * sizeof (*Destination));
- return ReturnValue;
-}
-#endif
/**
Returns the length of a Null-terminated Unicode string.
@@ -320,121 +191,6 @@ StrnCmp (
return *FirstString - *SecondString;
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Concatenates one Null-terminated Unicode string to another Null-terminated
- Unicode string, and returns the concatenated Unicode string.
-
- This function concatenates two Null-terminated Unicode strings. The contents
- of Null-terminated Unicode string Source are concatenated to the end of
- Null-terminated Unicode string Destination. The Null-terminated concatenated
- Unicode String is returned. If Source and Destination overlap, then the
- results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Destination contains more
- than PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination
- and Source results in a Unicode string with more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- @param Destination A pointer to a Null-terminated Unicode string.
- @param Source A pointer to a Null-terminated Unicode string.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrCat (
- IN OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source
- )
-{
- StrCpy (Destination + StrLen (Destination), Source);
-
- //
- // Size of the resulting string should never be zero.
- // PcdMaximumUnicodeStringLength is tested inside StrLen().
- //
- ASSERT (StrSize (Destination) != 0);
- return Destination;
-}
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Concatenates up to a specified length one Null-terminated Unicode to the end
- of another Null-terminated Unicode string, and returns the concatenated
- Unicode string.
-
- This function concatenates two Null-terminated Unicode strings. The contents
- of Null-terminated Unicode string Source are concatenated to the end of
- Null-terminated Unicode string Destination, and Destination is returned. At
- most, Length Unicode characters are concatenated from Source to the end of
- Destination, and Destination is always Null-terminated. If Length is 0, then
- Destination is returned unmodified. If Source and Destination overlap, then
- the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Length > 0 and Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Length > 0 and Source is NULL, then ASSERT().
- If Length > 0 and Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Length is greater than
- PcdMaximumUnicodeStringLength, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Destination contains more
- than PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination
- and Source results in a Unicode string with more than PcdMaximumUnicodeStringLength
- Unicode characters, not including the Null-terminator, then ASSERT().
-
- @param Destination A pointer to a Null-terminated Unicode string.
- @param Source A pointer to a Null-terminated Unicode string.
- @param Length The maximum number of Unicode characters to concatenate from
- Source.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-StrnCat (
- IN OUT CHAR16 *Destination,
- IN CONST CHAR16 *Source,
- IN UINTN Length
- )
-{
- UINTN DestinationLen;
-
- DestinationLen = StrLen (Destination);
- StrnCpy (Destination + DestinationLen, Source, Length);
- Destination[DestinationLen + Length] = L'\0';
-
- //
- // Size of the resulting string should never be zero.
- // PcdMaximumUnicodeStringLength is tested inside StrLen().
- //
- ASSERT (StrSize (Destination) != 0);
- return Destination;
-}
-#endif
/**
Returns the first occurrence of a Null-terminated Unicode sub-string
@@ -845,208 +601,6 @@ InternalAsciiIsHexaDecimalDigitCharacter (
(Char >= 'a' && Char <= 'f'));
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Convert a Null-terminated Unicode string to a Null-terminated
- ASCII string and returns the ASCII string.
-
- This function converts the content of the Unicode string Source
- to the ASCII string Destination by copying the lower 8 bits of
- each Unicode character. It returns Destination.
-
- The caller is responsible to make sure Destination points to a buffer with size
- equal or greater than ((StrLen (Source) + 1) * sizeof (CHAR8)) in bytes.
-
- If any Unicode characters in Source contain non-zero value in
- the upper 8 bits, then ASSERT().
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source is not aligned on a 16-bit boundary, then ASSERT().
- If Source and Destination overlap, then ASSERT().
-
- If PcdMaximumUnicodeStringLength is not zero, and Source contains
- more than PcdMaximumUnicodeStringLength Unicode characters, not including
- the Null-terminator, then ASSERT().
-
- If PcdMaximumAsciiStringLength is not zero, and Source contains more
- than PcdMaximumAsciiStringLength Unicode characters, not including the
- Null-terminator, then ASSERT().
-
- @param Source A pointer to a Null-terminated Unicode string.
- @param Destination A pointer to a Null-terminated ASCII string.
-
- @return Destination.
-
-**/
-CHAR8 *
-EFIAPI
-UnicodeStrToAsciiStr (
- IN CONST CHAR16 *Source,
- OUT CHAR8 *Destination
- )
-{
- CHAR8 *ReturnValue;
-
- ASSERT (Destination != NULL);
-
- //
- // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
- // Length tests are performed inside StrLen().
- //
- ASSERT (StrSize (Source) != 0);
-
- //
- // Source and Destination should not overlap
- //
- ASSERT ((UINTN) (Destination - (CHAR8 *) Source) >= StrSize (Source));
- ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));
-
-
- ReturnValue = Destination;
- while (*Source != '\0') {
- //
- // If any Unicode characters in Source contain
- // non-zero value in the upper 8 bits, then ASSERT().
- //
- ASSERT (*Source < 0x100);
- *(Destination++) = (CHAR8) *(Source++);
- }
-
- *Destination = '\0';
-
- //
- // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
- // Length tests are performed inside AsciiStrLen().
- //
- ASSERT (AsciiStrSize (ReturnValue) != 0);
-
- return ReturnValue;
-}
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Copies one Null-terminated ASCII string to another Null-terminated ASCII
- string and returns the new ASCII string.
-
- This function copies the contents of the ASCII string Source to the ASCII
- string Destination, and returns Destination. If Source and Destination
- overlap, then the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
-
- @param Destination A pointer to a Null-terminated ASCII string.
- @param Source A pointer to a Null-terminated ASCII string.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrCpy (
- OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source
- )
-{
- CHAR8 *ReturnValue;
-
- //
- // Destination cannot be NULL
- //
- ASSERT (Destination != NULL);
-
- //
- // Destination and source cannot overlap
- //
- ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));
- ASSERT ((UINTN)(Source - Destination) > AsciiStrLen (Source));
-
- ReturnValue = Destination;
- while (*Source != 0) {
- *(Destination++) = *(Source++);
- }
- *Destination = 0;
- return ReturnValue;
-}
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Copies up to a specified length one Null-terminated ASCII string to another
- Null-terminated ASCII string and returns the new ASCII string.
-
- This function copies the contents of the ASCII string Source to the ASCII
- string Destination, and returns Destination. At most, Length ASCII characters
- are copied from Source to Destination. If Length is 0, then Destination is
- returned unmodified. If Length is greater that the number of ASCII characters
- in Source, then Destination is padded with Null ASCII characters. If Source
- and Destination overlap, then the results are undefined.
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Length is greater than
- PcdMaximumAsciiStringLength, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
-
- @param Destination A pointer to a Null-terminated ASCII string.
- @param Source A pointer to a Null-terminated ASCII string.
- @param Length The maximum number of ASCII characters to copy.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrnCpy (
- OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source,
- IN UINTN Length
- )
-{
- CHAR8 *ReturnValue;
-
- if (Length == 0) {
- return Destination;
- }
-
- //
- // Destination cannot be NULL
- //
- ASSERT (Destination != NULL);
-
- //
- // Destination and source cannot overlap
- //
- ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source));
- ASSERT ((UINTN)(Source - Destination) >= Length);
-
- if (PcdGet32 (PcdMaximumAsciiStringLength) != 0) {
- ASSERT (Length <= PcdGet32 (PcdMaximumAsciiStringLength));
- }
-
- ReturnValue = Destination;
-
- while (*Source != 0 && Length > 0) {
- *(Destination++) = *(Source++);
- Length--;
- }
-
- ZeroMem (Destination, Length * sizeof (*Destination));
- return ReturnValue;
-}
-#endif
/**
Returns the length of a Null-terminated ASCII string.
@@ -1329,114 +883,6 @@ AsciiStrnCmp (
return *FirstString - *SecondString;
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Concatenates one Null-terminated ASCII string to another Null-terminated
- ASCII string, and returns the concatenated ASCII string.
-
- This function concatenates two Null-terminated ASCII strings. The contents of
- Null-terminated ASCII string Source are concatenated to the end of Null-
- terminated ASCII string Destination. The Null-terminated concatenated ASCII
- String is returned.
-
- If Destination is NULL, then ASSERT().
- If Source is NULL, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and Destination contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero and concatenating Destination and
- Source results in a ASCII string with more than PcdMaximumAsciiStringLength
- ASCII characters, then ASSERT().
-
- @param Destination A pointer to a Null-terminated ASCII string.
- @param Source A pointer to a Null-terminated ASCII string.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrCat (
- IN OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source
- )
-{
- AsciiStrCpy (Destination + AsciiStrLen (Destination), Source);
-
- //
- // Size of the resulting string should never be zero.
- // PcdMaximumUnicodeStringLength is tested inside StrLen().
- //
- ASSERT (AsciiStrSize (Destination) != 0);
- return Destination;
-}
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Concatenates up to a specified length one Null-terminated ASCII string to
- the end of another Null-terminated ASCII string, and returns the
- concatenated ASCII string.
-
- This function concatenates two Null-terminated ASCII strings. The contents
- of Null-terminated ASCII string Source are concatenated to the end of Null-
- terminated ASCII string Destination, and Destination is returned. At most,
- Length ASCII characters are concatenated from Source to the end of
- Destination, and Destination is always Null-terminated. If Length is 0, then
- Destination is returned unmodified. If Source and Destination overlap, then
- the results are undefined.
-
- If Length > 0 and Destination is NULL, then ASSERT().
- If Length > 0 and Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Length is greater than
- PcdMaximumAsciiStringLength, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Destination contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters, not including the Null-terminator,
- then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and
- Source results in a ASCII string with more than PcdMaximumAsciiStringLength
- ASCII characters, not including the Null-terminator, then ASSERT().
-
- @param Destination A pointer to a Null-terminated ASCII string.
- @param Source A pointer to a Null-terminated ASCII string.
- @param Length The maximum number of ASCII characters to concatenate from
- Source.
-
- @return Destination
-
-**/
-CHAR8 *
-EFIAPI
-AsciiStrnCat (
- IN OUT CHAR8 *Destination,
- IN CONST CHAR8 *Source,
- IN UINTN Length
- )
-{
- UINTN DestinationLen;
-
- DestinationLen = AsciiStrLen (Destination);
- AsciiStrnCpy (Destination + DestinationLen, Source, Length);
- Destination[DestinationLen + Length] = '\0';
-
- //
- // Size of the resulting string should never be zero.
- // PcdMaximumUnicodeStringLength is tested inside StrLen().
- //
- ASSERT (AsciiStrSize (Destination) != 0);
- return Destination;
-}
-#endif
/**
Returns the first occurrence of a Null-terminated ASCII sub-string
@@ -1684,78 +1130,6 @@ AsciiStrHexToUint64 (
return Result;
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Convert one Null-terminated ASCII string to a Null-terminated
- Unicode string and returns the Unicode string.
-
- This function converts the contents of the ASCII string Source to the Unicode
- string Destination, and returns Destination. The function terminates the
- Unicode string Destination by appending a Null-terminator character at the end.
- The caller is responsible to make sure Destination points to a buffer with size
- equal or greater than ((AsciiStrLen (Source) + 1) * sizeof (CHAR16)) in bytes.
-
- If Destination is NULL, then ASSERT().
- If Destination is not aligned on a 16-bit boundary, then ASSERT().
- If Source is NULL, then ASSERT().
- If Source and Destination overlap, then ASSERT().
- If PcdMaximumAsciiStringLength is not zero, and Source contains more than
- PcdMaximumAsciiStringLength ASCII characters not including the Null-terminator,
- then ASSERT().
- If PcdMaximumUnicodeStringLength is not zero, and Source contains more than
- PcdMaximumUnicodeStringLength ASCII characters not including the
- Null-terminator, then ASSERT().
-
- @param Source A pointer to a Null-terminated ASCII string.
- @param Destination A pointer to a Null-terminated Unicode string.
-
- @return Destination.
-
-**/
-CHAR16 *
-EFIAPI
-AsciiStrToUnicodeStr (
- IN CONST CHAR8 *Source,
- OUT CHAR16 *Destination
- )
-{
- CHAR16 *ReturnValue;
-
- ASSERT (Destination != NULL);
-
- //
- // ASSERT Source is less long than PcdMaximumAsciiStringLength
- //
- ASSERT (AsciiStrSize (Source) != 0);
-
- //
- // Source and Destination should not overlap
- //
- ASSERT ((UINTN) ((CHAR8 *) Destination - Source) > AsciiStrLen (Source));
- ASSERT ((UINTN) (Source - (CHAR8 *) Destination) >= (AsciiStrSize (Source) * sizeof (CHAR16)));
-
-
- ReturnValue = Destination;
- while (*Source != '\0') {
- *(Destination++) = (CHAR16)(UINT8) *(Source++);
- }
- //
- // End the Destination with a NULL.
- //
- *Destination = '\0';
-
- //
- // ASSERT Original Destination is less long than PcdMaximumUnicodeStringLength
- //
- ASSERT (StrSize (ReturnValue) != 0);
-
- return ReturnValue;
-}
-
-#endif
STATIC CHAR8 EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.c
new file mode 100644
index 00000000000..4827ff9a0f4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.c
@@ -0,0 +1,140 @@
+/** @file
+ Common Unit Test Host functions.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UnitTestHost.h"
+
+///
+/// Module global variable for simple system emulation of interrupt state
+///
+STATIC BOOLEAN mUnitTestHostBaseLibInterruptState;
+
+/**
+ Enables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibEnableInterrupts (
+ VOID
+ )
+{
+ mUnitTestHostBaseLibInterruptState = TRUE;
+}
+
+/**
+ Disables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibDisableInterrupts (
+ VOID
+ )
+{
+ mUnitTestHostBaseLibInterruptState = FALSE;
+}
+
+/**
+ Enables CPU interrupts for the smallest window required to capture any
+ pending interrupts.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibEnableDisableInterrupts (
+ VOID
+ )
+{
+ mUnitTestHostBaseLibInterruptState = FALSE;
+}
+
+/**
+ Set the current CPU interrupt state.
+
+ Sets the current CPU interrupt state to the state specified by
+ InterruptState. If InterruptState is TRUE, then interrupts are enabled. If
+ InterruptState is FALSE, then interrupts are disabled. InterruptState is
+ returned.
+
+ @param InterruptState TRUE if interrupts should enabled. FALSE if
+ interrupts should be disabled.
+
+ @return InterruptState
+
+**/
+BOOLEAN
+EFIAPI
+UnitTestHostBaseLibGetInterruptState (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibInterruptState;
+}
+
+/**
+ Enables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+EnableInterrupts (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.Common->EnableInterrupts ();
+}
+
+/**
+ Disables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+DisableInterrupts (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.Common->DisableInterrupts ();
+}
+
+/**
+ Enables CPU interrupts for the smallest window required to capture any
+ pending interrupts.
+
+**/
+VOID
+EFIAPI
+EnableDisableInterrupts (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.Common->EnableDisableInterrupts ();
+}
+
+/**
+ Set the current CPU interrupt state.
+
+ Sets the current CPU interrupt state to the state specified by
+ InterruptState. If InterruptState is TRUE, then interrupts are enabled. If
+ InterruptState is FALSE, then interrupts are disabled. InterruptState is
+ returned.
+
+ @param InterruptState TRUE if interrupts should enabled. FALSE if
+ interrupts should be disabled.
+
+ @return InterruptState
+
+**/
+BOOLEAN
+EFIAPI
+GetInterruptState (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.Common->GetInterruptState ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.h
new file mode 100644
index 00000000000..f7667e9402f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHost.h
@@ -0,0 +1,66 @@
+/** @file
+ Unit Test Host functions.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __UNIT_TEST_HOST_H__
+#define __UNIT_TEST_HOST_H__
+
+#include "BaseLibInternals.h"
+#include <Library/UnitTestHostBaseLib.h>
+
+/**
+ Enables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibEnableInterrupts (
+ VOID
+ );
+
+/**
+ Disables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibDisableInterrupts (
+ VOID
+ );
+
+/**
+ Enables CPU interrupts for the smallest window required to capture any
+ pending interrupts.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibEnableDisableInterrupts (
+ VOID
+ );
+
+/**
+ Set the current CPU interrupt state.
+
+ Sets the current CPU interrupt state to the state specified by
+ InterruptState. If InterruptState is TRUE, then interrupts are enabled. If
+ InterruptState is FALSE, then interrupts are disabled. InterruptState is
+ returned.
+
+ @param InterruptState TRUE if interrupts should enabled. FALSE if
+ interrupts should be disabled.
+
+ @return InterruptState
+
+**/
+BOOLEAN
+EFIAPI
+UnitTestHostBaseLibGetInterruptState (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
new file mode 100644
index 00000000000..90701fa1092
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
@@ -0,0 +1,251 @@
+## @file
+# Base Library implementation for use with host based unit tests.
+#
+# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UnitTestHostBaseLib
+ MODULE_UNI_FILE = UnitTestHostBaseLib.uni
+ FILE_GUID = 9555A0D3-09BA-46C4-A51A-45198E3C765E
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = BaseLib|HOST_APPLICATION
+ LIBRARY_CLASS = UnitTestHostBaseLib|HOST_APPLICATION
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64 RISCV64
+#
+
+[Sources]
+ CheckSum.c
+ SwitchStack.c
+ SwapBytes64.c
+ SwapBytes32.c
+ SwapBytes16.c
+ LongJump.c
+ SetJump.c
+ RShiftU64.c
+ RRotU64.c
+ RRotU32.c
+ MultU64x64.c
+ MultU64x32.c
+ MultS64x64.c
+ ModU64x32.c
+ LShiftU64.c
+ LRotU64.c
+ LRotU32.c
+ LowBitSet64.c
+ LowBitSet32.c
+ HighBitSet64.c
+ HighBitSet32.c
+ GetPowerOfTwo64.c
+ GetPowerOfTwo32.c
+ DivU64x64Remainder.c
+ DivU64x32Remainder.c
+ DivU64x32.c
+ DivS64x64Remainder.c
+ ARShiftU64.c
+ BitField.c
+ CpuDeadLoop.c
+ Cpu.c
+ LinkedList.c
+ SafeString.c
+ String.c
+ FilePaths.c
+ BaseLibInternals.h
+ UnitTestHost.c
+ UnitTestHost.h
+
+[Sources.Ia32]
+ Ia32/WriteMm7.c | MSFT
+ Ia32/WriteMm6.c | MSFT
+ Ia32/WriteMm5.c | MSFT
+ Ia32/WriteMm4.c | MSFT
+ Ia32/WriteMm3.c | MSFT
+ Ia32/WriteMm2.c | MSFT
+ Ia32/WriteMm1.c | MSFT
+ Ia32/WriteMm0.c | MSFT
+ Ia32/ReadMm7.c | MSFT
+ Ia32/ReadMm6.c | MSFT
+ Ia32/ReadMm5.c | MSFT
+ Ia32/ReadMm4.c | MSFT
+ Ia32/ReadMm3.c | MSFT
+ Ia32/ReadMm2.c | MSFT
+ Ia32/ReadMm1.c | MSFT
+ Ia32/ReadMm0.c | MSFT
+ Ia32/SwapBytes64.c | MSFT
+ Ia32/RRotU64.c | MSFT
+ Ia32/RShiftU64.c | MSFT
+ Ia32/ReadTsc.c | MSFT
+ Ia32/ReadEflags.c | MSFT
+ Ia32/ModU64x32.c | MSFT
+ Ia32/MultU64x64.c | MSFT
+ Ia32/MultU64x32.c | MSFT
+ Ia32/LShiftU64.c | MSFT
+ Ia32/LRotU64.c | MSFT
+ Ia32/FxRestore.c | MSFT
+ Ia32/FxSave.c | MSFT
+ Ia32/DivU64x32Remainder.c | MSFT
+ Ia32/DivU64x32.c | MSFT
+ Ia32/CpuPause.c | MSFT
+ Ia32/CpuBreakpoint.c | MSFT
+ Ia32/ARShiftU64.c | MSFT
+ Ia32/GccInline.c | GCC
+ Ia32/LongJump.nasm
+ Ia32/SetJump.nasm
+ Ia32/SwapBytes64.nasm| GCC
+ Ia32/DivU64x64Remainder.nasm
+ Ia32/DivU64x32Remainder.nasm| GCC
+ Ia32/ModU64x32.nasm| GCC
+ Ia32/DivU64x32.nasm| GCC
+ Ia32/MultU64x64.nasm| GCC
+ Ia32/MultU64x32.nasm| GCC
+ Ia32/RRotU64.nasm| GCC
+ Ia32/LRotU64.nasm| GCC
+ Ia32/ARShiftU64.nasm| GCC
+ Ia32/RShiftU64.nasm| GCC
+ Ia32/LShiftU64.nasm| GCC
+ Ia32/RdRand.nasm
+ Ia32/DivS64x64Remainder.c
+ Ia32/InternalSwitchStack.c | MSFT
+ Ia32/InternalSwitchStack.nasm | GCC
+ Ia32/Non-existing.c
+ Unaligned.c
+ X86MemoryFence.c | MSFT
+ X86FxSave.c
+ X86FxRestore.c
+ X86Msr.c
+ X86RdRand.c
+ X86SpeculationBarrier.c
+ X86UnitTestHost.c
+
+[Sources.X64]
+ X64/LongJump.nasm
+ X64/SetJump.nasm
+ X64/SwitchStack.nasm
+ X64/CpuBreakpoint.c | MSFT
+ X64/CpuPause.nasm| MSFT
+ X64/ReadTsc.nasm| MSFT
+ X64/WriteMm7.nasm| MSFT
+ X64/WriteMm6.nasm| MSFT
+ X64/WriteMm5.nasm| MSFT
+ X64/WriteMm4.nasm| MSFT
+ X64/WriteMm3.nasm| MSFT
+ X64/WriteMm2.nasm| MSFT
+ X64/WriteMm1.nasm| MSFT
+ X64/WriteMm0.nasm| MSFT
+ X64/ReadMm7.nasm| MSFT
+ X64/ReadMm6.nasm| MSFT
+ X64/ReadMm5.nasm| MSFT
+ X64/ReadMm4.nasm| MSFT
+ X64/ReadMm3.nasm| MSFT
+ X64/ReadMm2.nasm| MSFT
+ X64/ReadMm1.nasm| MSFT
+ X64/ReadMm0.nasm| MSFT
+ X64/FxRestore.nasm| MSFT
+ X64/FxSave.nasm| MSFT
+ X64/ReadEflags.nasm| MSFT
+ X64/Non-existing.c
+ Math64.c
+ Unaligned.c
+ X86MemoryFence.c | MSFT
+ X86FxSave.c
+ X86FxRestore.c
+ X86Msr.c
+ X86RdRand.c
+ X86SpeculationBarrier.c
+ X64/GccInline.c | GCC
+ X64/RdRand.nasm
+ ChkStkGcc.c | GCC
+ X86UnitTestHost.c
+
+[Sources.EBC]
+ Ebc/CpuBreakpoint.c
+ Ebc/SetJumpLongJump.c
+ Ebc/SwitchStack.c
+ Ebc/SpeculationBarrier.c
+ Unaligned.c
+ Math64.c
+
+[Sources.ARM]
+ Arm/InternalSwitchStack.c
+ Arm/Unaligned.c
+ Math64.c | RVCT
+ Math64.c | MSFT
+
+ Arm/SwitchStack.asm | RVCT
+ Arm/SetJumpLongJump.asm | RVCT
+ Arm/CpuPause.asm | RVCT
+ Arm/CpuBreakpoint.asm | RVCT
+ Arm/MemoryFence.asm | RVCT
+ Arm/SpeculationBarrier.S | RVCT
+
+ Arm/SwitchStack.asm | MSFT
+ Arm/SetJumpLongJump.asm | MSFT
+ Arm/CpuPause.asm | MSFT
+ Arm/CpuBreakpoint.asm | MSFT
+ Arm/MemoryFence.asm | MSFT
+ Arm/SpeculationBarrier.asm | MSFT
+
+ Arm/Math64.S | GCC
+ Arm/SwitchStack.S | GCC
+ Arm/SetJumpLongJump.S | GCC
+ Arm/CpuBreakpoint.S | GCC
+ Arm/MemoryFence.S | GCC
+ Arm/SpeculationBarrier.S | GCC
+
+[Sources.AARCH64]
+ Arm/InternalSwitchStack.c
+ Arm/Unaligned.c
+ Math64.c
+
+ AArch64/MemoryFence.S | GCC
+ AArch64/SwitchStack.S | GCC
+ AArch64/SetJumpLongJump.S | GCC
+ AArch64/CpuBreakpoint.S | GCC
+ AArch64/SpeculationBarrier.S | GCC
+
+ AArch64/MemoryFence.asm | MSFT
+ AArch64/SwitchStack.asm | MSFT
+ AArch64/SetJumpLongJump.asm | MSFT
+ AArch64/CpuBreakpoint.asm | MSFT
+ AArch64/SpeculationBarrier.asm | MSFT
+
+[Sources.RISCV64]
+ Math64.c
+ Unaligned.c
+ RiscV64/InternalSwitchStack.c
+ RiscV64/CpuBreakpoint.c
+ RiscV64/CpuPause.c
+ RiscV64/RiscVSetJumpLongJump.S | GCC
+ RiscV64/RiscVCpuBreakpoint.S | GCC
+ RiscV64/RiscVCpuPause.S | GCC
+ RiscV64/RiscVInterrupt.S | GCC
+ RiscV64/FlushCache.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ PcdLib
+ DebugLib
+ BaseMemoryLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength ## SOMETIMES_CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength ## SOMETIMES_CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength ## SOMETIMES_CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdControlFlowEnforcementPropertyMask ## SOMETIMES_CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdSpeculationBarrierType ## SOMETIMES_CONSUMES
+
+[FeaturePcd]
+ gEfiMdePkgTokenSpaceGuid.PcdVerifyNodeInList ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni
new file mode 100644
index 00000000000..e63ecef82c3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/UnitTestHostBaseLib.uni
@@ -0,0 +1,11 @@
+// /** @file
+// Base Library implementation for use with host based unit tests.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "Base Library implementation for use with host based unit tests."
+
+#string STR_MODULE_DESCRIPTION #language en-US "Base Library implementation for use with host based unit tests."
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInline.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInline.c
index 1fe474e78aa..69ec93cadba 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInline.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInline.c
@@ -1,7 +1,7 @@
/** @file
GCC inline implementation of BaseLib processor specific functions.
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -34,40 +34,6 @@ MemoryFence (
/**
- Enables CPU interrupts.
-
- Enables CPU interrupts.
-
-**/
-VOID
-EFIAPI
-EnableInterrupts (
- VOID
- )
-{
- __asm__ __volatile__ ("sti"::: "memory");
-}
-
-
-/**
- Disables CPU interrupts.
-
- Disables CPU interrupts.
-
-**/
-VOID
-EFIAPI
-DisableInterrupts (
- VOID
- )
-{
- __asm__ __volatile__ ("cli"::: "memory");
-}
-
-
-
-
-/**
Requests CPU to pause for a short period of time.
Requests CPU to pause for a short period of time. Typically used in MP
@@ -101,83 +67,6 @@ CpuBreakpoint (
}
-
-/**
- Returns a 64-bit Machine Specific Register(MSR).
-
- Reads and returns the 64-bit MSR specified by Index. No parameter checking is
- performed on Index, and some Index values may cause CPU exceptions. The
- caller must either guarantee that Index is valid, or the caller must set up
- exception handlers to catch the exceptions. This function is only available
- on IA-32 and X64.
-
- @param Index The 32-bit MSR index to read.
-
- @return The value of the MSR identified by Index.
-
-**/
-UINT64
-EFIAPI
-AsmReadMsr64 (
- IN UINT32 Index
- )
-{
- UINT32 LowData;
- UINT32 HighData;
-
- __asm__ __volatile__ (
- "rdmsr"
- : "=a" (LowData), // %0
- "=d" (HighData) // %1
- : "c" (Index) // %2
- );
-
- return (((UINT64)HighData) << 32) | LowData;
-}
-
-/**
- Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
- value.
-
- Writes the 64-bit value specified by Value to the MSR specified by Index. The
- 64-bit value written to the MSR is returned. No parameter checking is
- performed on Index or Value, and some of these may cause CPU exceptions. The
- caller must either guarantee that Index and Value are valid, or the caller
- must establish proper exception handlers. This function is only available on
- IA-32 and X64.
-
- @param Index The 32-bit MSR index to write.
- @param Value The 64-bit value to write to the MSR.
-
- @return Value
-
-**/
-UINT64
-EFIAPI
-AsmWriteMsr64 (
- IN UINT32 Index,
- IN UINT64 Value
- )
-{
- UINT32 LowData;
- UINT32 HighData;
-
- LowData = (UINT32)(Value);
- HighData = (UINT32)(Value >> 32);
-
- __asm__ __volatile__ (
- "wrmsr"
- :
- : "c" (Index),
- "a" (LowData),
- "d" (HighData)
- );
-
- return Value;
-}
-
-
-
/**
Reads the current value of the EFLAGS register.
@@ -205,965 +94,6 @@ AsmReadEflags (
return Eflags;
}
-
-
-/**
- Reads the current value of the Control Register 0 (CR0).
-
- Reads and returns the current value of CR0. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 0 (CR0).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr0 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%cr0,%0"
- : "=r" (Data) // %0
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of the Control Register 2 (CR2).
-
- Reads and returns the current value of CR2. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 2 (CR2).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr2 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%cr2, %0"
- : "=r" (Data) // %0
- );
-
- return Data;
-}
-
-/**
- Reads the current value of the Control Register 3 (CR3).
-
- Reads and returns the current value of CR3. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 3 (CR3).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr3 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%cr3, %0"
- : "=r" (Data) // %0
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of the Control Register 4 (CR4).
-
- Reads and returns the current value of CR4. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of the Control Register 4 (CR4).
-
-**/
-UINTN
-EFIAPI
-AsmReadCr4 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%cr4, %0"
- : "=r" (Data) // %0
- );
-
- return Data;
-}
-
-
-/**
- Writes a value to Control Register 0 (CR0).
-
- Writes and returns a new value to CR0. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr0 The value to write to CR0.
-
- @return The value written to CR0.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr0 (
- UINTN Cr0
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%cr0"
- :
- : "r" (Cr0)
- );
- return Cr0;
-}
-
-
-/**
- Writes a value to Control Register 2 (CR2).
-
- Writes and returns a new value to CR2. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr2 The value to write to CR2.
-
- @return The value written to CR2.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr2 (
- UINTN Cr2
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%cr2"
- :
- : "r" (Cr2)
- );
- return Cr2;
-}
-
-
-/**
- Writes a value to Control Register 3 (CR3).
-
- Writes and returns a new value to CR3. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr3 The value to write to CR3.
-
- @return The value written to CR3.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr3 (
- UINTN Cr3
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%cr3"
- :
- : "r" (Cr3)
- );
- return Cr3;
-}
-
-
-/**
- Writes a value to Control Register 4 (CR4).
-
- Writes and returns a new value to CR4. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Cr4 The value to write to CR4.
-
- @return The value written to CR4.
-
-**/
-UINTN
-EFIAPI
-AsmWriteCr4 (
- UINTN Cr4
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%cr4"
- :
- : "r" (Cr4)
- );
- return Cr4;
-}
-
-
-/**
- Reads the current value of Debug Register 0 (DR0).
-
- Reads and returns the current value of DR0. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 0 (DR0).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr0 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr0, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 1 (DR1).
-
- Reads and returns the current value of DR1. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 1 (DR1).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr1 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr1, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 2 (DR2).
-
- Reads and returns the current value of DR2. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 2 (DR2).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr2 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr2, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 3 (DR3).
-
- Reads and returns the current value of DR3. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 3 (DR3).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr3 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr3, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 4 (DR4).
-
- Reads and returns the current value of DR4. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 4 (DR4).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr4 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr4, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 5 (DR5).
-
- Reads and returns the current value of DR5. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 5 (DR5).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr5 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr5, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 6 (DR6).
-
- Reads and returns the current value of DR6. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 6 (DR6).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr6 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr6, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Debug Register 7 (DR7).
-
- Reads and returns the current value of DR7. This function is only available
- on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
- X64.
-
- @return The value of Debug Register 7 (DR7).
-
-**/
-UINTN
-EFIAPI
-AsmReadDr7 (
- VOID
- )
-{
- UINTN Data;
-
- __asm__ __volatile__ (
- "mov %%dr7, %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Writes a value to Debug Register 0 (DR0).
-
- Writes and returns a new value to DR0. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr0 The value to write to Dr0.
-
- @return The value written to Debug Register 0 (DR0).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr0 (
- UINTN Dr0
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr0"
- :
- : "r" (Dr0)
- );
- return Dr0;
-}
-
-
-/**
- Writes a value to Debug Register 1 (DR1).
-
- Writes and returns a new value to DR1. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr1 The value to write to Dr1.
-
- @return The value written to Debug Register 1 (DR1).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr1 (
- UINTN Dr1
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr1"
- :
- : "r" (Dr1)
- );
- return Dr1;
-}
-
-
-/**
- Writes a value to Debug Register 2 (DR2).
-
- Writes and returns a new value to DR2. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr2 The value to write to Dr2.
-
- @return The value written to Debug Register 2 (DR2).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr2 (
- UINTN Dr2
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr2"
- :
- : "r" (Dr2)
- );
- return Dr2;
-}
-
-
-/**
- Writes a value to Debug Register 3 (DR3).
-
- Writes and returns a new value to DR3. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr3 The value to write to Dr3.
-
- @return The value written to Debug Register 3 (DR3).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr3 (
- UINTN Dr3
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr3"
- :
- : "r" (Dr3)
- );
- return Dr3;
-}
-
-
-/**
- Writes a value to Debug Register 4 (DR4).
-
- Writes and returns a new value to DR4. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr4 The value to write to Dr4.
-
- @return The value written to Debug Register 4 (DR4).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr4 (
- UINTN Dr4
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr4"
- :
- : "r" (Dr4)
- );
- return Dr4;
-}
-
-
-/**
- Writes a value to Debug Register 5 (DR5).
-
- Writes and returns a new value to DR5. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr5 The value to write to Dr5.
-
- @return The value written to Debug Register 5 (DR5).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr5 (
- UINTN Dr5
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr5"
- :
- : "r" (Dr5)
- );
- return Dr5;
-}
-
-
-/**
- Writes a value to Debug Register 6 (DR6).
-
- Writes and returns a new value to DR6. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr6 The value to write to Dr6.
-
- @return The value written to Debug Register 6 (DR6).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr6 (
- UINTN Dr6
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr6"
- :
- : "r" (Dr6)
- );
- return Dr6;
-}
-
-
-/**
- Writes a value to Debug Register 7 (DR7).
-
- Writes and returns a new value to DR7. This function is only available on
- IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
-
- @param Dr7 The value to write to Dr7.
-
- @return The value written to Debug Register 7 (DR7).
-
-**/
-UINTN
-EFIAPI
-AsmWriteDr7 (
- UINTN Dr7
- )
-{
- __asm__ __volatile__ (
- "mov %0, %%dr7"
- :
- : "r" (Dr7)
- );
- return Dr7;
-}
-
-
-/**
- Reads the current value of Code Segment Register (CS).
-
- Reads and returns the current value of CS. This function is only available on
- IA-32 and X64.
-
- @return The current value of CS.
-
-**/
-UINT16
-EFIAPI
-AsmReadCs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%cs, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Data Segment Register (DS).
-
- Reads and returns the current value of DS. This function is only available on
- IA-32 and X64.
-
- @return The current value of DS.
-
-**/
-UINT16
-EFIAPI
-AsmReadDs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%ds, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Extra Segment Register (ES).
-
- Reads and returns the current value of ES. This function is only available on
- IA-32 and X64.
-
- @return The current value of ES.
-
-**/
-UINT16
-EFIAPI
-AsmReadEs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%es, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of FS Data Segment Register (FS).
-
- Reads and returns the current value of FS. This function is only available on
- IA-32 and X64.
-
- @return The current value of FS.
-
-**/
-UINT16
-EFIAPI
-AsmReadFs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%fs, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of GS Data Segment Register (GS).
-
- Reads and returns the current value of GS. This function is only available on
- IA-32 and X64.
-
- @return The current value of GS.
-
-**/
-UINT16
-EFIAPI
-AsmReadGs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%gs, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Stack Segment Register (SS).
-
- Reads and returns the current value of SS. This function is only available on
- IA-32 and X64.
-
- @return The current value of SS.
-
-**/
-UINT16
-EFIAPI
-AsmReadSs (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "mov %%ds, %0"
- :"=a" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current value of Task Register (TR).
-
- Reads and returns the current value of TR. This function is only available on
- IA-32 and X64.
-
- @return The current value of TR.
-
-**/
-UINT16
-EFIAPI
-AsmReadTr (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "str %0"
- : "=r" (Data)
- );
-
- return Data;
-}
-
-
-/**
- Reads the current Global Descriptor Table Register(GDTR) descriptor.
-
- Reads and returns the current GDTR descriptor and returns it in Gdtr. This
- function is only available on IA-32 and X64.
-
- @param Gdtr The pointer to a GDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86ReadGdtr (
- OUT IA32_DESCRIPTOR *Gdtr
- )
-{
- __asm__ __volatile__ (
- "sgdt %0"
- : "=m" (*Gdtr)
- );
-}
-
-
-/**
- Writes the current Global Descriptor Table Register (GDTR) descriptor.
-
- Writes and the current GDTR descriptor specified by Gdtr. This function is
- only available on IA-32 and X64.
-
- @param Gdtr The pointer to a GDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86WriteGdtr (
- IN CONST IA32_DESCRIPTOR *Gdtr
- )
-{
- __asm__ __volatile__ (
- "lgdt %0"
- :
- : "m" (*Gdtr)
- );
-
-}
-
-
-/**
- Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
-
- Reads and returns the current IDTR descriptor and returns it in Idtr. This
- function is only available on IA-32 and X64.
-
- @param Idtr The pointer to a IDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86ReadIdtr (
- OUT IA32_DESCRIPTOR *Idtr
- )
-{
- __asm__ __volatile__ (
- "sidt %0"
- : "=m" (*Idtr)
- );
-}
-
-
-/**
- Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
-
- Writes the current IDTR descriptor and returns it in Idtr. This function is
- only available on IA-32 and X64.
-
- @param Idtr The pointer to a IDTR descriptor.
-
-**/
-VOID
-EFIAPI
-InternalX86WriteIdtr (
- IN CONST IA32_DESCRIPTOR *Idtr
- )
-{
- __asm__ __volatile__ (
- "lidt %0"
- :
- : "m" (*Idtr)
- );
-}
-
-
-/**
- Reads the current Local Descriptor Table Register(LDTR) selector.
-
- Reads and returns the current 16-bit LDTR descriptor value. This function is
- only available on IA-32 and X64.
-
- @return The current selector of LDT.
-
-**/
-UINT16
-EFIAPI
-AsmReadLdtr (
- VOID
- )
-{
- UINT16 Data;
-
- __asm__ __volatile__ (
- "sldt %0"
- : "=g" (Data) // %0
- );
-
- return Data;
-}
-
-
-/**
- Writes the current Local Descriptor Table Register (GDTR) selector.
-
- Writes and the current LDTR descriptor specified by Ldtr. This function is
- only available on IA-32 and X64.
-
- @param Ldtr 16-bit LDTR selector value.
-
-**/
-VOID
-EFIAPI
-AsmWriteLdtr (
- IN UINT16 Ldtr
- )
-{
- __asm__ __volatile__ (
- "lldtw %0"
- :
- : "g" (Ldtr) // %0
- );
-}
-
-
/**
Save the current floating point/SSE/SSE2 context to a buffer.
@@ -1630,171 +560,3 @@ AsmReadTsc (
return (((UINT64)HiData) << 32) | LowData;
}
-
-
-/**
- Reads the current value of a Performance Counter (PMC).
-
- Reads and returns the current value of performance counter specified by
- Index. This function is only available on IA-32 and X64.
-
- @param Index The 32-bit Performance Counter index to read.
-
- @return The value of the PMC specified by Index.
-
-**/
-UINT64
-EFIAPI
-AsmReadPmc (
- IN UINT32 Index
- )
-{
- UINT32 LowData;
- UINT32 HiData;
-
- __asm__ __volatile__ (
- "rdpmc"
- : "=a" (LowData),
- "=d" (HiData)
- : "c" (Index)
- );
-
- return (((UINT64)HiData) << 32) | LowData;
-}
-
-
-/**
- Sets up a monitor buffer that is used by AsmMwait().
-
- Executes a MONITOR instruction with the register state specified by Eax, Ecx
- and Edx. Returns Eax. This function is only available on IA-32 and X64.
-
- @param Eax The value to load into EAX or RAX before executing the MONITOR
- instruction.
- @param Ecx The value to load into ECX or RCX before executing the MONITOR
- instruction.
- @param Edx The value to load into EDX or RDX before executing the MONITOR
- instruction.
-
- @return Eax
-
-**/
-UINTN
-EFIAPI
-AsmMonitor (
- IN UINTN Eax,
- IN UINTN Ecx,
- IN UINTN Edx
- )
-{
- __asm__ __volatile__ (
- "monitor"
- :
- : "a" (Eax),
- "c" (Ecx),
- "d" (Edx)
- );
-
- return Eax;
-}
-
-
-/**
- Executes an MWAIT instruction.
-
- Executes an MWAIT instruction with the register state specified by Eax and
- Ecx. Returns Eax. This function is only available on IA-32 and X64.
-
- @param Eax The value to load into EAX or RAX before executing the MONITOR
- instruction.
- @param Ecx The value to load into ECX or RCX before executing the MONITOR
- instruction.
-
- @return Eax
-
-**/
-UINTN
-EFIAPI
-AsmMwait (
- IN UINTN Eax,
- IN UINTN Ecx
- )
-{
- __asm__ __volatile__ (
- "mwait"
- :
- : "a" (Eax),
- "c" (Ecx)
- );
-
- return Eax;
-}
-
-
-/**
- Executes a WBINVD instruction.
-
- Executes a WBINVD instruction. This function is only available on IA-32 and
- X64.
-
-**/
-VOID
-EFIAPI
-AsmWbinvd (
- VOID
- )
-{
- __asm__ __volatile__ ("wbinvd":::"memory");
-}
-
-
-/**
- Executes a INVD instruction.
-
- Executes a INVD instruction. This function is only available on IA-32 and
- X64.
-
-**/
-VOID
-EFIAPI
-AsmInvd (
- VOID
- )
-{
- __asm__ __volatile__ ("invd":::"memory");
-
-}
-
-
-/**
- Flushes a cache line from all the instruction and data caches within the
- coherency domain of the CPU.
-
- Flushed the cache line specified by LinearAddress, and returns LinearAddress.
- This function is only available on IA-32 and X64.
-
- @param LinearAddress The address of the cache line to flush. If the CPU is
- in a physical addressing mode, then LinearAddress is a
- physical address. If the CPU is in a virtual
- addressing mode, then LinearAddress is a virtual
- address.
-
- @return LinearAddress
-**/
-VOID *
-EFIAPI
-AsmFlushCacheLine (
- IN VOID *LinearAddress
- )
-{
- __asm__ __volatile__ (
- "clflush (%0)"
- :
- : "r" (LinearAddress)
- : "memory"
- );
-
- return LinearAddress;
-}
-
-
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInlinePriv.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInlinePriv.c
new file mode 100644
index 00000000000..8da7cc3e62f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/GccInlinePriv.c
@@ -0,0 +1,1246 @@
+/** @file
+ GCC inline implementation of BaseLib processor specific functions that use
+ privlidged instructions.
+
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "BaseLibInternals.h"
+#include <Library/RegisterFilterLib.h>
+
+/**
+ Enables CPU interrupts.
+
+ Enables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+EnableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("sti"::: "memory");
+}
+
+
+/**
+ Disables CPU interrupts.
+
+ Disables CPU interrupts.
+
+**/
+VOID
+EFIAPI
+DisableInterrupts (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("cli"::: "memory");
+}
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and X64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadMsr64 (
+ IN UINT32 Index
+ )
+{
+ UINT32 LowData;
+ UINT32 HighData;
+ UINT64 Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrRead (Index, &Value);
+ if (Flag) {
+ __asm__ __volatile__ (
+ "rdmsr"
+ : "=a" (LowData), // %0
+ "=d" (HighData) // %1
+ : "c" (Index) // %2
+ );
+ Value = (((UINT64)HighData) << 32) | LowData;
+ }
+ FilterAfterMsrRead (Index, &Value);
+
+ return Value;
+}
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and X64.
+
+ @param Index The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+AsmWriteMsr64 (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ UINT32 LowData;
+ UINT32 HighData;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrWrite (Index, &Value);
+ if (Flag) {
+ LowData = (UINT32)(Value);
+ HighData = (UINT32)(Value >> 32);
+ __asm__ __volatile__ (
+ "wrmsr"
+ :
+ : "c" (Index),
+ "a" (LowData),
+ "d" (HighData)
+ );
+ }
+ FilterAfterMsrWrite (Index, &Value);
+
+ return Value;
+}
+
+/**
+ Reads the current value of the Control Register 0 (CR0).
+
+ Reads and returns the current value of CR0. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 0 (CR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr0 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%cr0,%0"
+ : "=r" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of the Control Register 2 (CR2).
+
+ Reads and returns the current value of CR2. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 2 (CR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr2 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%cr2, %0"
+ : "=r" (Data) // %0
+ );
+
+ return Data;
+}
+
+/**
+ Reads the current value of the Control Register 3 (CR3).
+
+ Reads and returns the current value of CR3. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 3 (CR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr3 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%cr3, %0"
+ : "=r" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of the Control Register 4 (CR4).
+
+ Reads and returns the current value of CR4. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of the Control Register 4 (CR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr4 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%cr4, %0"
+ : "=r" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes a value to Control Register 0 (CR0).
+
+ Writes and returns a new value to CR0. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr0 The value to write to CR0.
+
+ @return The value written to CR0.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr0 (
+ UINTN Cr0
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%cr0"
+ :
+ : "r" (Cr0)
+ );
+ return Cr0;
+}
+
+
+/**
+ Writes a value to Control Register 2 (CR2).
+
+ Writes and returns a new value to CR2. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr2 The value to write to CR2.
+
+ @return The value written to CR2.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr2 (
+ UINTN Cr2
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%cr2"
+ :
+ : "r" (Cr2)
+ );
+ return Cr2;
+}
+
+
+/**
+ Writes a value to Control Register 3 (CR3).
+
+ Writes and returns a new value to CR3. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr3 The value to write to CR3.
+
+ @return The value written to CR3.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr3 (
+ UINTN Cr3
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%cr3"
+ :
+ : "r" (Cr3)
+ );
+ return Cr3;
+}
+
+
+/**
+ Writes a value to Control Register 4 (CR4).
+
+ Writes and returns a new value to CR4. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Cr4 The value to write to CR4.
+
+ @return The value written to CR4.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr4 (
+ UINTN Cr4
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%cr4"
+ :
+ : "r" (Cr4)
+ );
+ return Cr4;
+}
+
+
+/**
+ Reads the current value of Debug Register 0 (DR0).
+
+ Reads and returns the current value of DR0. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr0 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr0, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 1 (DR1).
+
+ Reads and returns the current value of DR1. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr1 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr1, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 2 (DR2).
+
+ Reads and returns the current value of DR2. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr2 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr2, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 3 (DR3).
+
+ Reads and returns the current value of DR3. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr3 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr3, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 4 (DR4).
+
+ Reads and returns the current value of DR4. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr4 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr4, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 5 (DR5).
+
+ Reads and returns the current value of DR5. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr5 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr5, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 6 (DR6).
+
+ Reads and returns the current value of DR6. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr6 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr6, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Debug Register 7 (DR7).
+
+ Reads and returns the current value of DR7. This function is only available
+ on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ X64.
+
+ @return The value of Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr7 (
+ VOID
+ )
+{
+ UINTN Data;
+
+ __asm__ __volatile__ (
+ "mov %%dr7, %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes a value to Debug Register 0 (DR0).
+
+ Writes and returns a new value to DR0. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr0 The value to write to Dr0.
+
+ @return The value written to Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr0 (
+ UINTN Dr0
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr0"
+ :
+ : "r" (Dr0)
+ );
+ return Dr0;
+}
+
+
+/**
+ Writes a value to Debug Register 1 (DR1).
+
+ Writes and returns a new value to DR1. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr1 The value to write to Dr1.
+
+ @return The value written to Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr1 (
+ UINTN Dr1
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr1"
+ :
+ : "r" (Dr1)
+ );
+ return Dr1;
+}
+
+
+/**
+ Writes a value to Debug Register 2 (DR2).
+
+ Writes and returns a new value to DR2. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr2 The value to write to Dr2.
+
+ @return The value written to Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr2 (
+ UINTN Dr2
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr2"
+ :
+ : "r" (Dr2)
+ );
+ return Dr2;
+}
+
+
+/**
+ Writes a value to Debug Register 3 (DR3).
+
+ Writes and returns a new value to DR3. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr3 The value to write to Dr3.
+
+ @return The value written to Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr3 (
+ UINTN Dr3
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr3"
+ :
+ : "r" (Dr3)
+ );
+ return Dr3;
+}
+
+
+/**
+ Writes a value to Debug Register 4 (DR4).
+
+ Writes and returns a new value to DR4. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr4 The value to write to Dr4.
+
+ @return The value written to Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr4 (
+ UINTN Dr4
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr4"
+ :
+ : "r" (Dr4)
+ );
+ return Dr4;
+}
+
+
+/**
+ Writes a value to Debug Register 5 (DR5).
+
+ Writes and returns a new value to DR5. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr5 The value to write to Dr5.
+
+ @return The value written to Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr5 (
+ UINTN Dr5
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr5"
+ :
+ : "r" (Dr5)
+ );
+ return Dr5;
+}
+
+
+/**
+ Writes a value to Debug Register 6 (DR6).
+
+ Writes and returns a new value to DR6. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr6 The value to write to Dr6.
+
+ @return The value written to Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr6 (
+ UINTN Dr6
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr6"
+ :
+ : "r" (Dr6)
+ );
+ return Dr6;
+}
+
+
+/**
+ Writes a value to Debug Register 7 (DR7).
+
+ Writes and returns a new value to DR7. This function is only available on
+ IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
+
+ @param Dr7 The value to write to Dr7.
+
+ @return The value written to Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr7 (
+ UINTN Dr7
+ )
+{
+ __asm__ __volatile__ (
+ "mov %0, %%dr7"
+ :
+ : "r" (Dr7)
+ );
+ return Dr7;
+}
+
+
+/**
+ Reads the current value of Code Segment Register (CS).
+
+ Reads and returns the current value of CS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of CS.
+
+**/
+UINT16
+EFIAPI
+AsmReadCs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%cs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Data Segment Register (DS).
+
+ Reads and returns the current value of DS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of DS.
+
+**/
+UINT16
+EFIAPI
+AsmReadDs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%ds, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Extra Segment Register (ES).
+
+ Reads and returns the current value of ES. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of ES.
+
+**/
+UINT16
+EFIAPI
+AsmReadEs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%es, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of FS Data Segment Register (FS).
+
+ Reads and returns the current value of FS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of FS.
+
+**/
+UINT16
+EFIAPI
+AsmReadFs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%fs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of GS Data Segment Register (GS).
+
+ Reads and returns the current value of GS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of GS.
+
+**/
+UINT16
+EFIAPI
+AsmReadGs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%gs, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Stack Segment Register (SS).
+
+ Reads and returns the current value of SS. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of SS.
+
+**/
+UINT16
+EFIAPI
+AsmReadSs (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "mov %%ds, %0"
+ :"=a" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current value of Task Register (TR).
+
+ Reads and returns the current value of TR. This function is only available on
+ IA-32 and X64.
+
+ @return The current value of TR.
+
+**/
+UINT16
+EFIAPI
+AsmReadTr (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "str %0"
+ : "=r" (Data)
+ );
+
+ return Data;
+}
+
+
+/**
+ Reads the current Global Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current GDTR descriptor and returns it in Gdtr. This
+ function is only available on IA-32 and X64.
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86ReadGdtr (
+ OUT IA32_DESCRIPTOR *Gdtr
+ )
+{
+ __asm__ __volatile__ (
+ "sgdt %0"
+ : "=m" (*Gdtr)
+ );
+}
+
+
+/**
+ Writes the current Global Descriptor Table Register (GDTR) descriptor.
+
+ Writes and the current GDTR descriptor specified by Gdtr. This function is
+ only available on IA-32 and X64.
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86WriteGdtr (
+ IN CONST IA32_DESCRIPTOR *Gdtr
+ )
+{
+ __asm__ __volatile__ (
+ "lgdt %0"
+ :
+ : "m" (*Gdtr)
+ );
+
+}
+
+
+/**
+ Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current IDTR descriptor and returns it in Idtr. This
+ function is only available on IA-32 and X64.
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86ReadIdtr (
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "sidt %0"
+ : "=m" (*Idtr)
+ );
+}
+
+
+/**
+ Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
+
+ Writes the current IDTR descriptor and returns it in Idtr. This function is
+ only available on IA-32 and X64.
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+InternalX86WriteIdtr (
+ IN CONST IA32_DESCRIPTOR *Idtr
+ )
+{
+ __asm__ __volatile__ (
+ "lidt %0"
+ :
+ : "m" (*Idtr)
+ );
+}
+
+
+/**
+ Reads the current Local Descriptor Table Register(LDTR) selector.
+
+ Reads and returns the current 16-bit LDTR descriptor value. This function is
+ only available on IA-32 and X64.
+
+ @return The current selector of LDT.
+
+**/
+UINT16
+EFIAPI
+AsmReadLdtr (
+ VOID
+ )
+{
+ UINT16 Data;
+
+ __asm__ __volatile__ (
+ "sldt %0"
+ : "=g" (Data) // %0
+ );
+
+ return Data;
+}
+
+
+/**
+ Writes the current Local Descriptor Table Register (GDTR) selector.
+
+ Writes and the current LDTR descriptor specified by Ldtr. This function is
+ only available on IA-32 and X64.
+
+ @param Ldtr 16-bit LDTR selector value.
+
+**/
+VOID
+EFIAPI
+AsmWriteLdtr (
+ IN UINT16 Ldtr
+ )
+{
+ __asm__ __volatile__ (
+ "lldtw %0"
+ :
+ : "g" (Ldtr) // %0
+ );
+}
+
+/**
+ Reads the current value of a Performance Counter (PMC).
+
+ Reads and returns the current value of performance counter specified by
+ Index. This function is only available on IA-32 and X64.
+
+ @param Index The 32-bit Performance Counter index to read.
+
+ @return The value of the PMC specified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadPmc (
+ IN UINT32 Index
+ )
+{
+ UINT32 LowData;
+ UINT32 HiData;
+
+ __asm__ __volatile__ (
+ "rdpmc"
+ : "=a" (LowData),
+ "=d" (HiData)
+ : "c" (Index)
+ );
+
+ return (((UINT64)HiData) << 32) | LowData;
+}
+
+/**
+ Sets up a monitor buffer that is used by AsmMwait().
+
+ Executes a MONITOR instruction with the register state specified by Eax, Ecx
+ and Edx. Returns Eax. This function is only available on IA-32 and X64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+ @param Edx The value to load into EDX or RDX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+UINTN
+EFIAPI
+AsmMonitor (
+ IN UINTN Eax,
+ IN UINTN Ecx,
+ IN UINTN Edx
+ )
+{
+ __asm__ __volatile__ (
+ "monitor"
+ :
+ : "a" (Eax),
+ "c" (Ecx),
+ "d" (Edx)
+ );
+
+ return Eax;
+}
+
+/**
+ Executes an MWAIT instruction.
+
+ Executes an MWAIT instruction with the register state specified by Eax and
+ Ecx. Returns Eax. This function is only available on IA-32 and X64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+UINTN
+EFIAPI
+AsmMwait (
+ IN UINTN Eax,
+ IN UINTN Ecx
+ )
+{
+ __asm__ __volatile__ (
+ "mwait"
+ :
+ : "a" (Eax),
+ "c" (Ecx)
+ );
+
+ return Eax;
+}
+
+/**
+ Executes a WBINVD instruction.
+
+ Executes a WBINVD instruction. This function is only available on IA-32 and
+ X64.
+
+**/
+VOID
+EFIAPI
+AsmWbinvd (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("wbinvd":::"memory");
+}
+
+/**
+ Executes a INVD instruction.
+
+ Executes a INVD instruction. This function is only available on IA-32 and
+ X64.
+
+**/
+VOID
+EFIAPI
+AsmInvd (
+ VOID
+ )
+{
+ __asm__ __volatile__ ("invd":::"memory");
+
+}
+
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and X64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress
+**/
+VOID *
+EFIAPI
+AsmFlushCacheLine (
+ IN VOID *LinearAddress
+ )
+{
+ __asm__ __volatile__ (
+ "clflush (%0)"
+ :
+ : "r" (LinearAddress)
+ : "memory"
+ );
+
+ return LinearAddress;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/ReadMsr64.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/ReadMsr64.c
index 9b8d4adeba1..8222ab15ced 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/ReadMsr64.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/ReadMsr64.c
@@ -1,7 +1,7 @@
/** @file
CpuBreakpoint function.
- Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,6 +10,8 @@
Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
**/
+#include <Library/RegisterFilterLib.h>
+
unsigned __int64 __readmsr (int register);
#pragma intrinsic(__readmsr)
@@ -28,6 +30,15 @@ AsmReadMsr64 (
IN UINT32 Index
)
{
- return __readmsr (Index);
+ UINT64 Value;
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrRead (Index, &Value);
+ if (Flag) {
+ Value = __readmsr (Index);
+ }
+ FilterAfterMsrRead (Index, &Value);
+
+ return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/VmgExit.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/VmgExit.nasm
new file mode 100644
index 00000000000..695bab12e4e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/VmgExit.nasm
@@ -0,0 +1,32 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; VmgExit.Asm
+;
+; Abstract:
+;
+; AsmVmgExit function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ DEFAULT REL
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; AsmVmgExit (
+; VOID
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmVmgExit)
+ASM_PFX(AsmVmgExit):
+ rep vmmcall
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/WriteMsr64.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/WriteMsr64.c
index fcbee805580..50a8adfc4cb 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/WriteMsr64.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/WriteMsr64.c
@@ -1,7 +1,7 @@
/** @file
CpuBreakpoint function.
- Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,6 +10,8 @@
Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics.
**/
+#include <Library/RegisterFilterLib.h>
+
void __writemsr (unsigned long Register, unsigned __int64 Value);
#pragma intrinsic(__writemsr)
@@ -30,7 +32,14 @@ AsmWriteMsr64 (
IN UINT64 Value
)
{
- __writemsr (Index, Value);
+ BOOLEAN Flag;
+
+ Flag = FilterBeforeMsrWrite (Index, &Value);
+ if (Flag) {
+ __writemsr (Index, Value);
+ }
+ FilterAfterMsrWrite (Index, &Value);
+
return Value;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XGetBv.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XGetBv.nasm
new file mode 100644
index 00000000000..697fd4af6f8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XGetBv.nasm
@@ -0,0 +1,34 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; XGetBv.Asm
+;
+; Abstract:
+;
+; AsmXgetBv function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ DEFAULT REL
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmXGetBv (
+; IN UINT32 Index
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmXGetBv)
+ASM_PFX(AsmXGetBv):
+ xgetbv
+ shl rdx, 32
+ or rax, rdx
+ ret
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XSetBv.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XSetBv.nasm
new file mode 100644
index 00000000000..f4c66672bd3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X64/XSetBv.nasm
@@ -0,0 +1,34 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; XSetBv.nasm
+;
+; Abstract:
+;
+; AsmXSetBv function
+;
+; Notes:
+;
+;------------------------------------------------------------------------------
+
+ DEFAULT REL
+ SECTION .text
+
+;------------------------------------------------------------------------------
+; UINT64
+; EFIAPI
+; AsmXSetBv (
+; IN UINT32 Index,
+; IN UINT64 Value
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(AsmXSetBv)
+ASM_PFX(AsmXSetBv):
+ mov rax, rdx ; meanwhile, rax <- return value
+ shr rdx, 0x20 ; edx:eax contains the value to write
+ xsetbv
+ ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X86UnitTestHost.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X86UnitTestHost.c
new file mode 100644
index 00000000000..41b382965a3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseLib/X86UnitTestHost.c
@@ -0,0 +1,2977 @@
+/** @file
+ IA32/X64 specific Unit Test Host functions.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UnitTestHost.h"
+
+///
+/// Defines for mUnitTestHostBaseLibSegment indexes
+///
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_CS 0
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_DS 1
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_ES 2
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_FS 3
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_GS 4
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_SS 5
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_TR 6
+#define UNIT_TEST_HOST_BASE_LIB_SEGMENT_LDTR 7
+
+///
+/// Module global variables for simple system emulation of MSRs, CRx, DRx,
+/// GDTR, IDTR, and Segment Selectors.
+///
+STATIC UINT64 mUnitTestHostBaseLibMsr[2][0x1000];
+STATIC UINTN mUnitTestHostBaseLibCr[5];
+STATIC UINTN mUnitTestHostBaseLibDr[8];
+STATIC UINT16 mUnitTestHostBaseLibSegment[8];
+STATIC IA32_DESCRIPTOR mUnitTestHostBaseLibGdtr;
+STATIC IA32_DESCRIPTOR mUnitTestHostBaseLibIdtr;
+
+/**
+ Retrieves CPUID information.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index.
+ This function always returns Index.
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+ This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the CPUID
+ instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+
+ @return Index.
+
+**/
+UINT32
+EFIAPI
+UnitTestHostBaseLibAsmCpuid (
+ IN UINT32 Index,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ )
+{
+ if (Eax != NULL) {
+ *Eax = 0;
+ }
+ if (Ebx != NULL) {
+ *Ebx = 0;
+ }
+ if (Ecx != NULL) {
+ *Ecx = 0;
+ }
+ if (Edx != NULL) {
+ *Edx = 0;
+ }
+ return Index;
+}
+
+/**
+ Retrieves CPUID information using an extended leaf identifier.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index
+ and ECX set to the value specified by SubIndex. This function always returns
+ Index. This function is only available on IA-32 and x64.
+
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the
+ CPUID instruction.
+ @param SubIndex The 32-bit value to load into ECX prior to invoking the
+ CPUID instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+
+ @return Index.
+
+**/
+UINT32
+EFIAPI
+UnitTestHostBaseLibAsmCpuidEx (
+ IN UINT32 Index,
+ IN UINT32 SubIndex,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ )
+{
+ if (Eax != NULL) {
+ *Eax = 0;
+ }
+ if (Ebx != NULL) {
+ *Ebx = 0;
+ }
+ if (Ecx != NULL) {
+ *Ecx = 0;
+ }
+ if (Edx != NULL) {
+ *Edx = 0;
+ }
+ return Index;
+}
+
+/**
+ Set CD bit and clear NW bit of CR0 followed by a WBINVD.
+
+ Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0,
+ and executing a WBINVD instruction. This function is only available on IA-32 and x64.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmDisableCache (
+ VOID
+ )
+{
+}
+
+/**
+ Perform a WBINVD and clear both the CD and NW bits of CR0.
+
+ Enables the caches by executing a WBINVD instruction and then clear both the CD and NW
+ bits of CR0 to 0. This function is only available on IA-32 and x64.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmEnableCache (
+ VOID
+ )
+{
+}
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and x64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+UINT64
+EFIAPI
+UnitTestHostBaseLibAsmReadMsr64 (
+ IN UINT32 Index
+ )
+{
+ if (Index < 0x1000) {
+ return mUnitTestHostBaseLibMsr[0][Index];
+ }
+ if (Index >= 0xC0000000 && Index < 0xC0001000) {
+ return mUnitTestHostBaseLibMsr[1][Index];
+ }
+ return 0;
+}
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and x64.
+
+ @param Index The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+UnitTestHostBaseLibAsmWriteMsr64 (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ if (Index < 0x1000) {
+ mUnitTestHostBaseLibMsr[0][Index] = Value;
+ }
+ if (Index >= 0xC0000000 && Index < 0xC0001000) {
+ mUnitTestHostBaseLibMsr[1][Index - 0xC00000000] = Value;
+ }
+ return Value;
+}
+
+/**
+ Reads the current value of the Control Register 0 (CR0).
+
+ Reads and returns the current value of CR0. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 0 (CR0).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadCr0 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibCr[0];
+}
+
+/**
+ Reads the current value of the Control Register 2 (CR2).
+
+ Reads and returns the current value of CR2. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 2 (CR2).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadCr2 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibCr[2];
+}
+
+/**
+ Reads the current value of the Control Register 3 (CR3).
+
+ Reads and returns the current value of CR3. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 3 (CR3).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadCr3 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibCr[3];
+}
+
+/**
+ Reads the current value of the Control Register 4 (CR4).
+
+ Reads and returns the current value of CR4. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 4 (CR4).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadCr4 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibCr[4];
+}
+
+/**
+ Writes a value to Control Register 0 (CR0).
+
+ Writes and returns a new value to CR0. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr0 The value to write to CR0.
+
+ @return The value written to CR0.
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteCr0 (
+ UINTN Cr0
+ )
+{
+ mUnitTestHostBaseLibCr[0] = Cr0;
+ return Cr0;
+}
+
+/**
+ Writes a value to Control Register 2 (CR2).
+
+ Writes and returns a new value to CR2. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr2 The value to write to CR2.
+
+ @return The value written to CR2.
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteCr2 (
+ UINTN Cr2
+ )
+{
+ mUnitTestHostBaseLibCr[2] = Cr2;
+ return Cr2;
+}
+
+/**
+ Writes a value to Control Register 3 (CR3).
+
+ Writes and returns a new value to CR3. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr3 The value to write to CR3.
+
+ @return The value written to CR3.
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteCr3 (
+ UINTN Cr3
+ )
+{
+ mUnitTestHostBaseLibCr[3] = Cr3;
+ return Cr3;
+}
+
+/**
+ Writes a value to Control Register 4 (CR4).
+
+ Writes and returns a new value to CR4. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr4 The value to write to CR4.
+
+ @return The value written to CR4.
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteCr4 (
+ UINTN Cr4
+ )
+{
+ mUnitTestHostBaseLibCr[4] = Cr4;
+ return Cr4;
+}
+
+/**
+ Reads the current value of Debug Register 0 (DR0).
+
+ Reads and returns the current value of DR0. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr0 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[0];
+}
+
+/**
+ Reads the current value of Debug Register 1 (DR1).
+
+ Reads and returns the current value of DR1. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr1 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[1];
+}
+
+/**
+ Reads the current value of Debug Register 2 (DR2).
+
+ Reads and returns the current value of DR2. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr2 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[2];
+}
+
+/**
+ Reads the current value of Debug Register 3 (DR3).
+
+ Reads and returns the current value of DR3. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr3 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[3];
+}
+
+/**
+ Reads the current value of Debug Register 4 (DR4).
+
+ Reads and returns the current value of DR4. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr4 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[4];
+}
+
+/**
+ Reads the current value of Debug Register 5 (DR5).
+
+ Reads and returns the current value of DR5. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr5 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[5];
+}
+
+/**
+ Reads the current value of Debug Register 6 (DR6).
+
+ Reads and returns the current value of DR6. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr6 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[6];
+}
+
+/**
+ Reads the current value of Debug Register 7 (DR7).
+
+ Reads and returns the current value of DR7. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmReadDr7 (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibDr[7];
+}
+
+/**
+ Writes a value to Debug Register 0 (DR0).
+
+ Writes and returns a new value to DR0. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr0 The value to write to Dr0.
+
+ @return The value written to Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr0 (
+ UINTN Dr0
+ )
+{
+ mUnitTestHostBaseLibDr[0] = Dr0;
+ return Dr0;
+}
+
+/**
+ Writes a value to Debug Register 1 (DR1).
+
+ Writes and returns a new value to DR1. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr1 The value to write to Dr1.
+
+ @return The value written to Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr1 (
+ UINTN Dr1
+ )
+{
+ mUnitTestHostBaseLibDr[1] = Dr1;
+ return Dr1;
+}
+
+/**
+ Writes a value to Debug Register 2 (DR2).
+
+ Writes and returns a new value to DR2. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr2 The value to write to Dr2.
+
+ @return The value written to Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr2 (
+ UINTN Dr2
+ )
+{
+ mUnitTestHostBaseLibDr[2] = Dr2;
+ return Dr2;
+}
+
+/**
+ Writes a value to Debug Register 3 (DR3).
+
+ Writes and returns a new value to DR3. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr3 The value to write to Dr3.
+
+ @return The value written to Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr3 (
+ UINTN Dr3
+ )
+{
+ mUnitTestHostBaseLibDr[3] = Dr3;
+ return Dr3;
+}
+
+/**
+ Writes a value to Debug Register 4 (DR4).
+
+ Writes and returns a new value to DR4. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr4 The value to write to Dr4.
+
+ @return The value written to Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr4 (
+ UINTN Dr4
+ )
+{
+ mUnitTestHostBaseLibDr[4] = Dr4;
+ return Dr4;
+}
+
+/**
+ Writes a value to Debug Register 5 (DR5).
+
+ Writes and returns a new value to DR5. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr5 The value to write to Dr5.
+
+ @return The value written to Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr5 (
+ UINTN Dr5
+ )
+{
+ mUnitTestHostBaseLibDr[5] = Dr5;
+ return Dr5;
+}
+
+/**
+ Writes a value to Debug Register 6 (DR6).
+
+ Writes and returns a new value to DR6. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr6 The value to write to Dr6.
+
+ @return The value written to Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr6 (
+ UINTN Dr6
+ )
+{
+ mUnitTestHostBaseLibDr[6] = Dr6;
+ return Dr6;
+}
+
+/**
+ Writes a value to Debug Register 7 (DR7).
+
+ Writes and returns a new value to DR7. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr7 The value to write to Dr7.
+
+ @return The value written to Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmWriteDr7 (
+ UINTN Dr7
+ )
+{
+ mUnitTestHostBaseLibDr[7] = Dr7;
+ return Dr7;
+}
+
+/**
+ Reads the current value of Code Segment Register (CS).
+
+ Reads and returns the current value of CS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of CS.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadCs (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_CS];
+}
+
+/**
+ Reads the current value of Data Segment Register (DS).
+
+ Reads and returns the current value of DS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of DS.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadDs (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_DS];
+}
+
+/**
+ Reads the current value of Extra Segment Register (ES).
+
+ Reads and returns the current value of ES. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of ES.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadEs (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_ES];
+}
+
+/**
+ Reads the current value of FS Data Segment Register (FS).
+
+ Reads and returns the current value of FS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of FS.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadFs (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_FS];
+}
+
+/**
+ Reads the current value of GS Data Segment Register (GS).
+
+ Reads and returns the current value of GS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of GS.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadGs (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_GS];
+}
+
+/**
+ Reads the current value of Stack Segment Register (SS).
+
+ Reads and returns the current value of SS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of SS.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadSs (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_SS];
+}
+
+/**
+ Reads the current value of Task Register (TR).
+
+ Reads and returns the current value of TR. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of TR.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadTr (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_TR];
+}
+
+/**
+ Reads the current Global Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current GDTR descriptor and returns it in Gdtr. This
+ function is only available on IA-32 and x64.
+
+ If Gdtr is NULL, then ASSERT().
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmReadGdtr (
+ OUT IA32_DESCRIPTOR *Gdtr
+ )
+{
+ Gdtr = &mUnitTestHostBaseLibGdtr;
+}
+
+/**
+ Writes the current Global Descriptor Table Register (GDTR) descriptor.
+
+ Writes and the current GDTR descriptor specified by Gdtr. This function is
+ only available on IA-32 and x64.
+
+ If Gdtr is NULL, then ASSERT().
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmWriteGdtr (
+ IN CONST IA32_DESCRIPTOR *Gdtr
+ )
+{
+ CopyMem (&mUnitTestHostBaseLibGdtr, Gdtr, sizeof (IA32_DESCRIPTOR));
+}
+
+/**
+ Reads the current Interrupt Descriptor Table Register(IDTR) descriptor.
+
+ Reads and returns the current IDTR descriptor and returns it in Idtr. This
+ function is only available on IA-32 and x64.
+
+ If Idtr is NULL, then ASSERT().
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmReadIdtr (
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ Idtr = &mUnitTestHostBaseLibIdtr;
+}
+
+/**
+ Writes the current Interrupt Descriptor Table Register(IDTR) descriptor.
+
+ Writes the current IDTR descriptor and returns it in Idtr. This function is
+ only available on IA-32 and x64.
+
+ If Idtr is NULL, then ASSERT().
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmWriteIdtr (
+ IN CONST IA32_DESCRIPTOR *Idtr
+ )
+{
+ CopyMem (&mUnitTestHostBaseLibIdtr, Idtr, sizeof (IA32_DESCRIPTOR));
+}
+
+/**
+ Reads the current Local Descriptor Table Register(LDTR) selector.
+
+ Reads and returns the current 16-bit LDTR descriptor value. This function is
+ only available on IA-32 and x64.
+
+ @return The current selector of LDT.
+
+**/
+UINT16
+EFIAPI
+UnitTestHostBaseLibAsmReadLdtr (
+ VOID
+ )
+{
+ return mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_LDTR];
+}
+
+/**
+ Writes the current Local Descriptor Table Register (LDTR) selector.
+
+ Writes and the current LDTR descriptor specified by Ldtr. This function is
+ only available on IA-32 and x64.
+
+ @param Ldtr 16-bit LDTR selector value.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmWriteLdtr (
+ IN UINT16 Ldtr
+ )
+{
+ mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_LDTR] = Ldtr;
+}
+
+/**
+ Reads the current value of a Performance Counter (PMC).
+
+ Reads and returns the current value of performance counter specified by
+ Index. This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit Performance Counter index to read.
+
+ @return The value of the PMC specified by Index.
+
+**/
+UINT64
+EFIAPI
+UnitTestHostBaseLibAsmReadPmc (
+ IN UINT32 Index
+ )
+{
+ return 0;
+}
+
+/**
+ Sets up a monitor buffer that is used by AsmMwait().
+
+ Executes a MONITOR instruction with the register state specified by Eax, Ecx
+ and Edx. Returns Eax. This function is only available on IA-32 and x64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+ @param Edx The value to load into EDX or RDX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmMonitor (
+ IN UINTN Eax,
+ IN UINTN Ecx,
+ IN UINTN Edx
+ )
+{
+ return Eax;
+}
+
+/**
+ Executes an MWAIT instruction.
+
+ Executes an MWAIT instruction with the register state specified by Eax and
+ Ecx. Returns Eax. This function is only available on IA-32 and x64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+UINTN
+EFIAPI
+UnitTestHostBaseLibAsmMwait (
+ IN UINTN Eax,
+ IN UINTN Ecx
+ )
+{
+ return Eax;
+}
+
+/**
+ Executes a WBINVD instruction.
+
+ Executes a WBINVD instruction. This function is only available on IA-32 and
+ x64.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmWbinvd (
+ VOID
+ )
+{
+}
+
+/**
+ Executes a INVD instruction.
+
+ Executes a INVD instruction. This function is only available on IA-32 and
+ x64.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmInvd (
+ VOID
+ )
+{
+}
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and x64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress.
+**/
+VOID *
+EFIAPI
+UnitTestHostBaseLibAsmFlushCacheLine (
+ IN VOID *LinearAddress
+ )
+{
+ return LinearAddress;
+}
+
+/**
+ Enables the 32-bit paging mode on the CPU.
+
+ Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables
+ must be properly initialized prior to calling this service. This function
+ assumes the current execution mode is 32-bit protected mode. This function is
+ only available on IA-32. After the 32-bit paging mode is enabled, control is
+ transferred to the function specified by EntryPoint using the new stack
+ specified by NewStack and passing in the parameters specified by Context1 and
+ Context2. Context1 and Context2 are optional and may be NULL. The function
+ EntryPoint must never return.
+
+ If the current execution mode is not 32-bit protected mode, then ASSERT().
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ There are a number of constraints that must be followed before calling this
+ function:
+ 1) Interrupts must be disabled.
+ 2) The caller must be in 32-bit protected mode with flat descriptors. This
+ means all descriptors must have a base of 0 and a limit of 4GB.
+ 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat
+ descriptors.
+ 4) CR3 must point to valid page tables that will be used once the transition
+ is complete, and those page tables must guarantee that the pages for this
+ function and the stack are identity mapped.
+
+ @param EntryPoint A pointer to function to call with the new stack after
+ paging is enabled.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function as the first parameter after paging is enabled.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function as the second parameter after paging is enabled.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function after paging is enabled.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmEnablePaging32 (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack
+ )
+{
+ EntryPoint (Context1, Context2);
+}
+
+/**
+ Disables the 32-bit paging mode on the CPU.
+
+ Disables the 32-bit paging mode on the CPU and returns to 32-bit protected
+ mode. This function assumes the current execution mode is 32-paged protected
+ mode. This function is only available on IA-32. After the 32-bit paging mode
+ is disabled, control is transferred to the function specified by EntryPoint
+ using the new stack specified by NewStack and passing in the parameters
+ specified by Context1 and Context2. Context1 and Context2 are optional and
+ may be NULL. The function EntryPoint must never return.
+
+ If the current execution mode is not 32-bit paged mode, then ASSERT().
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ There are a number of constraints that must be followed before calling this
+ function:
+ 1) Interrupts must be disabled.
+ 2) The caller must be in 32-bit paged mode.
+ 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode.
+ 4) CR3 must point to valid page tables that guarantee that the pages for
+ this function and the stack are identity mapped.
+
+ @param EntryPoint A pointer to function to call with the new stack after
+ paging is disabled.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function as the first parameter after paging is disabled.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function as the second parameter after paging is
+ disabled.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function after paging is disabled.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmDisablePaging32 (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack
+ )
+{
+ EntryPoint (Context1, Context2);
+}
+
+/**
+ Enables the 64-bit paging mode on the CPU.
+
+ Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables
+ must be properly initialized prior to calling this service. This function
+ assumes the current execution mode is 32-bit protected mode with flat
+ descriptors. This function is only available on IA-32. After the 64-bit
+ paging mode is enabled, control is transferred to the function specified by
+ EntryPoint using the new stack specified by NewStack and passing in the
+ parameters specified by Context1 and Context2. Context1 and Context2 are
+ optional and may be 0. The function EntryPoint must never return.
+
+ If the current execution mode is not 32-bit protected mode with flat
+ descriptors, then ASSERT().
+ If EntryPoint is 0, then ASSERT().
+ If NewStack is 0, then ASSERT().
+
+ @param Cs The 16-bit selector to load in the CS before EntryPoint
+ is called. The descriptor in the GDT that this selector
+ references must be setup for long mode.
+ @param EntryPoint The 64-bit virtual address of the function to call with
+ the new stack after paging is enabled.
+ @param Context1 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the first parameter after
+ paging is enabled.
+ @param Context2 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the second parameter after
+ paging is enabled.
+ @param NewStack The 64-bit virtual address of the new stack to use for
+ the EntryPoint function after paging is enabled.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmEnablePaging64 (
+ IN UINT16 Cs,
+ IN UINT64 EntryPoint,
+ IN UINT64 Context1, OPTIONAL
+ IN UINT64 Context2, OPTIONAL
+ IN UINT64 NewStack
+ )
+{
+ SWITCH_STACK_ENTRY_POINT NewEntryPoint;
+
+ NewEntryPoint = (SWITCH_STACK_ENTRY_POINT)(UINTN)(EntryPoint);
+ NewEntryPoint ((VOID *)(UINTN)Context1, (VOID *)(UINTN)Context2);
+}
+
+/**
+ Disables the 64-bit paging mode on the CPU.
+
+ Disables the 64-bit paging mode on the CPU and returns to 32-bit protected
+ mode. This function assumes the current execution mode is 64-paging mode.
+ This function is only available on x64. After the 64-bit paging mode is
+ disabled, control is transferred to the function specified by EntryPoint
+ using the new stack specified by NewStack and passing in the parameters
+ specified by Context1 and Context2. Context1 and Context2 are optional and
+ may be 0. The function EntryPoint must never return.
+
+ If the current execution mode is not 64-bit paged mode, then ASSERT().
+ If EntryPoint is 0, then ASSERT().
+ If NewStack is 0, then ASSERT().
+
+ @param Cs The 16-bit selector to load in the CS before EntryPoint
+ is called. The descriptor in the GDT that this selector
+ references must be setup for 32-bit protected mode.
+ @param EntryPoint The 64-bit virtual address of the function to call with
+ the new stack after paging is disabled.
+ @param Context1 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the first parameter after
+ paging is disabled.
+ @param Context2 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the second parameter after
+ paging is disabled.
+ @param NewStack The 64-bit virtual address of the new stack to use for
+ the EntryPoint function after paging is disabled.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmDisablePaging64 (
+ IN UINT16 Cs,
+ IN UINT32 EntryPoint,
+ IN UINT32 Context1, OPTIONAL
+ IN UINT32 Context2, OPTIONAL
+ IN UINT32 NewStack
+ )
+{
+ SWITCH_STACK_ENTRY_POINT NewEntryPoint;
+
+ NewEntryPoint = (SWITCH_STACK_ENTRY_POINT)(UINTN)(EntryPoint);
+ NewEntryPoint ((VOID *)(UINTN)Context1, (VOID *)(UINTN)Context2);
+}
+
+/**
+ Retrieves the properties for 16-bit thunk functions.
+
+ Computes the size of the buffer and stack below 1MB required to use the
+ AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This
+ buffer size is returned in RealModeBufferSize, and the stack size is returned
+ in ExtraStackSize. If parameters are passed to the 16-bit real mode code,
+ then the actual minimum stack size is ExtraStackSize plus the maximum number
+ of bytes that need to be passed to the 16-bit real mode code.
+
+ If RealModeBufferSize is NULL, then ASSERT().
+ If ExtraStackSize is NULL, then ASSERT().
+
+ @param RealModeBufferSize A pointer to the size of the buffer below 1MB
+ required to use the 16-bit thunk functions.
+ @param ExtraStackSize A pointer to the extra size of stack below 1MB
+ that the 16-bit thunk functions require for
+ temporary storage in the transition to and from
+ 16-bit real mode.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmGetThunk16Properties (
+ OUT UINT32 *RealModeBufferSize,
+ OUT UINT32 *ExtraStackSize
+ )
+{
+ *RealModeBufferSize = 0;
+ *ExtraStackSize = 0;
+}
+
+/**
+ Prepares all structures a code required to use AsmThunk16().
+
+ Prepares all structures and code required to use AsmThunk16().
+
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.
+
+ If ThunkContext is NULL, then ASSERT().
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmPrepareThunk16 (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+{
+}
+
+/**
+ Transfers control to a 16-bit real mode entry point and returns the results.
+
+ Transfers control to a 16-bit real mode entry point and returns the results.
+ AsmPrepareThunk16() must be called with ThunkContext before this function is used.
+ This function must be called with interrupts disabled.
+
+ The register state from the RealModeState field of ThunkContext is restored just prior
+ to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState,
+ which is used to set the interrupt state when a 16-bit real mode entry point is called.
+ Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState.
+ The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to
+ the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function.
+ The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction,
+ so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment
+ and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry
+ point must exit with a RETF instruction. The register state is captured into RealModeState immediately
+ after the RETF instruction is executed.
+
+ If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,
+ or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure
+ the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode.
+
+ If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,
+ then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode.
+ This includes the base vectors, the interrupt masks, and the edge/level trigger mode.
+
+ If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code
+ is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits.
+
+ If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in
+ ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to
+ disable the A20 mask.
+
+ If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in
+ ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails,
+ then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.
+
+ If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in
+ ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.
+
+ If ThunkContext is NULL, then ASSERT().
+ If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT().
+ If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in
+ ThunkAttributes, then ASSERT().
+
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the
+ virtual to physical mappings for ThunkContext.RealModeBuffer are mapped 1:1.
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmThunk16 (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+{
+}
+
+/**
+ Prepares all structures and code for a 16-bit real mode thunk, transfers
+ control to a 16-bit real mode entry point, and returns the results.
+
+ Prepares all structures and code for a 16-bit real mode thunk, transfers
+ control to a 16-bit real mode entry point, and returns the results. If the
+ caller only need to perform a single 16-bit real mode thunk, then this
+ service should be used. If the caller intends to make more than one 16-bit
+ real mode thunk, then it is more efficient if AsmPrepareThunk16() is called
+ once and AsmThunk16() can be called for each 16-bit real mode thunk.
+
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.
+
+ See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions.
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmPrepareAndThunk16 (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+{
+}
+
+/**
+ Load given selector into TR register.
+
+ @param[in] Selector Task segment selector
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmWriteTr (
+ IN UINT16 Selector
+ )
+{
+ mUnitTestHostBaseLibSegment[UNIT_TEST_HOST_BASE_LIB_SEGMENT_TR] = Selector;
+}
+
+/**
+ Performs a serializing operation on all load-from-memory instructions that
+ were issued prior the AsmLfence function.
+
+ Executes a LFENCE instruction. This function is only available on IA-32 and x64.
+
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibAsmLfence (
+ VOID
+ )
+{
+}
+
+/**
+ Patch the immediate operand of an IA32 or X64 instruction such that the byte,
+ word, dword or qword operand is encoded at the end of the instruction's
+ binary representation.
+
+ This function should be used to update object code that was compiled with
+ NASM from assembly source code. Example:
+
+ NASM source code:
+
+ mov eax, strict dword 0 ; the imm32 zero operand will be patched
+ ASM_PFX(gPatchCr3):
+ mov cr3, eax
+
+ C source code:
+
+ X86_ASSEMBLY_PATCH_LABEL gPatchCr3;
+ PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);
+
+ @param[out] InstructionEnd Pointer right past the instruction to patch. The
+ immediate operand to patch is expected to
+ comprise the trailing bytes of the instruction.
+ If InstructionEnd is closer to address 0 than
+ ValueSize permits, then ASSERT().
+
+ @param[in] PatchValue The constant to write to the immediate operand.
+ The caller is responsible for ensuring that
+ PatchValue can be represented in the byte, word,
+ dword or qword operand (as indicated through
+ ValueSize); otherwise ASSERT().
+
+ @param[in] ValueSize The size of the operand in bytes; must be 1, 2,
+ 4, or 8. ASSERT() otherwise.
+**/
+VOID
+EFIAPI
+UnitTestHostBaseLibPatchInstructionX86 (
+ OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,
+ IN UINT64 PatchValue,
+ IN UINTN ValueSize
+ )
+{
+}
+
+/**
+ Retrieves CPUID information.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index.
+ This function always returns Index.
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+ This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the CPUID
+ instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+
+ @return Index.
+
+**/
+UINT32
+EFIAPI
+AsmCpuid (
+ IN UINT32 Index,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmCpuid (Index, Eax, Ebx, Ecx, Edx);
+}
+
+/**
+ Retrieves CPUID information using an extended leaf identifier.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index
+ and ECX set to the value specified by SubIndex. This function always returns
+ Index. This function is only available on IA-32 and x64.
+
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the
+ CPUID instruction.
+ @param SubIndex The 32-bit value to load into ECX prior to invoking the
+ CPUID instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+
+ @return Index.
+
+**/
+UINT32
+EFIAPI
+AsmCpuidEx (
+ IN UINT32 Index,
+ IN UINT32 SubIndex,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmCpuidEx (Index, SubIndex, Eax, Ebx, Ecx, Edx);
+}
+
+/**
+ Set CD bit and clear NW bit of CR0 followed by a WBINVD.
+
+ Disables the caches by setting the CD bit of CR0 to 1, clearing the NW bit of CR0 to 0,
+ and executing a WBINVD instruction. This function is only available on IA-32 and x64.
+
+**/
+VOID
+EFIAPI
+AsmDisableCache (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmDisableCache ();
+}
+
+/**
+ Perform a WBINVD and clear both the CD and NW bits of CR0.
+
+ Enables the caches by executing a WBINVD instruction and then clear both the CD and NW
+ bits of CR0 to 0. This function is only available on IA-32 and x64.
+
+**/
+VOID
+EFIAPI
+AsmEnableCache (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmEnableCache ();
+}
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and x64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadMsr64 (
+ IN UINT32 Index
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadMsr64 (Index);
+}
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and x64.
+
+ @param Index The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+AsmWriteMsr64 (
+ IN UINT32 Index,
+ IN UINT64 Value
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteMsr64 (Index, Value);
+}
+
+/**
+ Reads the current value of the Control Register 0 (CR0).
+
+ Reads and returns the current value of CR0. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 0 (CR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr0 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadCr0 ();
+}
+
+/**
+ Reads the current value of the Control Register 2 (CR2).
+
+ Reads and returns the current value of CR2. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 2 (CR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr2 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadCr2 ();
+}
+
+/**
+ Reads the current value of the Control Register 3 (CR3).
+
+ Reads and returns the current value of CR3. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 3 (CR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr3 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadCr3 ();
+}
+
+/**
+ Reads the current value of the Control Register 4 (CR4).
+
+ Reads and returns the current value of CR4. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of the Control Register 4 (CR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadCr4 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadCr4 ();
+}
+
+/**
+ Writes a value to Control Register 0 (CR0).
+
+ Writes and returns a new value to CR0. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr0 The value to write to CR0.
+
+ @return The value written to CR0.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr0 (
+ UINTN Cr0
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteCr0 (Cr0);
+}
+
+/**
+ Writes a value to Control Register 2 (CR2).
+
+ Writes and returns a new value to CR2. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr2 The value to write to CR2.
+
+ @return The value written to CR2.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr2 (
+ UINTN Cr2
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteCr2 (Cr2);
+}
+
+/**
+ Writes a value to Control Register 3 (CR3).
+
+ Writes and returns a new value to CR3. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr3 The value to write to CR3.
+
+ @return The value written to CR3.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr3 (
+ UINTN Cr3
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteCr3 (Cr3);
+}
+
+/**
+ Writes a value to Control Register 4 (CR4).
+
+ Writes and returns a new value to CR4. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Cr4 The value to write to CR4.
+
+ @return The value written to CR4.
+
+**/
+UINTN
+EFIAPI
+AsmWriteCr4 (
+ UINTN Cr4
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteCr4 (Cr4);
+}
+
+/**
+ Reads the current value of Debug Register 0 (DR0).
+
+ Reads and returns the current value of DR0. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr0 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr0 ();
+}
+
+/**
+ Reads the current value of Debug Register 1 (DR1).
+
+ Reads and returns the current value of DR1. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr1 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr1 ();
+}
+
+/**
+ Reads the current value of Debug Register 2 (DR2).
+
+ Reads and returns the current value of DR2. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr2 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr2 ();
+}
+
+/**
+ Reads the current value of Debug Register 3 (DR3).
+
+ Reads and returns the current value of DR3. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr3 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr3 ();
+}
+
+/**
+ Reads the current value of Debug Register 4 (DR4).
+
+ Reads and returns the current value of DR4. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr4 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr4 ();
+}
+
+/**
+ Reads the current value of Debug Register 5 (DR5).
+
+ Reads and returns the current value of DR5. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr5 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr5 ();
+}
+
+/**
+ Reads the current value of Debug Register 6 (DR6).
+
+ Reads and returns the current value of DR6. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr6 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr6 ();
+}
+
+/**
+ Reads the current value of Debug Register 7 (DR7).
+
+ Reads and returns the current value of DR7. This function is only available
+ on IA-32 and x64. This returns a 32-bit value on IA-32 and a 64-bit value on
+ x64.
+
+ @return The value of Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmReadDr7 (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDr7 ();
+}
+
+/**
+ Writes a value to Debug Register 0 (DR0).
+
+ Writes and returns a new value to DR0. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr0 The value to write to Dr0.
+
+ @return The value written to Debug Register 0 (DR0).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr0 (
+ UINTN Dr0
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr0 (Dr0);
+}
+
+/**
+ Writes a value to Debug Register 1 (DR1).
+
+ Writes and returns a new value to DR1. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr1 The value to write to Dr1.
+
+ @return The value written to Debug Register 1 (DR1).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr1 (
+ UINTN Dr1
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr1 (Dr1);
+}
+
+/**
+ Writes a value to Debug Register 2 (DR2).
+
+ Writes and returns a new value to DR2. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr2 The value to write to Dr2.
+
+ @return The value written to Debug Register 2 (DR2).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr2 (
+ UINTN Dr2
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr2 (Dr2);
+}
+
+/**
+ Writes a value to Debug Register 3 (DR3).
+
+ Writes and returns a new value to DR3. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr3 The value to write to Dr3.
+
+ @return The value written to Debug Register 3 (DR3).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr3 (
+ UINTN Dr3
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr3 (Dr3);
+}
+
+/**
+ Writes a value to Debug Register 4 (DR4).
+
+ Writes and returns a new value to DR4. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr4 The value to write to Dr4.
+
+ @return The value written to Debug Register 4 (DR4).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr4 (
+ UINTN Dr4
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr4 (Dr4);
+}
+
+/**
+ Writes a value to Debug Register 5 (DR5).
+
+ Writes and returns a new value to DR5. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr5 The value to write to Dr5.
+
+ @return The value written to Debug Register 5 (DR5).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr5 (
+ UINTN Dr5
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr5 (Dr5);
+}
+
+/**
+ Writes a value to Debug Register 6 (DR6).
+
+ Writes and returns a new value to DR6. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr6 The value to write to Dr6.
+
+ @return The value written to Debug Register 6 (DR6).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr6 (
+ UINTN Dr6
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr6 (Dr6);
+}
+
+/**
+ Writes a value to Debug Register 7 (DR7).
+
+ Writes and returns a new value to DR7. This function is only available on
+ IA-32 and x64. This writes a 32-bit value on IA-32 and a 64-bit value on x64.
+
+ @param Dr7 The value to write to Dr7.
+
+ @return The value written to Debug Register 7 (DR7).
+
+**/
+UINTN
+EFIAPI
+AsmWriteDr7 (
+ UINTN Dr7
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmWriteDr7 (Dr7);
+}
+
+/**
+ Reads the current value of Code Segment Register (CS).
+
+ Reads and returns the current value of CS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of CS.
+
+**/
+UINT16
+EFIAPI
+AsmReadCs (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadCs ();
+}
+
+/**
+ Reads the current value of Data Segment Register (DS).
+
+ Reads and returns the current value of DS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of DS.
+
+**/
+UINT16
+EFIAPI
+AsmReadDs (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadDs ();
+}
+
+/**
+ Reads the current value of Extra Segment Register (ES).
+
+ Reads and returns the current value of ES. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of ES.
+
+**/
+UINT16
+EFIAPI
+AsmReadEs (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadEs ();
+}
+
+/**
+ Reads the current value of FS Data Segment Register (FS).
+
+ Reads and returns the current value of FS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of FS.
+
+**/
+UINT16
+EFIAPI
+AsmReadFs (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadFs ();
+}
+
+/**
+ Reads the current value of GS Data Segment Register (GS).
+
+ Reads and returns the current value of GS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of GS.
+
+**/
+UINT16
+EFIAPI
+AsmReadGs (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadGs ();
+}
+
+/**
+ Reads the current value of Stack Segment Register (SS).
+
+ Reads and returns the current value of SS. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of SS.
+
+**/
+UINT16
+EFIAPI
+AsmReadSs (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadSs ();
+}
+
+/**
+ Reads the current value of Task Register (TR).
+
+ Reads and returns the current value of TR. This function is only available on
+ IA-32 and x64.
+
+ @return The current value of TR.
+
+**/
+UINT16
+EFIAPI
+AsmReadTr (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadTr ();
+}
+
+/**
+ Reads the current Global Descriptor Table Register(GDTR) descriptor.
+
+ Reads and returns the current GDTR descriptor and returns it in Gdtr. This
+ function is only available on IA-32 and x64.
+
+ If Gdtr is NULL, then ASSERT().
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+AsmReadGdtr (
+ OUT IA32_DESCRIPTOR *Gdtr
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmReadGdtr (Gdtr);
+}
+
+/**
+ Writes the current Global Descriptor Table Register (GDTR) descriptor.
+
+ Writes and the current GDTR descriptor specified by Gdtr. This function is
+ only available on IA-32 and x64.
+
+ If Gdtr is NULL, then ASSERT().
+
+ @param Gdtr The pointer to a GDTR descriptor.
+
+**/
+VOID
+EFIAPI
+AsmWriteGdtr (
+ IN CONST IA32_DESCRIPTOR *Gdtr
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmWriteGdtr (Gdtr);
+}
+
+/**
+ Reads the current Interrupt Descriptor Table Register(IDTR) descriptor.
+
+ Reads and returns the current IDTR descriptor and returns it in Idtr. This
+ function is only available on IA-32 and x64.
+
+ If Idtr is NULL, then ASSERT().
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+AsmReadIdtr (
+ OUT IA32_DESCRIPTOR *Idtr
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmReadIdtr (Idtr);
+}
+
+/**
+ Writes the current Interrupt Descriptor Table Register(IDTR) descriptor.
+
+ Writes the current IDTR descriptor and returns it in Idtr. This function is
+ only available on IA-32 and x64.
+
+ If Idtr is NULL, then ASSERT().
+
+ @param Idtr The pointer to a IDTR descriptor.
+
+**/
+VOID
+EFIAPI
+AsmWriteIdtr (
+ IN CONST IA32_DESCRIPTOR *Idtr
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmWriteIdtr (Idtr);
+}
+
+/**
+ Reads the current Local Descriptor Table Register(LDTR) selector.
+
+ Reads and returns the current 16-bit LDTR descriptor value. This function is
+ only available on IA-32 and x64.
+
+ @return The current selector of LDT.
+
+**/
+UINT16
+EFIAPI
+AsmReadLdtr (
+ VOID
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadLdtr ();
+}
+
+/**
+ Writes the current Local Descriptor Table Register (LDTR) selector.
+
+ Writes and the current LDTR descriptor specified by Ldtr. This function is
+ only available on IA-32 and x64.
+
+ @param Ldtr 16-bit LDTR selector value.
+
+**/
+VOID
+EFIAPI
+AsmWriteLdtr (
+ IN UINT16 Ldtr
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmWriteLdtr (Ldtr);
+}
+
+/**
+ Reads the current value of a Performance Counter (PMC).
+
+ Reads and returns the current value of performance counter specified by
+ Index. This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit Performance Counter index to read.
+
+ @return The value of the PMC specified by Index.
+
+**/
+UINT64
+EFIAPI
+AsmReadPmc (
+ IN UINT32 Index
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmReadPmc (Index);
+}
+
+/**
+ Sets up a monitor buffer that is used by AsmMwait().
+
+ Executes a MONITOR instruction with the register state specified by Eax, Ecx
+ and Edx. Returns Eax. This function is only available on IA-32 and x64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+ @param Edx The value to load into EDX or RDX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+UINTN
+EFIAPI
+AsmMonitor (
+ IN UINTN Eax,
+ IN UINTN Ecx,
+ IN UINTN Edx
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmMonitor (Eax, Ecx, Edx);
+}
+
+/**
+ Executes an MWAIT instruction.
+
+ Executes an MWAIT instruction with the register state specified by Eax and
+ Ecx. Returns Eax. This function is only available on IA-32 and x64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+UINTN
+EFIAPI
+AsmMwait (
+ IN UINTN Eax,
+ IN UINTN Ecx
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmMwait (Eax, Ecx);
+}
+
+/**
+ Executes a WBINVD instruction.
+
+ Executes a WBINVD instruction. This function is only available on IA-32 and
+ x64.
+
+**/
+VOID
+EFIAPI
+AsmWbinvd (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmWbinvd ();
+}
+
+/**
+ Executes a INVD instruction.
+
+ Executes a INVD instruction. This function is only available on IA-32 and
+ x64.
+
+**/
+VOID
+EFIAPI
+AsmInvd (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmInvd ();
+}
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and x64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress.
+**/
+VOID *
+EFIAPI
+AsmFlushCacheLine (
+ IN VOID *LinearAddress
+ )
+{
+ return gUnitTestHostBaseLib.X86->AsmFlushCacheLine (LinearAddress);
+}
+
+/**
+ Enables the 32-bit paging mode on the CPU.
+
+ Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables
+ must be properly initialized prior to calling this service. This function
+ assumes the current execution mode is 32-bit protected mode. This function is
+ only available on IA-32. After the 32-bit paging mode is enabled, control is
+ transferred to the function specified by EntryPoint using the new stack
+ specified by NewStack and passing in the parameters specified by Context1 and
+ Context2. Context1 and Context2 are optional and may be NULL. The function
+ EntryPoint must never return.
+
+ If the current execution mode is not 32-bit protected mode, then ASSERT().
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ There are a number of constraints that must be followed before calling this
+ function:
+ 1) Interrupts must be disabled.
+ 2) The caller must be in 32-bit protected mode with flat descriptors. This
+ means all descriptors must have a base of 0 and a limit of 4GB.
+ 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat
+ descriptors.
+ 4) CR3 must point to valid page tables that will be used once the transition
+ is complete, and those page tables must guarantee that the pages for this
+ function and the stack are identity mapped.
+
+ @param EntryPoint A pointer to function to call with the new stack after
+ paging is enabled.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function as the first parameter after paging is enabled.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function as the second parameter after paging is enabled.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function after paging is enabled.
+
+**/
+VOID
+EFIAPI
+AsmEnablePaging32 (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmEnablePaging32 (EntryPoint, Context1, Context2, NewStack);
+}
+
+/**
+ Disables the 32-bit paging mode on the CPU.
+
+ Disables the 32-bit paging mode on the CPU and returns to 32-bit protected
+ mode. This function assumes the current execution mode is 32-paged protected
+ mode. This function is only available on IA-32. After the 32-bit paging mode
+ is disabled, control is transferred to the function specified by EntryPoint
+ using the new stack specified by NewStack and passing in the parameters
+ specified by Context1 and Context2. Context1 and Context2 are optional and
+ may be NULL. The function EntryPoint must never return.
+
+ If the current execution mode is not 32-bit paged mode, then ASSERT().
+ If EntryPoint is NULL, then ASSERT().
+ If NewStack is NULL, then ASSERT().
+
+ There are a number of constraints that must be followed before calling this
+ function:
+ 1) Interrupts must be disabled.
+ 2) The caller must be in 32-bit paged mode.
+ 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode.
+ 4) CR3 must point to valid page tables that guarantee that the pages for
+ this function and the stack are identity mapped.
+
+ @param EntryPoint A pointer to function to call with the new stack after
+ paging is disabled.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function as the first parameter after paging is disabled.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function as the second parameter after paging is
+ disabled.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function after paging is disabled.
+
+**/
+VOID
+EFIAPI
+AsmDisablePaging32 (
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmDisablePaging32 (EntryPoint, Context1, Context2, NewStack);
+}
+
+/**
+ Enables the 64-bit paging mode on the CPU.
+
+ Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables
+ must be properly initialized prior to calling this service. This function
+ assumes the current execution mode is 32-bit protected mode with flat
+ descriptors. This function is only available on IA-32. After the 64-bit
+ paging mode is enabled, control is transferred to the function specified by
+ EntryPoint using the new stack specified by NewStack and passing in the
+ parameters specified by Context1 and Context2. Context1 and Context2 are
+ optional and may be 0. The function EntryPoint must never return.
+
+ If the current execution mode is not 32-bit protected mode with flat
+ descriptors, then ASSERT().
+ If EntryPoint is 0, then ASSERT().
+ If NewStack is 0, then ASSERT().
+
+ @param Cs The 16-bit selector to load in the CS before EntryPoint
+ is called. The descriptor in the GDT that this selector
+ references must be setup for long mode.
+ @param EntryPoint The 64-bit virtual address of the function to call with
+ the new stack after paging is enabled.
+ @param Context1 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the first parameter after
+ paging is enabled.
+ @param Context2 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the second parameter after
+ paging is enabled.
+ @param NewStack The 64-bit virtual address of the new stack to use for
+ the EntryPoint function after paging is enabled.
+
+**/
+VOID
+EFIAPI
+AsmEnablePaging64 (
+ IN UINT16 Cs,
+ IN UINT64 EntryPoint,
+ IN UINT64 Context1, OPTIONAL
+ IN UINT64 Context2, OPTIONAL
+ IN UINT64 NewStack
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmEnablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack);
+}
+
+/**
+ Disables the 64-bit paging mode on the CPU.
+
+ Disables the 64-bit paging mode on the CPU and returns to 32-bit protected
+ mode. This function assumes the current execution mode is 64-paging mode.
+ This function is only available on x64. After the 64-bit paging mode is
+ disabled, control is transferred to the function specified by EntryPoint
+ using the new stack specified by NewStack and passing in the parameters
+ specified by Context1 and Context2. Context1 and Context2 are optional and
+ may be 0. The function EntryPoint must never return.
+
+ If the current execution mode is not 64-bit paged mode, then ASSERT().
+ If EntryPoint is 0, then ASSERT().
+ If NewStack is 0, then ASSERT().
+
+ @param Cs The 16-bit selector to load in the CS before EntryPoint
+ is called. The descriptor in the GDT that this selector
+ references must be setup for 32-bit protected mode.
+ @param EntryPoint The 64-bit virtual address of the function to call with
+ the new stack after paging is disabled.
+ @param Context1 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the first parameter after
+ paging is disabled.
+ @param Context2 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the second parameter after
+ paging is disabled.
+ @param NewStack The 64-bit virtual address of the new stack to use for
+ the EntryPoint function after paging is disabled.
+
+**/
+VOID
+EFIAPI
+AsmDisablePaging64 (
+ IN UINT16 Cs,
+ IN UINT32 EntryPoint,
+ IN UINT32 Context1, OPTIONAL
+ IN UINT32 Context2, OPTIONAL
+ IN UINT32 NewStack
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmDisablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack);
+}
+
+/**
+ Retrieves the properties for 16-bit thunk functions.
+
+ Computes the size of the buffer and stack below 1MB required to use the
+ AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This
+ buffer size is returned in RealModeBufferSize, and the stack size is returned
+ in ExtraStackSize. If parameters are passed to the 16-bit real mode code,
+ then the actual minimum stack size is ExtraStackSize plus the maximum number
+ of bytes that need to be passed to the 16-bit real mode code.
+
+ If RealModeBufferSize is NULL, then ASSERT().
+ If ExtraStackSize is NULL, then ASSERT().
+
+ @param RealModeBufferSize A pointer to the size of the buffer below 1MB
+ required to use the 16-bit thunk functions.
+ @param ExtraStackSize A pointer to the extra size of stack below 1MB
+ that the 16-bit thunk functions require for
+ temporary storage in the transition to and from
+ 16-bit real mode.
+
+**/
+VOID
+EFIAPI
+AsmGetThunk16Properties (
+ OUT UINT32 *RealModeBufferSize,
+ OUT UINT32 *ExtraStackSize
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmGetThunk16Properties (RealModeBufferSize, ExtraStackSize);
+}
+
+/**
+ Prepares all structures a code required to use AsmThunk16().
+
+ Prepares all structures and code required to use AsmThunk16().
+
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.
+
+ If ThunkContext is NULL, then ASSERT().
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+VOID
+EFIAPI
+AsmPrepareThunk16 (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmPrepareThunk16 (ThunkContext);
+}
+
+/**
+ Transfers control to a 16-bit real mode entry point and returns the results.
+
+ Transfers control to a 16-bit real mode entry point and returns the results.
+ AsmPrepareThunk16() must be called with ThunkContext before this function is used.
+ This function must be called with interrupts disabled.
+
+ The register state from the RealModeState field of ThunkContext is restored just prior
+ to calling the 16-bit real mode entry point. This includes the EFLAGS field of RealModeState,
+ which is used to set the interrupt state when a 16-bit real mode entry point is called.
+ Control is transferred to the 16-bit real mode entry point specified by the CS and Eip fields of RealModeState.
+ The stack is initialized to the SS and ESP fields of RealModeState. Any parameters passed to
+ the 16-bit real mode code must be populated by the caller at SS:ESP prior to calling this function.
+ The 16-bit real mode entry point is invoked with a 16-bit CALL FAR instruction,
+ so when accessing stack contents, the 16-bit real mode code must account for the 16-bit segment
+ and 16-bit offset of the return address that were pushed onto the stack. The 16-bit real mode entry
+ point must exit with a RETF instruction. The register state is captured into RealModeState immediately
+ after the RETF instruction is executed.
+
+ If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,
+ or any of the 16-bit real mode code makes a SW interrupt, then the caller is responsible for making sure
+ the IDT at address 0 is initialized to handle any HW or SW interrupts that may occur while in 16-bit real mode.
+
+ If EFLAGS specifies interrupts enabled, or any of the 16-bit real mode code enables interrupts,
+ then the caller is responsible for making sure the 8259 PIC is in a state compatible with 16-bit real mode.
+ This includes the base vectors, the interrupt masks, and the edge/level trigger mode.
+
+ If THUNK_ATTRIBUTE_BIG_REAL_MODE is set in the ThunkAttributes field of ThunkContext, then the user code
+ is invoked in big real mode. Otherwise, the user code is invoked in 16-bit real mode with 64KB segment limits.
+
+ If neither THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 nor THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in
+ ThunkAttributes, then it is assumed that the user code did not enable the A20 mask, and no attempt is made to
+ disable the A20 mask.
+
+ If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is set and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is clear in
+ ThunkAttributes, then attempt to use the INT 15 service to disable the A20 mask. If this INT 15 call fails,
+ then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.
+
+ If THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 is clear and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL is set in
+ ThunkAttributes, then attempt to disable the A20 mask by directly accessing the 8042 keyboard controller I/O ports.
+
+ If ThunkContext is NULL, then ASSERT().
+ If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT().
+ If both THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 and THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL are set in
+ ThunkAttributes, then ASSERT().
+
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the
+ virtual to physical mappings for ThunkContext.RealModeBuffer are mapped 1:1.
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+VOID
+EFIAPI
+AsmThunk16 (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmThunk16 (ThunkContext);
+}
+
+/**
+ Prepares all structures and code for a 16-bit real mode thunk, transfers
+ control to a 16-bit real mode entry point, and returns the results.
+
+ Prepares all structures and code for a 16-bit real mode thunk, transfers
+ control to a 16-bit real mode entry point, and returns the results. If the
+ caller only need to perform a single 16-bit real mode thunk, then this
+ service should be used. If the caller intends to make more than one 16-bit
+ real mode thunk, then it is more efficient if AsmPrepareThunk16() is called
+ once and AsmThunk16() can be called for each 16-bit real mode thunk.
+
+ This interface is limited to be used in either physical mode or virtual modes with paging enabled where the
+ virtual to physical mappings for ThunkContext.RealModeBuffer is mapped 1:1.
+
+ See AsmPrepareThunk16() and AsmThunk16() for the detailed description and ASSERT() conditions.
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+VOID
+EFIAPI
+AsmPrepareAndThunk16 (
+ IN OUT THUNK_CONTEXT *ThunkContext
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmPrepareAndThunk16 (ThunkContext);
+}
+
+/**
+ Load given selector into TR register.
+
+ @param[in] Selector Task segment selector
+**/
+VOID
+EFIAPI
+AsmWriteTr (
+ IN UINT16 Selector
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmWriteTr (Selector);
+}
+
+/**
+ Performs a serializing operation on all load-from-memory instructions that
+ were issued prior the AsmLfence function.
+
+ Executes a LFENCE instruction. This function is only available on IA-32 and x64.
+
+**/
+VOID
+EFIAPI
+AsmLfence (
+ VOID
+ )
+{
+ gUnitTestHostBaseLib.X86->AsmLfence ();
+}
+
+/**
+ Patch the immediate operand of an IA32 or X64 instruction such that the byte,
+ word, dword or qword operand is encoded at the end of the instruction's
+ binary representation.
+
+ This function should be used to update object code that was compiled with
+ NASM from assembly source code. Example:
+
+ NASM source code:
+
+ mov eax, strict dword 0 ; the imm32 zero operand will be patched
+ ASM_PFX(gPatchCr3):
+ mov cr3, eax
+
+ C source code:
+
+ X86_ASSEMBLY_PATCH_LABEL gPatchCr3;
+ PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);
+
+ @param[out] InstructionEnd Pointer right past the instruction to patch. The
+ immediate operand to patch is expected to
+ comprise the trailing bytes of the instruction.
+ If InstructionEnd is closer to address 0 than
+ ValueSize permits, then ASSERT().
+
+ @param[in] PatchValue The constant to write to the immediate operand.
+ The caller is responsible for ensuring that
+ PatchValue can be represented in the byte, word,
+ dword or qword operand (as indicated through
+ ValueSize); otherwise ASSERT().
+
+ @param[in] ValueSize The size of the operand in bytes; must be 1, 2,
+ 4, or 8. ASSERT() otherwise.
+**/
+VOID
+EFIAPI
+PatchInstructionX86 (
+ OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,
+ IN UINT64 PatchValue,
+ IN UINTN ValueSize
+ )
+{
+ gUnitTestHostBaseLib.X86->PatchInstructionX86 (InstructionEnd, PatchValue, ValueSize);
+}
+
+///
+/// Common services
+///
+STATIC UNIT_TEST_HOST_BASE_LIB_COMMON mUnitTestHostBaseLibCommon = {
+ UnitTestHostBaseLibEnableInterrupts,
+ UnitTestHostBaseLibDisableInterrupts,
+ UnitTestHostBaseLibEnableDisableInterrupts,
+ UnitTestHostBaseLibGetInterruptState,
+};
+
+///
+/// IA32/X64 services
+///
+STATIC UNIT_TEST_HOST_BASE_LIB_X86 mUnitTestHostBaseLibX86 = {
+ UnitTestHostBaseLibAsmCpuid,
+ UnitTestHostBaseLibAsmCpuidEx,
+ UnitTestHostBaseLibAsmDisableCache,
+ UnitTestHostBaseLibAsmEnableCache,
+ UnitTestHostBaseLibAsmReadMsr64,
+ UnitTestHostBaseLibAsmWriteMsr64,
+ UnitTestHostBaseLibAsmReadCr0,
+ UnitTestHostBaseLibAsmReadCr2,
+ UnitTestHostBaseLibAsmReadCr3,
+ UnitTestHostBaseLibAsmReadCr4,
+ UnitTestHostBaseLibAsmWriteCr0,
+ UnitTestHostBaseLibAsmWriteCr2,
+ UnitTestHostBaseLibAsmWriteCr3,
+ UnitTestHostBaseLibAsmWriteCr4,
+ UnitTestHostBaseLibAsmReadDr0,
+ UnitTestHostBaseLibAsmReadDr1,
+ UnitTestHostBaseLibAsmReadDr2,
+ UnitTestHostBaseLibAsmReadDr3,
+ UnitTestHostBaseLibAsmReadDr4,
+ UnitTestHostBaseLibAsmReadDr5,
+ UnitTestHostBaseLibAsmReadDr6,
+ UnitTestHostBaseLibAsmReadDr7,
+ UnitTestHostBaseLibAsmWriteDr0,
+ UnitTestHostBaseLibAsmWriteDr1,
+ UnitTestHostBaseLibAsmWriteDr2,
+ UnitTestHostBaseLibAsmWriteDr3,
+ UnitTestHostBaseLibAsmWriteDr4,
+ UnitTestHostBaseLibAsmWriteDr5,
+ UnitTestHostBaseLibAsmWriteDr6,
+ UnitTestHostBaseLibAsmWriteDr7,
+ UnitTestHostBaseLibAsmReadCs,
+ UnitTestHostBaseLibAsmReadDs,
+ UnitTestHostBaseLibAsmReadEs,
+ UnitTestHostBaseLibAsmReadFs,
+ UnitTestHostBaseLibAsmReadGs,
+ UnitTestHostBaseLibAsmReadSs,
+ UnitTestHostBaseLibAsmReadTr,
+ UnitTestHostBaseLibAsmReadGdtr,
+ UnitTestHostBaseLibAsmWriteGdtr,
+ UnitTestHostBaseLibAsmReadIdtr,
+ UnitTestHostBaseLibAsmWriteIdtr,
+ UnitTestHostBaseLibAsmReadLdtr,
+ UnitTestHostBaseLibAsmWriteLdtr,
+ UnitTestHostBaseLibAsmReadPmc,
+ UnitTestHostBaseLibAsmMonitor,
+ UnitTestHostBaseLibAsmMwait,
+ UnitTestHostBaseLibAsmWbinvd,
+ UnitTestHostBaseLibAsmInvd,
+ UnitTestHostBaseLibAsmFlushCacheLine,
+ UnitTestHostBaseLibAsmEnablePaging32,
+ UnitTestHostBaseLibAsmDisablePaging32,
+ UnitTestHostBaseLibAsmEnablePaging64,
+ UnitTestHostBaseLibAsmDisablePaging64,
+ UnitTestHostBaseLibAsmGetThunk16Properties,
+ UnitTestHostBaseLibAsmPrepareThunk16,
+ UnitTestHostBaseLibAsmThunk16,
+ UnitTestHostBaseLibAsmPrepareAndThunk16,
+ UnitTestHostBaseLibAsmWriteTr,
+ UnitTestHostBaseLibAsmLfence,
+ UnitTestHostBaseLibPatchInstructionX86
+};
+
+///
+/// Structure of hook functions for BaseLib functions that can not be used from
+/// a host application. A simple emulation of these function is provided by
+/// default. A specific unit test can provide its own implementation for any
+/// of these functions.
+///
+UNIT_TEST_HOST_BASE_LIB gUnitTestHostBaseLib = {
+ &mUnitTestHostBaseLibCommon,
+ &mUnitTestHostBaseLibX86
+};
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S
index 8544c018c4f..858607b4ec5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareGuid.S
@@ -1,29 +1,7 @@
//
// Copyright (c) 2016, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Linaro nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
.text
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S
index 7e5bf8a6c33..dd9b58e9d1f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CompareMem.S
@@ -1,29 +1,7 @@
//
// Copyright (c) 2013, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Linaro nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Assumptions:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S
index ec5f6961687..2c6bc4d4ba9 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/CopyMem.S
@@ -1,57 +1,9 @@
//
// Copyright (c) 2012 - 2016, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Linaro nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-//
// Copyright (c) 2015 ARM Ltd
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// 3. The name of the company may not be used to endorse or promote
-// products derived from this software without specific prior written
-// permission.
-//
-// THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-// IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Assumptions:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S
index 3fe772fff7d..873b735846d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/ScanMem.S
@@ -1,29 +1,7 @@
//
// Copyright (c) 2014, ARM Limited
// All rights Reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the company nor the names of its contributors
-// may be used to endorse or promote products derived from this
-// software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Assumptions:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S
index 384fbdc6c04..eb58f8d92b3 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/AArch64/SetMem.S
@@ -1,57 +1,9 @@
//
// Copyright (c) 2012 - 2016, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Linaro nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-//
// Copyright (c) 2015 ARM Ltd
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// 3. The name of the company may not be used to endorse or promote
-// products derived from this software without specific prior written
-// permission.
-//
-// THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-// IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
-// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Assumptions:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S
index 78a45253b8e..69f6c7857d5 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.S
@@ -1,29 +1,7 @@
//
// Copyright (c) 2016, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Linaro nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
.text
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm
index 0373404ea9d..9e9eca33027 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareGuid.asm
@@ -1,29 +1,7 @@
;
; Copyright (c) 2016, Linaro Limited
; All rights reserved.
-;
-; Redistribution and use in source and binary forms, with or without
-; modification, are permitted provided that the following conditions are met:
-; * Redistributions of source code must retain the above copyright
-; notice, this list of conditions and the following disclaimer.
-; * Redistributions in binary form must reproduce the above copyright
-; notice, this list of conditions and the following disclaimer in the
-; documentation and/or other materials provided with the distribution.
-; * Neither the name of the Linaro nor the
-; names of its contributors may be used to endorse or promote products
-; derived from this software without specific prior written permission.
-;
-; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
;
EXPORT InternalMemCompareGuid
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S
index 8e17760f36b..92ae57168e3 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.S
@@ -1,29 +1,7 @@
//
// Copyright (c) 2013 - 2016, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-// * Neither the name of the Linaro nor the
-// names of its contributors may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Parameters and result.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm
index 4c72dcf3859..e0856ba7e9c 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/CompareMem.asm
@@ -1,29 +1,7 @@
;
; Copyright (c) 2013 - 2016, Linaro Limited
; All rights reserved.
-;
-; Redistribution and use in source and binary forms, with or without
-; modification, are permitted provided that the following conditions are met:
-; * Redistributions of source code must retain the above copyright
-; notice, this list of conditions and the following disclaimer.
-; * Redistributions in binary form must reproduce the above copyright
-; notice, this list of conditions and the following disclaimer in the
-; documentation and/or other materials provided with the distribution.
-; * Neither the name of the Linaro nor the
-; names of its contributors may be used to endorse or promote products
-; derived from this software without specific prior written permission.
-;
-; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Parameters and result.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S
index 5502f286537..aff958c0603 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.S
@@ -1,32 +1,6 @@
// Copyright (c) 2010-2011, Linaro Limited
// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//
-// * Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// * Neither the name of Linaro Limited nor the names of its
-// contributors may be used to endorse or promote products derived
-// from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
//
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm
index bb489f14cf7..361fd6202e6 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibOptDxe/Arm/ScanMem.asm
@@ -1,32 +1,6 @@
; Copyright (c) 2010-2011, Linaro Limited
; All rights reserved.
-;
-; Redistribution and use in source and binary forms, with or without
-; modification, are permitted provided that the following conditions
-; are met:
-;
-; * Redistributions of source code must retain the above copyright
-; notice, this list of conditions and the following disclaimer.
-;
-; * Redistributions in binary form must reproduce the above copyright
-; notice, this list of conditions and the following disclaimer in the
-; documentation and/or other materials provided with the distribution.
-;
-; * Neither the name of Linaro Limited nor the names of its
-; contributors may be used to endorse or promote products derived
-; from this software without specific prior written permission.
-;
-; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-; HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-; LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-; DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
;
;
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm
index a719a4aafc1..d3c1bd92d07 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem.nasm
@@ -34,7 +34,7 @@ ASM_PFX(InternalMemSetMem):
mov al, [esp + 16] ; al <- Value
xor ecx, ecx
sub ecx, edi
- and ecx, 15 ; ecx + edi aligns on 16-byte boundary
+ and ecx, 63 ; ecx + edi aligns on 16-byte boundary
jz .0
cmp ecx, edx
cmova ecx, edx
@@ -42,8 +42,8 @@ ASM_PFX(InternalMemSetMem):
rep stosb
.0:
mov ecx, edx
- and edx, 15
- shr ecx, 4 ; ecx <- # of DQwords to set
+ and edx, 63
+ shr ecx, 6 ; ecx <- # of DQwords to set
jz @SetBytes
mov ah, al ; ax <- Value | (Value << 8)
add esp, -16
@@ -53,7 +53,10 @@ ASM_PFX(InternalMemSetMem):
movlhps xmm0, xmm0 ; xmm0 <- Value repeats 16 times
.1:
movntdq [edi], xmm0 ; edi should be 16-byte aligned
- add edi, 16
+ movntdq [edi + 16], xmm0
+ movntdq [edi + 32], xmm0
+ movntdq [edi + 48], xmm0
+ add edi, 64
loop .1
mfence
movdqu xmm0, [esp] ; restore xmm0
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm
index 335756c965c..0503c20aff7 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem16.nasm
@@ -33,7 +33,7 @@ ASM_PFX(InternalMemSetMem16):
mov edi, [esp + 8]
xor ecx, ecx
sub ecx, edi
- and ecx, 15 ; ecx + edi aligns on 16-byte boundary
+ and ecx, 63 ; ecx + edi aligns on 16-byte boundary
mov eax, [esp + 16]
jz .0
shr ecx, 1
@@ -43,15 +43,18 @@ ASM_PFX(InternalMemSetMem16):
rep stosw
.0:
mov ecx, edx
- and edx, 7
- shr ecx, 3
+ and edx, 31
+ shr ecx, 5
jz @SetWords
movd xmm0, eax
pshuflw xmm0, xmm0, 0
movlhps xmm0, xmm0
.1:
movntdq [edi], xmm0 ; edi should be 16-byte aligned
- add edi, 16
+ movntdq [edi + 16], xmm0
+ movntdq [edi + 32], xmm0
+ movntdq [edi + 48], xmm0
+ add edi, 64
loop .1
mfence
@SetWords:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm
index 9274265902d..66be5762d03 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem32.nasm
@@ -43,14 +43,17 @@ ASM_PFX(InternalMemSetMem32):
rep stosd
.0:
mov ecx, edx
- and edx, 3
- shr ecx, 2
+ and edx, 15
+ shr ecx, 4
jz @SetDwords
movd xmm0, eax
pshufd xmm0, xmm0, 0
.1:
movntdq [edi], xmm0
- add edi, 16
+ movntdq [edi + 16], xmm0
+ movntdq [edi + 32], xmm0
+ movntdq [edi + 48], xmm0
+ add edi, 64
loop .1
mfence
@SetDwords:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm
index 4a79ae6f180..c59b8e18a0c 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/SetMem64.nasm
@@ -38,17 +38,29 @@ ASM_PFX(InternalMemSetMem64):
add edx, 8
dec ecx
.0:
- shr ecx, 1
+ push ebx
+ mov ebx, ecx
+ and ebx, 7
+ shr ecx, 3
jz @SetQwords
movlhps xmm0, xmm0
.1:
movntdq [edx], xmm0
- lea edx, [edx + 16]
+ movntdq [edx + 16], xmm0
+ movntdq [edx + 32], xmm0
+ movntdq [edx + 48], xmm0
+ lea edx, [edx + 64]
loop .1
mfence
@SetQwords:
- jnc .2
+ test ebx, ebx
+ jz .3
+ mov ecx, ebx
+.2
movq qword [edx], xmm0
-.2:
+ lea edx, [edx + 8]
+ loop .2
+.3:
+ pop ebx
ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm
index 423fd713658..f67fd178298 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/Ia32/ZeroMem.nasm
@@ -33,7 +33,7 @@ ASM_PFX(InternalMemZeroMem):
xor ecx, ecx
sub ecx, edi
xor eax, eax
- and ecx, 15
+ and ecx, 63
jz .0
cmp ecx, edx
cmova ecx, edx
@@ -41,13 +41,16 @@ ASM_PFX(InternalMemZeroMem):
rep stosb
.0:
mov ecx, edx
- and edx, 15
- shr ecx, 4
+ and edx, 63
+ shr ecx, 6
jz @ZeroBytes
pxor xmm0, xmm0
.1:
movntdq [edi], xmm0
- add edi, 16
+ movntdq [edi + 16], xmm0
+ movntdq [edi + 32], xmm0
+ movntdq [edi + 48], xmm0
+ add edi, 64
loop .1
mfence
@ZeroBytes:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm
index 5c7103e0048..ad3101632e4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem.nasm
@@ -42,8 +42,8 @@ ASM_PFX(InternalMemSetMem):
rep stosb
.0:
mov rcx, rdx
- and rdx, 15
- shr rcx, 4
+ and rdx, 63
+ shr rcx, 6
jz @SetBytes
mov ah, al ; ax <- Value repeats twice
movdqa [rsp + 0x10], xmm0 ; save xmm0
@@ -52,7 +52,10 @@ ASM_PFX(InternalMemSetMem):
movlhps xmm0, xmm0 ; xmm0 <- Value repeats 16 times
.1:
movntdq [rdi], xmm0 ; rdi should be 16-byte aligned
- add rdi, 16
+ movntdq [rdi + 16], xmm0
+ movntdq [rdi + 32], xmm0
+ movntdq [rdi + 48], xmm0
+ add rdi, 64
loop .1
mfence
movdqa xmm0, [rsp + 0x10] ; restore xmm0
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm
index d8c68d87445..ca53cf0fc38 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem16.nasm
@@ -33,7 +33,7 @@ ASM_PFX(InternalMemSetMem16):
mov r9, rdi
xor rcx, rcx
sub rcx, rdi
- and rcx, 15
+ and rcx, 63
mov rax, r8
jz .0
shr rcx, 1
@@ -43,15 +43,18 @@ ASM_PFX(InternalMemSetMem16):
rep stosw
.0:
mov rcx, rdx
- and edx, 7
- shr rcx, 3
+ and edx, 31
+ shr rcx, 5
jz @SetWords
movd xmm0, eax
pshuflw xmm0, xmm0, 0
movlhps xmm0, xmm0
.1:
movntdq [rdi], xmm0
- add rdi, 16
+ movntdq [rdi + 16], xmm0
+ movntdq [rdi + 32], xmm0
+ movntdq [rdi + 48], xmm0
+ add rdi, 64
loop .1
mfence
@SetWords:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm
index 0fb531660b0..013b5bc7de7 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem32.nasm
@@ -43,14 +43,17 @@ ASM_PFX(InternalMemSetMem32):
rep stosd
.0:
mov rcx, rdx
- and edx, 3
- shr rcx, 2
+ and edx, 15
+ shr rcx, 4
jz @SetDwords
movd xmm0, eax
pshufd xmm0, xmm0, 0
.1:
movntdq [rdi], xmm0
- add rdi, 16
+ movntdq [rdi + 16], xmm0
+ movntdq [rdi + 32], xmm0
+ movntdq [rdi + 48], xmm0
+ add rdi, 64
loop .1
mfence
@SetDwords:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm
index d4f740e9d47..bff2cf46504 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/SetMem64.nasm
@@ -37,17 +37,28 @@ ASM_PFX(InternalMemSetMem64):
add rdx, 8
dec rcx
.0:
- shr rcx, 1
+ push rbx
+ mov rbx, rcx
+ and rbx, 7
+ shr rcx, 3
jz @SetQwords
movlhps xmm0, xmm0
.1:
movntdq [rdx], xmm0
- lea rdx, [rdx + 16]
+ movntdq [rdx + 16], xmm0
+ movntdq [rdx + 32], xmm0
+ movntdq [rdx + 48], xmm0
+ lea rdx, [rdx + 64]
loop .1
mfence
@SetQwords:
- jnc .2
- mov [rdx], r8
+ push rdi
+ mov rcx, rbx
+ mov rax, r8
+ mov rdi, rdx
+ rep stosq
+ pop rdi
.2:
+ pop rbx
ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm
index f5d263f219c..03a5f6da07b 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseMemoryLibSse2/X64/ZeroMem.nasm
@@ -32,7 +32,7 @@ ASM_PFX(InternalMemZeroMem):
xor rcx, rcx
xor eax, eax
sub rcx, rdi
- and rcx, 15
+ and rcx, 63
mov r8, rdi
jz .0
cmp rcx, rdx
@@ -41,13 +41,16 @@ ASM_PFX(InternalMemZeroMem):
rep stosb
.0:
mov rcx, rdx
- and edx, 15
- shr rcx, 4
+ and edx, 63
+ shr rcx, 6
jz @ZeroBytes
pxor xmm0, xmm0
.1:
- movntdq [rdi], xmm0 ; rdi should be 16-byte aligned
- add rdi, 16
+ movntdq [rdi], xmm0
+ movntdq [rdi + 16], xmm0
+ movntdq [rdi + 32], xmm0
+ movntdq [rdi + 48], xmm0
+ add rdi, 64
loop .1
mfence
@ZeroBytes:
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePcdLibNull/PcdLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePcdLibNull/PcdLib.c
index b79cb089caf..9fd345b948f 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePcdLibNull/PcdLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePcdLibNull/PcdLib.c
@@ -386,367 +386,6 @@ LibPcdGetExSize (
}
-
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSet8 (
- IN UINTN TokenNumber,
- IN UINT8 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSet16 (
- IN UINTN TokenNumber,
- IN UINT16 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSet32 (
- IN UINTN TokenNumber,
- IN UINT32 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSet64 (
- IN UINTN TokenNumber,
- IN UINT64 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value
- specified by Buffer and SizeOfBuffer. Buffer is returned.
- If SizeOfBuffer is greater than the maximum size support by TokenNumber,
- then set SizeOfBuffer to the maximum size supported by TokenNumber and
- return NULL to indicate that the set operation was not actually performed.
-
- If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the
- maximum size supported by TokenName and NULL must be returned.
-
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pointer for the buffer been set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetPtr (
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN CONST VOID *Buffer
- )
-{
- ASSERT (FALSE);
-
- return NULL;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The boolean value to set.
-
- @return Return the value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetBool (
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- )
-{
- ASSERT (FALSE);
-
- return FALSE;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSetEx8 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT8 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSetEx16 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT16 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSetEx32 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT32 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSetEx64 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT64 Value
- )
-{
- ASSERT (FALSE);
-
- return 0;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value specified by
- Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than
- the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size
- supported by TokenNumber and return NULL to indicate that the set operation
- was not actually performed.
-
- If Guid is NULL, then ASSERT().
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pinter to the buffer been set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetExPtr (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN VOID *Buffer
- )
-{
- ASSERT (FALSE);
-
- return NULL;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The Boolean value to set.
-
- @return Return the value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetExBool (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- )
-{
- ASSERT (FALSE);
-
- return FALSE;
-}
-#endif
-
/**
This function provides a means by which to set a value for a given PCD token.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
index ae2b69310b0..a868f187ed8 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
@@ -1,7 +1,7 @@
## @file
-# Instance of PCI Express Library using the 256 MB PCI Express MMIO window.
+# Instance of PCI Express Library using the variable size PCI Express MMIO window.
#
-# PCI Express Library that uses the 256 MB PCI Express MMIO window to perform
+# PCI Express Library that uses the variable size PCI Express MMIO window to perform
# PCI Configuration cycles. Layers on top of an I/O Library instance.
#
# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
@@ -39,4 +39,4 @@
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
-
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/PciExpressLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/PciExpressLib.c
index e598690d26b..20bdb70bafd 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/PciExpressLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciExpressLib/PciExpressLib.c
@@ -22,7 +22,8 @@
/**
Assert the validity of a PCI address. A valid PCI address should contain 1's
- only in the low 28 bits.
+ only in the low 28 bits. PcdPciExpressBaseSize limits the size to the real
+ number of PCI busses in this segment.
@param A The address to validate.
@@ -109,6 +110,24 @@ GetPciExpressBaseAddress (
}
/**
+ Gets the size of PCI Express.
+
+ This internal functions retrieves PCI Express Base Size via a PCD entry
+ PcdPciExpressBaseSize.
+
+ @return The base size of PCI Express.
+
+**/
+STATIC
+UINTN
+PcdPciExpressBaseSize (
+ VOID
+ )
+{
+ return (UINTN) PcdGet64 (PcdPciExpressBaseSize);
+}
+
+/**
Reads an 8-bit PCI configuration register.
Reads and returns the 8-bit PCI configuration register specified by Address.
@@ -120,7 +139,8 @@ GetPciExpressBaseAddress (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT8
@@ -130,6 +150,9 @@ PciExpressRead8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioRead8 ((UINTN) GetPciExpressBaseAddress () + Address);
}
@@ -146,7 +169,8 @@ PciExpressRead8 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT8
@@ -157,6 +181,9 @@ PciExpressWrite8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioWrite8 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
}
@@ -177,7 +204,8 @@ PciExpressWrite8 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT8
@@ -188,6 +216,9 @@ PciExpressOr8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioOr8 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
}
@@ -208,7 +239,8 @@ PciExpressOr8 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -219,6 +251,9 @@ PciExpressAnd8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioAnd8 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
}
@@ -241,7 +276,8 @@ PciExpressAnd8 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -253,6 +289,9 @@ PciExpressAndThenOr8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioAndThenOr8 (
(UINTN) GetPciExpressBaseAddress () + Address,
AndData,
@@ -278,7 +317,9 @@ PciExpressAndThenOr8 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..7.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration
+ register.
**/
UINT8
@@ -290,6 +331,9 @@ PciExpressBitFieldRead8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioBitFieldRead8 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -318,7 +362,8 @@ PciExpressBitFieldRead8 (
Range 0..7.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -331,6 +376,9 @@ PciExpressBitFieldWrite8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioBitFieldWrite8 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -363,7 +411,8 @@ PciExpressBitFieldWrite8 (
Range 0..7.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -376,6 +425,9 @@ PciExpressBitFieldOr8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioBitFieldOr8 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -408,7 +460,8 @@ PciExpressBitFieldOr8 (
Range 0..7.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -421,6 +474,9 @@ PciExpressBitFieldAnd8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioBitFieldAnd8 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -457,7 +513,8 @@ PciExpressBitFieldAnd8 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -471,6 +528,9 @@ PciExpressBitFieldAndThenOr8 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT8) -1;
+ }
return MmioBitFieldAndThenOr8 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -493,7 +553,8 @@ PciExpressBitFieldAndThenOr8 (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT16
@@ -503,6 +564,9 @@ PciExpressRead16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioRead16 ((UINTN) GetPciExpressBaseAddress () + Address);
}
@@ -520,7 +584,8 @@ PciExpressRead16 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT16
@@ -531,6 +596,9 @@ PciExpressWrite16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioWrite16 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
}
@@ -552,7 +620,8 @@ PciExpressWrite16 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -563,6 +632,9 @@ PciExpressOr16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioOr16 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
}
@@ -584,7 +656,8 @@ PciExpressOr16 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -595,6 +668,9 @@ PciExpressAnd16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioAnd16 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
}
@@ -618,7 +694,8 @@ PciExpressAnd16 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -630,6 +707,9 @@ PciExpressAndThenOr16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioAndThenOr16 (
(UINTN) GetPciExpressBaseAddress () + Address,
AndData,
@@ -656,7 +736,9 @@ PciExpressAndThenOr16 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..15.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration
+ register.
**/
UINT16
@@ -668,6 +750,9 @@ PciExpressBitFieldRead16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioBitFieldRead16 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -697,7 +782,8 @@ PciExpressBitFieldRead16 (
Range 0..15.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -710,6 +796,9 @@ PciExpressBitFieldWrite16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioBitFieldWrite16 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -743,7 +832,8 @@ PciExpressBitFieldWrite16 (
Range 0..15.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -756,6 +846,9 @@ PciExpressBitFieldOr16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioBitFieldOr16 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -789,7 +882,8 @@ PciExpressBitFieldOr16 (
Range 0..15.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -802,6 +896,9 @@ PciExpressBitFieldAnd16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioBitFieldAnd16 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -839,7 +936,8 @@ PciExpressBitFieldAnd16 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -853,6 +951,9 @@ PciExpressBitFieldAndThenOr16 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT16) -1;
+ }
return MmioBitFieldAndThenOr16 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -875,7 +976,8 @@ PciExpressBitFieldAndThenOr16 (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT32
@@ -885,6 +987,9 @@ PciExpressRead32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioRead32 ((UINTN) GetPciExpressBaseAddress () + Address);
}
@@ -902,7 +1007,8 @@ PciExpressRead32 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT32
@@ -913,6 +1019,9 @@ PciExpressWrite32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioWrite32 ((UINTN) GetPciExpressBaseAddress () + Address, Value);
}
@@ -934,7 +1043,8 @@ PciExpressWrite32 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -945,6 +1055,9 @@ PciExpressOr32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioOr32 ((UINTN) GetPciExpressBaseAddress () + Address, OrData);
}
@@ -966,7 +1079,8 @@ PciExpressOr32 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -977,6 +1091,9 @@ PciExpressAnd32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioAnd32 ((UINTN) GetPciExpressBaseAddress () + Address, AndData);
}
@@ -1000,7 +1117,8 @@ PciExpressAnd32 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1012,6 +1130,9 @@ PciExpressAndThenOr32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioAndThenOr32 (
(UINTN) GetPciExpressBaseAddress () + Address,
AndData,
@@ -1038,7 +1159,9 @@ PciExpressAndThenOr32 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..31.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI
+ configuration register.
**/
UINT32
@@ -1050,6 +1173,9 @@ PciExpressBitFieldRead32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioBitFieldRead32 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -1079,7 +1205,8 @@ PciExpressBitFieldRead32 (
Range 0..31.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1092,6 +1219,9 @@ PciExpressBitFieldWrite32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioBitFieldWrite32 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -1125,7 +1255,8 @@ PciExpressBitFieldWrite32 (
Range 0..31.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1138,6 +1269,9 @@ PciExpressBitFieldOr32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioBitFieldOr32 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -1171,7 +1305,8 @@ PciExpressBitFieldOr32 (
Range 0..31.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1184,6 +1319,9 @@ PciExpressBitFieldAnd32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioBitFieldAnd32 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -1221,7 +1359,8 @@ PciExpressBitFieldAnd32 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1235,6 +1374,9 @@ PciExpressBitFieldAndThenOr32 (
)
{
ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= PcdPciExpressBaseSize()) {
+ return (UINT32) -1;
+ }
return MmioBitFieldAndThenOr32 (
(UINTN) GetPciExpressBaseAddress () + Address,
StartBit,
@@ -1264,7 +1406,8 @@ PciExpressBitFieldAndThenOr32 (
@param Size The size in bytes of the transfer.
@param Buffer The pointer to a buffer receiving the data read.
- @return Size read data from StartAddress.
+ @retval (UINTN)-1 Invalid PCI address.
+ @retval other Size read data from StartAddress.
**/
UINTN
@@ -1278,6 +1421,9 @@ PciExpressReadBuffer (
UINTN ReturnValue;
ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+ if (StartAddress >= PcdPciExpressBaseSize()) {
+ return (UINTN) -1;
+ }
ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
if (Size == 0) {
@@ -1364,7 +1510,8 @@ PciExpressReadBuffer (
@param Size The size in bytes of the transfer.
@param Buffer The pointer to a buffer containing the data to write.
- @return Size written to StartAddress.
+ @retval (UINTN)-1 Invalid PCI address.
+ @retval other Size written to StartAddress.
**/
UINTN
@@ -1378,6 +1525,9 @@ PciExpressWriteBuffer (
UINTN ReturnValue;
ASSERT_INVALID_PCI_ADDRESS (StartAddress);
+ if (StartAddress >= PcdPciExpressBaseSize()) {
+ return (UINTN) -1;
+ }
ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
if (Size == 0) {
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c
index e90379d4a2d..69186859865 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePciSegmentInfoLibNull/PciSegmentInfoLib.c
@@ -2,7 +2,7 @@
Default PCI Segment Information Library that returns one segment whose
segment base address equals to PcdPciExpressBaseAddress.
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -21,6 +21,7 @@
@retval A callee owned array holding the segment information.
**/
PCI_SEGMENT_INFO *
+EFIAPI
GetPciSegmentInfo (
UINTN *Count
)
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLib.c
index 267d74404d7..7df0f165784 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLib.c
@@ -343,65 +343,6 @@ UnicodeSPrintAsciiFormat (
return NumberOfPrinted;
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Converts a decimal value to a Null-terminated Unicode string.
-
- Converts the decimal number specified by Value to a Null-terminated Unicode
- string specified by Buffer containing at most Width characters. No padding of spaces
- is ever performed. If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
- The number of Unicode characters in Buffer is returned not including the Null-terminator.
- If the conversion contains more than Width characters, then only the first
- Width characters are returned, and the total number of characters
- required to perform the conversion is returned.
- Additional conversion parameters are specified in Flags.
-
- The Flags bit LEFT_JUSTIFY is always ignored.
- All conversions are left justified in Buffer.
- If Width is 0, PREFIX_ZERO is ignored in Flags.
- If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
- are inserted every 3rd digit starting from the right.
- If RADIX_HEX is set in Flags, then the output buffer will be
- formatted in hexadecimal format.
- If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
- then Buffer is padded with '0' characters so the combination of the optional '-'
- sign character, '0' characters, digit characters for Value, and the Null-terminator
- add up to Width characters.
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Buffer is NULL, then ASSERT().
- If Buffer is not aligned on a 16-bit boundary, then ASSERT().
- If unsupported bits are set in Flags, then ASSERT().
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
-
- @param Buffer The pointer to the output buffer for the produced Null-terminated
- Unicode string.
- @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
- @param Value The 64-bit signed value to convert to a string.
- @param Width The maximum number of Unicode characters to place in Buffer, not including
- the Null-terminator.
-
- @return The number of Unicode characters in Buffer not including the Null-terminator.
-
-**/
-UINTN
-EFIAPI
-UnicodeValueToString (
- IN OUT CHAR16 *Buffer,
- IN UINTN Flags,
- IN INT64 Value,
- IN UINTN Width
- )
-{
- ASSERT_UNICODE_BUFFER(Buffer);
- return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 2);
-}
-
-#endif
/**
Converts a decimal value to a Null-terminated Unicode string.
@@ -780,65 +721,6 @@ AsciiSPrintUnicodeFormat (
return NumberOfPrinted;
}
-
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function is deprecated for security reason.
-
- Converts a decimal value to a Null-terminated ASCII string.
-
- Converts the decimal number specified by Value to a Null-terminated ASCII string
- specified by Buffer containing at most Width characters. No padding of spaces
- is ever performed.
- If Width is 0 then a width of MAXIMUM_VALUE_CHARACTERS is assumed.
- The number of ASCII characters in Buffer is returned not including the Null-terminator.
- If the conversion contains more than Width characters, then only the first Width
- characters are returned, and the total number of characters required to perform
- the conversion is returned.
- Additional conversion parameters are specified in Flags.
- The Flags bit LEFT_JUSTIFY is always ignored.
- All conversions are left justified in Buffer.
- If Width is 0, PREFIX_ZERO is ignored in Flags.
- If COMMA_TYPE is set in Flags, then PREFIX_ZERO is ignored in Flags, and commas
- are inserted every 3rd digit starting from the right.
- If RADIX_HEX is set in Flags, then the output buffer will be
- formatted in hexadecimal format.
- If Value is < 0 and RADIX_HEX is not set in Flags, then the fist character in Buffer is a '-'.
- If PREFIX_ZERO is set in Flags and PREFIX_ZERO is not being ignored,
- then Buffer is padded with '0' characters so the combination of the optional '-'
- sign character, '0' characters, digit characters for Value, and the Null-terminator
- add up to Width characters.
-
- If Buffer is NULL, then ASSERT().
- If unsupported bits are set in Flags, then ASSERT().
- If both COMMA_TYPE and RADIX_HEX are set in Flags, then ASSERT().
- If Width >= MAXIMUM_VALUE_CHARACTERS, then ASSERT()
-
- @param Buffer The pointer to the output buffer for the produced Null-terminated
- ASCII string.
- @param Flags The bitmask of flags that specify left justification, zero pad, and commas.
- @param Value The 64-bit signed value to convert to a string.
- @param Width The maximum number of ASCII characters to place in Buffer, not including
- the Null-terminator.
-
- @return The number of ASCII characters in Buffer not including the Null-terminator.
-
-**/
-UINTN
-EFIAPI
-AsciiValueToString (
- OUT CHAR8 *Buffer,
- IN UINTN Flags,
- IN INT64 Value,
- IN UINTN Width
- )
-{
- return BasePrintLibConvertValueToString (Buffer, Flags, Value, Width, 1);
-}
-
-#endif
-
/**
Converts a decimal value to a Null-terminated Ascii string.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLibInternal.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLibInternal.c
index 067e16372e2..4a2aa4e2889 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLibInternal.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BasePrintLib/PrintLibInternal.c
@@ -27,13 +27,22 @@
GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
-GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 * CONST mStatusString[] = {
+//
+// Longest string: RETURN_WARN_BUFFER_TOO_SMALL => 24 characters plus NUL byte
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mWarningString[][24+1] = {
"Success", // RETURN_SUCCESS = 0
"Warning Unknown Glyph", // RETURN_WARN_UNKNOWN_GLYPH = 1
"Warning Delete Failure", // RETURN_WARN_DELETE_FAILURE = 2
"Warning Write Failure", // RETURN_WARN_WRITE_FAILURE = 3
"Warning Buffer Too Small", // RETURN_WARN_BUFFER_TOO_SMALL = 4
"Warning Stale Data", // RETURN_WARN_STALE_DATA = 5
+};
+
+//
+// Longest string: RETURN_INCOMPATIBLE_VERSION => 20 characters plus NUL byte
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 mErrorString[][20+1] = {
"Load Error", // RETURN_LOAD_ERROR = 1 | MAX_BIT
"Invalid Parameter", // RETURN_INVALID_PARAMETER = 2 | MAX_BIT
"Unsupported", // RETURN_UNSUPPORTED = 3 | MAX_BIT
@@ -996,12 +1005,12 @@ BasePrintLibSPrintMarker (
//
Index = Status & ~MAX_BIT;
if (Index > 0 && Index <= ERROR_STATUS_NUMBER) {
- ArgumentString = mStatusString [Index + WARNING_STATUS_NUMBER];
+ ArgumentString = mErrorString [Index - 1];
}
} else {
Index = Status;
if (Index <= WARNING_STATUS_NUMBER) {
- ArgumentString = mStatusString [Index];
+ ArgumentString = mWarningString [Index];
}
}
if (ArgumentString == ValueBuffer) {
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S
new file mode 100644
index 00000000000..a3d41518d48
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.S
@@ -0,0 +1,31 @@
+#------------------------------------------------------------------------------
+#
+# ArmReadIdIsar0() for AArch64
+#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+.text
+.p2align 2
+GCC_ASM_EXPORT(ArmReadIdIsar0)
+
+#/**
+# Reads the ID_AA64ISAR0 Register.
+#
+# @return The contents of the ID_AA64ISAR0 register.
+#
+#**/
+#UINT64
+#EFIAPI
+#ArmReadIdIsar0 (
+# VOID
+# );
+#
+ASM_PFX(ArmReadIdIsar0):
+ mrs x0, id_aa64isar0_el1 // Read ID_AA64ISAR0 Register
+ ret
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm
new file mode 100644
index 00000000000..c04636437e0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmReadIdIsar0.asm
@@ -0,0 +1,30 @@
+;------------------------------------------------------------------------------
+;
+; ArmReadIdIsar0() for AArch64
+;
+; Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+ EXPORT ArmReadIdIsar0
+ AREA BaseLib_LowLevel, CODE, READONLY
+
+;/**
+; Reads the ID_AA64ISAR0 Register.
+;
+; @return The contents of the ID_AA64ISAR0 register.
+;
+;**/
+;UINT64
+;EFIAPI
+;ArmReadIdIsar0 (
+; VOID
+; );
+;
+ArmReadIdIsar0
+ mrs x0, id_aa64isar0_el1 // Read ID_AA64ISAR0 Register
+ ret
+
+ END
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
new file mode 100644
index 00000000000..3844c6eb1be
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
@@ -0,0 +1,37 @@
+#------------------------------------------------------------------------------
+#
+# ArmRndr() for AArch64
+#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#------------------------------------------------------------------------------
+
+#include "BaseRngLibInternals.h"
+
+.text
+.p2align 2
+GCC_ASM_EXPORT(ArmRndr)
+
+#/**
+# Generates a random number using RNDR.
+# Returns TRUE on success; FALSE on failure.
+#
+# @param[out] Rand Buffer pointer to store the 64-bit random value.
+#
+# @retval TRUE Random number generated successfully.
+# @retval FALSE Failed to generate the random number.
+#
+#**/
+#BOOLEAN
+#EFIAPI
+#ArmRndr (
+# OUT UINT64 *Rand
+# );
+#
+ASM_PFX(ArmRndr):
+ mrs x1, RNDR
+ str x1, [x0]
+ cset x0, ne // RNDR sets NZCV to 0b0100 on failure
+ ret
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
new file mode 100644
index 00000000000..76f6e960ac1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
@@ -0,0 +1,39 @@
+;------------------------------------------------------------------------------
+;
+; ArmRndr() for AArch64
+;
+; Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+#include "BaseRngLibInternals.h"
+
+ EXPORT ArmRndr
+ AREA BaseLib_LowLevel, CODE, READONLY
+
+
+;/**
+; Generates a random number using RNDR.
+; Returns TRUE on success; FALSE on failure.
+;
+; @param[out] Rand Buffer pointer to store the 64-bit random value.
+;
+; @retval TRUE Random number generated successfully.
+; @retval FALSE Failed to generate the random number.
+;
+;**/
+;BOOLEAN
+;EFIAPI
+;ArmRndr (
+; OUT UINT64 *Rand
+; );
+;
+ArmRndr
+ mrs x1, RNDR
+ str x1, [x0]
+ cset x0, ne // RNDR sets NZCV to 0b0100 on failure
+ ret
+
+ END
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
new file mode 100644
index 00000000000..a25ad1e4a36
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
@@ -0,0 +1,42 @@
+/** @file
+ Random number generator service that uses the RNDR instruction
+ to provide pseudorandom numbers.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef ARM_RNG_H_
+#define ARM_RNG_H_
+
+/**
+ Generates a random number using RNDR.
+ Returns TRUE on success; FALSE on failure.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArmRndr (
+ OUT UINT64 *Rand
+ );
+
+/**
+ Reads the ID_AA64ISAR0 Register.
+
+ @return The contents of the ID_AA64ISAR0 register.
+
+**/
+UINT64
+EFIAPI
+ArmReadIdIsar0 (
+ VOID
+ );
+
+#endif /* ARM_RNG_H_ */
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/Rndr.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
new file mode 100644
index 00000000000..6ffb327af66
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
@@ -0,0 +1,139 @@
+/** @file
+ Random number generator service that uses the RNDR instruction
+ to provide pseudorandom numbers.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/RngLib.h>
+
+#include "ArmRng.h"
+#include "BaseRngLibInternals.h"
+
+STATIC BOOLEAN mRndrSupported;
+
+//
+// Bit mask used to determine if RNDR instruction is supported.
+//
+#define RNDR_MASK ((UINT64)MAX_UINT16 << 60U)
+
+/**
+ The constructor function checks whether or not RNDR instruction is supported
+ by the host hardware.
+
+ The constructor function checks whether or not RNDR instruction is supported.
+ It will ASSERT() if RNDR instruction is not supported.
+ It will always return EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+BaseRngLibConstructor (
+ VOID
+ )
+{
+ UINT64 Isar0;
+ //
+ // Determine RNDR support by examining bits 63:60 of the ISAR0 register returned by
+ // MSR. A non-zero value indicates that the processor supports the RNDR instruction.
+ //
+ Isar0 = ArmReadIdIsar0 ();
+ ASSERT ((Isar0 & RNDR_MASK) != 0);
+
+ mRndrSupported = ((Isar0 & RNDR_MASK) != 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ UINT64 Rand64;
+
+ if (ArchGetRandomNumber64 (&Rand64)) {
+ *Rand = Rand64 & MAX_UINT16;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Generates a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ UINT64 Rand64;
+
+ if (ArchGetRandomNumber64 (&Rand64)) {
+ *Rand = Rand64 & MAX_UINT32;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Generates a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ return ArmRndr (Rand);
+}
+
+/**
+ Checks whether RNDR is supported.
+
+ @retval TRUE RNDR is supported.
+ @retval FALSE RNDR is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ArchIsRngSupported (
+ VOID
+ )
+{
+ return mRndrSupported;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRng.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRng.c
index 020112169a5..e6573e425dc 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRng.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRng.c
@@ -1,8 +1,10 @@
/** @file
- Random number generator services that uses RdRand instruction access
- to provide high-quality random numbers.
+ Random number generator services that uses CPU RNG instructions to
+ provide random numbers.
+Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,46 +12,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
-//
-// Bit mask used to determine if RdRand instruction is supported.
-//
-#define RDRAND_MASK BIT30
+#include "BaseRngLibInternals.h"
//
// Limited retry number when valid random data is returned.
// Uses the recommended value defined in Section 7.3.17 of "Intel 64 and IA-32
-// Architectures Software Developer's Mannual".
+// Architectures Software Developer's Manual".
//
-#define RDRAND_RETRY_LIMIT 10
-
-/**
- The constructor function checks whether or not RDRAND instruction is supported
- by the host hardware.
-
- The constructor function checks whether or not RDRAND instruction is supported.
- It will ASSERT() if RDRAND instruction is not supported.
- It will always return RETURN_SUCCESS.
-
- @retval RETURN_SUCCESS The constructor always returns EFI_SUCCESS.
-
-**/
-RETURN_STATUS
-EFIAPI
-BaseRngLibConstructor (
- VOID
- )
-{
- UINT32 RegEcx;
-
- //
- // Determine RDRAND support by examining bit 30 of the ECX register returned by
- // CPUID. A value of 1 indicates that processor support RDRAND instruction.
- //
- AsmCpuid (1, 0, 0, &RegEcx, 0);
- ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+#define GETRANDOM_RETRY_LIMIT 10
- return RETURN_SUCCESS;
-}
/**
Generates a 16-bit random number.
@@ -72,11 +43,19 @@ GetRandomNumber16 (
ASSERT (Rand != NULL);
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// A loop to fetch a 16 bit random value with a retry count limit.
//
- for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) {
- if (AsmRdRand16 (Rand)) {
+ for (Index = 0; Index < GETRANDOM_RETRY_LIMIT; Index++) {
+ if (ArchGetRandomNumber16 (Rand)) {
return TRUE;
}
}
@@ -105,11 +84,19 @@ GetRandomNumber32 (
ASSERT (Rand != NULL);
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// A loop to fetch a 32 bit random value with a retry count limit.
//
- for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) {
- if (AsmRdRand32 (Rand)) {
+ for (Index = 0; Index < GETRANDOM_RETRY_LIMIT; Index++) {
+ if (ArchGetRandomNumber32 (Rand)) {
return TRUE;
}
}
@@ -138,11 +125,19 @@ GetRandomNumber64 (
ASSERT (Rand != NULL);
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// A loop to fetch a 64 bit random value with a retry count limit.
//
- for (Index = 0; Index < RDRAND_RETRY_LIMIT; Index++) {
- if (AsmRdRand64 (Rand)) {
+ for (Index = 0; Index < GETRANDOM_RETRY_LIMIT; Index++) {
+ if (ArchGetRandomNumber64 (Rand)) {
return TRUE;
}
}
@@ -169,6 +164,14 @@ GetRandomNumber128 (
{
ASSERT (Rand != NULL);
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ if (!ArchIsRngSupported ()) {
+ return FALSE;
+ }
+
//
// Read first 64 bits
//
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.inf
index 3c25cc71114..e546efe9ed2 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.inf
@@ -1,9 +1,10 @@
## @file
# Instance of RNG (Random Number Generator) Library.
#
-# BaseRng Library that uses CPU RdRand instruction access to provide
-# high-quality random numbers.
+# BaseRng Library that uses CPU RNG instructions (e.g. RdRand) to
+# provide random numbers.
#
+# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -22,11 +23,25 @@
CONSTRUCTOR = BaseRngLibConstructor
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
-[Sources.Ia32, Sources.X64]
+[Sources]
BaseRng.c
+ BaseRngLibInternals.h
+
+[Sources.Ia32, Sources.X64]
+ Rand/RdRand.c
+
+[Sources.AARCH64]
+ AArch64/Rndr.c
+ AArch64/ArmRng.h
+
+ AArch64/ArmReadIdIsar0.S | GCC
+ AArch64/ArmRng.S | GCC
+
+ AArch64/ArmReadIdIsar0.asm | MSFT
+ AArch64/ArmRng.asm | MSFT
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.uni
index f3ed954c520..4e1fbfb0e40 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.uni
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLib.uni
@@ -1,8 +1,8 @@
// /** @file
// Instance of RNG (Random Number Generator) Library.
//
-// BaseRng Library that uses CPU RdRand instruction access to provide
-// high-quality random numbers.
+// BaseRng Library that uses CPU RNG instructions to provide
+// random numbers.
//
// Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
//
@@ -13,5 +13,4 @@
#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library"
-#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RdRand instruction access to provide high-quality random numbers"
-
+#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses CPU RNG instructions to provide random numbers"
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
new file mode 100644
index 00000000000..93d107ab9d4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
@@ -0,0 +1,78 @@
+/** @file
+
+ Architecture specific interface to RNG functionality.
+
+Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BASE_RNGLIB_INTERNALS_H_
+
+/**
+ Generates a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber16 (
+ OUT UINT16 *Rand
+ );
+
+/**
+ Generates a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber32 (
+ OUT UINT32 *Rand
+ );
+
+/**
+ Generates a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber64 (
+ OUT UINT64 *Rand
+ );
+
+/**
+ Checks whether the RNG instruction is supported.
+
+ @retval TRUE RNG instruction is supported.
+ @retval FALSE RNG instruction is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ArchIsRngSupported (
+ VOID
+ );
+
+#if defined (MDE_CPU_AARCH64)
+
+// RNDR, Random Number
+#define RNDR S3_3_C2_C4_0
+
+#endif
+
+#endif // BASE_RNGLIB_INTERNALS_H_
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/Rand/RdRand.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/Rand/RdRand.c
new file mode 100644
index 00000000000..d8834ab99b6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLib/Rand/RdRand.c
@@ -0,0 +1,131 @@
+/** @file
+ Random number generator services that uses RdRand instruction access
+ to provide high-quality random numbers.
+
+Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+
+#include "BaseRngLibInternals.h"
+
+//
+// Bit mask used to determine if RdRand instruction is supported.
+//
+#define RDRAND_MASK BIT30
+
+
+STATIC BOOLEAN mRdRandSupported;
+
+/**
+ The constructor function checks whether or not RDRAND instruction is supported
+ by the host hardware.
+
+ The constructor function checks whether or not RDRAND instruction is supported.
+ It will ASSERT() if RDRAND instruction is not supported.
+ It will always return EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+BaseRngLibConstructor (
+ VOID
+ )
+{
+ UINT32 RegEcx;
+
+ //
+ // Determine RDRAND support by examining bit 30 of the ECX register returned by
+ // CPUID. A value of 1 indicates that processor support RDRAND instruction.
+ //
+ AsmCpuid (1, 0, 0, &RegEcx, 0);
+ ASSERT ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+
+ mRdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Generates a 16-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ return AsmRdRand16 (Rand);
+}
+
+/**
+ Generates a 32-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ return AsmRdRand32 (Rand);
+}
+
+/**
+ Generates a 64-bit random number.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+ArchGetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ return AsmRdRand64 (Rand);
+}
+
+/**
+ Checks whether RDRAND is supported.
+
+ @retval TRUE RDRAND is supported.
+ @retval FALSE RDRAND is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ArchIsRngSupported (
+ VOID
+ )
+{
+ /*
+ Existing software depends on this always returning TRUE, so for
+ now hard-code it.
+
+ return mRdRandSupported;
+ */
+ return TRUE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
new file mode 100644
index 00000000000..600d4014b92
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
@@ -0,0 +1,36 @@
+## @file
+# Instance of RNG (Random Number Generator) Library.
+#
+# BaseRng Library that uses the TimerLib to provide reasonably random numbers.
+# Do NOT use this on a production system as this uses the system performance
+# counter rather than a true source of random in addition to having a weak
+# random algorithm. This is provided primarily as a source of entropy for
+# OpenSSL for platforms that do not have a good built in RngLib as this
+# emulates what was done before (though it isn't perfect).
+#
+# Copyright (c) Microsoft Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = BaseRngLibTimerLib
+ MODULE_UNI_FILE = BaseRngLibTimerLib.uni
+ FILE_GUID = 74950C45-10FC-4AB5-B114-49C87C17409B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RngLib
+
+[Sources]
+ RngLibTimer.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ TimerLib
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.uni
new file mode 100644
index 00000000000..fde24b9f010
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.uni
@@ -0,0 +1,15 @@
+// @file
+// Instance of RNG (Random Number Generator) Library.
+//
+// RngLib that uses TimerLib's performance counter to provide random numbers.
+//
+// Copyright (c) Microsoft Corporation.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses the TimerLib to provide low-entropy random numbers"
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/RngLibTimer.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/RngLibTimer.c
new file mode 100644
index 00000000000..9aa654fa4b1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseRngLibTimerLib/RngLibTimer.c
@@ -0,0 +1,189 @@
+/** @file
+ BaseRng Library that uses the TimerLib to provide reasonably random numbers.
+ Do not use this on a production system.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+
+#define DEFAULT_DELAY_TIME_IN_MICROSECONDS 10
+
+/**
+ Using the TimerLib GetPerformanceCounterProperties() we delay
+ for enough time for the PerformanceCounter to increment.
+
+ If the return value from GetPerformanceCounterProperties (TimerLib)
+ is zero, this function will return 10 and attempt to assert.
+ **/
+STATIC
+UINT32
+CalculateMinimumDecentDelayInMicroseconds (
+ VOID
+ )
+{
+ UINT64 CounterHz;
+
+ // Get the counter properties
+ CounterHz = GetPerformanceCounterProperties (NULL, NULL);
+ // Make sure we won't divide by zero
+ if (CounterHz == 0) {
+ ASSERT(CounterHz != 0); // Assert so the developer knows something is wrong
+ return DEFAULT_DELAY_TIME_IN_MICROSECONDS;
+ }
+ // Calculate the minimum delay based on 1.5 microseconds divided by the hertz.
+ // We calculate the length of a cycle (1/CounterHz) and multiply it by 1.5 microseconds
+ // This ensures that the performance counter has increased by at least one
+ return (UINT32)(MAX (DivU64x64Remainder (1500000,CounterHz, NULL), 1));
+}
+
+
+/**
+ Generates a 16-bit random number.
+
+ if Rand is NULL, then ASSERT().
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ UINT32 Index;
+ UINT8 *RandPtr;
+ UINT32 DelayInMicroSeconds;
+
+ ASSERT (Rand != NULL);
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+ DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
+ RandPtr = (UINT8*)Rand;
+ // Get 2 bytes of random ish data
+ for (Index = 0; Index < sizeof(UINT16); Index ++) {
+ *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
+ // Delay to give the performance counter a chance to change
+ MicroSecondDelay (DelayInMicroSeconds);
+ RandPtr++;
+ }
+ return TRUE;
+}
+
+/**
+ Generates a 32-bit random number.
+
+ if Rand is NULL, then ASSERT().
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ UINT32 Index;
+ UINT8 *RandPtr;
+ UINT32 DelayInMicroSeconds;
+
+ ASSERT (Rand != NULL);
+
+ if (NULL == Rand) {
+ return FALSE;
+ }
+
+ RandPtr = (UINT8 *) Rand;
+ DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
+ // Get 4 bytes of random ish data
+ for (Index = 0; Index < sizeof(UINT32); Index ++) {
+ *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
+ // Delay to give the performance counter a chance to change
+ MicroSecondDelay (DelayInMicroSeconds);
+ RandPtr++;
+ }
+ return TRUE;
+}
+
+/**
+ Generates a 64-bit random number.
+
+ if Rand is NULL, then ASSERT().
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ UINT32 Index;
+ UINT8 *RandPtr;
+ UINT32 DelayInMicroSeconds;
+
+ ASSERT (Rand != NULL);
+
+ if (NULL == Rand) {
+ return FALSE;
+ }
+
+ RandPtr = (UINT8 *)Rand;
+ DelayInMicroSeconds = CalculateMinimumDecentDelayInMicroseconds ();
+ // Get 8 bytes of random ish data
+ for (Index = 0; Index < sizeof(UINT64); Index ++) {
+ *RandPtr = (UINT8)(GetPerformanceCounter () & 0xFF);
+ // Delay to give the performance counter a chance to change
+ MicroSecondDelay (DelayInMicroSeconds);
+ RandPtr++;
+ }
+
+ return TRUE;
+}
+
+/**
+ Generates a 128-bit random number.
+
+ if Rand is NULL, then ASSERT().
+
+ @param[out] Rand Buffer pointer to store the 128-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber128 (
+ OUT UINT64 *Rand
+ )
+{
+ ASSERT (Rand != NULL);
+ // This should take around 80ms
+
+ // Read first 64 bits
+ if (!GetRandomNumber64 (Rand)) {
+ return FALSE;
+ }
+
+ // Read second 64 bits
+ return GetRandomNumber64 (++Rand);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
index 1ead5b877c8..5176aff7354 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
@@ -36,5 +36,5 @@
BaseLib
DebugLib
-[FixedPcd]
+[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxePcdLib/DxePcdLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxePcdLib/DxePcdLib.c
index f02d95cd6cc..2fc00349793 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxePcdLib/DxePcdLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxePcdLib/DxePcdLib.c
@@ -474,405 +474,6 @@ LibPcdGetExSize (
}
-
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSet8 (
- IN UINTN TokenNumber,
- IN UINT8 Value
- )
-{
- GetPcdProtocol()->Set8 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSet16 (
- IN UINTN TokenNumber,
- IN UINT16 Value
- )
-{
- GetPcdProtocol()->Set16 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSet32 (
- IN UINTN TokenNumber,
- IN UINT32 Value
- )
-{
- GetPcdProtocol()->Set32 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSet64 (
- IN UINTN TokenNumber,
- IN UINT64 Value
- )
-{
- GetPcdProtocol()->Set64 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value
- specified by Buffer and SizeOfBuffer. Buffer is returned.
- If SizeOfBuffer is greater than the maximum size support by TokenNumber,
- then set SizeOfBuffer to the maximum size supported by TokenNumber and
- return NULL to indicate that the set operation was not actually performed.
-
- If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the
- maximum size supported by TokenName and NULL must be returned.
-
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pointer for the buffer been set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetPtr (
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN CONST VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN InputSizeOfBuffer;
-
- ASSERT (SizeOfBuffer != NULL);
-
- if (*SizeOfBuffer > 0) {
- ASSERT (Buffer != NULL);
- }
-
- InputSizeOfBuffer = *SizeOfBuffer;
- Status = GetPcdProtocol()->SetPtr (TokenNumber, SizeOfBuffer, (VOID *) Buffer);
- if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) {
- return NULL;
- }
-
- return (VOID *)Buffer;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The boolean value to set.
-
- @return Return the value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetBool (
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- )
-{
- GetPcdProtocol()->SetBool (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSetEx8 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT8 Value
- )
-{
- ASSERT (Guid != NULL);
-
- GetPiPcdProtocol()->Set8 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSetEx16 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT16 Value
- )
-{
- ASSERT (Guid != NULL);
-
- GetPiPcdProtocol()->Set16 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSetEx32 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT32 Value
- )
-{
- ASSERT (Guid != NULL);
-
- GetPiPcdProtocol()->Set32 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSetEx64 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT64 Value
- )
-{
- ASSERT (Guid != NULL);
-
- GetPiPcdProtocol()->Set64 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value specified by
- Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than
- the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size
- supported by TokenNumber and return NULL to indicate that the set operation
- was not actually performed.
-
- If Guid is NULL, then ASSERT().
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pointer to the buffer been set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetExPtr (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN InputSizeOfBuffer;
-
- ASSERT (Guid != NULL);
-
- ASSERT (SizeOfBuffer != NULL);
-
- if (*SizeOfBuffer > 0) {
- ASSERT (Buffer != NULL);
- }
-
- InputSizeOfBuffer = *SizeOfBuffer;
- Status = GetPiPcdProtocol()->SetPtr (Guid, TokenNumber, SizeOfBuffer, Buffer);
- if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) {
- return NULL;
- }
-
- return Buffer;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The Boolean value to set.
-
- @return Return the value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetExBool (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- )
-{
- ASSERT (Guid != NULL);
-
- GetPiPcdProtocol()->SetBool (Guid, TokenNumber, Value);
-
- return Value;
-}
-#endif
-
/**
This function provides a means by which to set a value for a given PCD token.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.c
new file mode 100644
index 00000000000..c4ef2b02f88
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.c
@@ -0,0 +1,199 @@
+/** @file
+ Provides an implementation of the library class RngLib that uses the Rng protocol.
+
+ Copyright (c) Microsoft Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/RngLib.h>
+#include <Protocol/Rng.h>
+
+/**
+ Routine Description:
+
+ Generates a random number via the NIST
+ 800-9A algorithm. Refer to
+ http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf
+ for more information.
+
+ @param[out] Buffer Buffer to receive the random number.
+ @param[in] BufferSize Number of bytes in Buffer.
+
+ @retval EFI_SUCCESS or underlying failure code.
+**/
+STATIC
+EFI_STATUS
+GenerateRandomNumberViaNist800Algorithm (
+ OUT UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_RNG_PROTOCOL *RngProtocol;
+
+ RngProtocol = NULL;
+
+ if (Buffer == NULL) {
+ DEBUG((DEBUG_ERROR, "%a: Buffer == NULL.\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);
+ if (EFI_ERROR (Status) || RngProtocol == NULL) {
+ DEBUG((DEBUG_ERROR, "%a: Could not locate RNG prototocol, Status = %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Ctr256Guid, BufferSize, Buffer);
+ DEBUG((DEBUG_INFO, "%a: GetRNG algorithm CTR-256 - Status = %r\n", __FUNCTION__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hmac256Guid, BufferSize, Buffer);
+ DEBUG((DEBUG_INFO, "%a: GetRNG algorithm HMAC-256 - Status = %r\n", __FUNCTION__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RngProtocol->GetRNG (RngProtocol, &gEfiRngAlgorithmSp80090Hash256Guid, BufferSize, Buffer);
+ DEBUG((DEBUG_INFO, "%a: GetRNG algorithm Hash-256 - Status = %r\n", __FUNCTION__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ // If all the other methods have failed, use the default method from the RngProtocol
+ Status = RngProtocol->GetRNG (RngProtocol, NULL, BufferSize, Buffer);
+ DEBUG((DEBUG_INFO, "%a: GetRNG algorithm Hash-256 - Status = %r\n", __FUNCTION__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+ // If we get to this point, we have failed
+ DEBUG((DEBUG_ERROR, "%a: GetRNG() failed, staus = %r\n", __FUNCTION__, Status));
+
+ return Status;
+}// GenerateRandomNumberViaNist800Algorithm()
+
+
+/**
+ Generates a 16-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL)
+ {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof(UINT16));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Generates a 32-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8*)Rand, sizeof(UINT32));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Generates a 64-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8*)Rand, sizeof(UINT64));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ Generates a 128-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 128-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber128 (
+ OUT UINT64 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8*)Rand, 2 * sizeof(UINT64));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.inf
new file mode 100644
index 00000000000..4ef2a8a73b6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.inf
@@ -0,0 +1,38 @@
+# @file
+# Provides implementation of the library class RngLib that uses the RngProtocol
+#
+# @copyright
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = DxeRngLib
+ MODULE_UNI_FILE = DxeRngLib.uni
+ FILE_GUID = FF9F84C5-A33E-44E3-9BB5-0D654B2D4149
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RngLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[Sources]
+ DxeRngLib.c
+
+[LibraryClasses]
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiRngProtocolGuid ## CONSUMES
+
+[Depex]
+ gEfiRngProtocolGuid
+
+[Guids]
+ gEfiRngAlgorithmSp80090Ctr256Guid
+ gEfiRngAlgorithmSp80090Hash256Guid
+ gEfiRngAlgorithmSp80090Hmac256Guid
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.uni
new file mode 100644
index 00000000000..c904e54b6fb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRngLib/DxeRngLib.uni
@@ -0,0 +1,15 @@
+// @file
+// Instance of RNG (Random Number Generator) Library.
+//
+// RngLib that uses the Rng Protocol to provide random numbers.
+//
+// Copyright (c) Microsoft Corporation.
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Instance of RNG Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "BaseRng Library that uses the Rng Protocol to provide random numbers"
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf
index 65ad387c648..e0a71cbfe09 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/DxeRuntimePciExpressLib.inf
@@ -47,3 +47,4 @@
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c
index 17f15186a6f..255d43a8a46 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/DxeRuntimePciExpressLib/PciExpressLib.c
@@ -25,6 +25,16 @@
#include <Library/DxeServicesTableLib.h>
#include <Library/UefiRuntimeLib.h>
+/**
+ Assert the validity of a PCI address. A valid PCI address should contain 1's
+ only in the low 28 bits.
+
+ @param A The address to validate.
+
+**/
+#define ASSERT_INVALID_PCI_ADDRESS(A) \
+ ASSERT (((A) & ~0xfffffff) == 0)
+
///
/// Define table for mapping PCI Express MMIO physical addresses to virtual addresses at OS runtime
///
@@ -39,9 +49,10 @@ typedef struct {
EFI_EVENT mDxeRuntimePciExpressLibVirtualNotifyEvent = NULL;
///
-/// Module global that contains the base physical address of the PCI Express MMIO range.
+/// Module global that contains the base physical address and size of the PCI Express MMIO range.
///
UINTN mDxeRuntimePciExpressLibPciExpressBaseAddress = 0;
+UINTN mDxeRuntimePciExpressLibPciExpressBaseSize = 0;
///
/// The number of PCI devices that have been registered for runtime access.
@@ -120,6 +131,7 @@ DxeRuntimePciExpressLibConstructor (
// Cache the physical address of the PCI Express MMIO range into a module global variable
//
mDxeRuntimePciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+ mDxeRuntimePciExpressLibPciExpressBaseSize = (UINTN) PcdGet64 (PcdPciExpressBaseSize);
//
// Register SetVirtualAddressMap () notify function
@@ -179,8 +191,12 @@ DxeRuntimePciExpressLibDestructor (
This internal functions retrieves PCI Express Base Address via a PCD entry
PcdPciExpressBaseAddress.
- @param Address The address that encodes the PCI Bus, Device, Function and Register.
- @return The base address of PCI Express.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
+ @param Address The address that encodes the PCI Bus, Device, Function and Register.
+
+ @retval (UINTN)-1 Invalid PCI address.
+ @retval other The base address of PCI Express.
**/
UINTN
@@ -193,7 +209,14 @@ GetPciExpressAddress (
//
// Make sure Address is valid
//
- ASSERT (((Address) & ~0xfffffff) == 0);
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINTN) -1;
+ }
//
// Convert Address to a physical address in the MMIO PCI Express range
@@ -236,7 +259,6 @@ GetPciExpressAddress (
//
// No match was found. This is a critical error at OS runtime, so ASSERT() and force a breakpoint.
//
- ASSERT (FALSE);
CpuBreakpoint();
//
@@ -288,7 +310,14 @@ PciExpressRegisterForRuntimeAccess (
//
// Make sure Address is valid
//
- ASSERT (((Address) & ~0xfffffff) == 0);
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return RETURN_UNSUPPORTED;
+ }
//
// Convert Address to a physical address in the MMIO PCI Express range
@@ -354,8 +383,8 @@ PciExpressRegisterForRuntimeAccess (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
-
- @return The read value from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT8
@@ -364,6 +393,10 @@ PciExpressRead8 (
IN UINTN Address
)
{
+ ASSERT_INVALID_PCI_ADDRESS (Address);
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioRead8 (GetPciExpressAddress (Address));
}
@@ -380,7 +413,8 @@ PciExpressRead8 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT8
@@ -390,6 +424,9 @@ PciExpressWrite8 (
IN UINT8 Value
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioWrite8 (GetPciExpressAddress (Address), Value);
}
@@ -410,7 +447,8 @@ PciExpressWrite8 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -420,6 +458,9 @@ PciExpressOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioOr8 (GetPciExpressAddress (Address), OrData);
}
@@ -440,7 +481,8 @@ PciExpressOr8 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -450,6 +492,9 @@ PciExpressAnd8 (
IN UINT8 AndData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioAnd8 (GetPciExpressAddress (Address), AndData);
}
@@ -472,7 +517,8 @@ PciExpressAnd8 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -483,6 +529,9 @@ PciExpressAndThenOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioAndThenOr8 (
GetPciExpressAddress (Address),
AndData,
@@ -508,7 +557,8 @@ PciExpressAndThenOr8 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..7.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration register.
**/
UINT8
@@ -519,6 +569,9 @@ PciExpressBitFieldRead8 (
IN UINTN EndBit
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldRead8 (
GetPciExpressAddress (Address),
StartBit,
@@ -547,7 +600,8 @@ PciExpressBitFieldRead8 (
Range 0..7.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -559,6 +613,9 @@ PciExpressBitFieldWrite8 (
IN UINT8 Value
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldWrite8 (
GetPciExpressAddress (Address),
StartBit,
@@ -591,7 +648,8 @@ PciExpressBitFieldWrite8 (
Range 0..7.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -603,6 +661,9 @@ PciExpressBitFieldOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldOr8 (
GetPciExpressAddress (Address),
StartBit,
@@ -635,7 +696,8 @@ PciExpressBitFieldOr8 (
Range 0..7.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -647,6 +709,9 @@ PciExpressBitFieldAnd8 (
IN UINT8 AndData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldAnd8 (
GetPciExpressAddress (Address),
StartBit,
@@ -683,7 +748,8 @@ PciExpressBitFieldAnd8 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -696,6 +762,9 @@ PciExpressBitFieldAndThenOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldAndThenOr8 (
GetPciExpressAddress (Address),
StartBit,
@@ -718,7 +787,8 @@ PciExpressBitFieldAndThenOr8 (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT16
@@ -727,6 +797,9 @@ PciExpressRead16 (
IN UINTN Address
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioRead16 (GetPciExpressAddress (Address));
}
@@ -744,7 +817,8 @@ PciExpressRead16 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT16
@@ -754,6 +828,9 @@ PciExpressWrite16 (
IN UINT16 Value
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioWrite16 (GetPciExpressAddress (Address), Value);
}
@@ -775,7 +852,8 @@ PciExpressWrite16 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -785,6 +863,9 @@ PciExpressOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioOr16 (GetPciExpressAddress (Address), OrData);
}
@@ -806,7 +887,8 @@ PciExpressOr16 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -816,6 +898,9 @@ PciExpressAnd16 (
IN UINT16 AndData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioAnd16 (GetPciExpressAddress (Address), AndData);
}
@@ -839,7 +924,8 @@ PciExpressAnd16 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -850,6 +936,9 @@ PciExpressAndThenOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioAndThenOr16 (
GetPciExpressAddress (Address),
AndData,
@@ -876,7 +965,8 @@ PciExpressAndThenOr16 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..15.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration register.
**/
UINT16
@@ -887,6 +977,9 @@ PciExpressBitFieldRead16 (
IN UINTN EndBit
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldRead16 (
GetPciExpressAddress (Address),
StartBit,
@@ -916,7 +1009,8 @@ PciExpressBitFieldRead16 (
Range 0..15.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -928,6 +1022,9 @@ PciExpressBitFieldWrite16 (
IN UINT16 Value
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldWrite16 (
GetPciExpressAddress (Address),
StartBit,
@@ -961,7 +1058,8 @@ PciExpressBitFieldWrite16 (
Range 0..15.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -973,6 +1071,9 @@ PciExpressBitFieldOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldOr16 (
GetPciExpressAddress (Address),
StartBit,
@@ -1006,7 +1107,8 @@ PciExpressBitFieldOr16 (
Range 0..15.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -1018,6 +1120,9 @@ PciExpressBitFieldAnd16 (
IN UINT16 AndData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldAnd16 (
GetPciExpressAddress (Address),
StartBit,
@@ -1055,7 +1160,8 @@ PciExpressBitFieldAnd16 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -1068,6 +1174,9 @@ PciExpressBitFieldAndThenOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldAndThenOr16 (
GetPciExpressAddress (Address),
StartBit,
@@ -1090,7 +1199,8 @@ PciExpressBitFieldAndThenOr16 (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT32
@@ -1099,6 +1209,9 @@ PciExpressRead32 (
IN UINTN Address
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioRead32 (GetPciExpressAddress (Address));
}
@@ -1116,7 +1229,8 @@ PciExpressRead32 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT32
@@ -1126,6 +1240,9 @@ PciExpressWrite32 (
IN UINT32 Value
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioWrite32 (GetPciExpressAddress (Address), Value);
}
@@ -1147,7 +1264,8 @@ PciExpressWrite32 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1157,6 +1275,9 @@ PciExpressOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioOr32 (GetPciExpressAddress (Address), OrData);
}
@@ -1178,7 +1299,8 @@ PciExpressOr32 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1188,6 +1310,9 @@ PciExpressAnd32 (
IN UINT32 AndData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioAnd32 (GetPciExpressAddress (Address), AndData);
}
@@ -1211,7 +1336,8 @@ PciExpressAnd32 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1222,6 +1348,9 @@ PciExpressAndThenOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioAndThenOr32 (
GetPciExpressAddress (Address),
AndData,
@@ -1248,7 +1377,8 @@ PciExpressAndThenOr32 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..31.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration register.
**/
UINT32
@@ -1259,6 +1389,9 @@ PciExpressBitFieldRead32 (
IN UINTN EndBit
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldRead32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1288,7 +1421,8 @@ PciExpressBitFieldRead32 (
Range 0..31.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1300,6 +1434,9 @@ PciExpressBitFieldWrite32 (
IN UINT32 Value
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldWrite32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1333,7 +1470,8 @@ PciExpressBitFieldWrite32 (
Range 0..31.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1345,6 +1483,9 @@ PciExpressBitFieldOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldOr32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1378,7 +1519,8 @@ PciExpressBitFieldOr32 (
Range 0..31.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1390,6 +1532,9 @@ PciExpressBitFieldAnd32 (
IN UINT32 AndData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldAnd32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1427,7 +1572,8 @@ PciExpressBitFieldAnd32 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1440,6 +1586,9 @@ PciExpressBitFieldAndThenOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldAndThenOr32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1469,7 +1618,8 @@ PciExpressBitFieldAndThenOr32 (
@param Size The size in bytes of the transfer.
@param Buffer The pointer to a buffer receiving the data read.
- @return Size read data from StartAddress.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other Size read data from StartAddress.
**/
UINTN
@@ -1485,9 +1635,16 @@ PciExpressReadBuffer (
//
// Make sure Address is valid
//
- ASSERT (((StartAddress) & ~0xfffffff) == 0);
+ ASSERT_INVALID_PCI_ADDRESS (StartAddress);
ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (StartAddress >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINTN) -1;
+ }
+
if (Size == 0) {
return Size;
}
@@ -1572,7 +1729,8 @@ PciExpressReadBuffer (
@param Size The size in bytes of the transfer.
@param Buffer The pointer to a buffer containing the data to write.
- @return Size written to StartAddress.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other Size written to StartAddress.
**/
UINTN
@@ -1588,9 +1746,16 @@ PciExpressWriteBuffer (
//
// Make sure Address is valid
//
- ASSERT (((StartAddress) & ~0xfffffff) == 0);
+ ASSERT_INVALID_PCI_ADDRESS (StartAddress);
ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (StartAddress >= mDxeRuntimePciExpressLibPciExpressBaseSize) {
+ return (UINTN) -1;
+ }
+
if (Size == 0) {
return 0;
}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.c
new file mode 100644
index 00000000000..dcf9d71a2b7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.c
@@ -0,0 +1,44 @@
+/** @file
+ Null instance of MM Unblock Page Library.
+
+ This library provides an interface to request non-MMRAM pages to be mapped/unblocked
+ from inside MM environment.
+
+ For MM modules that need to access regions outside of MMRAMs, the agents that set up
+ these regions are responsible for invoking this API in order for these memory areas
+ to be accessed from inside MM.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+/**
+ This API provides a way to unblock certain data pages to be accessible inside MM environment.
+
+ @param UnblockAddress The address of buffer caller requests to unblock, the address
+ has to be page aligned.
+ @param NumberOfPages The number of pages requested to be unblocked from MM
+ environment.
+
+ @retval RETURN_SUCCESS The request goes through successfully.
+ @retval RETURN_NOT_AVAILABLE_YET The requested functionality is not produced yet.
+ @retval RETURN_UNSUPPORTED The requested functionality is not supported on current platform.
+ @retval RETURN_SECURITY_VIOLATION The requested address failed to pass security check for
+ unblocking.
+ @retval RETURN_INVALID_PARAMETER Input address either NULL pointer or not page aligned.
+ @retval RETURN_ACCESS_DENIED The request is rejected due to system has passed certain boot
+ phase.
+
+**/
+RETURN_STATUS
+EFIAPI
+MmUnblockMemoryRequest (
+ IN PHYSICAL_ADDRESS UnblockAddress,
+ IN UINT64 NumberOfPages
+ )
+{
+ return RETURN_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
new file mode 100644
index 00000000000..93d54c1ed25
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
@@ -0,0 +1,34 @@
+## @file
+# Null instance of MM Unblock Page Library.
+#
+# This library provides an interface to request non-MMRAM pages to be mapped/unblocked
+# from inside MM environment.
+#
+# For MM modules that need to access regions outside of MMRAMs, the agents that set up
+# these regions are responsible for invoking this API in order for these memory areas
+# to be accessed from inside MM.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = MmUnblockMemoryLibNull
+ MODULE_UNI_FILE = MmUnblockMemoryLibNull.uni
+ FILE_GUID = 9E890F68-5C95-4C31-95DD-59E6286F85EA
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MmUnblockMemoryLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MmUnblockMemoryLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.uni
new file mode 100644
index 00000000000..d7f2709a3dc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Null instance of MM Unblock Page Library.
+//
+// This library provides an interface to request non-MMRAM pages to be mapped/unblocked
+// from inside MM environment.
+//
+// For MM modules that need to access regions outside of MMRAMs, the agents that set up
+// these regions are responsible for invoking this API in order for these memory areas
+// to be accessed from inside MM.
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Null instance of MM Unblock Page Library."
+
+#string STR_MODULE_DESCRIPTION #language en-US "This library provides an interface to request non-MMRAM pages to be mapped/unblocked from inside MM environment.\n"
+ "For MM modules that need to access regions outside of MMRAMs, the agents that set up these regions are responsible for invoking this API in order for these memory areas to be accessed from inside MM."
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/PeiPcdLib/PeiPcdLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/PeiPcdLib/PeiPcdLib.c
index 87202285480..82191463b0c 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/PeiPcdLib/PeiPcdLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/PeiPcdLib/PeiPcdLib.c
@@ -474,403 +474,6 @@ LibPcdGetExSize (
}
-
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSet8 (
- IN UINTN TokenNumber,
- IN UINT8 Value
- )
-{
- (GetPcdPpiPointer ())->Set8 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSet16 (
- IN UINTN TokenNumber,
- IN UINT16 Value
- )
-{
- (GetPcdPpiPointer ())->Set16 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSet32 (
- IN UINTN TokenNumber,
- IN UINT32 Value
- )
-{
- (GetPcdPpiPointer ())->Set32 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSet64 (
- IN UINTN TokenNumber,
- IN UINT64 Value
- )
-{
- (GetPcdPpiPointer ())->Set64 (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value
- specified by Buffer and SizeOfBuffer. Buffer is returned.
- If SizeOfBuffer is greater than the maximum size support by TokenNumber,
- then set SizeOfBuffer to the maximum size supported by TokenNumber and
- return NULL to indicate that the set operation was not actually performed.
-
- If SizeOfBuffer is set to MAX_ADDRESS, then SizeOfBuffer must be set to the
- maximum size supported by TokenName and NULL must be returned.
-
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pointer for the buffer been set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetPtr (
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN CONST VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN InputSizeOfBuffer;
-
- ASSERT (SizeOfBuffer != NULL);
-
- if (*SizeOfBuffer > 0) {
- ASSERT (Buffer != NULL);
- }
-
- InputSizeOfBuffer = *SizeOfBuffer;
- Status = (GetPcdPpiPointer ())->SetPtr (TokenNumber, SizeOfBuffer, (VOID *) Buffer);
- if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) {
- return NULL;
- }
-
- return (VOID *) Buffer;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber
- to the value specified by Value. Value is returned.
-
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The boolean value to set.
-
- @return Return the value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetBool (
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- )
-{
- (GetPcdPpiPointer ())->SetBool (TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 8-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 8-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT8
-EFIAPI
-LibPcdSetEx8 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT8 Value
- )
-{
- ASSERT (Guid != NULL);
-
- (GetPiPcdPpiPointer ())->Set8 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 16-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 16-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT16
-EFIAPI
-LibPcdSetEx16 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT16 Value
- )
-{
- ASSERT (Guid != NULL);
-
- (GetPiPcdPpiPointer ())->Set16 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 32-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 32-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT32
-EFIAPI
-LibPcdSetEx32 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT32 Value
- )
-{
- ASSERT (Guid != NULL);
-
- (GetPiPcdPpiPointer ())->Set32 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the 64-bit value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The 64-bit value to set.
-
- @return Return the value that was set.
-
-**/
-UINT64
-EFIAPI
-LibPcdSetEx64 (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN UINT64 Value
- )
-{
- ASSERT (Guid != NULL);
-
- (GetPiPcdPpiPointer ())->Set64 (Guid, TokenNumber, Value);
-
- return Value;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets a buffer for the token specified by TokenNumber to the value specified by
- Buffer and SizeOfBuffer. Buffer is returned. If SizeOfBuffer is greater than
- the maximum size support by TokenNumber, then set SizeOfBuffer to the maximum size
- supported by TokenNumber and return NULL to indicate that the set operation
- was not actually performed.
-
- If Guid is NULL, then ASSERT().
- If SizeOfBuffer is NULL, then ASSERT().
- If SizeOfBuffer > 0 and Buffer is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in, out] SizeOfBuffer The size, in bytes, of Buffer.
- @param[in] Buffer A pointer to the buffer to set.
-
- @return Return the pinter to the buffer been set.
-
-**/
-VOID *
-EFIAPI
-LibPcdSetExPtr (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN OUT UINTN *SizeOfBuffer,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINTN InputSizeOfBuffer;
-
- ASSERT (SizeOfBuffer != NULL);
- if (*SizeOfBuffer > 0) {
- ASSERT (Buffer != NULL);
- }
- ASSERT (Guid != NULL);
-
- InputSizeOfBuffer = *SizeOfBuffer;
- Status = (GetPiPcdPpiPointer ())->SetPtr (Guid, TokenNumber, SizeOfBuffer, Buffer);
- if (EFI_ERROR (Status) && (*SizeOfBuffer < InputSizeOfBuffer)) {
- return NULL;
- }
-
- return Buffer;
-}
-
-
-
-/**
- This function provides a means by which to set a value for a given PCD token.
-
- Sets the Boolean value for the token specified by TokenNumber and
- Guid to the value specified by Value. Value is returned.
-
- If Guid is NULL, then ASSERT().
-
- @param[in] Guid The pointer to a 128-bit unique value that
- designates which namespace to set a value from.
- @param[in] TokenNumber The PCD token number to set a current value for.
- @param[in] Value The Boolean value to set.
-
- @return Return the value that was set.
-
-**/
-BOOLEAN
-EFIAPI
-LibPcdSetExBool (
- IN CONST GUID *Guid,
- IN UINTN TokenNumber,
- IN BOOLEAN Value
- )
-{
- ASSERT (Guid != NULL);
-
- (GetPiPcdPpiPointer ())->SetBool (Guid, TokenNumber, Value);
-
- return Value;
-}
-#endif
-
/**
This function provides a means by which to set a value for a given PCD token.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.c
new file mode 100644
index 00000000000..5fe27dcf25f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.c
@@ -0,0 +1,271 @@
+/** @file
+ Null instance of RegisterFilterLib.
+
+ Copyright (c) 2021 Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/RegisterFilterLib.h>
+
+/**
+ Filter IO read operation before read IO port.
+ It is used to filter IO read operation.
+
+ It will return the flag to decide whether require read real IO port.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in,out] Buffer The destination buffer to store the results.
+
+ @retval TRUE Need to excute the IO read.
+ @retval FALSE Skip the IO read.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN OUT VOID *Buffer
+ )
+{
+ return TRUE;
+}
+
+/**
+ Trace IO read operation after read IO port.
+ It is used to trace IO operation.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The destination buffer to store the results.
+
+**/
+VOID
+EFIAPI
+FilterAfterIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ )
+{
+ return;
+}
+
+/**
+ Filter IO Write operation before wirte IO port.
+ It is used to filter IO operation.
+
+ It will return the flag to decide whether require read write IO port.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The source buffer from which to write data.
+
+ @retval TRUE Need to excute the IO write.
+ @retval FALSE Skip the IO write.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ )
+{
+ return TRUE;
+}
+
+ /**
+ Trace IO Write operation after wirte IO port.
+ It is used to trace IO operation.
+
+ @param[in] Width Signifies the width of the I/O operation.
+ @param[in] Address The base address of the I/O operation.
+ @param[in] Buffer The source buffer from which to Write data.
+
+**/
+VOID
+EFIAPI
+FilterAfterIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ )
+{
+ return;
+}
+
+/**
+ Filter memory IO before Read operation.
+
+ It will return the flag to decide whether require read real MMIO.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in,out] Buffer The destination buffer to store the results.
+
+ @retval TRUE Need to excute the MMIO read.
+ @retval FALSE Skip the MMIO read.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMmIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN OUT VOID *Buffer
+ )
+{
+ return TRUE;
+}
+
+/**
+ Tracer memory IO after read operation.
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The destination buffer to store the results.
+
+**/
+VOID
+EFIAPI
+FilterAfterMmIoRead (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ )
+{
+ return;
+}
+
+/**
+ Filter memory IO before write operation.
+
+ It will return the flag to decide whether require wirte real MMIO.
+ It can be used for emulation environment.
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The source buffer from which to write data.
+
+ @retval TRUE Need to excute the MMIO write.
+ @retval FALSE Skip the MMIO write.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMmIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ )
+{
+ return TRUE;
+}
+
+/**
+ Tracer memory IO after write operation.
+
+ @param[in] Width Signifies the width of the memory I/O operation.
+ @param[in] Address The base address of the memory I/O operation.
+ @param[in] Buffer The source buffer from which to write data.
+
+**/
+VOID
+EFIAPI
+FilterAfterMmIoWrite (
+ IN FILTER_IO_WIDTH Width,
+ IN UINTN Address,
+ IN VOID *Buffer
+ )
+{
+ return;
+}
+
+/**
+ Filter MSR before read operation.
+
+ It will return the flag to decide whether require read real MSR.
+ It can be used for emulation environment.
+
+ @param Index The Register index of the MSR.
+ @param Value Point to the data will be read from the MSR.
+
+ @retval TRUE Need to excute the MSR read.
+ @retval FALSE Skip the MSR read.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMsrRead (
+ IN UINT32 Index,
+ IN OUT UINT64 *Value
+ )
+{
+ return TRUE;
+}
+
+/**
+ Trace MSR after read operation.
+
+ @param Index The Register index of the MSR.
+ @param Value Point to the data has been be read from the MSR.
+
+**/
+VOID
+EFIAPI
+FilterAfterMsrRead (
+ IN UINT32 Index,
+ IN UINT64 *Value
+ )
+{
+ return;
+}
+
+/**
+ Filter MSR before write operation.
+
+ It will return the flag to decide whether require write real MSR.
+ It can be used for emulation environment.
+
+ @param Index The Register index of the MSR.
+ @param Value Point to the data want to be written to the MSR.
+
+ @retval TRUE Need to excute the MSR write.
+ @retval FALSE Skip the MSR write.
+
+**/
+BOOLEAN
+EFIAPI
+FilterBeforeMsrWrite (
+ IN UINT32 Index,
+ IN UINT64 *Value
+ )
+{
+ return TRUE;
+}
+
+/**
+ Trace MSR after write operation.
+
+ @param Index The Register index of the MSR.
+ @param Value Point to the data has been be written to the MSR.
+
+**/
+VOID
+EFIAPI
+FilterAfterMsrWrite (
+ IN UINT32 Index,
+ IN UINT64 *Value
+ )
+{
+ return;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
new file mode 100644
index 00000000000..1357077af65
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
@@ -0,0 +1,23 @@
+## @file
+# Null instance of RegisterFilterLib.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = FilterLibNull
+ MODULE_UNI_FILE = FilterLibNull.uni
+ FILE_GUID = 9F555194-A410-4AD6-B3FC-53F6E10FA793
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RegisterFilterLib
+
+[Sources]
+ RegisterFilterLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.uni b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.uni
new file mode 100644
index 00000000000..ed64c7e63db
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Null instance of RegisterFilterLib.
+//
+// Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Null instance of RegisterFilterLib."
+#string STR_MODULE_DESCRIPTION #language en-US "Null instance of RegisterFilterLib."
+
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c
index 7555c9aa2eb..2a30b956d7d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.c
@@ -6,7 +6,7 @@
**/
-#include <PiSmm.h>
+#include <PiMm.h>
#include <Library/SmiHandlerProfileLib.h>
/**
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
index 61c43b4ef2f..228f8032ed0 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
@@ -15,7 +15,7 @@
FILE_GUID = B43D1B52-6251-4E6F-82EC-A599A5EE94C1
MODULE_TYPE = DXE_SMM_DRIVER
VERSION_STRING = 1.0
- LIBRARY_CLASS = SmiHandlerProfileLib|DXE_SMM_DRIVER SMM_CORE
+ LIBRARY_CLASS = SmiHandlerProfileLib|DXE_SMM_DRIVER SMM_CORE MM_STANDALONE MM_CORE_STANDALONE
#
# The following information is for reference only and not required by the build tools.
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
index 2b07cda94de..35ba79c44b9 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/PciExpressLib.c
@@ -20,9 +20,10 @@
#include <Library/PcdLib.h>
///
-/// Module global that contains the base physical address of the PCI Express MMIO range.
+/// Module global that contains the base physical address and size of the PCI Express MMIO range.
///
UINTN mSmmPciExpressLibPciExpressBaseAddress = 0;
+UINTN mSmmPciExpressLibPciExpressBaseSize = 0;
/**
The constructor function caches the PCI Express Base Address
@@ -40,9 +41,10 @@ SmmPciExpressLibConstructor (
)
{
//
- // Cache the physical address of the PCI Express MMIO range into a module global variable
+ // Cache the physical address and size of the PCI Express MMIO range into a module global variable
//
mSmmPciExpressLibPciExpressBaseAddress = (UINTN) PcdGet64 (PcdPciExpressBaseAddress);
+ mSmmPciExpressLibPciExpressBaseSize = (UINTN) PcdGet64 (PcdPciExpressBaseSize);
return EFI_SUCCESS;
}
@@ -97,8 +99,12 @@ PciExpressRegisterForRuntimeAccess (
mSmmPciExpressLibPciExpressBaseAddress is initialized in the library constructor from PCD entry
PcdPciExpressBaseAddress.
+ If Address > 0x0FFFFFFF, then ASSERT().
+
@param Address The address that encodes the PCI Bus, Device, Function and Register.
- @return MMIO address corresponding to Address.
+
+ @retval (UINTN)-1 Invalid PCI address.
+ @retval other MMIO address corresponding to Address.
**/
UINTN
@@ -110,6 +116,12 @@ GetPciExpressAddress (
// Make sure Address is valid
//
ASSERT_INVALID_PCI_ADDRESS (Address);
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINTN) -1;
+ }
return mSmmPciExpressLibPciExpressBaseAddress + Address;
}
@@ -125,7 +137,8 @@ GetPciExpressAddress (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT8
@@ -134,6 +147,9 @@ PciExpressRead8 (
IN UINTN Address
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioRead8 (GetPciExpressAddress (Address));
}
@@ -150,7 +166,8 @@ PciExpressRead8 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT8
@@ -160,6 +177,9 @@ PciExpressWrite8 (
IN UINT8 Value
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioWrite8 (GetPciExpressAddress (Address), Value);
}
@@ -180,7 +200,8 @@ PciExpressWrite8 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -190,6 +211,9 @@ PciExpressOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioOr8 (GetPciExpressAddress (Address), OrData);
}
@@ -210,7 +234,8 @@ PciExpressOr8 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -220,6 +245,9 @@ PciExpressAnd8 (
IN UINT8 AndData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioAnd8 (GetPciExpressAddress (Address), AndData);
}
@@ -242,7 +270,8 @@ PciExpressAnd8 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -253,6 +282,9 @@ PciExpressAndThenOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioAndThenOr8 (
GetPciExpressAddress (Address),
AndData,
@@ -278,7 +310,8 @@ PciExpressAndThenOr8 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..7.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration register.
**/
UINT8
@@ -289,6 +322,9 @@ PciExpressBitFieldRead8 (
IN UINTN EndBit
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldRead8 (
GetPciExpressAddress (Address),
StartBit,
@@ -317,7 +353,8 @@ PciExpressBitFieldRead8 (
Range 0..7.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -329,6 +366,9 @@ PciExpressBitFieldWrite8 (
IN UINT8 Value
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldWrite8 (
GetPciExpressAddress (Address),
StartBit,
@@ -361,7 +401,8 @@ PciExpressBitFieldWrite8 (
Range 0..7.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -373,6 +414,9 @@ PciExpressBitFieldOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldOr8 (
GetPciExpressAddress (Address),
StartBit,
@@ -405,7 +449,8 @@ PciExpressBitFieldOr8 (
Range 0..7.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -417,6 +462,9 @@ PciExpressBitFieldAnd8 (
IN UINT8 AndData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldAnd8 (
GetPciExpressAddress (Address),
StartBit,
@@ -453,7 +501,8 @@ PciExpressBitFieldAnd8 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT8
@@ -466,6 +515,9 @@ PciExpressBitFieldAndThenOr8 (
IN UINT8 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT8) -1;
+ }
return MmioBitFieldAndThenOr8 (
GetPciExpressAddress (Address),
StartBit,
@@ -488,7 +540,8 @@ PciExpressBitFieldAndThenOr8 (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT16
@@ -497,6 +550,9 @@ PciExpressRead16 (
IN UINTN Address
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioRead16 (GetPciExpressAddress (Address));
}
@@ -514,7 +570,8 @@ PciExpressRead16 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT16
@@ -524,6 +581,9 @@ PciExpressWrite16 (
IN UINT16 Value
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioWrite16 (GetPciExpressAddress (Address), Value);
}
@@ -545,7 +605,8 @@ PciExpressWrite16 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -555,6 +616,9 @@ PciExpressOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioOr16 (GetPciExpressAddress (Address), OrData);
}
@@ -576,7 +640,8 @@ PciExpressOr16 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -586,6 +651,9 @@ PciExpressAnd16 (
IN UINT16 AndData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioAnd16 (GetPciExpressAddress (Address), AndData);
}
@@ -609,7 +677,8 @@ PciExpressAnd16 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -620,6 +689,9 @@ PciExpressAndThenOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioAndThenOr16 (
GetPciExpressAddress (Address),
AndData,
@@ -646,7 +718,8 @@ PciExpressAndThenOr16 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..15.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration register.
**/
UINT16
@@ -657,6 +730,9 @@ PciExpressBitFieldRead16 (
IN UINTN EndBit
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldRead16 (
GetPciExpressAddress (Address),
StartBit,
@@ -686,7 +762,8 @@ PciExpressBitFieldRead16 (
Range 0..15.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -698,6 +775,9 @@ PciExpressBitFieldWrite16 (
IN UINT16 Value
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldWrite16 (
GetPciExpressAddress (Address),
StartBit,
@@ -731,7 +811,8 @@ PciExpressBitFieldWrite16 (
Range 0..15.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -743,6 +824,9 @@ PciExpressBitFieldOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldOr16 (
GetPciExpressAddress (Address),
StartBit,
@@ -776,7 +860,8 @@ PciExpressBitFieldOr16 (
Range 0..15.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -788,6 +873,9 @@ PciExpressBitFieldAnd16 (
IN UINT16 AndData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldAnd16 (
GetPciExpressAddress (Address),
StartBit,
@@ -825,7 +913,8 @@ PciExpressBitFieldAnd16 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT16
@@ -838,6 +927,9 @@ PciExpressBitFieldAndThenOr16 (
IN UINT16 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT16) -1;
+ }
return MmioBitFieldAndThenOr16 (
GetPciExpressAddress (Address),
StartBit,
@@ -860,7 +952,8 @@ PciExpressBitFieldAndThenOr16 (
@param Address The address that encodes the PCI Bus, Device, Function and
Register.
- @return The read value from the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The read value from the PCI configuration register.
**/
UINT32
@@ -869,6 +962,9 @@ PciExpressRead32 (
IN UINTN Address
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioRead32 (GetPciExpressAddress (Address));
}
@@ -886,7 +982,8 @@ PciExpressRead32 (
Register.
@param Value The value to write.
- @return The value written to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written to the PCI configuration register.
**/
UINT32
@@ -896,6 +993,9 @@ PciExpressWrite32 (
IN UINT32 Value
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioWrite32 (GetPciExpressAddress (Address), Value);
}
@@ -917,7 +1017,8 @@ PciExpressWrite32 (
Register.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -927,6 +1028,9 @@ PciExpressOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioOr32 (GetPciExpressAddress (Address), OrData);
}
@@ -948,7 +1052,8 @@ PciExpressOr32 (
Register.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -958,6 +1063,9 @@ PciExpressAnd32 (
IN UINT32 AndData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioAnd32 (GetPciExpressAddress (Address), AndData);
}
@@ -981,7 +1089,8 @@ PciExpressAnd32 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -992,6 +1101,9 @@ PciExpressAndThenOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioAndThenOr32 (
GetPciExpressAddress (Address),
AndData,
@@ -1018,7 +1130,8 @@ PciExpressAndThenOr32 (
@param EndBit The ordinal of the most significant bit in the bit field.
Range 0..31.
- @return The value of the bit field read from the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value of the bit field read from the PCI configuration register.
**/
UINT32
@@ -1029,6 +1142,9 @@ PciExpressBitFieldRead32 (
IN UINTN EndBit
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldRead32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1058,7 +1174,8 @@ PciExpressBitFieldRead32 (
Range 0..31.
@param Value The new value of the bit field.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1070,6 +1187,9 @@ PciExpressBitFieldWrite32 (
IN UINT32 Value
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldWrite32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1103,7 +1223,8 @@ PciExpressBitFieldWrite32 (
Range 0..31.
@param OrData The value to OR with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1115,6 +1236,9 @@ PciExpressBitFieldOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldOr32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1148,7 +1272,8 @@ PciExpressBitFieldOr32 (
Range 0..31.
@param AndData The value to AND with the PCI configuration register.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1160,6 +1285,9 @@ PciExpressBitFieldAnd32 (
IN UINT32 AndData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldAnd32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1197,7 +1325,8 @@ PciExpressBitFieldAnd32 (
@param AndData The value to AND with the PCI configuration register.
@param OrData The value to OR with the result of the AND operation.
- @return The value written back to the PCI configuration register.
+ @retval 0xFFFFFFFF Invalid PCI address.
+ @retval other The value written back to the PCI configuration register.
**/
UINT32
@@ -1210,6 +1339,9 @@ PciExpressBitFieldAndThenOr32 (
IN UINT32 OrData
)
{
+ if (Address >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINT32) -1;
+ }
return MmioBitFieldAndThenOr32 (
GetPciExpressAddress (Address),
StartBit,
@@ -1239,7 +1371,8 @@ PciExpressBitFieldAndThenOr32 (
@param Size The size in bytes of the transfer.
@param Buffer The pointer to a buffer receiving the data read.
- @return Size read data from StartAddress.
+ @retval (UINTN)-1 Invalid PCI address.
+ @retval other Size read data from StartAddress.
**/
UINTN
@@ -1258,6 +1391,13 @@ PciExpressReadBuffer (
ASSERT_INVALID_PCI_ADDRESS (StartAddress);
ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (StartAddress >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINTN) -1;
+ }
+
if (Size == 0) {
return Size;
}
@@ -1342,7 +1482,8 @@ PciExpressReadBuffer (
@param Size The size in bytes of the transfer.
@param Buffer The pointer to a buffer containing the data to write.
- @return Size written to StartAddress.
+ @retval (UINTN)-1 Invalid PCI address.
+ @retval other Size written to StartAddress.
**/
UINTN
@@ -1361,6 +1502,13 @@ PciExpressWriteBuffer (
ASSERT_INVALID_PCI_ADDRESS (StartAddress);
ASSERT (((StartAddress & 0xFFF) + Size) <= 0x1000);
+ //
+ // Make sure the Address is in MMCONF address space
+ //
+ if (StartAddress >= mSmmPciExpressLibPciExpressBaseSize) {
+ return (UINTN) -1;
+ }
+
if (Size == 0) {
return 0;
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
index 8855ee32c39..523a3e1d9f1 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
@@ -35,3 +35,4 @@
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c
index db77bf115f0..fba95cf47a2 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.c
@@ -1,7 +1,7 @@
/** @file
Entry point to a Standalone MM driver.
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2018, ARM Ltd. All rights reserved.<BR>
Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
@@ -11,12 +11,52 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <PiMm.h>
+#include <Protocol/LoadedImage.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/MmServicesTableLib.h>
#include <Library/StandaloneMmDriverEntryPoint.h>
/**
+ Unloads an image from memory.
+
+ This function is a callback that a driver registers to do cleanup
+ when the UnloadImage boot service function is called.
+
+ @param ImageHandle The handle to the image to unload.
+
+ @return Status returned by all unload().
+
+**/
+EFI_STATUS
+EFIAPI
+_DriverUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If an UnloadImage() handler is specified, then call it
+ //
+ Status = ProcessModuleUnloadList (ImageHandle);
+
+ //
+ // If the driver specific unload handler does not return an error, then call all of the
+ // library destructors. If the unload handler returned an error, then the driver can not be
+ // unloaded, and the library destructors should not be called
+ //
+ if (!EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, gMmst);
+ }
+
+ //
+ // Return the status from the driver specific unload handler
+ //
+ return Status;
+}
+
+/**
The entry point of PE/COFF Image for a Standalone MM Driver.
This function is the entry point for a Standalone MM Driver.
@@ -46,6 +86,7 @@ _ModuleEntryPoint (
)
{
EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
if (_gMmRevision != 0) {
//
@@ -63,6 +104,19 @@ _ModuleEntryPoint (
ProcessLibraryConstructorList (ImageHandle, MmSystemTable);
//
+ // Install unload handler...
+ //
+ if (_gDriverUnloadImageCount != 0) {
+ Status = gMmst->MmHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ LoadedImage->Unload = _DriverUnloadHandler;
+ }
+
+ //
// Call the driver entry point
//
Status = ProcessModuleEntryPointList (ImageHandle, MmSystemTable);
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
index 635033e2517..a83545aac05 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
@@ -1,7 +1,7 @@
## @file
# Module entry point library for Standalone MM driver.
#
-# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016-2018, ARM Ltd. All rights reserved.<BR>
# Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
#
@@ -36,3 +36,6 @@
BaseLib
DebugLib
MmServicesTableLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c
index a478b26af15..fd802ef49b2 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilities.c
@@ -807,39 +807,6 @@ UefiDevicePathLibIsDevicePathMultiInstance (
/**
- Retrieves the device path protocol from a handle.
-
- This function returns the device path protocol from the handle specified by Handle.
- If Handle is NULL or Handle does not contain a device path protocol, then NULL
- is returned.
-
- @param Handle The handle from which to retrieve the device
- path protocol.
-
- @return The device path protocol from the handle specified by Handle.
-
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-DevicePathFromHandle (
- IN EFI_HANDLE Handle
- )
-{
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_STATUS Status;
-
- Status = gBS->HandleProtocol (
- Handle,
- &gEfiDevicePathProtocolGuid,
- (VOID *) &DevicePath
- );
- if (EFI_ERROR (Status)) {
- DevicePath = NULL;
- }
- return DevicePath;
-}
-
-/**
Allocates a device path for a file and appends it to an existing device path.
If Device is a valid device handle that contains a device path protocol, then a device path for
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesDxeSmm.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesDxeSmm.c
new file mode 100644
index 00000000000..2dd5fc9b1ed
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesDxeSmm.c
@@ -0,0 +1,51 @@
+/** @file
+ Device Path services. The thing to remember is device paths are built out of
+ nodes. The device path is terminated by an end node that is length
+ sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
+ all over this file.
+
+ The only place where multi-instance device paths are supported is in
+ environment varibles. Multi-instance device paths should never be placed
+ on a Handle.
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiDevicePathLib.h"
+
+
+/**
+ Retrieves the device path protocol from a handle.
+
+ This function returns the device path protocol from the handle specified by Handle.
+ If Handle is NULL or Handle does not contain a device path protocol, then NULL
+ is returned.
+
+ @param Handle The handle from which to retrieve the device
+ path protocol.
+
+ @return The device path protocol from the handle specified by Handle.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+DevicePathFromHandle (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID *) &DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ DevicePath = NULL;
+ }
+ return DevicePath;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesStandaloneMm.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesStandaloneMm.c
new file mode 100644
index 00000000000..11bc510615a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/DevicePathUtilitiesStandaloneMm.c
@@ -0,0 +1,40 @@
+/** @file
+ Device Path services. The thing to remember is device paths are built out of
+ nodes. The device path is terminated by an end node that is length
+ sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL)
+ all over this file.
+
+ The only place where multi-instance device paths are supported is in
+ environment varibles. Multi-instance device paths should never be placed
+ on a Handle.
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiDevicePathLib.h"
+
+
+/**
+ Retrieves the device path protocol from a handle.
+
+ This function returns the device path protocol from the handle specified by Handle.
+ If Handle is NULL or Handle does not contain a device path protocol, then NULL
+ is returned.
+
+ @param Handle The handle from which to retrieve the device
+ path protocol.
+
+ @return The device path protocol from the handle specified by Handle.
+
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+DevicePathFromHandle (
+ IN EFI_HANDLE Handle
+ )
+{
+ return NULL;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
index 65b876f4dd0..8bf47cbadd4 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
@@ -26,6 +26,7 @@
[Sources]
DevicePathUtilities.c
+ DevicePathUtilitiesDxeSmm.c
DevicePathToText.c
DevicePathFromText.c
UefiDevicePathLib.c
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf
index f5606a9ef5e..4cfb170e824 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf
@@ -29,6 +29,7 @@
[Sources]
DevicePathUtilities.c
+ DevicePathUtilitiesDxeSmm.c
DevicePathToText.c
DevicePathFromText.c
UefiDevicePathLibOptionalDevicePathProtocol.c
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibStandaloneMm.inf
new file mode 100644
index 00000000000..6185c15bb42
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibStandaloneMm.inf
@@ -0,0 +1,75 @@
+## @file
+# Instance of Device Path Library based on Memory Allocation Library.
+#
+# Device Path Library that layers on top of the Memory Allocation Library.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiDevicePathLib
+ MODULE_UNI_FILE = UefiDevicePathLib.uni
+ FILE_GUID = D8E58437-44D3-4154-B7A7-EB794923EF12
+ MODULE_TYPE = MM_STANDALONE
+ PI_SPECIFICATION_VERSION = 0x00010032
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DevicePathLib | MM_STANDALONE MM_CORE_STANDALONE
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ DevicePathUtilities.c
+ DevicePathUtilitiesStandaloneMm.c
+ DevicePathToText.c
+ DevicePathFromText.c
+ UefiDevicePathLib.c
+ UefiDevicePathLib.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ DebugLib
+ BaseMemoryLib
+ PcdLib
+ PrintLib
+
+[Guids]
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiVTUTF8Guid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiVT100Guid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiVT100PlusGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiPcAnsiGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiUartDevicePathGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiSasDevicePathGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiVirtualDiskGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiVirtualCdGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiPersistentVirtualDiskGuid
+ ## SOMETIMES_CONSUMES ## GUID
+ gEfiPersistentVirtualCdGuid
+
+[Protocols]
+ gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiDebugPortProtocolGuid ## UNDEFINED
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumDevicePathNodeCount ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c
index 9390308d059..f0edb8ba4b7 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.c
@@ -969,6 +969,7 @@ FileHandleReadLine(
UINTN CharSize;
UINTN CountSoFar;
UINTN CrCount;
+ UINTN OldSize;
UINT64 OriginalFilePosition;
if (Handle == NULL
@@ -1039,10 +1040,11 @@ FileHandleReadLine(
// if we ran out of space tell when...
//
if ((CountSoFar+1-CrCount)*sizeof(CHAR16) > *Size){
+ OldSize = *Size;
*Size = (CountSoFar+1-CrCount)*sizeof(CHAR16);
if (!Truncate) {
- if (Buffer != NULL && *Size != 0) {
- ZeroMem(Buffer, *Size);
+ if (Buffer != NULL && OldSize != 0) {
+ ZeroMem(Buffer, OldSize);
}
FileHandleSetPosition(Handle, OriginalFilePosition);
return (EFI_BUFFER_TOO_SMALL);
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiLib/UefiLib.c b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiLib/UefiLib.c
index bd29f091a60..fde5dcd9096 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiLib/UefiLib.c
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Library/UefiLib/UefiLib.c
@@ -839,7 +839,7 @@ LookupUnicodeString2 (
SupportedLanguages += 3;
}
} else {
- Found = !IsLanguageSupported(Language, SupportedLanguages);
+ Found = !IsLanguageSupported(SupportedLanguages, Language);
}
@@ -1133,7 +1133,7 @@ AddUnicodeString2 (
SupportedLanguages += 3;
}
} else {
- Found = !IsLanguageSupported(Language, SupportedLanguages);
+ Found = !IsLanguageSupported(SupportedLanguages, Language);
}
//
// If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
@@ -1285,98 +1285,6 @@ FreeUnicodeStringTable (
return EFI_SUCCESS;
}
-#ifndef DISABLE_NEW_DEPRECATED_INTERFACES
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Returns a pointer to an allocated buffer that contains the contents of a
- variable retrieved through the UEFI Runtime Service GetVariable(). The
- returned buffer is allocated using AllocatePool(). The caller is responsible
- for freeing this buffer with FreePool().
-
- If Name is NULL, then ASSERT().
- If Guid is NULL, then ASSERT().
-
- @param[in] Name The pointer to a Null-terminated Unicode string.
- @param[in] Guid The pointer to an EFI_GUID structure
-
- @retval NULL The variable could not be retrieved.
- @retval NULL There are not enough resources available for the variable contents.
- @retval Other A pointer to allocated buffer containing the variable contents.
-
-**/
-VOID *
-EFIAPI
-GetVariable (
- IN CONST CHAR16 *Name,
- IN CONST EFI_GUID *Guid
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- VOID *Value;
-
- ASSERT (Name != NULL);
- ASSERT (Guid != NULL);
-
- //
- // Try to get the variable size.
- //
- Value = NULL;
- Size = 0;
- Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value);
- if (Status != EFI_BUFFER_TOO_SMALL) {
- return NULL;
- }
-
- //
- // Allocate buffer to get the variable.
- //
- Value = AllocatePool (Size);
- if (Value == NULL) {
- return NULL;
- }
-
- //
- // Get the variable data.
- //
- Status = gRT->GetVariable ((CHAR16 *) Name, (EFI_GUID *) Guid, NULL, &Size, Value);
- if (EFI_ERROR (Status)) {
- FreePool(Value);
- return NULL;
- }
-
- return Value;
-}
-
-/**
- [ATTENTION] This function will be deprecated for security reason.
-
- Returns a pointer to an allocated buffer that contains the contents of a
- variable retrieved through the UEFI Runtime Service GetVariable(). This
- function always uses the EFI_GLOBAL_VARIABLE GUID to retrieve variables.
- The returned buffer is allocated using AllocatePool(). The caller is
- responsible for freeing this buffer with FreePool().
-
- If Name is NULL, then ASSERT().
-
- @param[in] Name The pointer to a Null-terminated Unicode string.
-
- @retval NULL The variable could not be retrieved.
- @retval NULL There are not enough resources available for the variable contents.
- @retval Other A pointer to allocated buffer containing the variable contents.
-
-**/
-VOID *
-EFIAPI
-GetEfiGlobalVariable (
- IN CONST CHAR16 *Name
- )
-{
- return GetVariable (Name, &gEfiGlobalVariableGuid);
-}
-#endif
/**
Returns the status whether get the variable success. The function retrieves
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/MdeLibs.dsc.inc b/src/VBox/Devices/EFI/Firmware/MdePkg/MdeLibs.dsc.inc
new file mode 100644
index 00000000000..54846cff81b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/MdeLibs.dsc.inc
@@ -0,0 +1,15 @@
+## @file
+# Mde DSC include file for [LibraryClasses*] section of all Architectures.
+#
+# This file can be included to the [LibraryClasses*] section(s) of a platform DSC file
+# by using "!include MdePkg/MdeLibs.dsc.inc" to specify the library instances
+# of some EDKII basic/common library classes.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[LibraryClasses]
+ RegisterFilterLib|MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.ci.yaml
index 25931afcb16..dfa7801ef3d 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.ci.yaml
@@ -2,9 +2,25 @@
# CI configuration for MdePkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ ## options defined .pytool/Plugin/LicenseCheck
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
## options defined ci/Plugin/CompilerPlugin
"CompilerPlugin": {
"DscPath": "MdePkg.dsc"
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dec b/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dec
index 2aa92306804..90fe1fdaaab 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dec
@@ -4,9 +4,9 @@
# It also provides the definitions(including PPIs/PROTOCOLs/GUIDs) of
# EFI1.10/UEFI2.7/PI1.7 and some Industry Standards.
#
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
-# (C) Copyright 2016 - 2020 Hewlett Packard Enterprise Development LP<BR>
+# (C) Copyright 2016 - 2021 Hewlett Packard Enterprise Development LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -23,6 +23,7 @@
[Includes]
Include
+ Test/UnitTest/Include
[Includes.IA32]
Include/Ia32
@@ -251,6 +252,26 @@
#
UnitTestLib|Include/Library/UnitTestLib.h
+ ## @libraryclass Extension to BaseLib for host based unit tests that allows a
+ # subset of BaseLib services to be hooked for emulation.
+ #
+ UnitTestHostBaseLib|Test/UnitTest/Include/Library/UnitTestHostBaseLib.h
+
+ ## @libraryclass This library provides an interface to request non-MMRAM pages to be mapped
+ # or unblocked from inside MM environment.
+ #
+ MmUnblockMemoryLib|Include/Library/MmUnblockMemoryLib.h
+
+ ## @libraryclass This library provides interfances to filter and trace port IO/MMIO/MSR access.
+ #
+ #
+ RegisterFilterLib|Include/Library/RegisterFilterLib.h
+
+[LibraryClasses.IA32, LibraryClasses.X64, LibraryClasses.AARCH64]
+ ## @libraryclass Provides services to generate random number.
+ #
+ RngLib|Include/Library/RngLib.h
+
[LibraryClasses.IA32, LibraryClasses.X64]
## @libraryclass Abstracts both S/W SMI generation and detection.
##
@@ -272,10 +293,6 @@
#
SmmPeriodicSmiLib|Include/Library/SmmPeriodicSmiLib.h
- ## @libraryclass Provides services to generate random number.
- #
- RngLib|Include/Library/RngLib.h
-
## @libraryclass Provides services to log the SMI handler registration.
SmiHandlerProfileLib|Include/Library/SmiHandlerProfileLib.h
@@ -663,13 +680,16 @@
gEfiJsonCapsuleIdGuid = { 0x67d6f4cd, 0xd6b8, 0x4573, { 0xbf, 0x4a, 0xde, 0x5e, 0x25, 0x2d, 0x61, 0xae }}
## Include/Guid/HiiPlatformSetupFormset.h
- gEfiHiiResetStyleFormsetGuid = { 0x790217bd, 0xbecf, 0x485b, { 0x91, 0x70, 0x5f, 0xf7, 0x11, 0x31, 0x8b, 0x27 }}
+ gEfiHiiRestStyleFormsetGuid = { 0x790217bd, 0xbecf, 0x485b, { 0x91, 0x70, 0x5f, 0xf7, 0x11, 0x31, 0x8b, 0x27 }}
# GUIDs defined in UEFI2.8a
#
## Include/Guid/RtPropertiesTable.h
gEfiRtPropertiesTableGuid = { 0xeb66918a, 0x7eef, 0x402a, { 0x84, 0x2e, 0x93, 0x1d, 0x21, 0xc3, 0x8a, 0xe9 }}
+ ## Include/Protocol/SerilaIo.h
+ gEfiSerialTerminalDeviceTypeGuid = { 0x6AD9A60F, 0x5815, 0x4C7C, { 0x8A, 0x10, 0x50, 0x53, 0xD2, 0xBF, 0x7A, 0x1B }}
+
#
# GUID defined in PI1.0
#
@@ -1840,6 +1860,19 @@
gEfiNvdimmLabelProtocolGuid = { 0xd40b6b80, 0x97d5, 0x4282, { 0xbb, 0x1d, 0x22, 0x3a, 0x16, 0x91, 0x80, 0x58 }}
#
+ # Protocols defined in UEFI2.8
+ #
+ ## Include/Protocol/RestEx.h
+ gEfiRestExProtocolGuid = { 0x55648b91, 0xe7d, 0x40a3, { 0xa9, 0xb3, 0xa8, 0x15, 0xd7, 0xea, 0xdf, 0x97 }}
+ gEfiRestExServiceBindingProtocolGuid = { 0x456bbe01, 0x99d0, 0x45ea, { 0xbb, 0x5f, 0x16, 0xd8, 0x4b, 0xed, 0xc5, 0x59 }}
+
+ ## Include/Protocol/RestJsonStructure.h
+ gEfiRestJsonStructureProtocolGuid = { 0xa9a048f6, 0x48a0, 0x4714, {0xb7, 0xda, 0xa9, 0xad,0x87, 0xd4, 0xda, 0xc9 }}
+
+ ## Include/Protocol/RedfishDiscover.h
+ gEfiRedfishDiscoverProtocolGuid = { 0x5db12509, 0x4550, 0x4347, { 0x96, 0xb3, 0x73, 0xc0, 0xff, 0x6e, 0x86, 0x9f }}
+
+ #
# Protocols defined in Shell2.0
#
## Include/Protocol/Shell.h
@@ -2233,10 +2266,6 @@
# @ValidList 0x80000001 | 8, 16, 32
gEfiMdePkgTokenSpaceGuid.PcdPort80DataWidth|8|UINT8|0x0000002d
- ## This value is used to configure X86 Processor FSB clock.
- # @Prompt FSB Clock.
- gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000|UINT32|0x0000000c
-
## The maximum printable number of characters. UefLib functions: AsciiPrint(), AsciiErrorPrint(),
# PrintXY(), AsciiPrintXY(), Print(), ErrorPrint() base on this PCD value to print characters.
# @Prompt Maximum Printable Number of Characters.
@@ -2265,6 +2294,10 @@
# @Prompt PCI Express Base Address.
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xE0000000|UINT64|0x0000000a
+ ## This value is used to set the size of PCI express hierarchy. The default is 256 MB.
+ # @Prompt PCI Express Base Size.
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize|0x10000000|UINT64|0x0000000f
+
## Default current ISO 639-2 language: English & French.
# @Prompt Default Value of LangCodes Variable.
gEfiMdePkgTokenSpaceGuid.PcdUefiVariableDefaultLangCodes|"engfraengfra"|VOID*|0x0000001c
@@ -2336,5 +2369,9 @@
# @Prompt Boot Timeout (s)
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0xffff|UINT16|0x0000002c
+ ## This value is used to configure X86 Processor FSB clock.
+ # @Prompt FSB Clock.
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock|200000000|UINT32|0x0000000c
+
[UserExtensions.TianoCore."ExtraFiles"]
MdePkgExtra.uni
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dsc b/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dsc
index 0f1c7044b6e..b4c466902a7 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/MdePkg.dsc
@@ -1,7 +1,7 @@
## @file
# EFI/PI MdePkg Package
#
-# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
# Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
#
@@ -21,6 +21,8 @@
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
+!include MdePkg/MdeLibs.dsc.inc
+
[PcdsFeatureFlag]
gEfiMdePkgTokenSpaceGuid.PcdUgaConsumeSupport|TRUE
@@ -35,7 +37,9 @@
[Components]
MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf
MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
@@ -60,6 +64,10 @@
MdePkg/Library/BasePostCodeLibPort80/BasePostCodeLibPort80.inf
MdePkg/Library/BasePrintLib/BasePrintLib.inf
MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ MdePkg/Library/DxeRngLib/DxeRngLib.inf
+ MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
+ MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
+
MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
@@ -67,7 +75,6 @@
MdePkg/Library/BaseUefiDecompressLib/BaseUefiTianoCustomDecompressLib.inf
MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
- MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
@@ -104,6 +111,7 @@
MdePkg/Library/UefiDebugLibDebugPortProtocol/UefiDebugLibDebugPortProtocol.inf
MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibStandaloneMm.inf
MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf
MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
@@ -121,6 +129,8 @@
MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
+ MdePkg/Library/RegisterFilterLibNull/RegisterFilterLibNull.inf
+
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
#
# Add UEFI Target Based Unit Tests
@@ -135,6 +145,9 @@
MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibSmm.inf
MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibUefiShell.inf
+[Components.IA32, Components.X64, Components.AARCH64]
+ MdePkg/Library/BaseRngLib/BaseRngLib.inf
+
[Components.IA32, Components.X64]
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
@@ -158,10 +171,10 @@
MdePkg/Library/BaseS3StallLib/BaseS3StallLib.inf
MdePkg/Library/SmmMemLib/SmmMemLib.inf
MdePkg/Library/SmmIoLib/SmmIoLib.inf
- MdePkg/Library/BaseRngLib/BaseRngLib.inf
MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
MdePkg/Library/SmiHandlerProfileLibNull/SmiHandlerProfileLibNull.inf
MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
+ MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
[Components.EBC]
MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
@@ -172,4 +185,3 @@
MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
[BuildOptions]
- *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Test/MdePkgHostTest.dsc b/src/VBox/Devices/EFI/Firmware/MdePkg/Test/MdePkgHostTest.dsc
index ebfcf98f8d3..d612e95fa21 100644
--- a/src/VBox/Devices/EFI/Firmware/MdePkg/Test/MdePkgHostTest.dsc
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Test/MdePkgHostTest.dsc
@@ -28,3 +28,8 @@
#
MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf
MdePkg/Test/UnitTest/Library/BaseLib/BaseLibUnitTestsHost.inf
+
+ #
+ # Build HOST_APPLICATION Libraries
+ #
+ MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
diff --git a/src/VBox/Devices/EFI/Firmware/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h b/src/VBox/Devices/EFI/Firmware/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h
new file mode 100644
index 00000000000..a13d059f184
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h
@@ -0,0 +1,582 @@
+/** @file
+ Unit Test Host BaseLib hooks.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __UNIT_TEST_HOST_BASE_LIB_H__
+#define __UNIT_TEST_HOST_BASE_LIB_H__
+
+/**
+ Prototype of service with no parameters and no return value.
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_VOID)(
+ VOID
+ );
+
+/**
+ Prototype of service that reads and returns a BOOLEAN value.
+
+ @return The value read.
+**/
+typedef
+BOOLEAN
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_READ_BOOLEAN)(
+ VOID
+ );
+
+/**
+ Prototype of service that reads and returns a UINT16 value.
+
+ @return The value read.
+**/
+typedef
+UINT16
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_READ_UINT16)(
+ VOID
+ );
+
+/**
+ Prototype of service that reads and returns a UINTN value.
+
+ @return The value read.
+**/
+typedef
+UINTN
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_READ_UINTN)(
+ VOID
+ );
+
+/**
+ Prototype of service that writes and returns a UINT16 value.
+
+ @param[in] Value The value to write.
+
+ @return The value written.
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_WRITE_UINT16)(
+ IN UINT16 Value
+ );
+
+/**
+ Prototype of service that writes and returns a UINTN value.
+
+ @param[in] Value The value to write.
+
+ @return The value written.
+**/
+typedef
+UINTN
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN)(
+ IN UINTN Value
+ );
+
+/**
+ Prototype of service that reads and returns an IA32_DESCRIPTOR.
+
+ @param[out] Ia32Descriptor Pointer to the descriptor read.
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_READ_IA32_DESCRIPTOR)(
+ OUT IA32_DESCRIPTOR *Ia32Descriptor
+ );
+
+/**
+ Prototype of service that writes an IA32_DESCRIPTOR.
+
+ @param[in] Ia32Descriptor Pointer to the descriptor to write.
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_WRITE_IA32_DESCRIPTOR)(
+ IN CONST IA32_DESCRIPTOR *Ia32Descriptor
+ );
+
+/**
+ Retrieves CPUID information.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index.
+ This function always returns Index.
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+ This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the CPUID
+ instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+
+ @return Index.
+
+**/
+typedef
+UINT32
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_CPUID)(
+ IN UINT32 Index,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ );
+
+/**
+ Retrieves CPUID information using an extended leaf identifier.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index
+ and ECX set to the value specified by SubIndex. This function always returns
+ Index. This function is only available on IA-32 and x64.
+
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the
+ CPUID instruction.
+ @param SubIndex The 32-bit value to load into ECX prior to invoking the
+ CPUID instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be
+ NULL.
+
+ @return Index.
+
+**/
+typedef
+UINT32
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_CPUID_EX)(
+ IN UINT32 Index,
+ IN UINT32 SubIndex,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ );
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and x64.
+
+ @param Index The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by Index.
+
+**/
+typedef
+UINT64
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_READ_MSR_64)(
+ IN UINT32 Index
+ );
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and x64.
+
+ @param Index The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+typedef
+UINT64
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_WRITE_MSR_64)(
+ IN UINT32 Index,
+ IN UINT64 Value
+ );
+
+/**
+ Reads the current value of a Performance Counter (PMC).
+
+ Reads and returns the current value of performance counter specified by
+ Index. This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit Performance Counter index to read.
+
+ @return The value of the PMC specified by Index.
+
+**/
+typedef
+UINT64
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_READ_PMC)(
+ IN UINT32 Index
+ );
+
+/**
+ Sets up a monitor buffer that is used by AsmMwait().
+
+ Executes a MONITOR instruction with the register state specified by Eax, Ecx
+ and Edx. Returns Eax. This function is only available on IA-32 and x64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+ @param Edx The value to load into EDX or RDX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+typedef
+UINTN
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_MONITOR)(
+ IN UINTN Eax,
+ IN UINTN Ecx,
+ IN UINTN Edx
+ );
+
+/**
+ Executes an MWAIT instruction.
+
+ Executes an MWAIT instruction with the register state specified by Eax and
+ Ecx. Returns Eax. This function is only available on IA-32 and x64.
+
+ @param Eax The value to load into EAX or RAX before executing the MONITOR
+ instruction.
+ @param Ecx The value to load into ECX or RCX before executing the MONITOR
+ instruction.
+
+ @return Eax
+
+**/
+typedef
+UINTN
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_MWAIT)(
+ IN UINTN Eax,
+ IN UINTN Ecx
+ );
+
+/**
+ Flushes a cache line from all the instruction and data caches within the
+ coherency domain of the CPU.
+
+ Flushed the cache line specified by LinearAddress, and returns LinearAddress.
+ This function is only available on IA-32 and x64.
+
+ @param LinearAddress The address of the cache line to flush. If the CPU is
+ in a physical addressing mode, then LinearAddress is a
+ physical address. If the CPU is in a virtual
+ addressing mode, then LinearAddress is a virtual
+ address.
+
+ @return LinearAddress.
+**/
+typedef
+VOID *
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_FLUSH_CACHE_LINE)(
+ IN VOID *LinearAddress
+ );
+
+/**
+ Prototype of service that enables ot disables 32-bit paging modes.
+
+ @param EntryPoint A pointer to function to call with the new stack after
+ paging is enabled.
+ @param Context1 A pointer to the context to pass into the EntryPoint
+ function as the first parameter after paging is enabled.
+ @param Context2 A pointer to the context to pass into the EntryPoint
+ function as the second parameter after paging is enabled.
+ @param NewStack A pointer to the new stack to use for the EntryPoint
+ function after paging is enabled.
+
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_PAGING_32)(
+ IN SWITCH_STACK_ENTRY_POINT EntryPoint,
+ IN VOID *Context1, OPTIONAL
+ IN VOID *Context2, OPTIONAL
+ IN VOID *NewStack
+ );
+
+/**
+ Enables the 64-bit paging mode on the CPU.
+
+ Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables
+ must be properly initialized prior to calling this service. This function
+ assumes the current execution mode is 32-bit protected mode with flat
+ descriptors. This function is only available on IA-32. After the 64-bit
+ paging mode is enabled, control is transferred to the function specified by
+ EntryPoint using the new stack specified by NewStack and passing in the
+ parameters specified by Context1 and Context2. Context1 and Context2 are
+ optional and may be 0. The function EntryPoint must never return.
+
+ If the current execution mode is not 32-bit protected mode with flat
+ descriptors, then ASSERT().
+ If EntryPoint is 0, then ASSERT().
+ If NewStack is 0, then ASSERT().
+
+ @param Cs The 16-bit selector to load in the CS before EntryPoint
+ is called. The descriptor in the GDT that this selector
+ references must be setup for long mode.
+ @param EntryPoint The 64-bit virtual address of the function to call with
+ the new stack after paging is enabled.
+ @param Context1 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the first parameter after
+ paging is enabled.
+ @param Context2 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the second parameter after
+ paging is enabled.
+ @param NewStack The 64-bit virtual address of the new stack to use for
+ the EntryPoint function after paging is enabled.
+
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_ENABLE_PAGING_64)(
+ IN UINT16 Cs,
+ IN UINT64 EntryPoint,
+ IN UINT64 Context1, OPTIONAL
+ IN UINT64 Context2, OPTIONAL
+ IN UINT64 NewStack
+ );
+
+/**
+ Disables the 64-bit paging mode on the CPU.
+
+ Disables the 64-bit paging mode on the CPU and returns to 32-bit protected
+ mode. This function assumes the current execution mode is 64-paging mode.
+ This function is only available on x64. After the 64-bit paging mode is
+ disabled, control is transferred to the function specified by EntryPoint
+ using the new stack specified by NewStack and passing in the parameters
+ specified by Context1 and Context2. Context1 and Context2 are optional and
+ may be 0. The function EntryPoint must never return.
+
+ If the current execution mode is not 64-bit paged mode, then ASSERT().
+ If EntryPoint is 0, then ASSERT().
+ If NewStack is 0, then ASSERT().
+
+ @param Cs The 16-bit selector to load in the CS before EntryPoint
+ is called. The descriptor in the GDT that this selector
+ references must be setup for 32-bit protected mode.
+ @param EntryPoint The 64-bit virtual address of the function to call with
+ the new stack after paging is disabled.
+ @param Context1 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the first parameter after
+ paging is disabled.
+ @param Context2 The 64-bit virtual address of the context to pass into
+ the EntryPoint function as the second parameter after
+ paging is disabled.
+ @param NewStack The 64-bit virtual address of the new stack to use for
+ the EntryPoint function after paging is disabled.
+
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_DISABLE_PAGING_64)(
+ IN UINT16 Cs,
+ IN UINT32 EntryPoint,
+ IN UINT32 Context1, OPTIONAL
+ IN UINT32 Context2, OPTIONAL
+ IN UINT32 NewStack
+ );
+
+/**
+ Retrieves the properties for 16-bit thunk functions.
+
+ Computes the size of the buffer and stack below 1MB required to use the
+ AsmPrepareThunk16(), AsmThunk16() and AsmPrepareAndThunk16() functions. This
+ buffer size is returned in RealModeBufferSize, and the stack size is returned
+ in ExtraStackSize. If parameters are passed to the 16-bit real mode code,
+ then the actual minimum stack size is ExtraStackSize plus the maximum number
+ of bytes that need to be passed to the 16-bit real mode code.
+
+ If RealModeBufferSize is NULL, then ASSERT().
+ If ExtraStackSize is NULL, then ASSERT().
+
+ @param RealModeBufferSize A pointer to the size of the buffer below 1MB
+ required to use the 16-bit thunk functions.
+ @param ExtraStackSize A pointer to the extra size of stack below 1MB
+ that the 16-bit thunk functions require for
+ temporary storage in the transition to and from
+ 16-bit real mode.
+
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_GET_THUNK_16_PROPERTIES)(
+ OUT UINT32 *RealModeBufferSize,
+ OUT UINT32 *ExtraStackSize
+ );
+
+/**
+ Prototype of services that operates on a THUNK_CONTEXT structure.
+
+ @param ThunkContext A pointer to the context structure that describes the
+ 16-bit real mode code to call.
+
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_THUNK_16)(
+ IN OUT THUNK_CONTEXT *ThunkContext
+ );
+
+/**
+ Patch the immediate operand of an IA32 or X64 instruction such that the byte,
+ word, dword or qword operand is encoded at the end of the instruction's
+ binary representation.
+
+ This function should be used to update object code that was compiled with
+ NASM from assembly source code. Example:
+
+ NASM source code:
+
+ mov eax, strict dword 0 ; the imm32 zero operand will be patched
+ ASM_PFX(gPatchCr3):
+ mov cr3, eax
+
+ C source code:
+
+ X86_ASSEMBLY_PATCH_LABEL gPatchCr3;
+ PatchInstructionX86 (gPatchCr3, AsmReadCr3 (), 4);
+
+ @param[out] InstructionEnd Pointer right past the instruction to patch. The
+ immediate operand to patch is expected to
+ comprise the trailing bytes of the instruction.
+ If InstructionEnd is closer to address 0 than
+ ValueSize permits, then ASSERT().
+
+ @param[in] PatchValue The constant to write to the immediate operand.
+ The caller is responsible for ensuring that
+ PatchValue can be represented in the byte, word,
+ dword or qword operand (as indicated through
+ ValueSize); otherwise ASSERT().
+
+ @param[in] ValueSize The size of the operand in bytes; must be 1, 2,
+ 4, or 8. ASSERT() otherwise.
+**/
+typedef
+VOID
+(EFIAPI *UNIT_TEST_HOST_BASE_LIB_ASM_PATCH_INSTRUCTION_X86)(
+ OUT X86_ASSEMBLY_PATCH_LABEL *InstructionEnd,
+ IN UINT64 PatchValue,
+ IN UINTN ValueSize
+ );
+
+///
+/// Common services
+///
+typedef struct {
+ UNIT_TEST_HOST_BASE_LIB_VOID EnableInterrupts;
+ UNIT_TEST_HOST_BASE_LIB_VOID DisableInterrupts;
+ UNIT_TEST_HOST_BASE_LIB_VOID EnableDisableInterrupts;
+ UNIT_TEST_HOST_BASE_LIB_READ_BOOLEAN GetInterruptState;
+} UNIT_TEST_HOST_BASE_LIB_COMMON;
+
+///
+/// IA32/X64 services
+///
+typedef struct {
+ UNIT_TEST_HOST_BASE_LIB_ASM_CPUID AsmCpuid;
+ UNIT_TEST_HOST_BASE_LIB_ASM_CPUID_EX AsmCpuidEx;
+ UNIT_TEST_HOST_BASE_LIB_VOID AsmDisableCache;
+ UNIT_TEST_HOST_BASE_LIB_VOID AsmEnableCache;
+ UNIT_TEST_HOST_BASE_LIB_ASM_READ_MSR_64 AsmReadMsr64;
+ UNIT_TEST_HOST_BASE_LIB_ASM_WRITE_MSR_64 AsmWriteMsr64;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadCr0;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadCr2;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadCr3;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadCr4;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteCr0;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteCr2;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteCr3;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteCr4;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr0;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr1;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr2;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr3;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr4;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr5;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr6;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINTN AsmReadDr7;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr0;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr1;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr2;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr3;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr4;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr5;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr6;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINTN AsmWriteDr7;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadCs;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadDs;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadEs;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadFs;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadGs;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadSs;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadTr;
+ UNIT_TEST_HOST_BASE_LIB_ASM_READ_IA32_DESCRIPTOR AsmReadGdtr;
+ UNIT_TEST_HOST_BASE_LIB_ASM_WRITE_IA32_DESCRIPTOR AsmWriteGdtr;
+ UNIT_TEST_HOST_BASE_LIB_ASM_READ_IA32_DESCRIPTOR AsmReadIdtr;
+ UNIT_TEST_HOST_BASE_LIB_ASM_WRITE_IA32_DESCRIPTOR AsmWriteIdtr;
+ UNIT_TEST_HOST_BASE_LIB_READ_UINT16 AsmReadLdtr;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINT16 AsmWriteLdtr;
+ UNIT_TEST_HOST_BASE_LIB_ASM_READ_PMC AsmReadPmc;
+ UNIT_TEST_HOST_BASE_LIB_ASM_MONITOR AsmMonitor;
+ UNIT_TEST_HOST_BASE_LIB_ASM_MWAIT AsmMwait;
+ UNIT_TEST_HOST_BASE_LIB_VOID AsmWbinvd;
+ UNIT_TEST_HOST_BASE_LIB_VOID AsmInvd;
+ UNIT_TEST_HOST_BASE_LIB_ASM_FLUSH_CACHE_LINE AsmFlushCacheLine;
+ UNIT_TEST_HOST_BASE_LIB_ASM_PAGING_32 AsmEnablePaging32;
+ UNIT_TEST_HOST_BASE_LIB_ASM_PAGING_32 AsmDisablePaging32;
+ UNIT_TEST_HOST_BASE_LIB_ASM_ENABLE_PAGING_64 AsmEnablePaging64;
+ UNIT_TEST_HOST_BASE_LIB_ASM_DISABLE_PAGING_64 AsmDisablePaging64;
+ UNIT_TEST_HOST_BASE_LIB_ASM_GET_THUNK_16_PROPERTIES AsmGetThunk16Properties;
+ UNIT_TEST_HOST_BASE_LIB_ASM_THUNK_16 AsmPrepareThunk16;
+ UNIT_TEST_HOST_BASE_LIB_ASM_THUNK_16 AsmThunk16;
+ UNIT_TEST_HOST_BASE_LIB_ASM_THUNK_16 AsmPrepareAndThunk16;
+ UNIT_TEST_HOST_BASE_LIB_WRITE_UINT16 AsmWriteTr;
+ UNIT_TEST_HOST_BASE_LIB_VOID AsmLfence;
+ UNIT_TEST_HOST_BASE_LIB_ASM_PATCH_INSTRUCTION_X86 PatchInstructionX86;
+} UNIT_TEST_HOST_BASE_LIB_X86;
+
+///
+/// Data structure that contains pointers structures of common services and CPU
+/// architctuire specific services. Support for additional CPU architectures
+/// can be added to the end of this structure.
+///
+typedef struct {
+ UNIT_TEST_HOST_BASE_LIB_COMMON *Common;
+ UNIT_TEST_HOST_BASE_LIB_X86 *X86;
+} UNIT_TEST_HOST_BASE_LIB;
+
+extern UNIT_TEST_HOST_BASE_LIB gUnitTestHostBaseLib;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDhcp.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDhcp.c
index 3d63e9cb690..79ae3f0291c 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDhcp.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDhcp.c
@@ -131,7 +131,7 @@ ParseDhcp4Ack (
return EFI_OUT_OF_RESOURCES;
}
- for(Count=0; Count < ServerCount; Count++){
+ for (Count=0; Count < ServerCount; Count++) {
CopyMem (ServerList + Count, &OptionList[Index]->Data[4 * Count], sizeof (EFI_IPv4_ADDRESS));
}
@@ -225,7 +225,7 @@ ParseDhcp6Ack (
return EFI_OUT_OF_RESOURCES;
}
- for(Count=0; Count < ServerCount; Count++){
+ for (Count=0; Count < ServerCount; Count++) {
CopyMem (ServerList + Count, &OptionList[Index]->Data[16 * Count], sizeof (EFI_IPv6_ADDRESS));
}
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDriver.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDriver.c
index eae7bdbae99..e8cac3a776d 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDriver.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsDriver.c
@@ -197,11 +197,11 @@ DnsDestroyService (
{
UdpIoFreeIo (DnsSb->ConnectUdp);
- if (DnsSb->TimerToGetMap != NULL){
+ if (DnsSb->TimerToGetMap != NULL) {
gBS->CloseEvent (DnsSb->TimerToGetMap);
}
- if (DnsSb->Timer != NULL){
+ if (DnsSb->Timer != NULL) {
gBS->CloseEvent (DnsSb->Timer);
}
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.c
index 270f1f2a842..32fba800ee2 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.c
@@ -799,7 +799,7 @@ UpdateDns4Cache (
Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
return EFI_SUCCESS;
- }else {
+ } else {
return EFI_ACCESS_DENIED;
}
}
@@ -897,7 +897,7 @@ UpdateDns6Cache (
Item->DnsCache.Timeout = DnsCacheEntry.Timeout;
return EFI_SUCCESS;
- }else {
+ } else {
return EFI_ACCESS_DENIED;
}
}
@@ -1080,7 +1080,7 @@ IsValidDnsResponse (
NET_LIST_FOR_EACH (Entry, &TokensMap->Used) {
*Item = NET_LIST_USER_STRUCT (Entry, NET_MAP_ITEM, Link);
Packet = (NET_BUF *) ((*Item)->Value);
- if (Packet == NULL){
+ if (Packet == NULL) {
continue;
} else {
@@ -2127,7 +2127,7 @@ DnsOnTimerRetransmit (
}
}
}
- }else {
+ } else {
//
// Iterate through all the children of the DNS service instance. Time
// out the packet. If maximum retries reached, clean the Token up.
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.h b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.h
index 74f3dd88cfd..e594544d846 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.h
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsImpl.h
@@ -125,7 +125,7 @@ typedef struct {
EFI_DNS6_COMPLETION_TOKEN *Token;
} DNS6_TOKEN_ENTRY;
-union _DNS_FLAGS{
+union _DNS_FLAGS {
struct {
UINT16 RCode:4;
UINT16 Zero:3;
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsProtocol.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsProtocol.c
index 4e4e2446a4f..84237885b73 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsProtocol.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/DnsDxe/DnsProtocol.c
@@ -217,7 +217,7 @@ Dns4Configure (
Dns4InstanceCancelToken(Instance, NULL);
}
- if (Instance->UdpIo != NULL){
+ if (Instance->UdpIo != NULL) {
UdpIoCleanIo (Instance->UdpIo);
}
@@ -1061,7 +1061,7 @@ Dns6Configure (
Dns6InstanceCancelToken(Instance, NULL);
}
- if (Instance->UdpIo != NULL){
+ if (Instance->UdpIo != NULL) {
UdpIoCleanIo (Instance->UdpIo);
}
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootClient.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootClient.c
index 768385d62c3..b59af6d5583 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootClient.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootClient.c
@@ -977,7 +977,7 @@ HttpBootGetBootFile (
// Accept
// User-Agent
//
- HttpIoHeader = HttpBootCreateHeader (3);
+ HttpIoHeader = HttpIoCreateHeader (3);
if (HttpIoHeader == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ERROR_2;
@@ -995,7 +995,7 @@ HttpBootGetBootFile (
if (EFI_ERROR (Status)) {
goto ERROR_3;
}
- Status = HttpBootSetHeader (
+ Status = HttpIoSetHeader (
HttpIoHeader,
HTTP_HEADER_HOST,
HostName
@@ -1008,7 +1008,7 @@ HttpBootGetBootFile (
//
// Add HTTP header field 2: Accept
//
- Status = HttpBootSetHeader (
+ Status = HttpIoSetHeader (
HttpIoHeader,
HTTP_HEADER_ACCEPT,
"*/*"
@@ -1020,7 +1020,7 @@ HttpBootGetBootFile (
//
// Add HTTP header field 3: User-Agent
//
- Status = HttpBootSetHeader (
+ Status = HttpIoSetHeader (
HttpIoHeader,
HTTP_HEADER_USER_AGENT,
HTTP_USER_AGENT_EFI_HTTP_BOOT
@@ -1291,7 +1291,7 @@ ERROR_4:
FreePool (RequestData);
}
ERROR_3:
- HttpBootFreeHeader (HttpIoHeader);
+ HttpIoFreeHeader (HttpIoHeader);
ERROR_2:
if (Cache != NULL) {
FreePool (Cache);
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.h
index 8e1033c4cec..55491935c98 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.h
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.h
@@ -2,7 +2,7 @@
UEFI HTTP boot driver's private data structure and interfaces declaration.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+(C) Copyright 2016 - 2020 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -28,6 +28,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DebugLib.h>
#include <Library/NetLib.h>
#include <Library/HttpLib.h>
+#include <Library/HttpIoLib.h>
#include <Library/HiiLib.h>
#include <Library/PrintLib.h>
#include <Library/DpcLib.h>
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.inf b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
index 5bca66d9a27..d64755ffe9f 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
@@ -2,6 +2,7 @@
# This modules produce the Load File Protocol for UEFI HTTP boot.
#
# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett-Packard Development Company, L.P.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -52,6 +53,7 @@
DebugLib
NetLib
HttpLib
+ HttpIoLib
HiiLib
PrintLib
DpcLib
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.c
index 2ee6e35791e..44966fe6596 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.c
@@ -2,7 +2,7 @@
Support functions implementation for UEFI HTTP boot driver.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+(C) Copyright 2016 - 2020 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -491,565 +491,6 @@ Exit:
return Status;
}
-/**
- Create a HTTP_IO_HEADER to hold the HTTP header items.
-
- @param[in] MaxHeaderCount The maximum number of HTTP header in this holder.
-
- @return A pointer of the HTTP header holder or NULL if failed.
-
-**/
-HTTP_IO_HEADER *
-HttpBootCreateHeader (
- UINTN MaxHeaderCount
- )
-{
- HTTP_IO_HEADER *HttpIoHeader;
-
- if (MaxHeaderCount == 0) {
- return NULL;
- }
-
- HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER));
- if (HttpIoHeader == NULL) {
- return NULL;
- }
-
- HttpIoHeader->MaxHeaderCount = MaxHeaderCount;
- HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1);
-
- return HttpIoHeader;
-}
-
-/**
- Destroy the HTTP_IO_HEADER and release the resources.
-
- @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.
-
-**/
-VOID
-HttpBootFreeHeader (
- IN HTTP_IO_HEADER *HttpIoHeader
- )
-{
- UINTN Index;
-
- if (HttpIoHeader != NULL) {
- if (HttpIoHeader->HeaderCount != 0) {
- for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) {
- FreePool (HttpIoHeader->Headers[Index].FieldName);
- FreePool (HttpIoHeader->Headers[Index].FieldValue);
- }
- }
- FreePool (HttpIoHeader);
- }
-}
-
-/**
- Set or update a HTTP header with the field name and corresponding value.
-
- @param[in] HttpIoHeader Point to the HTTP header holder.
- @param[in] FieldName Null terminated string which describes a field name.
- @param[in] FieldValue Null terminated string which describes the corresponding field value.
-
- @retval EFI_SUCCESS The HTTP header has been set or updated.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
- @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.
- @retval Other Unexpected error happened.
-
-**/
-EFI_STATUS
-HttpBootSetHeader (
- IN HTTP_IO_HEADER *HttpIoHeader,
- IN CHAR8 *FieldName,
- IN CHAR8 *FieldValue
- )
-{
- EFI_HTTP_HEADER *Header;
- UINTN StrSize;
- CHAR8 *NewFieldValue;
-
- if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);
- if (Header == NULL) {
- //
- // Add a new header.
- //
- if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {
- return EFI_OUT_OF_RESOURCES;
- }
- Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];
-
- StrSize = AsciiStrSize (FieldName);
- Header->FieldName = AllocatePool (StrSize);
- if (Header->FieldName == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (Header->FieldName, FieldName, StrSize);
- Header->FieldName[StrSize -1] = '\0';
-
- StrSize = AsciiStrSize (FieldValue);
- Header->FieldValue = AllocatePool (StrSize);
- if (Header->FieldValue == NULL) {
- FreePool (Header->FieldName);
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (Header->FieldValue, FieldValue, StrSize);
- Header->FieldValue[StrSize -1] = '\0';
-
- HttpIoHeader->HeaderCount++;
- } else {
- //
- // Update an existing one.
- //
- StrSize = AsciiStrSize (FieldValue);
- NewFieldValue = AllocatePool (StrSize);
- if (NewFieldValue == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- CopyMem (NewFieldValue, FieldValue, StrSize);
- NewFieldValue[StrSize -1] = '\0';
-
- if (Header->FieldValue != NULL) {
- FreePool (Header->FieldValue);
- }
- Header->FieldValue = NewFieldValue;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Notify the callback function when an event is triggered.
-
- @param[in] Context The opaque parameter to the function.
-
-**/
-VOID
-EFIAPI
-HttpIoNotifyDpc (
- IN VOID *Context
- )
-{
- *((BOOLEAN *) Context) = TRUE;
-}
-
-/**
- Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK.
-
- @param[in] Event The event signaled.
- @param[in] Context The opaque parameter to the function.
-
-**/
-VOID
-EFIAPI
-HttpIoNotify (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- //
- // Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK
- //
- QueueDpc (TPL_CALLBACK, HttpIoNotifyDpc, Context);
-}
-
-/**
- Create a HTTP_IO to access the HTTP service. It will create and configure
- a HTTP child handle.
-
- @param[in] Image The handle of the driver image.
- @param[in] Controller The handle of the controller.
- @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
- @param[in] ConfigData The HTTP_IO configuration data.
- @param[in] Callback Callback function which will be invoked when specified
- HTTP_IO_CALLBACK_EVENT happened.
- @param[in] Context The Context data which will be passed to the Callback function.
- @param[out] HttpIo The HTTP_IO.
-
- @retval EFI_SUCCESS The HTTP_IO is created and configured.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_UNSUPPORTED One or more of the control options are not
- supported in the implementation.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval Others Failed to create the HTTP_IO or configure it.
-
-**/
-EFI_STATUS
-HttpIoCreateIo (
- IN EFI_HANDLE Image,
- IN EFI_HANDLE Controller,
- IN UINT8 IpVersion,
- IN HTTP_IO_CONFIG_DATA *ConfigData,
- IN HTTP_IO_CALLBACK Callback,
- IN VOID *Context,
- OUT HTTP_IO *HttpIo
- )
-{
- EFI_STATUS Status;
- EFI_HTTP_CONFIG_DATA HttpConfigData;
- EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;
- EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;
- EFI_HTTP_PROTOCOL *Http;
- EFI_EVENT Event;
-
- if ((Image == NULL) || (Controller == NULL) || (ConfigData == NULL) || (HttpIo == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {
- return EFI_UNSUPPORTED;
- }
-
- ZeroMem (HttpIo, sizeof (HTTP_IO));
-
- //
- // Create the HTTP child instance and get the HTTP protocol.
- //
- Status = NetLibCreateServiceChild (
- Controller,
- Image,
- &gEfiHttpServiceBindingProtocolGuid,
- &HttpIo->Handle
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- Status = gBS->OpenProtocol (
- HttpIo->Handle,
- &gEfiHttpProtocolGuid,
- (VOID **) &Http,
- Image,
- Controller,
- EFI_OPEN_PROTOCOL_BY_DRIVER
- );
- if (EFI_ERROR (Status) || (Http == NULL)) {
- goto ON_ERROR;
- }
-
- //
- // Init the configuration data and configure the HTTP child.
- //
- HttpIo->Image = Image;
- HttpIo->Controller = Controller;
- HttpIo->IpVersion = IpVersion;
- HttpIo->Http = Http;
- HttpIo->Callback = Callback;
- HttpIo->Context = Context;
-
- ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
- HttpConfigData.HttpVersion = HttpVersion11;
- HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;
- if (HttpIo->IpVersion == IP_VERSION_4) {
- HttpConfigData.LocalAddressIsIPv6 = FALSE;
-
- Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
- Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;
- IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
- IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
- HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;
- } else {
- HttpConfigData.LocalAddressIsIPv6 = TRUE;
- Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;
- IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);
- HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;
- }
-
- Status = Http->Configure (Http, &HttpConfigData);
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
-
- //
- // Create events for various asynchronous operations.
- //
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- HttpIoNotify,
- &HttpIo->IsTxDone,
- &Event
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- HttpIo->ReqToken.Event = Event;
- HttpIo->ReqToken.Message = &HttpIo->ReqMessage;
-
- Status = gBS->CreateEvent (
- EVT_NOTIFY_SIGNAL,
- TPL_NOTIFY,
- HttpIoNotify,
- &HttpIo->IsRxDone,
- &Event
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- HttpIo->RspToken.Event = Event;
- HttpIo->RspToken.Message = &HttpIo->RspMessage;
-
- //
- // Create TimeoutEvent for response
- //
- Status = gBS->CreateEvent (
- EVT_TIMER,
- TPL_CALLBACK,
- NULL,
- NULL,
- &Event
- );
- if (EFI_ERROR (Status)) {
- goto ON_ERROR;
- }
- HttpIo->TimeoutEvent = Event;
-
- return EFI_SUCCESS;
-
-ON_ERROR:
- HttpIoDestroyIo (HttpIo);
-
- return Status;
-}
-
-/**
- Destroy the HTTP_IO and release the resources.
-
- @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
-
-**/
-VOID
-HttpIoDestroyIo (
- IN HTTP_IO *HttpIo
- )
-{
- EFI_HTTP_PROTOCOL *Http;
- EFI_EVENT Event;
-
- if (HttpIo == NULL) {
- return;
- }
-
- Event = HttpIo->ReqToken.Event;
- if (Event != NULL) {
- gBS->CloseEvent (Event);
- }
-
- Event = HttpIo->RspToken.Event;
- if (Event != NULL) {
- gBS->CloseEvent (Event);
- }
-
- Event = HttpIo->TimeoutEvent;
- if (Event != NULL) {
- gBS->CloseEvent (Event);
- }
-
- Http = HttpIo->Http;
- if (Http != NULL) {
- Http->Configure (Http, NULL);
- gBS->CloseProtocol (
- HttpIo->Handle,
- &gEfiHttpProtocolGuid,
- HttpIo->Image,
- HttpIo->Controller
- );
- }
-
- NetLibDestroyServiceChild (
- HttpIo->Controller,
- HttpIo->Image,
- &gEfiHttpServiceBindingProtocolGuid,
- HttpIo->Handle
- );
-}
-
-/**
- Synchronously send a HTTP REQUEST message to the server.
-
- @param[in] HttpIo The HttpIo wrapping the HTTP service.
- @param[in] Request A pointer to storage such data as URL and HTTP method.
- @param[in] HeaderCount Number of HTTP header structures in Headers list.
- @param[in] Headers Array containing list of HTTP headers.
- @param[in] BodyLength Length in bytes of the HTTP body.
- @param[in] Body Body associated with the HTTP request.
-
- @retval EFI_SUCCESS The HTTP request is transmitted.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
- @retval Others Other errors as indicated.
-
-**/
-EFI_STATUS
-HttpIoSendRequest (
- IN HTTP_IO *HttpIo,
- IN EFI_HTTP_REQUEST_DATA *Request,
- IN UINTN HeaderCount,
- IN EFI_HTTP_HEADER *Headers,
- IN UINTN BodyLength,
- IN VOID *Body
- )
-{
- EFI_STATUS Status;
- EFI_HTTP_PROTOCOL *Http;
-
- if (HttpIo == NULL || HttpIo->Http == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- HttpIo->ReqToken.Status = EFI_NOT_READY;
- HttpIo->ReqToken.Message->Data.Request = Request;
- HttpIo->ReqToken.Message->HeaderCount = HeaderCount;
- HttpIo->ReqToken.Message->Headers = Headers;
- HttpIo->ReqToken.Message->BodyLength = BodyLength;
- HttpIo->ReqToken.Message->Body = Body;
-
- if (HttpIo->Callback != NULL) {
- Status = HttpIo->Callback (
- HttpIoRequest,
- HttpIo->ReqToken.Message,
- HttpIo->Context
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- //
- // Queue the request token to HTTP instances.
- //
- Http = HttpIo->Http;
- HttpIo->IsTxDone = FALSE;
- Status = Http->Request (
- Http,
- &HttpIo->ReqToken
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Poll the network until transmit finish.
- //
- while (!HttpIo->IsTxDone) {
- Http->Poll (Http);
- }
-
- return HttpIo->ReqToken.Status;
-}
-
-/**
- Synchronously receive a HTTP RESPONSE message from the server.
-
- @param[in] HttpIo The HttpIo wrapping the HTTP service.
- @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
- FALSE to continue receive the previous response message.
- @param[out] ResponseData Point to a wrapper of the received response data.
-
- @retval EFI_SUCCESS The HTTP response is received.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
- @retval Others Other errors as indicated.
-
-**/
-EFI_STATUS
-HttpIoRecvResponse (
- IN HTTP_IO *HttpIo,
- IN BOOLEAN RecvMsgHeader,
- OUT HTTP_IO_RESPONSE_DATA *ResponseData
- )
-{
- EFI_STATUS Status;
- EFI_HTTP_PROTOCOL *Http;
-
- if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Start the timer, and wait Timeout seconds to receive the header packet.
- //
- Status = gBS->SetTimer (HttpIo->TimeoutEvent, TimerRelative, HTTP_BOOT_RESPONSE_TIMEOUT * TICKS_PER_MS);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Queue the response token to HTTP instances.
- //
- HttpIo->RspToken.Status = EFI_NOT_READY;
- if (RecvMsgHeader) {
- HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;
- } else {
- HttpIo->RspToken.Message->Data.Response = NULL;
- }
- HttpIo->RspToken.Message->HeaderCount = 0;
- HttpIo->RspToken.Message->Headers = NULL;
- HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;
- HttpIo->RspToken.Message->Body = ResponseData->Body;
-
- Http = HttpIo->Http;
- HttpIo->IsRxDone = FALSE;
- Status = Http->Response (
- Http,
- &HttpIo->RspToken
- );
-
- if (EFI_ERROR (Status)) {
- gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
- return Status;
- }
-
- //
- // Poll the network until receive finish.
- //
- while (!HttpIo->IsRxDone && ((HttpIo->TimeoutEvent == NULL) || EFI_ERROR (gBS->CheckEvent (HttpIo->TimeoutEvent)))) {
- Http->Poll (Http);
- }
-
- gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
-
- if (!HttpIo->IsRxDone) {
- //
- // Timeout occurs, cancel the response token.
- //
- Http->Cancel (Http, &HttpIo->RspToken);
-
- Status = EFI_TIMEOUT;
-
- return Status;
- } else {
- HttpIo->IsRxDone = FALSE;
- }
-
- if ((HttpIo->Callback != NULL) &&
- (HttpIo->RspToken.Status == EFI_SUCCESS || HttpIo->RspToken.Status == EFI_HTTP_ERROR)) {
- Status = HttpIo->Callback (
- HttpIoResponse,
- HttpIo->RspToken.Message,
- HttpIo->Context
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
- }
-
- //
- // Store the received data into the wrapper.
- //
- ResponseData->Status = HttpIo->RspToken.Status;
- ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;
- ResponseData->Headers = HttpIo->RspToken.Message->Headers;
- ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;
-
- return Status;
-}
/**
This function checks the HTTP(S) URI scheme.
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.h b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.h
index 277f0e70c74..ea1de45eac6 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.h
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpBootDxe/HttpBootSupport.h
@@ -2,6 +2,7 @@
Support functions declaration for UEFI HTTP boot driver.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+(C) Copyright 2020 Hewlett-Packard Development Company, L.P.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -86,155 +87,6 @@ HttpBootPrintErrorMessage (
EFI_HTTP_STATUS_CODE StatusCode
);
-//
-// A wrapper structure to hold the HTTP headers.
-//
-typedef struct {
- UINTN MaxHeaderCount;
- UINTN HeaderCount;
- EFI_HTTP_HEADER *Headers;
-} HTTP_IO_HEADER;
-
-/**
- Create a HTTP_IO_HEADER to hold the HTTP header items.
-
- @param[in] MaxHeaderCount The maximum number of HTTP header in this holder.
-
- @return A pointer of the HTTP header holder or NULL if failed.
-
-**/
-HTTP_IO_HEADER *
-HttpBootCreateHeader (
- IN UINTN MaxHeaderCount
- );
-
-/**
- Destroy the HTTP_IO_HEADER and release the resources.
-
- @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.
-
-**/
-VOID
-HttpBootFreeHeader (
- IN HTTP_IO_HEADER *HttpIoHeader
- );
-
-/**
- Set or update a HTTP header with the field name and corresponding value.
-
- @param[in] HttpIoHeader Point to the HTTP header holder.
- @param[in] FieldName Null terminated string which describes a field name.
- @param[in] FieldValue Null terminated string which describes the corresponding field value.
-
- @retval EFI_SUCCESS The HTTP header has been set or updated.
- @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
- @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.
- @retval Other Unexpected error happened.
-
-**/
-EFI_STATUS
-HttpBootSetHeader (
- IN HTTP_IO_HEADER *HttpIoHeader,
- IN CHAR8 *FieldName,
- IN CHAR8 *FieldValue
- );
-
-///
-/// HTTP_IO_CALLBACK_EVENT
-///
-typedef enum {
- HttpIoRequest,
- HttpIoResponse
-} HTTP_IO_CALLBACK_EVENT;
-
-/**
- HttpIo Callback function which will be invoked when specified HTTP_IO_CALLBACK_EVENT happened.
-
- @param[in] EventType Indicate the Event type that occurs in the current callback.
- @param[in] Message HTTP message which will be send to, or just received from HTTP server.
- @param[in] Context The Callback Context pointer.
-
- @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP process.
- @retval Others Tells the HttpIo to abort the current HTTP process.
-**/
-typedef
-EFI_STATUS
-(EFIAPI * HTTP_IO_CALLBACK) (
- IN HTTP_IO_CALLBACK_EVENT EventType,
- IN EFI_HTTP_MESSAGE *Message,
- IN VOID *Context
- );
-
-//
-// HTTP_IO configuration data for IPv4
-//
-typedef struct {
- EFI_HTTP_VERSION HttpVersion;
- UINT32 RequestTimeOut; // In milliseconds.
- UINT32 ResponseTimeOut; // In milliseconds.
- BOOLEAN UseDefaultAddress;
- EFI_IPv4_ADDRESS LocalIp;
- EFI_IPv4_ADDRESS SubnetMask;
- UINT16 LocalPort;
-} HTTP4_IO_CONFIG_DATA;
-
-//
-// HTTP_IO configuration data for IPv6
-//
-typedef struct {
- EFI_HTTP_VERSION HttpVersion;
- UINT32 RequestTimeOut; // In milliseconds.
- BOOLEAN UseDefaultAddress;
- EFI_IPv6_ADDRESS LocalIp;
- UINT16 LocalPort;
-} HTTP6_IO_CONFIG_DATA;
-
-
-//
-// HTTP_IO configuration
-//
-typedef union {
- HTTP4_IO_CONFIG_DATA Config4;
- HTTP6_IO_CONFIG_DATA Config6;
-} HTTP_IO_CONFIG_DATA;
-
-//
-// HTTP_IO wrapper of the EFI HTTP service.
-//
-typedef struct {
- UINT8 IpVersion;
- EFI_HANDLE Image;
- EFI_HANDLE Controller;
- EFI_HANDLE Handle;
-
- EFI_HTTP_PROTOCOL *Http;
-
- HTTP_IO_CALLBACK Callback;
- VOID *Context;
-
- EFI_HTTP_TOKEN ReqToken;
- EFI_HTTP_MESSAGE ReqMessage;
- EFI_HTTP_TOKEN RspToken;
- EFI_HTTP_MESSAGE RspMessage;
-
- BOOLEAN IsTxDone;
- BOOLEAN IsRxDone;
-
- EFI_EVENT TimeoutEvent;
-} HTTP_IO;
-
-//
-// A wrapper structure to hold the received HTTP response data.
-//
-typedef struct {
- EFI_HTTP_RESPONSE_DATA Response;
- UINTN HeaderCount;
- EFI_HTTP_HEADER *Headers;
- UINTN BodyLength;
- CHAR8 *Body;
- EFI_STATUS Status;
-} HTTP_IO_RESPONSE_DATA;
-
/**
Retrieve the host address using the EFI_DNS6_PROTOCOL.
@@ -268,98 +120,6 @@ HttpBootCommonNotify (
);
/**
- Create a HTTP_IO to access the HTTP service. It will create and configure
- a HTTP child handle.
-
- @param[in] Image The handle of the driver image.
- @param[in] Controller The handle of the controller.
- @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
- @param[in] ConfigData The HTTP_IO configuration data.
- @param[in] Callback Callback function which will be invoked when specified
- HTTP_IO_CALLBACK_EVENT happened.
- @param[in] Context The Context data which will be passed to the Callback function.
- @param[out] HttpIo The HTTP_IO.
-
- @retval EFI_SUCCESS The HTTP_IO is created and configured.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_UNSUPPORTED One or more of the control options are not
- supported in the implementation.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval Others Failed to create the HTTP_IO or configure it.
-
-**/
-EFI_STATUS
-HttpIoCreateIo (
- IN EFI_HANDLE Image,
- IN EFI_HANDLE Controller,
- IN UINT8 IpVersion,
- IN HTTP_IO_CONFIG_DATA *ConfigData,
- IN HTTP_IO_CALLBACK Callback,
- IN VOID *Context,
- OUT HTTP_IO *HttpIo
- );
-
-/**
- Destroy the HTTP_IO and release the resources.
-
- @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
-
-**/
-VOID
-HttpIoDestroyIo (
- IN HTTP_IO *HttpIo
- );
-
-/**
- Synchronously send a HTTP REQUEST message to the server.
-
- @param[in] HttpIo The HttpIo wrapping the HTTP service.
- @param[in] Request A pointer to storage such data as URL and HTTP method.
- @param[in] HeaderCount Number of HTTP header structures in Headers list.
- @param[in] Headers Array containing list of HTTP headers.
- @param[in] BodyLength Length in bytes of the HTTP body.
- @param[in] Body Body associated with the HTTP request.
-
- @retval EFI_SUCCESS The HTTP request is transmitted.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
- @retval Others Other errors as indicated.
-
-**/
-EFI_STATUS
-HttpIoSendRequest (
- IN HTTP_IO *HttpIo,
- IN EFI_HTTP_REQUEST_DATA *Request, OPTIONAL
- IN UINTN HeaderCount,
- IN EFI_HTTP_HEADER *Headers, OPTIONAL
- IN UINTN BodyLength,
- IN VOID *Body OPTIONAL
- );
-
-/**
- Synchronously receive a HTTP RESPONSE message from the server.
-
- @param[in] HttpIo The HttpIo wrapping the HTTP service.
- @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
- FALSE to continue receive the previous response message.
- @param[out] ResponseData Point to a wrapper of the received response data.
-
- @retval EFI_SUCCESS The HTTP response is received.
- @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
- @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
- @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
- @retval Others Other errors as indicated.
-
-**/
-EFI_STATUS
-HttpIoRecvResponse (
- IN HTTP_IO *HttpIo,
- IN BOOLEAN RecvMsgHeader,
- OUT HTTP_IO_RESPONSE_DATA *ResponseData
- );
-
-/**
This function checks the HTTP(S) URI scheme.
@param[in] Uri The pointer to the URI string.
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpDxe/HttpProto.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpDxe/HttpProto.c
index b124424d1ef..598742a937c 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpDxe/HttpProto.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/HttpDxe/HttpProto.c
@@ -873,6 +873,7 @@ HttpCleanProtocol (
// Destroy the TLS instance.
//
HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);
+ HttpInstance->TlsChildHandle = NULL;
}
if (HttpInstance->Tcp4ChildHandle != NULL) {
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpIoLib.h b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpIoLib.h
new file mode 100644
index 00000000000..812749a2523
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpIoLib.h
@@ -0,0 +1,328 @@
+/** @file
+ HttpIoLib.h.
+
+(C) Copyright 2020 Hewlett-Packard Development Company, L.P.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef HTTP_IO_LIB_H_
+#define HTTP_IO_LIB_H_
+
+#include <IndustryStandard/Http11.h>
+
+#include <Library/DpcLib.h>
+#include <Library/HttpLib.h>
+#include <Library/NetLib.h>
+
+#define HTTP_IO_MAX_SEND_PAYLOAD 1024
+#define HTTP_IO_CHUNK_SIZE_STRING_LEN 50
+#define HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH 256
+
+///
+/// HTTP_IO_CALLBACK_EVENT
+///
+typedef enum {
+ HttpIoRequest,
+ HttpIoResponse
+} HTTP_IO_CALLBACK_EVENT;
+
+/**
+ HttpIo Callback function which will be invoked when specified HTTP_IO_CALLBACK_EVENT happened.
+
+ @param[in] EventType Indicate the Event type that occurs in the current callback.
+ @param[in] Message HTTP message which will be send to, or just received from HTTP server.
+ @param[in] Context The Callback Context pointer.
+
+ @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP process.
+ @retval Others Tells the HttpIo to abort the current HTTP process.
+**/
+typedef
+EFI_STATUS
+(EFIAPI * HTTP_IO_CALLBACK) (
+ IN HTTP_IO_CALLBACK_EVENT EventType,
+ IN EFI_HTTP_MESSAGE *Message,
+ IN VOID *Context
+ );
+
+///
+/// A wrapper structure to hold the received HTTP response data.
+///
+typedef struct {
+ EFI_HTTP_RESPONSE_DATA Response;
+ UINTN HeaderCount;
+ EFI_HTTP_HEADER *Headers;
+ UINTN BodyLength;
+ CHAR8 *Body;
+ EFI_STATUS Status;
+} HTTP_IO_RESPONSE_DATA;
+
+///
+/// HTTP_IO configuration data for IPv4
+///
+typedef struct {
+ EFI_HTTP_VERSION HttpVersion;
+ UINT32 RequestTimeOut; ///< In milliseconds.
+ UINT32 ResponseTimeOut; ///< In milliseconds.
+ BOOLEAN UseDefaultAddress;
+ EFI_IPv4_ADDRESS LocalIp;
+ EFI_IPv4_ADDRESS SubnetMask;
+ UINT16 LocalPort;
+} HTTP4_IO_CONFIG_DATA;
+
+///
+/// HTTP_IO configuration data for IPv6
+///
+typedef struct {
+ EFI_HTTP_VERSION HttpVersion;
+ UINT32 RequestTimeOut; ///< In milliseconds.
+ BOOLEAN UseDefaultAddress;
+ EFI_IPv6_ADDRESS LocalIp;
+ UINT16 LocalPort;
+} HTTP6_IO_CONFIG_DATA;
+
+///
+/// HTTP_IO configuration
+///
+typedef union {
+ HTTP4_IO_CONFIG_DATA Config4;
+ HTTP6_IO_CONFIG_DATA Config6;
+} HTTP_IO_CONFIG_DATA;
+
+///
+/// HTTP_IO wrapper of the EFI HTTP service.
+///
+typedef struct {
+ UINT8 IpVersion;
+ EFI_HANDLE Image;
+ EFI_HANDLE Controller;
+ EFI_HANDLE Handle;
+
+ EFI_HTTP_PROTOCOL *Http;
+
+ HTTP_IO_CALLBACK Callback;
+ VOID *Context;
+
+ EFI_HTTP_TOKEN ReqToken;
+ EFI_HTTP_MESSAGE ReqMessage;
+ EFI_HTTP_TOKEN RspToken;
+ EFI_HTTP_MESSAGE RspMessage;
+
+ BOOLEAN IsTxDone;
+ BOOLEAN IsRxDone;
+
+ EFI_EVENT TimeoutEvent;
+ UINT32 Timeout;
+} HTTP_IO;
+
+///
+/// Process code of HTTP chunk transfer.
+///
+typedef enum {
+ HttpIoSendChunkNone = 0,
+ HttpIoSendChunkHeaderZeroContent,
+ HttpIoSendChunkContent,
+ HttpIoSendChunkEndChunk,
+ HttpIoSendChunkFinish
+} HTTP_IO_SEND_CHUNK_PROCESS;
+
+///
+/// Process code of HTTP non chunk transfer.
+///
+typedef enum {
+ HttpIoSendNonChunkNone = 0,
+ HttpIoSendNonChunkHeaderZeroContent,
+ HttpIoSendNonChunkContent,
+ HttpIoSendNonChunkFinish
+} HTTP_IO_SEND_NON_CHUNK_PROCESS;
+
+///
+/// Chunk links for HTTP chunked transfer coding.
+///
+typedef struct {
+ LIST_ENTRY NextChunk;
+ UINTN Length;
+ CHAR8 *Data;
+} HTTP_IO_CHUNKS;
+
+/**
+ Notify the callback function when an event is triggered.
+
+ @param[in] Context The opaque parameter to the function.
+
+**/
+VOID
+EFIAPI
+HttpIoNotifyDpc (
+ IN VOID *Context
+ );
+
+/**
+ Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK.
+
+ @param[in] Event The event signaled.
+ @param[in] Context The opaque parameter to the function.
+
+**/
+VOID
+EFIAPI
+HttpIoNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the HTTP_IO and release the resources.
+
+ @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
+
+**/
+VOID
+HttpIoDestroyIo (
+ IN HTTP_IO *HttpIo
+ );
+
+/**
+ Create a HTTP_IO to access the HTTP service. It will create and configure
+ a HTTP child handle.
+
+ @param[in] Image The handle of the driver image.
+ @param[in] Controller The handle of the controller.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+ @param[in] ConfigData The HTTP_IO configuration data.
+ @param[in] Callback Callback function which will be invoked when specified
+ HTTP_IO_CALLBACK_EVENT happened.
+ @param[in] Context The Context data which will be passed to the Callback function.
+ @param[out] HttpIo The HTTP_IO.
+
+ @retval EFI_SUCCESS The HTTP_IO is created and configured.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_UNSUPPORTED One or more of the control options are not
+ supported in the implementation.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval Others Failed to create the HTTP_IO or configure it.
+
+**/
+EFI_STATUS
+HttpIoCreateIo (
+ IN EFI_HANDLE Image,
+ IN EFI_HANDLE Controller,
+ IN UINT8 IpVersion,
+ IN HTTP_IO_CONFIG_DATA *ConfigData,
+ IN HTTP_IO_CALLBACK Callback,
+ IN VOID *Context,
+ OUT HTTP_IO *HttpIo
+ );
+
+/**
+ Synchronously send a HTTP REQUEST message to the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] Request A pointer to storage such data as URL and HTTP method.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] BodyLength Length in bytes of the HTTP body.
+ @param[in] Body Body associated with the HTTP request.
+
+ @retval EFI_SUCCESS The HTTP request is transmitted.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoSendRequest (
+ IN HTTP_IO *HttpIo,
+ IN EFI_HTTP_REQUEST_DATA *Request, OPTIONAL
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers, OPTIONAL
+ IN UINTN BodyLength,
+ IN VOID *Body OPTIONAL
+ );
+
+/**
+ Synchronously receive a HTTP RESPONSE message from the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
+ FALSE to continue receive the previous response message.
+ @param[out] ResponseData Point to a wrapper of the received response data.
+
+ @retval EFI_SUCCESS The HTTP response is received.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoRecvResponse (
+ IN HTTP_IO *HttpIo,
+ IN BOOLEAN RecvMsgHeader,
+ OUT HTTP_IO_RESPONSE_DATA *ResponseData
+ );
+
+/**
+ Get the value of the content length if there is a "Content-Length" header.
+
+ @param[in] HeaderCount Number of HTTP header structures in Headers.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[out] ContentLength Pointer to save the value of the content length.
+
+ @retval EFI_SUCCESS Successfully get the content length.
+ @retval EFI_NOT_FOUND No "Content-Length" header in the Headers.
+
+**/
+EFI_STATUS
+HttpIoGetContentLength (
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ OUT UINTN *ContentLength
+ );
+
+/**
+ Synchronously receive a HTTP RESPONSE message from the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] HeaderCount Number of headers in Headers.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[out] ChunkListHead A pointer to receivce list head of chunked data.
+ Caller has to release memory of ChunkListHead
+ and all list entries.
+ @param[out] ContentLength Total content length
+
+ @retval EFI_SUCCESS The HTTP chunked transfer is received.
+ @retval EFI_NOT_FOUND No chunked transfer coding header found.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_INVALID_PARAMETER Improper parameters.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoGetChunkedTransferContent (
+ IN HTTP_IO *HttpIo,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ OUT LIST_ENTRY **ChunkListHead,
+ OUT UINTN *ContentLength
+ );
+
+/**
+ Send HTTP request in chunks.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] SendChunkProcess Pointer to current chunk process status.
+ @param[out] RequestMessage Request to send.
+
+ @retval EFI_SUCCESS Successfully to send chunk data according to SendChunkProcess.
+ @retval Other Other errors.
+
+**/
+EFI_STATUS
+HttpIoSendChunkedTransfer (
+ IN HTTP_IO *HttpIo,
+ IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess,
+ IN EFI_HTTP_MESSAGE *RequestMessage
+);
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpLib.h b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpLib.h
index f46d513d05b..793c2475cd2 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpLib.h
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Include/Library/HttpLib.h
@@ -476,6 +476,59 @@ HttpIsValidHttpHeader (
IN CHAR8 *FieldName
);
+//
+// A wrapper structure to hold the HTTP headers.
+//
+typedef struct {
+ UINTN MaxHeaderCount;
+ UINTN HeaderCount;
+ EFI_HTTP_HEADER *Headers;
+} HTTP_IO_HEADER;
+
+
+/**
+ Create a HTTP_IO_HEADER to hold the HTTP header items.
+
+ @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.
+
+ @return A pointer of the HTTP header holder or NULL if failed.
+
+**/
+HTTP_IO_HEADER *
+HttpIoCreateHeader (
+ UINTN MaxHeaderCount
+ );
+
+/**
+ Destroy the HTTP_IO_HEADER and release the resources.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.
+
+**/
+VOID
+HttpIoFreeHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader
+ );
+
+/**
+ Set or update a HTTP header with the field name and corresponding value.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder.
+ @param[in] FieldName Null terminated string which describes a field name.
+ @param[in] FieldValue Null terminated string which describes the corresponding field value.
+
+ @retval EFI_SUCCESS The HTTP header has been set or updated.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.
+ @retval Other Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpIoSetHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader,
+ IN CHAR8 *FieldName,
+ IN CHAR8 *FieldValue
+ );
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c
new file mode 100644
index 00000000000..b03e5858215
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.c
@@ -0,0 +1,854 @@
+/** @file
+ Http IO Helper Library.
+
+ (C) Copyright 2020 Hewlett-Packard Development Company, L.P.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/Http.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Notify the callback function when an event is triggered.
+
+ @param[in] Context The opaque parameter to the function.
+
+**/
+VOID
+EFIAPI
+HttpIoNotifyDpc (
+ IN VOID *Context
+ )
+{
+ *((BOOLEAN *) Context) = TRUE;
+}
+
+/**
+ Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK.
+
+ @param[in] Event The event signaled.
+ @param[in] Context The opaque parameter to the function.
+
+**/
+VOID
+EFIAPI
+HttpIoNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ //
+ // Request HttpIoNotifyDpc as a DPC at TPL_CALLBACK
+ //
+ QueueDpc (TPL_CALLBACK, HttpIoNotifyDpc, Context);
+}
+
+/**
+ Destroy the HTTP_IO and release the resources.
+
+ @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed.
+
+**/
+VOID
+HttpIoDestroyIo (
+ IN HTTP_IO *HttpIo
+ )
+{
+ EFI_HTTP_PROTOCOL *Http;
+ EFI_EVENT Event;
+
+ if (HttpIo == NULL) {
+ return;
+ }
+
+ Event = HttpIo->ReqToken.Event;
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ Event = HttpIo->RspToken.Event;
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ Event = HttpIo->TimeoutEvent;
+ if (Event != NULL) {
+ gBS->CloseEvent (Event);
+ }
+
+ Http = HttpIo->Http;
+ if (Http != NULL) {
+ Http->Configure (Http, NULL);
+ gBS->CloseProtocol (
+ HttpIo->Handle,
+ &gEfiHttpProtocolGuid,
+ HttpIo->Image,
+ HttpIo->Controller
+ );
+ }
+
+ NetLibDestroyServiceChild (
+ HttpIo->Controller,
+ HttpIo->Image,
+ &gEfiHttpServiceBindingProtocolGuid,
+ HttpIo->Handle
+ );
+}
+
+/**
+ Create a HTTP_IO to access the HTTP service. It will create and configure
+ a HTTP child handle.
+
+ @param[in] Image The handle of the driver image.
+ @param[in] Controller The handle of the controller.
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
+ @param[in] ConfigData The HTTP_IO configuration data ,
+ NULL means not to configure the HTTP child.
+ @param[in] Callback Callback function which will be invoked when specified
+ HTTP_IO_CALLBACK_EVENT happened.
+ @param[in] Context The Context data which will be passed to the Callback function.
+ @param[out] HttpIo The HTTP_IO.
+
+ @retval EFI_SUCCESS The HTTP_IO is created and configured.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_UNSUPPORTED One or more of the control options are not
+ supported in the implementation.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval Others Failed to create the HTTP_IO or configure it.
+
+**/
+EFI_STATUS
+HttpIoCreateIo (
+ IN EFI_HANDLE Image,
+ IN EFI_HANDLE Controller,
+ IN UINT8 IpVersion,
+ IN HTTP_IO_CONFIG_DATA *ConfigData, OPTIONAL
+ IN HTTP_IO_CALLBACK Callback,
+ IN VOID *Context,
+ OUT HTTP_IO *HttpIo
+ )
+{
+ EFI_STATUS Status;
+ EFI_HTTP_CONFIG_DATA HttpConfigData;
+ EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;
+ EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;
+ EFI_HTTP_PROTOCOL *Http;
+ EFI_EVENT Event;
+
+ if ((Image == NULL) || (Controller == NULL) || (HttpIo == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IpVersion != IP_VERSION_4 && IpVersion != IP_VERSION_6) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ZeroMem (HttpIo, sizeof (HTTP_IO));
+ ZeroMem (&HttpConfigData, sizeof (EFI_HTTP_CONFIG_DATA));
+
+ //
+ // Create the HTTP child instance and get the HTTP protocol.
+ //
+ Status = NetLibCreateServiceChild (
+ Controller,
+ Image,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &HttpIo->Handle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->OpenProtocol (
+ HttpIo->Handle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ Image,
+ Controller,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status) || (Http == NULL)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Init the configuration data and configure the HTTP child.
+ //
+ HttpIo->Image = Image;
+ HttpIo->Controller = Controller;
+ HttpIo->IpVersion = IpVersion;
+ HttpIo->Http = Http;
+ HttpIo->Callback = Callback;
+ HttpIo->Context = Context;
+ HttpIo->Timeout = PcdGet32 (PcdHttpIoTimeout);
+
+ if (ConfigData != NULL) {
+ if (HttpIo->IpVersion == IP_VERSION_4) {
+ HttpConfigData.LocalAddressIsIPv6 = FALSE;
+ HttpConfigData.HttpVersion = ConfigData->Config4.HttpVersion;
+ HttpConfigData.TimeOutMillisec = ConfigData->Config4.RequestTimeOut;
+
+ Http4AccessPoint.UseDefaultAddress = ConfigData->Config4.UseDefaultAddress;
+ Http4AccessPoint.LocalPort = ConfigData->Config4.LocalPort;
+ IP4_COPY_ADDRESS (&Http4AccessPoint.LocalAddress, &ConfigData->Config4.LocalIp);
+ IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);
+ HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint;
+ } else {
+ HttpConfigData.LocalAddressIsIPv6 = TRUE;
+ HttpConfigData.HttpVersion = ConfigData->Config6.HttpVersion;
+ HttpConfigData.TimeOutMillisec = ConfigData->Config6.RequestTimeOut;
+
+ Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;
+ IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);
+ HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;
+ }
+
+ Status = Http->Configure (Http, &HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ }
+
+ //
+ // Create events for variuos asynchronous operations.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpIoNotify,
+ &HttpIo->IsTxDone,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ HttpIo->ReqToken.Event = Event;
+ HttpIo->ReqToken.Message = &HttpIo->ReqMessage;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ HttpIoNotify,
+ &HttpIo->IsRxDone,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ HttpIo->RspToken.Event = Event;
+ HttpIo->RspToken.Message = &HttpIo->RspMessage;
+
+ //
+ // Create TimeoutEvent for response
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ HttpIo->TimeoutEvent = Event;
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ HttpIoDestroyIo (HttpIo);
+
+ return Status;
+}
+
+/**
+ Synchronously send a HTTP REQUEST message to the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] Request A pointer to storage such data as URL and HTTP method.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] BodyLength Length in bytes of the HTTP body.
+ @param[in] Body Body associated with the HTTP request.
+
+ @retval EFI_SUCCESS The HTTP request is trasmitted.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoSendRequest (
+ IN HTTP_IO *HttpIo,
+ IN EFI_HTTP_REQUEST_DATA *Request,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN UINTN BodyLength,
+ IN VOID *Body
+ )
+{
+ EFI_STATUS Status;
+ EFI_HTTP_PROTOCOL *Http;
+
+ if (HttpIo == NULL || HttpIo->Http == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HttpIo->ReqToken.Status = EFI_NOT_READY;
+ HttpIo->ReqToken.Message->Data.Request = Request;
+ HttpIo->ReqToken.Message->HeaderCount = HeaderCount;
+ HttpIo->ReqToken.Message->Headers = Headers;
+ HttpIo->ReqToken.Message->BodyLength = BodyLength;
+ HttpIo->ReqToken.Message->Body = Body;
+
+ if (HttpIo->Callback != NULL) {
+ Status = HttpIo->Callback (
+ HttpIoRequest,
+ HttpIo->ReqToken.Message,
+ HttpIo->Context
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Queue the request token to HTTP instances.
+ //
+ Http = HttpIo->Http;
+ HttpIo->IsTxDone = FALSE;
+ Status = Http->Request (
+ Http,
+ &HttpIo->ReqToken
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Poll the network until transmit finish.
+ //
+ while (!HttpIo->IsTxDone) {
+ Http->Poll (Http);
+ }
+
+ return HttpIo->ReqToken.Status;
+}
+
+/**
+ Synchronously receive a HTTP RESPONSE message from the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] RecvMsgHeader TRUE to receive a new HTTP response (from message header).
+ FALSE to continue receive the previous response message.
+ @param[out] ResponseData Point to a wrapper of the received response data.
+
+ @retval EFI_SUCCESS The HTTP response is received.
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoRecvResponse (
+ IN HTTP_IO *HttpIo,
+ IN BOOLEAN RecvMsgHeader,
+ OUT HTTP_IO_RESPONSE_DATA *ResponseData
+ )
+{
+ EFI_STATUS Status;
+ EFI_HTTP_PROTOCOL *Http;
+
+ if (HttpIo == NULL || HttpIo->Http == NULL || ResponseData == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Queue the response token to HTTP instances.
+ //
+ HttpIo->RspToken.Status = EFI_NOT_READY;
+ if (RecvMsgHeader) {
+ HttpIo->RspToken.Message->Data.Response = &ResponseData->Response;
+ } else {
+ HttpIo->RspToken.Message->Data.Response = NULL;
+ }
+ HttpIo->RspToken.Message->HeaderCount = 0;
+ HttpIo->RspToken.Message->Headers = NULL;
+ HttpIo->RspToken.Message->BodyLength = ResponseData->BodyLength;
+ HttpIo->RspToken.Message->Body = ResponseData->Body;
+
+ Http = HttpIo->Http;
+ HttpIo->IsRxDone = FALSE;
+
+ //
+ // Start the timer, and wait Timeout seconds to receive the header packet.
+ //
+ Status = gBS->SetTimer (HttpIo->TimeoutEvent, TimerRelative, HttpIo->Timeout * TICKS_PER_MS);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = Http->Response (
+ Http,
+ &HttpIo->RspToken
+ );
+
+ if (EFI_ERROR (Status)) {
+ //
+ // Remove timeout timer from the event list.
+ //
+ gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
+ return Status;
+ }
+
+ //
+ // Poll the network until receive finish.
+ //
+ while (!HttpIo->IsRxDone && EFI_ERROR (gBS->CheckEvent (HttpIo->TimeoutEvent))) {
+ Http->Poll (Http);
+ }
+
+ //
+ // Remove timeout timer from the event list.
+ //
+ gBS->SetTimer (HttpIo->TimeoutEvent, TimerCancel, 0);
+
+ if (!HttpIo->IsRxDone) {
+ //
+ // Timeout occurs, cancel the response token.
+ //
+ Http->Cancel (Http, &HttpIo->RspToken);
+
+ Status = EFI_TIMEOUT;
+
+ return Status;
+ } else {
+ HttpIo->IsRxDone = FALSE;
+ }
+
+ if ((HttpIo->Callback != NULL) &&
+ (HttpIo->RspToken.Status == EFI_SUCCESS || HttpIo->RspToken.Status == EFI_HTTP_ERROR)) {
+ Status = HttpIo->Callback (
+ HttpIoResponse,
+ HttpIo->RspToken.Message,
+ HttpIo->Context
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Store the received data into the wrapper.
+ //
+ ResponseData->Status = HttpIo->RspToken.Status;
+ ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;
+ ResponseData->Headers = HttpIo->RspToken.Message->Headers;
+ ResponseData->BodyLength = HttpIo->RspToken.Message->BodyLength;
+
+ return Status;
+}
+
+/**
+ Get the value of the content length if there is a "Content-Length" header.
+
+ @param[in] HeaderCount Number of HTTP header structures in Headers.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[out] ContentLength Pointer to save the value of the content length.
+
+ @retval EFI_SUCCESS Successfully get the content length.
+ @retval EFI_NOT_FOUND No "Content-Length" header in the Headers.
+
+**/
+EFI_STATUS
+HttpIoGetContentLength (
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ OUT UINTN *ContentLength
+ )
+{
+ EFI_HTTP_HEADER *Header;
+
+ Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_CONTENT_LENGTH);
+ if (Header == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ return AsciiStrDecimalToUintnS (Header->FieldValue, (CHAR8 **) NULL, ContentLength);
+}
+/**
+ Send HTTP request in chunks.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] SendChunkProcess Pointer to current chunk process status.
+ @param[in] RequestMessage Request to send.
+
+ @retval EFI_SUCCESS Successfully to send chunk data according to SendChunkProcess.
+ @retval Other Other errors.
+
+**/
+EFI_STATUS
+HttpIoSendChunkedTransfer (
+ IN HTTP_IO *HttpIo,
+ IN HTTP_IO_SEND_CHUNK_PROCESS *SendChunkProcess,
+ IN EFI_HTTP_MESSAGE *RequestMessage
+)
+{
+ EFI_STATUS Status;
+ EFI_HTTP_HEADER *NewHeaders;
+ EFI_HTTP_HEADER *ContentLengthHeader;
+ UINTN AddNewHeader;
+ UINTN HeaderCount;
+ CHAR8 *MessageBody;
+ UINTN MessageBodyLength;
+ UINTN ChunkLength;
+ CHAR8 ChunkLengthStr [HTTP_IO_CHUNK_SIZE_STRING_LEN];
+ EFI_HTTP_REQUEST_DATA *SentRequestData;
+
+ AddNewHeader = 0;
+ NewHeaders = NULL;
+ MessageBody = NULL;
+ ContentLengthHeader = NULL;
+ MessageBodyLength = 0;
+
+ switch (*SendChunkProcess) {
+ case HttpIoSendChunkHeaderZeroContent:
+ ContentLengthHeader = HttpFindHeader (RequestMessage->HeaderCount, RequestMessage->Headers, HTTP_HEADER_CONTENT_LENGTH);
+ if (ContentLengthHeader == NULL) {
+ AddNewHeader = 1;
+ }
+
+ NewHeaders = AllocateZeroPool ((RequestMessage->HeaderCount + AddNewHeader) * sizeof(EFI_HTTP_HEADER));
+ CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
+ if (AddNewHeader == 0) {
+ //
+ // Override content-length to Transfer-Encoding.
+ //
+ ContentLengthHeader = HttpFindHeader (RequestMessage->HeaderCount, NewHeaders, HTTP_HEADER_CONTENT_LENGTH);
+ ContentLengthHeader->FieldName = NULL;
+ ContentLengthHeader->FieldValue = NULL;
+ } else {
+ ContentLengthHeader = NewHeaders + RequestMessage->HeaderCount;
+ }
+ HttpSetFieldNameAndValue (ContentLengthHeader, HTTP_HEADER_TRANSFER_ENCODING, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED);
+ HeaderCount = RequestMessage->HeaderCount + AddNewHeader;
+ MessageBodyLength = 0;
+ MessageBody = NULL;
+ SentRequestData = RequestMessage->Data.Request;
+ break;
+
+ case HttpIoSendChunkContent:
+ HeaderCount = 0;
+ NewHeaders = NULL;
+ SentRequestData = NULL;
+ if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
+ MessageBodyLength = HTTP_IO_MAX_SEND_PAYLOAD;
+ } else {
+ MessageBodyLength = RequestMessage->BodyLength;
+ }
+ AsciiSPrint (
+ ChunkLengthStr,
+ HTTP_IO_CHUNK_SIZE_STRING_LEN,
+ "%x%c%c",
+ MessageBodyLength,
+ CHUNKED_TRANSFER_CODING_CR,
+ CHUNKED_TRANSFER_CODING_LF
+ );
+ ChunkLength = AsciiStrLen (ChunkLengthStr);
+ MessageBody = AllocatePool (ChunkLength + MessageBodyLength + 2);
+ if (MessageBody == NULL) {
+ DEBUG((DEBUG_ERROR, "Not enough memory for chunk transfer\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Build up the chunk transfer paylaod.
+ //
+ CopyMem (MessageBody, ChunkLengthStr, ChunkLength);
+ CopyMem (MessageBody + ChunkLength, RequestMessage->Body, MessageBodyLength);
+ *(MessageBody + ChunkLength + MessageBodyLength) = CHUNKED_TRANSFER_CODING_CR;
+ *(MessageBody + ChunkLength + MessageBodyLength + 1) = CHUNKED_TRANSFER_CODING_LF;
+ //
+ // Change variables for the next chunk trasnfer.
+ //
+ RequestMessage->BodyLength -= MessageBodyLength;
+ RequestMessage->Body = (VOID *)((CHAR8 *)RequestMessage->Body + MessageBodyLength);
+ MessageBodyLength += (ChunkLength + 2);
+ if (RequestMessage->BodyLength == 0) {
+ *SendChunkProcess = HttpIoSendChunkEndChunk;
+ }
+ break;
+
+ case HttpIoSendChunkEndChunk:
+ HeaderCount = 0;
+ NewHeaders = NULL;
+ SentRequestData = NULL;
+ AsciiSPrint (
+ ChunkLengthStr,
+ HTTP_IO_CHUNK_SIZE_STRING_LEN,
+ "0%c%c%c%c",
+ CHUNKED_TRANSFER_CODING_CR,
+ CHUNKED_TRANSFER_CODING_LF,
+ CHUNKED_TRANSFER_CODING_CR,
+ CHUNKED_TRANSFER_CODING_LF
+ );
+ MessageBody = AllocatePool (AsciiStrLen(ChunkLengthStr));
+ if (MessageBody == NULL) {
+ DEBUG((DEBUG_ERROR, "Not enough memory for the end chunk transfer\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (MessageBody, ChunkLengthStr, AsciiStrLen (ChunkLengthStr));
+ MessageBodyLength = AsciiStrLen (ChunkLengthStr);
+ *SendChunkProcess = HttpIoSendChunkFinish;
+ break;
+
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = HttpIoSendRequest (
+ HttpIo,
+ SentRequestData,
+ HeaderCount,
+ NewHeaders,
+ MessageBodyLength,
+ MessageBody
+ );
+ if (ContentLengthHeader != NULL) {
+ if (ContentLengthHeader->FieldName != NULL) {
+ FreePool (ContentLengthHeader->FieldName);
+ }
+ if (ContentLengthHeader->FieldValue != NULL) {
+ FreePool (ContentLengthHeader->FieldValue);
+ }
+ }
+ if (NewHeaders != NULL) {
+ FreePool (NewHeaders);
+ }
+ if (MessageBody != NULL) {
+ FreePool (MessageBody);
+ }
+ return Status;
+}
+
+/**
+ Synchronously receive a HTTP RESPONSE message from the server.
+
+ @param[in] HttpIo The HttpIo wrapping the HTTP service.
+ @param[in] HeaderCount Number of headers in Headers.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[out] ChunkListHead A pointer to receive list head
+ of chunked data. Caller has to
+ release memory of ChunkListHead
+ and all list entries.
+ @param[out] ContentLength Total content length
+
+ @retval EFI_SUCCESS The HTTP chunked transfer is received.
+ @retval EFI_NOT_FOUND No chunked transfer coding header found.
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
+ @retval EFI_INVALID_PARAMETER Improper parameters.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+HttpIoGetChunkedTransferContent (
+ IN HTTP_IO *HttpIo,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ OUT LIST_ENTRY **ChunkListHead,
+ OUT UINTN *ContentLength
+ )
+{
+ EFI_HTTP_HEADER *Header;
+ CHAR8 ChunkSizeAscii [256];
+ EFI_STATUS Status;
+ UINTN Index;
+ HTTP_IO_RESPONSE_DATA ResponseData;
+ UINTN TotalLength;
+ UINTN MaxTotalLength;
+ LIST_ENTRY *HttpChunks;
+ HTTP_IO_CHUNKS *ThisChunk;
+ LIST_ENTRY *ThisListEntry;
+
+ if (ChunkListHead == NULL || ContentLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ContentLength = 0;
+ Header = HttpFindHeader (HeaderCount, Headers, HTTP_HEADER_TRANSFER_ENCODING);
+ if (Header == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (AsciiStrCmp (Header->FieldValue, HTTP_HEADER_TRANSFER_ENCODING_CHUNKED) != 0) {
+ return EFI_NOT_FOUND;
+ }
+ //
+ // Loop to get all chunks.
+ //
+ TotalLength = 0;
+ MaxTotalLength = PcdGet32 (PcdMaxHttpChunkTransfer);
+ HttpChunks = (LIST_ENTRY *)AllocateZeroPool (sizeof (LIST_ENTRY));
+ if (HttpChunks == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ExitDeleteChunks;
+ }
+ InitializeListHead (HttpChunks);
+ DEBUG ((DEBUG_INFO, " Chunked transfer\n"));
+ while (TRUE) {
+ ZeroMem((VOID *)&ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
+ ResponseData.BodyLength = HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH;
+ ResponseData.Body = ChunkSizeAscii;
+ Status = HttpIoRecvResponse (
+ HttpIo,
+ FALSE,
+ &ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ExitDeleteChunks;
+ }
+ //
+ // Decoding Chunked Transfer Coding.
+ // Only decode chunk-size and last chunk.
+ //
+ DEBUG ((DEBUG_INFO, " Chunk HTTP Response StatusCode - %d\n", ResponseData.Response.StatusCode));
+ //
+ // Break if this is last chunk.
+ //
+ if (ChunkSizeAscii [0] == CHUNKED_TRANSFER_CODING_LAST_CHUNK) {
+ //
+ // Check if this is a valid Last-Chunk.
+ //
+ if ((ChunkSizeAscii [1] != CHUNKED_TRANSFER_CODING_CR) ||
+ (ChunkSizeAscii [2] != CHUNKED_TRANSFER_CODING_LF)
+ ) {
+ DEBUG ((DEBUG_ERROR, " This is an invalid Last-chunk\n"));
+ Status = EFI_INVALID_PARAMETER;
+ goto ExitDeleteChunks;
+ }
+
+ Status = EFI_SUCCESS;
+ DEBUG ((DEBUG_INFO, " Last-chunk\n"));
+ ThisChunk = (HTTP_IO_CHUNKS *)AllocateZeroPool (sizeof (HTTP_IO_CHUNKS));
+ if (ThisChunk == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ExitDeleteChunks;
+ }
+
+ InitializeListHead (&ThisChunk->NextChunk);
+ ThisChunk->Length = ResponseData.BodyLength - 1 - 2; // Minus sizeof '0' and CRLF.
+ ThisChunk->Data = (CHAR8 *)AllocatePool (ThisChunk->Length);
+ if (ThisChunk->Data == NULL) {
+ FreePool ((UINT8 *)ThisChunk);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ExitDeleteChunks;
+ }
+ CopyMem ((UINT8 *)ThisChunk->Data, (UINT8 *)ResponseData.Body + 1, ThisChunk->Length);
+ TotalLength += ThisChunk->Length;
+ InsertTailList (HttpChunks, &ThisChunk->NextChunk);
+ break;
+ }
+
+ //
+ // Get the chunk length
+ //
+ Index = 0;
+ while ((ChunkSizeAscii [Index] != CHUNKED_TRANSFER_CODING_EXTENSION_SEPARATOR) &&
+ (ChunkSizeAscii [Index] != (CHAR8)CHUNKED_TRANSFER_CODING_CR) &&
+ (Index != HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH)) {
+ Index ++;
+ }
+
+ if (Index == HTTP_IO_CHUNKED_TRANSFER_CODING_DATA_LENGTH) {
+ Status = EFI_NOT_FOUND;
+ goto ExitDeleteChunks;
+ }
+ ChunkSizeAscii[Index] = 0;
+ AsciiStrHexToUintnS (ChunkSizeAscii, NULL, ContentLength);
+ DEBUG ((DEBUG_INFO, " Length of this chunk %d\n", *ContentLength));
+ //
+ // Receive the data;
+ //
+ ThisChunk = (HTTP_IO_CHUNKS *)AllocateZeroPool (sizeof (HTTP_IO_CHUNKS));
+ if (ThisChunk == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ExitDeleteChunks;
+ }
+ ResponseData.BodyLength = *ContentLength;
+ ResponseData.Body = (CHAR8 *)AllocatePool (*ContentLength);
+ if (ResponseData.Body == NULL) {
+ FreePool (ThisChunk);
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ExitDeleteChunks;
+ }
+ InitializeListHead (&ThisChunk->NextChunk);
+ ThisChunk->Length = *ContentLength;
+ ThisChunk->Data = ResponseData.Body;
+ InsertTailList (HttpChunks, &ThisChunk->NextChunk);
+ Status = HttpIoRecvResponse (
+ HttpIo,
+ FALSE,
+ &ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ExitDeleteChunks;
+ }
+ //
+ // Read CRLF
+ //
+ ZeroMem((VOID *)&ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
+ ResponseData.BodyLength = 2;
+ ResponseData.Body = ChunkSizeAscii;
+ Status = HttpIoRecvResponse (
+ HttpIo,
+ FALSE,
+ &ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ExitDeleteChunks;
+ }
+ //
+ // Verify the end of chunk payload.
+ //
+ if ((ChunkSizeAscii [0] != CHUNKED_TRANSFER_CODING_CR) ||
+ (ChunkSizeAscii [1] != CHUNKED_TRANSFER_CODING_LF)
+ ) {
+ DEBUG ((DEBUG_ERROR, " This is an invalid End-of-chunk notation.\n"));
+ goto ExitDeleteChunks;
+ }
+ TotalLength += *ContentLength;
+ if (TotalLength > MaxTotalLength) {
+ DEBUG ((DEBUG_ERROR, " Total chunk transfer payload exceeds the size defined by PcdMaxHttpChunkTransfer.\n"));
+ goto ExitDeleteChunks;
+ }
+ }
+
+ *ContentLength = TotalLength;
+ *ChunkListHead = HttpChunks;
+ DEBUG ((DEBUG_INFO, " Total of lengh of chunks :%d\n", TotalLength));
+ return EFI_SUCCESS;
+
+ExitDeleteChunks:
+ if (HttpChunks != NULL) {
+ while (!IsListEmpty(HttpChunks)) {
+ ThisListEntry = GetFirstNode (HttpChunks);
+ RemoveEntryList (ThisListEntry);
+ ThisChunk = (HTTP_IO_CHUNKS *)ThisListEntry;
+ if (ThisChunk->Data != NULL) {
+ FreePool (ThisChunk->Data);
+ }
+ FreePool(ThisListEntry);
+ }
+ FreePool (HttpChunks);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
new file mode 100644
index 00000000000..15b433651cb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
@@ -0,0 +1,46 @@
+## @file
+# This library instance provides HTTP IO helper functions.
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = DxeHttpIoLib
+ MODULE_UNI_FILE = DxeHttpIoLib.uni
+ FILE_GUID = 50B198F8-7986-4F51-A857-CFE4643D59F3
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HttpIoLib| DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARM64 RISCV64
+#
+
+[Sources]
+ DxeHttpIoLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ NetworkPkg/NetworkPkg.dec
+
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DpcLib
+ MemoryAllocationLib
+ PrintLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiHttpProtocolGuid ## SOMETIMES_CONSUMES
+
+[Pcd]
+ gEfiNetworkPkgTokenSpaceGuid.PcdMaxHttpChunkTransfer ## SOMETIMES_CONSUMES
+ gEfiNetworkPkgTokenSpaceGuid.PcdHttpIoTimeout ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni
new file mode 100644
index 00000000000..f30c572382d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.uni
@@ -0,0 +1,12 @@
+// /** @file
+// The library instance provides HTTP IO helper functions.
+//
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "HTTP IO Helper Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "The library instance provides HTTP IO helper functions."
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
index 003913ad177..a5f06db418e 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c
@@ -3,7 +3,7 @@
It provides the helper routines to parse the HTTP message byte stream.
Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
-(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+(C) Copyright 2016 - 2020 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1122,6 +1122,7 @@ HttpParseMessageBody (
CHAR8 *Char;
UINTN RemainderLengthInThis;
UINTN LengthForCallback;
+ UINTN PortionLength;
EFI_STATUS Status;
HTTP_BODY_PARSER *Parser;
@@ -1173,19 +1174,31 @@ HttpParseMessageBody (
//
// Identity transfer-coding, just notify user to save the body data.
//
+ PortionLength = MIN (
+ BodyLength,
+ Parser->ContentLength - Parser->ParsedBodyLength
+ );
+ if (PortionLength == 0) {
+ //
+ // Got BodyLength, but no ContentLength. Use BodyLength.
+ //
+ PortionLength = BodyLength;
+ Parser->ContentLength = PortionLength;
+ }
+
if (Parser->Callback != NULL) {
Status = Parser->Callback (
BodyParseEventOnData,
Char,
- MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength),
+ PortionLength,
Parser->Context
);
if (EFI_ERROR (Status)) {
return Status;
}
}
- Char += MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength);
- Parser->ParsedBodyLength += MIN (BodyLength, Parser->ContentLength - Parser->ParsedBodyLength);
+ Char += PortionLength;
+ Parser->ParsedBodyLength += PortionLength;
if (Parser->ParsedBodyLength == Parser->ContentLength) {
Parser->State = BodyParserComplete;
if (Parser->Callback != NULL) {
@@ -2082,3 +2095,135 @@ HttpIsValidHttpHeader (
return TRUE;
}
+
+/**
+ Create a HTTP_IO_HEADER to hold the HTTP header items.
+
+ @param[in] MaxHeaderCount The maximun number of HTTP header in this holder.
+
+ @return A pointer of the HTTP header holder or NULL if failed.
+
+**/
+HTTP_IO_HEADER *
+HttpIoCreateHeader (
+ UINTN MaxHeaderCount
+ )
+{
+ HTTP_IO_HEADER *HttpIoHeader;
+
+ if (MaxHeaderCount == 0) {
+ return NULL;
+ }
+
+ HttpIoHeader = AllocateZeroPool (sizeof (HTTP_IO_HEADER) + MaxHeaderCount * sizeof (EFI_HTTP_HEADER));
+ if (HttpIoHeader == NULL) {
+ return NULL;
+ }
+
+ HttpIoHeader->MaxHeaderCount = MaxHeaderCount;
+ HttpIoHeader->Headers = (EFI_HTTP_HEADER *) (HttpIoHeader + 1);
+
+ return HttpIoHeader;
+}
+
+/**
+ Destroy the HTTP_IO_HEADER and release the resources.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder to be destroyed.
+
+**/
+VOID
+HttpIoFreeHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader
+ )
+{
+ UINTN Index;
+
+ if (HttpIoHeader != NULL) {
+ if (HttpIoHeader->HeaderCount != 0) {
+ for (Index = 0; Index < HttpIoHeader->HeaderCount; Index++) {
+ FreePool (HttpIoHeader->Headers[Index].FieldName);
+ ZeroMem (HttpIoHeader->Headers[Index].FieldValue, AsciiStrSize (HttpIoHeader->Headers[Index].FieldValue));
+ FreePool (HttpIoHeader->Headers[Index].FieldValue);
+ }
+ }
+ FreePool (HttpIoHeader);
+ }
+}
+
+/**
+ Set or update a HTTP header with the field name and corresponding value.
+
+ @param[in] HttpIoHeader Point to the HTTP header holder.
+ @param[in] FieldName Null terminated string which describes a field name.
+ @param[in] FieldValue Null terminated string which describes the corresponding field value.
+
+ @retval EFI_SUCCESS The HTTP header has been set or updated.
+ @retval EFI_INVALID_PARAMETER Any input parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Insufficient resource to complete the operation.
+ @retval Other Unexpected error happened.
+
+**/
+EFI_STATUS
+HttpIoSetHeader (
+ IN HTTP_IO_HEADER *HttpIoHeader,
+ IN CHAR8 *FieldName,
+ IN CHAR8 *FieldValue
+ )
+{
+ EFI_HTTP_HEADER *Header;
+ UINTN StrSize;
+ CHAR8 *NewFieldValue;
+
+ if (HttpIoHeader == NULL || FieldName == NULL || FieldValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Header = HttpFindHeader (HttpIoHeader->HeaderCount, HttpIoHeader->Headers, FieldName);
+ if (Header == NULL) {
+ //
+ // Add a new header.
+ //
+ if (HttpIoHeader->HeaderCount >= HttpIoHeader->MaxHeaderCount) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Header = &HttpIoHeader->Headers[HttpIoHeader->HeaderCount];
+
+ StrSize = AsciiStrSize (FieldName);
+ Header->FieldName = AllocatePool (StrSize);
+ if (Header->FieldName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Header->FieldName, FieldName, StrSize);
+ Header->FieldName[StrSize -1] = '\0';
+
+ StrSize = AsciiStrSize (FieldValue);
+ Header->FieldValue = AllocatePool (StrSize);
+ if (Header->FieldValue == NULL) {
+ FreePool (Header->FieldName);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (Header->FieldValue, FieldValue, StrSize);
+ Header->FieldValue[StrSize -1] = '\0';
+
+ HttpIoHeader->HeaderCount++;
+ } else {
+ //
+ // Update an existing one.
+ //
+ StrSize = AsciiStrSize (FieldValue);
+ NewFieldValue = AllocatePool (StrSize);
+ if (NewFieldValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (NewFieldValue, FieldValue, StrSize);
+ NewFieldValue[StrSize -1] = '\0';
+
+ if (Header->FieldValue != NULL) {
+ FreePool (Header->FieldValue);
+ }
+ Header->FieldValue = NewFieldValue;
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.dsc.inc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.dsc.inc
index d79d5298624..82e1df18e6c 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.dsc.inc
@@ -7,7 +7,7 @@
# This file defines one build flag PLATFORMX64_ENABLE to support
# IA32 PEI and X64 DXE platform. Its default value is FALSE.
#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -30,6 +30,9 @@
[LibraryClasses]
!include NetworkPkg/NetworkLibs.dsc.inc
+[BuildOptions]
+!include NetworkPkg/NetworkBuildOptions.dsc.inc
+
!if $(PLATFORMX64_ENABLE) == TRUE
[Components.X64]
!include NetworkPkg/NetworkComponents.dsc.inc
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.fdf.inc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.fdf.inc
index 784908f339c..877ff39a626 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.fdf.inc
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/Network.fdf.inc
@@ -46,10 +46,13 @@
INF NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
!endif
- !if $(NETWORK_HTTP_BOOT_ENABLE) == TRUE
+ !if ($(NETWORK_HTTP_BOOT_ENABLE) == TRUE) OR ($(NETWORK_HTTP_ENABLE) == TRUE)
INF NetworkPkg/DnsDxe/DnsDxe.inf
INF NetworkPkg/HttpDxe/HttpDxe.inf
INF NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
+ !endif
+
+ !if $(NETWORK_HTTP_BOOT_ENABLE) == TRUE
INF NetworkPkg/HttpBootDxe/HttpBootDxe.inf
!endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkBuildOptions.dsc.inc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkBuildOptions.dsc.inc
new file mode 100644
index 00000000000..d0d0d3f1be4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkBuildOptions.dsc.inc
@@ -0,0 +1,22 @@
+## @file
+# Network DSC include file for [BuildOptions] sections of all Architectures.
+#
+# This file can be included in the [BuildOptions*] section(s) of a platform DSC file
+# by using "!include NetworkPkg/NetworkBuildOptions.dsc.inc", to specify the C language
+# feature test macros (eg., API deprecation macros) according to the flags described
+# in "NetworkDefines.dsc.inc".
+#
+# Supported tool chain families: "GCC", "INTEL", "MSFT", "RVCT".
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!if $(NETWORK_ISCSI_ENABLE) == TRUE
+ MSFT:*_*_*_CC_FLAGS = /D ENABLE_MD5_DEPRECATED_INTERFACES
+ INTEL:*_*_*_CC_FLAGS = /D ENABLE_MD5_DEPRECATED_INTERFACES
+ GCC:*_*_*_CC_FLAGS = -D ENABLE_MD5_DEPRECATED_INTERFACES
+ RVCT:*_*_*_CC_FLAGS = -DENABLE_MD5_DEPRECATED_INTERFACES
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkComponents.dsc.inc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkComponents.dsc.inc
index c0bae651f3e..d6c526562ce 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkComponents.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkComponents.dsc.inc
@@ -48,10 +48,13 @@
NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
!endif
- !if $(NETWORK_HTTP_BOOT_ENABLE) == TRUE
+ !if ($(NETWORK_HTTP_BOOT_ENABLE) == TRUE) OR ($(NETWORK_HTTP_ENABLE) == TRUE)
NetworkPkg/DnsDxe/DnsDxe.inf
NetworkPkg/HttpDxe/HttpDxe.inf
NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
+ !endif
+
+ !if $(NETWORK_HTTP_BOOT_ENABLE) == TRUE
NetworkPkg/HttpBootDxe/HttpBootDxe.inf
!endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkDefines.dsc.inc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkDefines.dsc.inc
index 53a18c42db1..ac5c8e92172 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkDefines.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkDefines.dsc.inc
@@ -15,12 +15,14 @@
# DEFINE NETWORK_IP4_ENABLE = TRUE
# DEFINE NETWORK_IP6_ENABLE = TRUE
# DEFINE NETWORK_TLS_ENABLE = TRUE
+# DEFINE NETWORK_HTTP_ENABLE = FALSE
# DEFINE NETWORK_HTTP_BOOT_ENABLE = TRUE
# DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = FALSE
-# DEFINE NETWORK_ISCSI_ENABLE = TRUE
+# DEFINE NETWORK_ISCSI_ENABLE = FALSE
# DEFINE NETWORK_VLAN_ENABLE = TRUE
#
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -73,10 +75,21 @@
DEFINE NETWORK_TLS_ENABLE = TRUE
!endif
+!ifndef NETWORK_HTTP_ENABLE
+ #
+ # This flag is to enable or disable HTTP(S) feature.
+ # The default is set to FALSE to not affecting the existing
+ # platforms.
+ # NETWORK_HTTP_ENABLE set to FALSE is not affecting NETWORK_HTTP_BOOT_ENABLE
+ # when NETWORK_HTTP_BOOT_ENABLE is TRUE.
+ DEFINE NETWORK_HTTP_ENABLE = FALSE
+!endif
+
!ifndef NETWORK_HTTP_BOOT_ENABLE
#
# This flag is to enable or disable HTTP(S) boot feature.
#
+ #
DEFINE NETWORK_HTTP_BOOT_ENABLE = TRUE
!endif
@@ -101,7 +114,7 @@
# Both OpensslLib.inf and OpensslLibCrypto.inf library instance can be used
# since libssl is not required for iSCSI.
#
- DEFINE NETWORK_ISCSI_ENABLE = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = FALSE
!endif
!if $(NETWORK_ENABLE) == TRUE
@@ -112,7 +125,9 @@
!error "Must enable at least IP4 or IP6 stack if NETWORK_ENABLE is set to TRUE!"
!endif
- !if ($(NETWORK_HTTP_BOOT_ENABLE) == TRUE) AND ($(NETWORK_TLS_ENABLE) == FALSE) AND ($(NETWORK_ALLOW_HTTP_CONNECTIONS) == FALSE)
- !error "Must enable TLS to support HTTPS, or allow unsecured HTTP connection, if NETWORK_HTTP_BOOT_ENABLE is set to TRUE!"
+ !if ($(NETWORK_HTTP_BOOT_ENABLE) == TRUE) OR ($(NETWORK_HTTP_ENABLE) == TRUE)
+ !if ($(NETWORK_TLS_ENABLE) == FALSE) AND ($(NETWORK_ALLOW_HTTP_CONNECTIONS) == FALSE)
+ !error "Must enable TLS to support HTTPS, or allow unsecured HTTP connection, if NETWORK_HTTP_BOOT_ENABLE or NETWORK_HTTP_ENABLE is set to TRUE!"
+ !endif
!endif
!endif
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkLibs.dsc.inc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkLibs.dsc.inc
index c77bb37df96..65e0590f1bc 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkLibs.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkLibs.dsc.inc
@@ -6,6 +6,7 @@
# of EDKII network library classes.
#
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -16,5 +17,7 @@
IpIoLib|NetworkPkg/Library/DxeIpIoLib/DxeIpIoLib.inf
UdpIoLib|NetworkPkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
TcpIoLib|NetworkPkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
- # HttpLib is used for Http Boot
+ # HttpLib and HttpIoLib are used for Http Boot and other
+ # HTTP applications.
HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.ci.yaml
index 3e34258900d..580c98a9c5b 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.ci.yaml
@@ -2,9 +2,25 @@
# CI configuration for NetworkPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
"CompilerPlugin": {
"DscPath": "NetworkPkg.dsc"
},
@@ -56,6 +72,7 @@
"BLD_*_NETWORK_IP4_ENABLE": "TRUE",
"BLD_*_NETWORK_IP6_ENABLE": "TRUE",
"BLD_*_NETWORK_TLS_ENABLE": "TRUE",
+ "BLD_*_NETWORK_HTTP_ENABLE": "FALSE",
"BLD_*_NETWORK_HTTP_BOOT_ENABLE": "TRUE",
"BLD_*_NETWORK_ISCSI_ENABLE": "TRUE",
}
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dec b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dec
index ecc22fd2bff..49747f184dc 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dec
@@ -3,8 +3,8 @@
#
# This package provides network modules that conform to UEFI 2.4 specification.
#
-# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
-# (C) Copyright 2015-2017 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -41,6 +41,10 @@
# This library is only intended to be used by UEFI network stack modules.
HttpLib|Include/Library/HttpLib.h
+ ## @libraryclass Http IO helper routines for HTTP transfer.
+ # This library is only intended to be used by UEFI network stack modules.
+ HttpIoLib|Include/Library/HttpIoLib.h
+
## @libraryclass Library for Deferred Procedure Calls.
DpcLib|Include/Library/DpcLib.h
@@ -89,6 +93,14 @@
# @Prompt Max attempt number.
gEfiNetworkPkgTokenSpaceGuid.PcdMaxIScsiAttemptNumber|0x08|UINT8|0x0000000D
+ ## The maximum size of total HTTP chunk transfer.
+ # @Prompt Max size of total HTTP chunk transfer. the default value is 12MB.
+ gEfiNetworkPkgTokenSpaceGuid.PcdMaxHttpChunkTransfer|0x0C00000|UINT32|0x0000000E
+
+ ## The Timeout value of HTTP IO.
+ # @Prompt The Timeout value of HTTP Io. Default value is 5000.
+ gEfiNetworkPkgTokenSpaceGuid.PcdHttpIoTimeout|5000|UINT32|0x0000000F
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Indicates whether HTTP connections (i.e., unsecured) are permitted or not.
# TRUE - HTTP connections are allowed. Both the "https://" and "http://" URI schemes are permitted.
diff --git a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dsc b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dsc
index 0777709931b..c613ae8a4f1 100644
--- a/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/NetworkPkg/NetworkPkg.dsc
@@ -2,7 +2,7 @@
# UEFI 2.4 Network Module Package for All Architectures
#
# (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
-# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -18,6 +18,10 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+ DEFINE NETWORK_ISCSI_ENABLE = TRUE
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
@@ -40,6 +44,7 @@
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
!ifdef CONTINUOUS_INTEGRATION
BaseCryptLib|CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -106,6 +111,7 @@
NetworkPkg/Application/VConfig/VConfig.inf
NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf
NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
NetworkPkg/Library/DxeIpIoLib/DxeIpIoLib.inf
NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
NetworkPkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/8254TimerDxe/Timer.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/8254TimerDxe/Timer.c
index 6b5fa872063..d5c559c1eff 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/8254TimerDxe/Timer.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/8254TimerDxe/Timer.c
@@ -79,8 +79,6 @@ TimerInterruptHandler (
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
- mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq0);
-
if (mTimerNotifyFunction != NULL) {
//
// @bug : This does not handle missed timer interrupts
@@ -89,6 +87,9 @@ TimerInterruptHandler (
}
gBS->RestoreTPL (OriginalTPL);
+
+ DisableInterrupts ();
+ mLegacy8259->EndOfInterrupt (mLegacy8259, Efi8259Irq0);
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.dsc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.dsc
new file mode 100644
index 00000000000..bffb749c3a8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -0,0 +1,856 @@
+## @file
+# EFI/Framework Open Virtual Machine Firmware (OVMF) platform for SEV secure
+# virtual machine remote attestation and secret injection
+#
+# Copyright (c) 2020 James Bottomley, IBM Corporation.
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = Ovmf
+ PLATFORM_GUID = 07ff380c-4760-4823-8f59-ec2cb06fbc16
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/AmdSev
+ SUPPORTED_ARCHITECTURES = X64
+ BUILD_TARGETS = NOOPT|DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = OvmfPkg/AmdSev/AmdSevX64.fdf
+ PREBUILD = sh OvmfPkg/AmdSev/Grub/grub.sh
+
+ #
+ # Defines for default states. These can be changed on the command line.
+ # -D FLAG=VALUE
+ #
+ DEFINE SOURCE_DEBUG_ENABLE = FALSE
+ DEFINE TPM_ENABLE = FALSE
+ DEFINE TPM_CONFIG_ENABLE = FALSE
+
+ #
+ # Shell can be useful for debugging but should not be enabled for production
+ #
+ DEFINE BUILD_SHELL = FALSE
+
+ #
+ # Device drivers
+ #
+ DEFINE PVSCSI_ENABLE = TRUE
+ DEFINE MPT_SCSI_ENABLE = TRUE
+ DEFINE LSI_SCSI_ENABLE = FALSE
+
+ #
+ # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
+ # one of the supported values, in place of any of the convenience macros, is
+ # permitted.
+ #
+!ifdef $(FD_SIZE_1MB)
+ DEFINE FD_SIZE_IN_KB = 1024
+!else
+!ifdef $(FD_SIZE_2MB)
+ DEFINE FD_SIZE_IN_KB = 2048
+!else
+!ifdef $(FD_SIZE_4MB)
+ DEFINE FD_SIZE_IN_KB = 4096
+!else
+ DEFINE FD_SIZE_IN_KB = 4096
+!endif
+!endif
+!endif
+
+[BuildOptions]
+ GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
+ INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+ MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(TOOL_CHAIN_TAG) != "CLANGPDB"
+ GCC:*_*_*_CC_FLAGS = -mno-mmx -mno-sse
+!endif
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ MSFT:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+ GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+ INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+!endif
+ RELEASE_*_*_GENFW_FLAGS = --zero
+
+ #
+ # Disable deprecated APIs.
+ #
+ MSFT:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
+ INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
+ GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+
+[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.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+ PciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf
+ PciCapPciSegmentLib|OvmfPkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf
+ PciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
+ MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+ SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
+ QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+ FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+ DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+
+ LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
+
+ AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+ VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+
+!if $(BUILD_SHELL) == TRUE
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+!endif
+
+ SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+ XenHypercallLib|OvmfPkg/Library/XenHypercallLib/XenHypercallLib.inf
+ XenPlatformLib|OvmfPkg/Library/XenPlatformLib/XenPlatformLib.inf
+
+!if $(TPM_ENABLE) == TRUE
+ Tpm12CommandLib|SecurityPkg/Library/Tpm12CommandLib/Tpm12CommandLib.inf
+ Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+ Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+ Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
+ TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+!else
+ Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf
+ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+!endif
+
+[LibraryClasses.common]
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
+
+[LibraryClasses.common.SEC]
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
+!endif
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+!if $(TOOL_CHAIN_TAG) == "XCODE5"
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
+!else
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+!endif
+ VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
+
+[LibraryClasses.common.PEI_CORE]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+ MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+ QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
+
+!if $(TPM_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+ Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
+!endif
+
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+ QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf
+ PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
+ QemuBootOrderLib|OvmfPkg/Library/QemuBootOrderLib/QemuBootOrderLib.inf
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxDxeLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+ MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+ QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+ QemuLoadImageLib|OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
+!if $(TPM_ENABLE) == TRUE
+ Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
+!endif
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+ MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
+!endif
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.SMM_CORE]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/DxeResetSystemLib.inf
+ SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
+ MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+ SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+ gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
+ # match PcdFlashNvStorageVariableSize purely for convenience
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400
+ # match PcdFlashNvStorageVariableSize purely for convenience
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000
+!endif
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
+
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+
+ # DEBUG_INIT 0x00000001 // Initialization
+ # DEBUG_WARN 0x00000002 // Warnings
+ # DEBUG_LOAD 0x00000004 // Load events
+ # DEBUG_FS 0x00000008 // EFI File system
+ # DEBUG_POOL 0x00000010 // Alloc & Free (pool)
+ # DEBUG_PAGE 0x00000020 // Alloc & Free (page)
+ # DEBUG_INFO 0x00000040 // Informational debug messages
+ # DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers
+ # DEBUG_VARIABLE 0x00000100 // Variable
+ # DEBUG_BM 0x00000400 // Boot Manager
+ # DEBUG_BLKIO 0x00001000 // BlkIo Driver
+ # DEBUG_NET 0x00004000 // SNP Driver
+ # DEBUG_UNDI 0x00010000 // UNDI Driver
+ # DEBUG_LOADFILE 0x00020000 // LoadFile
+ # DEBUG_EVENT 0x00080000 // Event messages
+ # DEBUG_GCD 0x00100000 // Global Coherency Database changes
+ # DEBUG_CACHE 0x00200000 // Memory range cachability changes
+ # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may
+ # // significantly impact boot performance
+ # DEBUG_ERROR 0x80000000 // Error
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+!endif
+
+ # This PCD is used to set the base address of the PCI express hierarchy. It
+ # is only consulted when OVMF runs on Q35. In that case it is programmed into
+ # the PCIEXBAR register.
+ #
+ # On Q35 machine types that QEMU intends to support in the long term, QEMU
+ # never lets the RAM below 4 GB exceed 2816 MB.
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xB0000000
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
+!endif
+
+ #
+ # The NumberOfPages values below are ad-hoc. They are updated sporadically at
+ # best (please refer to git-blame for past updates). The values capture a set
+ # of BIN hints that made sense at a particular time, for some (now likely
+ # unknown) workloads / boot paths.
+ #
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS|0x80
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory|0x10
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0x80
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0x100
+ gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0x100
+
+ # IRQs 5, 9, 10, 11 are level-triggered
+ gUefiOvmfPkgTokenSpaceGuid.Pcd8259LegacyModeEdgeLevel|0x0E20
+
+ # Point to the MdeModulePkg/Application/UiApp/UiApp.inf
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|TRUE
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|800
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable|FALSE
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId|0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x800000000
+
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
+
+ # Set video resolution for text setup.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0208
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE
+
+ # Noexec settings for DXE.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE
+
+ # UefiCpuPkg PCDs related to initial AP bringup and general AP management.
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber|0
+
+ # Set memory encryption mask
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+
+ # Set SEV-ES defaults
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0
+
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x00
+
+!if $(TPM_ENABLE) == TRUE
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+!endif
+
+[PcdsDynamicHii]
+!if $(TPM_ENABLE) == TRUE && $(TPM_CONFIG_ENABLE) == TRUE
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x8|3|NV,BS
+!endif
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform.
+#
+################################################################################
+[Components]
+ OvmfPkg/ResetVector/ResetVector.inf
+
+ #
+ # SEC Phase modules
+ #
+ OvmfPkg/Sec/SecMain.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ #
+ # PEI Phase modules
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+ OvmfPkg/PlatformPei/PlatformPei.inf
+ UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+ UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+ OvmfPkg/AmdSev/SecretPei/SecretPei.inf
+
+!if $(TPM_ENABLE) == TRUE
+ OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
+ OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+ SecurityPkg/Tcg/TcgPei/TcgPei.inf
+ SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
+ <LibraryClasses>
+ HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
+ }
+!endif
+
+ #
+ # DXE Phase modules
+ #
+ MdeModulePkg/Core/Dxe/DxeMain.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ }
+
+ MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+ MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+ <LibraryClasses>
+!if $(TPM_ENABLE) == TRUE
+ NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf
+ NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+!endif
+ }
+
+ MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+ OvmfPkg/8259InterruptControllerDxe/8259.inf
+ UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+ UefiCpuPkg/CpuDxe/CpuDxe.inf
+ OvmfPkg/8254TimerDxe/8254Timer.inf
+ OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
+ OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
+ MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
+ <LibraryClasses>
+ PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
+ NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
+ }
+ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+ MdeModulePkg/Universal/Metronome/Metronome.inf
+ PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+ MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+ MdeModulePkg/Logo/LogoDxe.inf
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+ }
+ OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+ OvmfPkg/Virtio10Dxe/Virtio10.inf
+ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+ OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+ OvmfPkg/VirtioRngDxe/VirtioRng.inf
+ OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
+ OvmfPkg/XenBusDxe/XenBusDxe.inf
+ OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
+!if $(PVSCSI_ENABLE) == TRUE
+ OvmfPkg/PvScsiDxe/PvScsiDxe.inf
+!endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+ OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+ OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
+ <LibraryClasses>
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+ MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+ MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+ MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+ FatPkg/EnhancedFatDxe/Fat.inf
+ MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+ OvmfPkg/SataControllerDxe/SataControllerDxe.inf
+ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+ OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+ OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
+ OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
+
+ #
+ # ISA Support
+ #
+ OvmfPkg/SioBusDxe/SioBusDxe.inf
+ MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+ MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+
+ #
+ # SMBIOS Support
+ #
+ MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf {
+ <LibraryClasses>
+ NULL|OvmfPkg/Library/SmbiosVersionLib/DetectSmbiosVersionLib.inf
+ }
+ OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+ #
+ # ACPI Support
+ #
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+ OvmfPkg/AcpiTables/AcpiTables.inf
+ MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+
+ #
+ # Usb Support
+ #
+ MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+ MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+ MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+ MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+ MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+ MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(BUILD_SHELL) == TRUE
+ OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
+!endif
+ OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
+ OvmfPkg/AmdSev/Grub/Grub.inf
+!if $(BUILD_SHELL) == TRUE
+ ShellPkg/Application/Shell/Shell.inf {
+ <LibraryClasses>
+ ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+ HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+
+ <PcdsFixedAtBuild>
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+ }
+!endif
+
+ OvmfPkg/PlatformDxe/Platform.inf
+ OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+ OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+
+ #
+ # Variable driver stack (non-SMM)
+ #
+ OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+ OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
+ <LibraryClasses>
+ PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
+ }
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ }
+
+ #
+ # TPM support
+ #
+!if $(TPM_ENABLE) == TRUE
+ SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf {
+ <LibraryClasses>
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
+ NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
+ HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
+ }
+!if $(TPM_CONFIG_ENABLE) == TRUE
+ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
+!endif
+ SecurityPkg/Tcg/TcgDxe/TcgDxe.inf {
+ <LibraryClasses>
+ Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf
+ }
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.fdf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.fdf
new file mode 100644
index 00000000000..f82ed5fcd5f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -0,0 +1,460 @@
+## @file
+# Open Virtual Machine Firmware: FDF
+#
+# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+
+[Defines]
+!include OvmfPkg/OvmfPkgDefines.fdf.inc
+
+#
+# Build the variable store and the firmware code as one unified flash device
+# image.
+#
+[FD.OVMF]
+BaseAddress = $(FW_BASE_ADDRESS)
+Size = $(FW_SIZE)
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(FW_BLOCKS)
+
+!include OvmfPkg/VarStore.fdf.inc
+
+$(VARS_SIZE)|$(FVMAIN_SIZE)
+FV = FVMAIN_COMPACT
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+FV = SECFV
+
+################################################################################
+
+[FD.MEMFD]
+BaseAddress = $(MEMFD_BASE_ADDRESS)
+Size = 0xD00000
+ErasePolarity = 1
+BlockSize = 0x10000
+NumBlocks = 0xD0
+
+0x000000|0x006000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+
+0x006000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
+
+0x007000|0x001000
+gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+
+0x008000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize
+
+0x009000|0x002000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
+
+0x00B000|0x001000
+gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize
+
+0x00C000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
+
+0x00D000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+
+0x010000|0x010000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+
+0x020000|0x0E0000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+FV = PEIFV
+
+0x100000|0xC00000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+FV = DXEFV
+
+################################################################################
+
+[FV.SECFV]
+FvNameGuid = 763BED0D-DE9F-48F5-81F1-3E90E1B1A015
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+#
+# SEC Phase modules
+#
+# The code in this FV handles the initial firmware startup, and
+# decompresses the PEI and DXE FVs which handles the rest of the boot sequence.
+#
+INF OvmfPkg/Sec/SecMain.inf
+
+INF RuleOverride=RESET_VECTOR OvmfPkg/ResetVector/ResetVector.inf
+
+################################################################################
+[FV.PEIFV]
+FvNameGuid = 6938079B-B503-4E3D-9D24-B28337A25806
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+}
+
+#
+# PEI Phase modules
+#
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+INF OvmfPkg/PlatformPei/PlatformPei.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+INF OvmfPkg/AmdSev/SecretPei/SecretPei.inf
+
+!if $(TPM_ENABLE) == TRUE
+INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
+INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
+INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+!endif
+
+################################################################################
+
+[FV.DXEFV]
+FvForceRebase = FALSE
+FvNameGuid = 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI DXE {
+ INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+ INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+ INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+}
+
+#
+# DXE Phase modules
+#
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+INF OvmfPkg/8259InterruptControllerDxe/8259.inf
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF UefiCpuPkg/CpuDxe/CpuDxe.inf
+INF OvmfPkg/8254TimerDxe/8254Timer.inf
+INF OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
+INF OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
+INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+INF OvmfPkg/Virtio10Dxe/Virtio10.inf
+INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+INF OvmfPkg/VirtioRngDxe/VirtioRng.inf
+INF OvmfPkg/XenIoPciDxe/XenIoPciDxe.inf
+INF OvmfPkg/XenBusDxe/XenBusDxe.inf
+INF OvmfPkg/XenPvBlkDxe/XenPvBlkDxe.inf
+!if $(PVSCSI_ENABLE) == TRUE
+INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf
+!endif
+!if $(MPT_SCSI_ENABLE) == TRUE
+INF OvmfPkg/MptScsiDxe/MptScsiDxe.inf
+!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
+
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+INF MdeModulePkg/Application/UiApp/UiApp.inf
+INF OvmfPkg/QemuKernelLoaderFsDxe/QemuKernelLoaderFsDxe.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+INF OvmfPkg/SataControllerDxe/SataControllerDxe.inf
+INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+INF OvmfPkg/SioBusDxe/SioBusDxe.inf
+!if $(SOURCE_DEBUG_ENABLE) == FALSE
+INF MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+!endif
+INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+
+INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+INF OvmfPkg/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf
+INF RuleOverride=ACPITABLE OvmfPkg/AcpiTables/AcpiTables.inf
+INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+
+INF FatPkg/EnhancedFatDxe/Fat.inf
+INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
+!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(BUILD_SHELL) == TRUE
+INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
+!endif
+INF OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
+INF OvmfPkg/AmdSev/Grub/Grub.inf
+!if $(BUILD_SHELL) == TRUE
+INF ShellPkg/Application/Shell/Shell.inf
+!endif
+
+INF MdeModulePkg/Logo/LogoDxe.inf
+
+#
+# Usb Support
+#
+INF MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
+INF MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
+INF MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
+INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
+
+INF OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+
+INF OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf
+INF OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
+INF OvmfPkg/PlatformDxe/Platform.inf
+INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+
+
+#
+# Variable driver stack (non-SMM)
+#
+INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
+INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+
+#
+# TPM support
+#
+!if $(TPM_ENABLE) == TRUE
+INF SecurityPkg/Tcg/TcgDxe/TcgDxe.inf
+INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+!if $(TPM_CONFIG_ENABLE) == TRUE
+INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
+!endif
+!endif
+
+################################################################################
+
+[FV.FVMAIN_COMPACT]
+FvNameGuid = 48DB5E17-707C-472D-91CD-1613E7EF51B0
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+ #
+ # These firmware volumes will have files placed in them uncompressed,
+ # and then both firmware volumes will be compressed in a single
+ # compression operation in order to achieve better overall compression.
+ #
+ SECTION FV_IMAGE = PEIFV
+ SECTION FV_IMAGE = DXEFV
+ }
+ }
+
+!include OvmfPkg/FvmainCompactScratchEnd.fdf.inc
+
+################################################################################
+
+[Rule.Common.SEC]
+ FILE SEC = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ RAW ACPI Optional |.acpi
+ RAW ASL Optional |.aml
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+ FILE FREEFORM = $(NAMED_GUID) {
+ RAW ACPI |.acpi
+ RAW ASL |.aml
+ }
+
+[Rule.Common.SEC.RESET_VECTOR]
+ FILE RAW = $(NAMED_GUID) {
+ RAW BIN Align = 16 |.bin
+ }
+
+[Rule.Common.SMM_CORE]
+ FILE SMM_CORE = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_SMM_DRIVER]
+ FILE SMM = $(NAMED_GUID) {
+ SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/.gitignore b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/.gitignore
new file mode 100644
index 00000000000..7e3b30951f2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/.gitignore
@@ -0,0 +1 @@
+grub.efi
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/Grub.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/Grub.inf
new file mode 100644
index 00000000000..08212d5d3d8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/Grub.inf
@@ -0,0 +1,39 @@
+## @file
+# Create a Firmware Volume based Grub Bootloader
+#
+# Copyright (C) 2020 James Bottomley, IBM Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = Grub
+ # This is gGrubFileGuid
+ FILE_GUID = b5ae312c-bc8a-43b1-9c62-ebb826dd5d07
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UefiMain
+
+[Packages]
+ OvmfPkg/OvmfPkg.dec
+
+#
+# The following information is for reference only and not required by
+# the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+##
+# Note: The version of grub.efi this picks up can be generated by
+# grub.sh which must be specified as a PREBUILD in the .dsc file. If
+# grub.efi is newer than either grub.sh or grub.cfg then grub.sh will
+# exit with success meaning that if you move your own version of grub
+# in here (after checking out grub.sh and grub.cfg), PREBUILD won't
+# overwrite it.
+##
+[Binaries]
+ PE32|grub.efi|*
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.cfg b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.cfg
new file mode 100644
index 00000000000..ee183693b56
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.cfg
@@ -0,0 +1,46 @@
+## @file
+# Execute a script to recover the SEV supplied secret and use it to
+# decrypt a luks volume. For security, the kernel must be on an encrypted
+# volume so reboot if none are found.
+#
+# Copyright (C) 2020 James Bottomley, IBM Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+echo "Entering grub config"
+sevsecret
+if [ $? -ne 0 ]; then
+ echo "Failed to locate anything in the SEV secret area, prompting for password"
+ cryptomount -a
+else
+ cryptomount -s
+ if [ $? -ne 0 ]; then
+ echo "Failed to mount root securely, retrying with password prompt"
+ cryptomount -a
+ fi
+fi
+set root=
+for f in (crypto*); do
+ if [ -e $f/boot/grub/grub.cfg ]; then
+ set root=$f
+ set prefix=($root)/boot/grub
+ break;
+ fi
+done
+if [ x$root = x ]; then
+ echo "Failed to find any grub configuration on the encrypted volume"
+ sleep 5
+ reboot
+fi
+# rest of modules to get boot to work
+set modules="
+ boot
+ loadenv
+ "
+for f in $modules; do
+ insmod $f
+done
+echo "Transferring to ${prefix}/grub.cfg"
+source $prefix/grub.cfg
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.sh b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.sh
new file mode 100644
index 00000000000..99807d7291b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/Grub/grub.sh
@@ -0,0 +1,93 @@
+## @file
+# Build a version of grub capable of decrypting a luks volume with a SEV
+# Supplied secret
+#
+# Copyright (C) 2020 James Bottomley, IBM Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+set -e
+remove_efi=1
+
+cleanup() {
+ # remove the intermediates
+ for f in disk.fat grub-bootstrap.cfg; do
+ rm -f -- "${basedir}/$f"
+ done
+ if [ $remove_efi -eq 1 ]; then
+ rm -f -- "${basedir}/grub.efi"
+ fi
+}
+
+trap cleanup EXIT
+
+GRUB_MODULES="
+ part_msdos
+ part_gpt
+ cryptodisk
+ luks
+ gcry_rijndael
+ gcry_sha256
+ ext2
+ btrfs
+ xfs
+ fat
+ configfile
+ memdisk
+ sleep
+ normal
+ echo
+ test
+ regexp
+ linux
+ linuxefi
+ reboot
+ sevsecret
+ "
+basedir=$(dirname -- "$0")
+
+# don't run a build if grub.efi exists and is newer than the config files
+if [ -e "${basedir}/grub.efi" ] && \
+ [ "${basedir}/grub.efi" -nt "${basedir}/grub.cfg" ] && \
+ [ "${basedir}/grub.efi" -nt "${basedir}/grub.sh" ]; then
+ remove_efi=0
+ echo "preserving existing grub.efi" >&2
+ exit 0
+fi
+
+##
+# different distributions have different names for grub-mkimage, so
+# search all the known ones
+##
+mkimage=
+for b in grub2-mkimage grub-mkimage; do
+ if which "$b" > /dev/null 2>&1; then
+ mkimage="$b"
+ break
+ fi
+done
+if [ -z "$mkimage" ]; then
+ echo "Can't find grub mkimage" >&2
+ exit 1
+fi
+
+# GRUB's rescue parser doesn't understand 'if'.
+echo 'normal (memdisk)/grub.cfg' > "${basedir}/grub-bootstrap.cfg"
+
+# Now build a memdisk with the correct grub.cfg
+rm -f -- "${basedir}/disk.fat"
+mkfs.msdos -C -- "${basedir}/disk.fat" 64
+mcopy -i "${basedir}/disk.fat" -- "${basedir}/grub.cfg" ::grub.cfg
+
+
+${mkimage} -O x86_64-efi \
+ -p '(crypto0)' \
+ -c "${basedir}/grub-bootstrap.cfg" \
+ -m "${basedir}/disk.fat" \
+ -o "${basedir}/grub.efi" \
+ ${GRUB_MODULES}
+
+remove_efi=0
+echo "grub.efi generated in ${basedir}"
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
new file mode 100644
index 00000000000..fcbd3dd71e8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.c
@@ -0,0 +1,27 @@
+/** @file
+ SEV Secret configuration table constructor
+
+ Copyright (C) 2020 James Bottomley, IBM Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <PiDxe.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Guid/ConfidentialComputingSecret.h>
+
+STATIC CONFIDENTIAL_COMPUTING_SECRET_LOCATION mSecretDxeTable = {
+ FixedPcdGet32 (PcdSevLaunchSecretBase),
+ FixedPcdGet32 (PcdSevLaunchSecretSize),
+};
+
+EFI_STATUS
+EFIAPI
+InitializeSecretDxe(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return gBS->InstallConfigurationTable (
+ &gConfidentialComputingSecretGuid,
+ &mSecretDxeTable
+ );
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
new file mode 100644
index 00000000000..c59e5b49f77
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretDxe/SecretDxe.inf
@@ -0,0 +1,37 @@
+## @file
+# Sev Secret configuration Table installer
+#
+# Copyright (C) 2020 James Bottomley, IBM Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecretDxe
+ FILE_GUID = 6e2b9619-8810-4e9d-a177-d432bb9abeda
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSecretDxe
+
+[Sources]
+ SecretDxe.c
+
+[Packages]
+ OvmfPkg/OvmfPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gConfidentialComputingSecretGuid
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.c
new file mode 100644
index 00000000000..57e3d26509f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.c
@@ -0,0 +1,25 @@
+/** @file
+ SEV Secret boot time HOB placement
+
+ Copyright (C) 2020 James Bottomley, IBM Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <PiPei.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+
+EFI_STATUS
+EFIAPI
+InitializeSecretPei (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdSevLaunchSecretBase),
+ PcdGet32 (PcdSevLaunchSecretSize),
+ EfiBootServicesData
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
new file mode 100644
index 00000000000..3e28650de17
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSev/SecretPei/SecretPei.inf
@@ -0,0 +1,35 @@
+## @file
+# PEI support for SEV Secrets
+#
+# Copyright (C) 2020 James Bottomley, IBM Corporation.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecretPei
+ FILE_GUID = 45260dde-0c3c-4b41-a226-ef3803fac7d4
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeSecretPei
+
+[Sources]
+ SecretPei.c
+
+[Packages]
+ OvmfPkg/OvmfPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ HobLib
+ PeimEntryPoint
+ PcdLib
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index 378cd923a9a..92ed471572c 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -4,12 +4,13 @@
in APRIORI. It clears C-bit from MMIO and NonExistent Memory space when SEV
is enabled.
- Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
+#include <IndustryStandard/Q35MchIch9.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
@@ -66,6 +67,23 @@ AmdSevDxeEntryPoint (
}
//
+ // If PCI Express is enabled, the MMCONFIG area has been reserved, rather
+ // than marked as MMIO, and so the C-bit won't be cleared by the above walk
+ // through the GCD map. Check for the MMCONFIG area and clear the C-bit for
+ // the range.
+ //
+ if (PcdGet16 (PcdOvmfHostBridgePciDevId) == INTEL_Q35_MCH_DEVICE_ID) {
+ Status = MemEncryptSevClearPageEncMask (
+ 0,
+ FixedPcdGet64 (PcdPciExpressBaseAddress),
+ EFI_SIZE_TO_PAGES (SIZE_256MB),
+ FALSE
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ //
// When SMM is enabled, clear the C-bit from SMM Saved State Area
//
// NOTES: The SavedStateArea address cleared here is before SMBASE
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
index 8dc5579df6c..5343e289441 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
@@ -2,7 +2,7 @@
#
# Driver clears the encryption attribute from MMIO regions when SEV is enabled
#
-# Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -39,3 +39,9 @@
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
new file mode 100644
index 00000000000..13e0febc08c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.c
@@ -0,0 +1,252 @@
+/** @file
+ bhyve ACPI Platform Driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AcpiPlatform.h"
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ return AcpiProtocol->InstallAcpiTable (
+ AcpiProtocol,
+ AcpiTableBuffer,
+ AcpiTableBufferSize,
+ TableKey
+ );
+}
+
+
+/**
+ Locate the first instance of a protocol. If the protocol requested is an
+ FV protocol, then it will return the first FV that contains the ACPI table
+ storage file.
+
+ @param Instance Return pointer to the first instance of the protocol
+
+ @return EFI_SUCCESS The function completed successfully.
+ @return EFI_NOT_FOUND The protocol could not be located.
+ @return EFI_OUT_OF_RESOURCES There are not enough resources to find the protocol.
+
+**/
+EFI_STATUS
+LocateFvInstanceWithTables (
+ OUT EFI_FIRMWARE_VOLUME2_PROTOCOL **Instance
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EFI_FV_FILETYPE FileType;
+ UINT32 FvStatus;
+ EFI_FV_FILE_ATTRIBUTES Attributes;
+ UINTN Size;
+ UINTN Index;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance;
+
+ FvStatus = 0;
+
+ //
+ // Locate protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Defined errors at this time are not found and out of resources.
+ //
+ return Status;
+ }
+
+ //
+ // Looking for FV with ACPI storage file
+ //
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ //
+ // Get the protocol on this handle
+ // This should not fail because of LocateHandleBuffer
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID**) &FvInstance
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // See if it has the ACPI storage file
+ //
+ Status = FvInstance->ReadFile (
+ FvInstance,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ NULL,
+ &Size,
+ &FileType,
+ &Attributes,
+ &FvStatus
+ );
+
+ //
+ // If we found it, then we are done
+ //
+ if (Status == EFI_SUCCESS) {
+ *Instance = FvInstance;
+ break;
+ }
+ }
+
+ //
+ // Our exit status is determined by the success of the previous operations
+ // If the protocol was found, Instance already points to it.
+ //
+
+ //
+ // Free any allocated buffers
+ //
+ gBS->FreePool (HandleBuffer);
+
+ return Status;
+}
+
+
+/**
+ Find ACPI tables in an FV and install them.
+
+ This is now a fall-back path. Normally, we will search for tables provided
+ by the VMM first.
+
+ If that fails, we use this function to load the ACPI tables from an FV. The
+ sources for the FV based tables is located under OvmfPkg/AcpiTables.
+
+ @param AcpiTable Protocol instance pointer
+
+**/
+EFI_STATUS
+EFIAPI
+InstallOvmfFvTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FwVol;
+ INTN Instance;
+ EFI_ACPI_COMMON_HEADER *CurrentTable;
+ UINTN TableHandle;
+ UINT32 FvStatus;
+ UINTN TableSize;
+ UINTN Size;
+ EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
+
+ Instance = 0;
+ CurrentTable = NULL;
+ TableHandle = 0;
+
+ TableInstallFunction = BhyveInstallAcpiTable;
+
+ //
+ // set FwVol (and use an ASSERT() below) to suppress incorrect
+ // compiler/analyzer warnings
+ //
+ FwVol = NULL;
+ //
+ // Locate the firmware volume protocol
+ //
+ Status = LocateFvInstanceWithTables (&FwVol);
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+ ASSERT (FwVol != NULL);
+
+ //
+ // Read tables from the storage file.
+ //
+ while (Status == EFI_SUCCESS) {
+
+ Status = FwVol->ReadSection (
+ FwVol,
+ (EFI_GUID*)PcdGetPtr (PcdAcpiTableStorageFile),
+ EFI_SECTION_RAW,
+ Instance,
+ (VOID**) &CurrentTable,
+ &Size,
+ &FvStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add the table
+ //
+ TableHandle = 0;
+
+ TableSize = ((EFI_ACPI_DESCRIPTION_HEADER *) CurrentTable)->Length;
+ ASSERT (Size >= TableSize);
+
+ //
+ // Install ACPI table
+ //
+ Status = TableInstallFunction (
+ AcpiTable,
+ CurrentTable,
+ TableSize,
+ &TableHandle
+ );
+
+ //
+ // Free memory allocated by ReadSection
+ //
+ gBS->FreePool (CurrentTable);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_ABORTED;
+ }
+
+ //
+ // Increment the instance
+ //
+ Instance++;
+ CurrentTable = NULL;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Effective entrypoint of Acpi Platform driver.
+
+ @param ImageHandle
+ @param SystemTable
+
+ @return EFI_SUCCESS
+ @return EFI_LOAD_ERROR
+ @return EFI_OUT_OF_RESOURCES
+
+**/
+EFI_STATUS
+EFIAPI
+InstallAcpiTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = InstallOvmfFvTables (AcpiTable);
+
+ return Status;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
new file mode 100644
index 00000000000..1fac2112c00
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatform.h
@@ -0,0 +1,73 @@
+/** @file
+ bhyve ACPI Platform Driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _ACPI_PLATFORM_H_INCLUDED_
+#define _ACPI_PLATFORM_H_INCLUDED_
+
+#include <PiDxe.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/PciIo.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/XenPlatformLib.h>
+#include <IndustryStandard/Acpi.h>
+
+typedef struct {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 PciAttributes;
+} ORIGINAL_ATTRIBUTES;
+
+typedef struct S3_CONTEXT S3_CONTEXT;
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ );
+
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable(
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ );
+
+EFI_STATUS
+EFIAPI
+InstallXenTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol
+ );
+
+EFI_STATUS
+EFIAPI
+InstallAcpiTables (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiTable
+ );
+
+VOID
+EnablePciDecoding (
+ OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+ OUT UINTN *Count
+ );
+
+VOID
+RestorePciDecoding (
+ IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+ IN UINTN Count
+ );
+
+#endif /* _ACPI_PLATFORM_H_INCLUDED_ */
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
new file mode 100644
index 00000000000..094ef9482d1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
@@ -0,0 +1,65 @@
+## @file
+# OVMF ACPI Platform Driver
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = AcpiPlatform
+ FILE_GUID = D5F92408-BAB5-44CA-8A60-C212F01D7E9D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiPlatformEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ AcpiPlatform.c
+ AcpiPlatform.h
+ Bhyve.c
+ EntryPoint.c
+ PciDecoding.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ BhyveFwCtlLib
+ DebugLib
+ DxeServicesTableLib
+ MemoryAllocationLib
+ OrderedCollectionLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+ gRootBridgesConnectedEventGroupGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiTableStorageFile
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+
+[Depex]
+ gEfiAcpiTableProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
new file mode 100644
index 00000000000..61198c842d2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/Bhyve.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+ * Copyright (C) 2012, Red Hat, Inc.
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+#include "AcpiPlatform.h"
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/BhyveFwCtlLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+STATIC
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiMadtTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ UINT32 CpuCount;
+ UINTN cSize;
+ UINTN NewBufferSize;
+ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER *Madt;
+ EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE *LocalApic;
+ EFI_ACPI_1_0_IO_APIC_STRUCTURE *IoApic;
+ EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE *Iso;
+ VOID *Ptr;
+ UINTN Loop;
+ EFI_STATUS Status;
+
+ ASSERT (AcpiTableBufferSize >= sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+
+ // Query the host for the number of vCPUs
+ CpuCount = 0;
+ cSize = sizeof(CpuCount);
+ if (BhyveFwCtlGet ("hw.ncpu", &CpuCount, &cSize) == RETURN_SUCCESS) {
+ DEBUG ((DEBUG_INFO, "Retrieved CpuCount %d\n", CpuCount));
+ ASSERT (CpuCount >= 1);
+ } else {
+ DEBUG ((DEBUG_INFO, "CpuCount retrieval error\n"));
+ CpuCount = 1;
+ }
+
+ NewBufferSize = 1 * sizeof (*Madt) +
+ CpuCount * sizeof (*LocalApic) +
+ 1 * sizeof (*IoApic) +
+ 1 * sizeof (*Iso);
+
+ Madt = AllocatePool (NewBufferSize);
+ if (Madt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (&(Madt->Header), AcpiTableBuffer, sizeof (EFI_ACPI_DESCRIPTION_HEADER));
+ Madt->Header.Length = (UINT32) NewBufferSize;
+ Madt->LocalApicAddress = 0xFEE00000;
+ Madt->Flags = EFI_ACPI_1_0_PCAT_COMPAT;
+ Ptr = Madt + 1;
+
+ LocalApic = Ptr;
+ for (Loop = 0; Loop < CpuCount; ++Loop) {
+ LocalApic->Type = EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC;
+ LocalApic->Length = sizeof (*LocalApic);
+ LocalApic->AcpiProcessorId = (UINT8) Loop;
+ LocalApic->ApicId = (UINT8) Loop;
+ LocalApic->Flags = 1; // enabled
+ ++LocalApic;
+ }
+ Ptr = LocalApic;
+
+ IoApic = Ptr;
+ IoApic->Type = EFI_ACPI_1_0_IO_APIC;
+ IoApic->Length = sizeof (*IoApic);
+ IoApic->IoApicId = (UINT8) CpuCount;
+ IoApic->Reserved = EFI_ACPI_RESERVED_BYTE;
+ IoApic->IoApicAddress = 0xFEC00000;
+ IoApic->SystemVectorBase = 0x00000000;
+ Ptr = IoApic + 1;
+
+ //
+ // IRQ0 (8254 Timer) => IRQ2 (PIC) Interrupt Source Override Structure
+ //
+ Iso = Ptr;
+ Iso->Type = EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE;
+ Iso->Length = sizeof (*Iso);
+ Iso->Bus = 0x00; // ISA
+ Iso->Source = 0x00; // IRQ0
+ Iso->GlobalSystemInterruptVector = 0x00000002;
+ Iso->Flags = 0x0000; // Conforms to specs of the bus
+ Ptr = Iso + 1;
+
+ ASSERT ((UINTN) ((UINT8 *)Ptr - (UINT8 *)Madt) == NewBufferSize);
+ Status = InstallAcpiTable (AcpiProtocol, Madt, NewBufferSize, TableKey);
+
+ FreePool (Madt);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+BhyveInstallAcpiTable (
+ IN EFI_ACPI_TABLE_PROTOCOL *AcpiProtocol,
+ IN VOID *AcpiTableBuffer,
+ IN UINTN AcpiTableBufferSize,
+ OUT UINTN *TableKey
+ )
+{
+ EFI_ACPI_DESCRIPTION_HEADER *Hdr;
+ EFI_ACPI_TABLE_INSTALL_ACPI_TABLE TableInstallFunction;
+
+ Hdr = (EFI_ACPI_DESCRIPTION_HEADER*) AcpiTableBuffer;
+ switch (Hdr->Signature) {
+ case EFI_ACPI_1_0_APIC_SIGNATURE:
+ TableInstallFunction = BhyveInstallAcpiMadtTable;
+ break;
+ default:
+ TableInstallFunction = InstallAcpiTable;
+ }
+
+ return TableInstallFunction (
+ AcpiProtocol,
+ AcpiTableBuffer,
+ AcpiTableBufferSize,
+ TableKey
+ );
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c
new file mode 100644
index 00000000000..6433788035f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/EntryPoint.c
@@ -0,0 +1,90 @@
+/** @file
+ Entry point of OVMF ACPI Platform Driver
+
+ Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include "AcpiPlatform.h"
+
+STATIC
+EFI_ACPI_TABLE_PROTOCOL *
+FindAcpiTableProtocol (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+
+ Status = gBS->LocateProtocol (
+ &gEfiAcpiTableProtocolGuid,
+ NULL,
+ (VOID**)&AcpiTable
+ );
+ ASSERT_EFI_ERROR (Status);
+ return AcpiTable;
+}
+
+
+STATIC
+VOID
+EFIAPI
+OnRootBridgesConnected (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO,
+ "%a: root bridges have been connected, installing ACPI tables\n",
+ __FUNCTION__));
+ Status = InstallAcpiTables (FindAcpiTableProtocol ());
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: InstallAcpiTables: %r\n", __FUNCTION__, Status));
+ }
+ gBS->CloseEvent (Event);
+}
+
+
+EFI_STATUS
+EFIAPI
+AcpiPlatformEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT RootBridgesConnected;
+
+ //
+ // If the platform doesn't support PCI, or PCI enumeration has been disabled,
+ // install the tables at once, and let the entry point's return code reflect
+ // the full functionality.
+ //
+ if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+ DEBUG ((DEBUG_INFO, "%a: PCI or its enumeration disabled, installing "
+ "ACPI tables\n", __FUNCTION__));
+ return InstallAcpiTables (FindAcpiTableProtocol ());
+ }
+
+ //
+ // Otherwise, delay installing the ACPI tables until root bridges are
+ // connected. The entry point's return status will only reflect the callback
+ // setup. (Note that we're a DXE_DRIVER; our entry point function is invoked
+ // strictly before BDS is entered and can connect the root bridges.)
+ //
+ Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
+ OnRootBridgesConnected, NULL /* Context */,
+ &gRootBridgesConnectedEventGroupGuid, &RootBridgesConnected);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO,
+ "%a: waiting for root bridges to be connected, registered callback\n",
+ __FUNCTION__));
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c
new file mode 100644
index 00000000000..a5b58a9578d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiPlatformDxe/PciDecoding.c
@@ -0,0 +1,192 @@
+/** @file
+ Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
+ regenerates the ACPI tables.
+
+ Copyright (C) 2016, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/MemoryAllocationLib.h>
+
+#include "AcpiPlatform.h"
+
+
+/**
+ Collect all PciIo protocol instances in the system. Save their original
+ attributes, and enable IO and MMIO decoding for each.
+
+ This is a best effort function; it doesn't return status codes. Its
+ caller is supposed to proceed even if this function fails.
+
+ @param[out] OriginalAttributes On output, a dynamically allocated array of
+ ORIGINAL_ATTRIBUTES elements. The array lists
+ the PciIo protocol instances found in the
+ system at the time of the call, plus the
+ original PCI attributes for each.
+
+ Before returning, the function enables IO and
+ MMIO decoding for each PciIo instance it
+ finds.
+
+ On error, or when no such instances are
+ found, OriginalAttributes is set to NULL.
+
+ @param[out] Count On output, the number of elements in
+ OriginalAttributes. On error it is set to
+ zero.
+**/
+VOID
+EnablePciDecoding (
+ OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
+ OUT UINTN *Count
+ )
+{
+ EFI_STATUS Status;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ ORIGINAL_ATTRIBUTES *OrigAttrs;
+ UINTN Idx;
+
+ *OriginalAttributes = NULL;
+ *Count = 0;
+
+ if (PcdGetBool (PcdPciDisableBusEnumeration)) {
+ //
+ // The platform downloads ACPI tables from QEMU in general, but there are
+ // no root bridges in this execution. We're done.
+ //
+ return;
+ }
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid,
+ NULL /* SearchKey */, &NoHandles, &Handles);
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // No PCI devices were found on either of the root bridges. We're done.
+ //
+ return;
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,
+ Status));
+ return;
+ }
+
+ OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
+ if (OrigAttrs == NULL) {
+ DEBUG ((DEBUG_WARN, "%a: AllocatePool(): out of resources\n",
+ __FUNCTION__));
+ goto FreeHandles;
+ }
+
+ for (Idx = 0; Idx < NoHandles; ++Idx) {
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT64 Attributes;
+
+ //
+ // Look up PciIo on the handle and stash it
+ //
+ Status = gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid,
+ (VOID**)&PciIo);
+ ASSERT_EFI_ERROR (Status);
+ OrigAttrs[Idx].PciIo = PciIo;
+
+ //
+ // Stash the current attributes
+ //
+ Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,
+ &OrigAttrs[Idx].PciAttributes);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",
+ __FUNCTION__, Status));
+ goto RestoreAttributes;
+ }
+
+ //
+ // Retrieve supported attributes
+ //
+ Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0,
+ &Attributes);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n",
+ __FUNCTION__, Status));
+ goto RestoreAttributes;
+ }
+
+ //
+ // Enable IO and MMIO decoding
+ //
+ Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
+ Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,
+ Attributes, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n",
+ __FUNCTION__, Status));
+ goto RestoreAttributes;
+ }
+ }
+
+ //
+ // Success
+ //
+ FreePool (Handles);
+ *OriginalAttributes = OrigAttrs;
+ *Count = NoHandles;
+ return;
+
+RestoreAttributes:
+ while (Idx > 0) {
+ --Idx;
+ OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo,
+ EfiPciIoAttributeOperationSet,
+ OrigAttrs[Idx].PciAttributes,
+ NULL
+ );
+ }
+ FreePool (OrigAttrs);
+
+FreeHandles:
+ FreePool (Handles);
+}
+
+
+/**
+ Restore the original PCI attributes saved with EnablePciDecoding().
+
+ @param[in] OriginalAttributes The array allocated and populated by
+ EnablePciDecoding(). This parameter may be
+ NULL. If OriginalAttributes is NULL, then the
+ function is a no-op; otherwise the PciIo
+ attributes will be restored, and the
+ OriginalAttributes array will be freed.
+
+ @param[in] Count The Count value stored by EnablePciDecoding(),
+ the number of elements in OriginalAttributes.
+ Count may be zero if and only if
+ OriginalAttributes is NULL.
+**/
+VOID
+RestorePciDecoding (
+ IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
+ IN UINTN Count
+ )
+{
+ UINTN Idx;
+
+ ASSERT ((OriginalAttributes == NULL) == (Count == 0));
+ if (OriginalAttributes == NULL) {
+ return;
+ }
+
+ for (Idx = 0; Idx < Count; ++Idx) {
+ OriginalAttributes[Idx].PciIo->Attributes (
+ OriginalAttributes[Idx].PciIo,
+ EfiPciIoAttributeOperationSet,
+ OriginalAttributes[Idx].PciAttributes,
+ NULL
+ );
+ }
+ FreePool (OriginalAttributes);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
new file mode 100644
index 00000000000..b75c76f0429
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
@@ -0,0 +1,39 @@
+## @file
+# Component description file for PlatformAcpiTables module.
+#
+# ACPI table data and ASL sources required to boot the platform.
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = PlatformAcpiTables
+ FILE_GUID = B4BA6241-936C-4485-A483-9FA832C758CA
+ MODULE_TYPE = USER_DEFINED
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ Dsdt.asl
+ Facp.aslc
+ Facs.aslc
+ Hpet.aslc
+ Madt.aslc
+ Mcfg.aslc
+ Platform.h
+ Spcr.aslc
+
+[Packages]
+ MdePkg/MdePkg.dec
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl
new file mode 100644
index 00000000000..ed996c252d6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Dsdt.asl
@@ -0,0 +1,1140 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+/*
+ * Intel ACPI Component Architecture
+ * AML Disassembler version 20100528
+ *
+ * Disassembly of DSDT.dat, Sat Apr 18 15:41:05 2015
+ *
+ *
+ * Original Table Header:
+ * Signature "DSDT"
+ * Length 0x000008FA (2298)
+ * Revision 0x02
+ * Checksum 0xC4
+ * OEM ID "BHYVE "
+ * OEM Table ID "BVDSDT "
+ * OEM Revision 0x00000001 (1)
+ * Compiler ID "INTL"
+ * Compiler Version 0x20150204 (538247684)
+ */
+DefinitionBlock ("DSDT.aml", "DSDT", 2, "BHYVE", "BVDSDT", 0x00000001)
+{
+ Name (_S5, Package (0x02)
+ {
+ 0x05,
+ Zero
+ })
+ Name (PICM, Zero)
+ Method (_PIC, 1, NotSerialized)
+ {
+ Store (Arg0, PICM)
+ }
+
+ Scope (_SB)
+ {
+ Device (PC00)
+ {
+ Name (_HID, EisaId ("PNP0A03"))
+ Name (_ADR, Zero)
+ Method (_BBN, 0, NotSerialized)
+ {
+ Return (Zero)
+ }
+
+ Name (_CRS, ResourceTemplate ()
+ {
+ WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
+ 0x0000, // Granularity
+ 0x0000, // Range Minimum
+ 0x00FF, // Range Maximum
+ 0x0000, // Translation Offset
+ 0x0100, // Length
+ ,, )
+ IO (Decode16,
+ 0x03C0, // Range Minimum
+ 0x03C0, // Range Maximum
+ 0x00, // Alignment
+ 0x20, // Length
+ )
+ IO (Decode16,
+ 0x0CF8, // Range Minimum
+ 0x0CF8, // Range Maximum
+ 0x01, // Alignment
+ 0x08, // Length
+ )
+ WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, // Granularity
+ 0x0000, // Range Minimum
+ 0x0CF7, // Range Maximum
+ 0x0000, // Translation Offset
+ 0x0CF8, // Length
+ ,, , TypeStatic)
+ WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
+ 0x0000, // Granularity
+ 0x0D00, // Range Minimum
+ 0xFFFF, // Range Maximum
+ 0x0000, // Translation Offset
+ 0xF300, // Length
+ ,, , TypeStatic)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
+ 0x00000000, // Granularity
+ 0x000A0000, // Range Minimum
+ 0x000BFFFF, // Range Maximum
+ 0x00000000, // Translation Offset
+ 0x00020000, // Length
+ ,, , AddressRangeMemory, TypeStatic)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x00000000, // Granularity
+ 0xC0000000, // Range Minimum
+ 0xDFFFFFFF, // Range Maximum
+ 0x00000000, // Translation Offset
+ 0x20000000, // Range Length
+ ,, PW32)
+ DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x00000000, // Granularity
+ 0xF0000000, // Range Minimum
+ 0xF07FFFFF, // Range Maximum
+ 0x00000000, // Translation Offset
+ 0x00800000, // Range Length
+ ,, FB32)
+ QWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
+ 0x0000000000000000, // Granularity
+ 0x000000D000000000, // Range Minimum
+ 0x000000D0000FFFFF, // Range Maximum
+ 0x0000000000000000, // Translation Offset
+ 0x0000000000100000, // Length
+ ,, , AddressRangeMemory, TypeStatic)
+ })
+ Name (PPRT, Package ()
+ {
+ Package () { 0x0000FFFF, 0, LPC.LNKF, Zero },
+ Package () { 0x0000FFFF, 1, LPC.LNKG, Zero },
+ Package () { 0x0000FFFF, 2, LPC.LNKH, Zero },
+ Package () { 0x0000FFFF, 3, LPC.LNKA, Zero },
+
+ Package () { 0x0001FFFF, 0, LPC.LNKG, Zero },
+ Package () { 0x0001FFFF, 1, LPC.LNKH, Zero },
+ Package () { 0x0001FFFF, 2, LPC.LNKA, Zero },
+ Package () { 0x0001FFFF, 3, LPC.LNKB, Zero },
+
+ Package () { 0x0002FFFF, 0, LPC.LNKH, Zero },
+ Package () { 0x0002FFFF, 1, LPC.LNKA, Zero },
+ Package () { 0x0002FFFF, 2, LPC.LNKB, Zero },
+ Package () { 0x0002FFFF, 3, LPC.LNKC, Zero },
+
+ Package () { 0x0003FFFF, 0, LPC.LNKA, Zero },
+ Package () { 0x0003FFFF, 1, LPC.LNKB, Zero },
+ Package () { 0x0003FFFF, 2, LPC.LNKC, Zero },
+ Package () { 0x0003FFFF, 3, LPC.LNKD, Zero },
+
+ Package () { 0x0004FFFF, 0, LPC.LNKB, Zero },
+ Package () { 0x0004FFFF, 1, LPC.LNKC, Zero },
+ Package () { 0x0004FFFF, 2, LPC.LNKD, Zero },
+ Package () { 0x0004FFFF, 3, LPC.LNKE, Zero },
+
+ Package () { 0x0005FFFF, 0, LPC.LNKC, Zero },
+ Package () { 0x0005FFFF, 1, LPC.LNKD, Zero },
+ Package () { 0x0005FFFF, 2, LPC.LNKE, Zero },
+ Package () { 0x0005FFFF, 3, LPC.LNKF, Zero },
+
+ Package () { 0x0006FFFF, 0, LPC.LNKD, Zero },
+ Package () { 0x0006FFFF, 1, LPC.LNKE, Zero },
+ Package () { 0x0006FFFF, 2, LPC.LNKF, Zero },
+ Package () { 0x0006FFFF, 3, LPC.LNKG, Zero },
+
+ Package () { 0x0007FFFF, 0, LPC.LNKE, Zero },
+ Package () { 0x0007FFFF, 1, LPC.LNKF, Zero },
+ Package () { 0x0007FFFF, 2, LPC.LNKG, Zero },
+ Package () { 0x0007FFFF, 3, LPC.LNKH, Zero },
+
+ Package () { 0x0008FFFF, 0, LPC.LNKF, Zero },
+ Package () { 0x0008FFFF, 1, LPC.LNKG, Zero },
+ Package () { 0x0008FFFF, 2, LPC.LNKH, Zero },
+ Package () { 0x0008FFFF, 3, LPC.LNKA, Zero },
+
+ Package () { 0x0009FFFF, 0, LPC.LNKG, Zero },
+ Package () { 0x0009FFFF, 1, LPC.LNKH, Zero },
+ Package () { 0x0009FFFF, 2, LPC.LNKA, Zero },
+ Package () { 0x0009FFFF, 3, LPC.LNKB, Zero },
+
+ Package () { 0x000AFFFF, 0, LPC.LNKH, Zero },
+ Package () { 0x000AFFFF, 1, LPC.LNKA, Zero },
+ Package () { 0x000AFFFF, 2, LPC.LNKB, Zero },
+ Package () { 0x000AFFFF, 3, LPC.LNKC, Zero },
+
+ Package () { 0x000BFFFF, 0, LPC.LNKA, Zero },
+ Package () { 0x000BFFFF, 1, LPC.LNKB, Zero },
+ Package () { 0x000BFFFF, 2, LPC.LNKC, Zero },
+ Package () { 0x000BFFFF, 3, LPC.LNKD, Zero },
+
+ Package () { 0x000CFFFF, 0, LPC.LNKB, Zero },
+ Package () { 0x000CFFFF, 1, LPC.LNKC, Zero },
+ Package () { 0x000CFFFF, 2, LPC.LNKD, Zero },
+ Package () { 0x000CFFFF, 3, LPC.LNKE, Zero },
+
+ Package () { 0x000DFFFF, 0, LPC.LNKC, Zero },
+ Package () { 0x000DFFFF, 1, LPC.LNKD, Zero },
+ Package () { 0x000DFFFF, 2, LPC.LNKE, Zero },
+ Package () { 0x000DFFFF, 3, LPC.LNKF, Zero },
+
+ Package () { 0x000EFFFF, 0, LPC.LNKD, Zero },
+ Package () { 0x000EFFFF, 1, LPC.LNKE, Zero },
+ Package () { 0x000EFFFF, 2, LPC.LNKF, Zero },
+ Package () { 0x000EFFFF, 3, LPC.LNKG, Zero },
+
+ Package () { 0x000FFFFF, 0, LPC.LNKE, Zero },
+ Package () { 0x000FFFFF, 1, LPC.LNKF, Zero },
+ Package () { 0x000FFFFF, 2, LPC.LNKG, Zero },
+ Package () { 0x000FFFFF, 3, LPC.LNKH, Zero },
+
+ Package () { 0x0010FFFF, 0, LPC.LNKF, Zero },
+ Package () { 0x0010FFFF, 1, LPC.LNKG, Zero },
+ Package () { 0x0010FFFF, 2, LPC.LNKH, Zero },
+ Package () { 0x0010FFFF, 3, LPC.LNKA, Zero },
+
+ Package () { 0x0011FFFF, 0, LPC.LNKG, Zero },
+ Package () { 0x0011FFFF, 1, LPC.LNKH, Zero },
+ Package () { 0x0011FFFF, 2, LPC.LNKA, Zero },
+ Package () { 0x0011FFFF, 3, LPC.LNKB, Zero },
+
+ Package () { 0x0012FFFF, 0, LPC.LNKH, Zero },
+ Package () { 0x0012FFFF, 1, LPC.LNKA, Zero },
+ Package () { 0x0012FFFF, 2, LPC.LNKB, Zero },
+ Package () { 0x0012FFFF, 3, LPC.LNKC, Zero },
+
+ Package () { 0x0013FFFF, 0, LPC.LNKA, Zero },
+ Package () { 0x0013FFFF, 1, LPC.LNKB, Zero },
+ Package () { 0x0013FFFF, 2, LPC.LNKC, Zero },
+ Package () { 0x0013FFFF, 3, LPC.LNKD, Zero },
+
+ Package () { 0x0014FFFF, 0, LPC.LNKB, Zero },
+ Package () { 0x0014FFFF, 1, LPC.LNKC, Zero },
+ Package () { 0x0014FFFF, 2, LPC.LNKD, Zero },
+ Package () { 0x0014FFFF, 3, LPC.LNKE, Zero },
+
+ Package () { 0x0015FFFF, 0, LPC.LNKC, Zero },
+ Package () { 0x0015FFFF, 1, LPC.LNKD, Zero },
+ Package () { 0x0015FFFF, 2, LPC.LNKE, Zero },
+ Package () { 0x0015FFFF, 3, LPC.LNKF, Zero },
+
+ Package () { 0x0016FFFF, 0, LPC.LNKD, Zero },
+ Package () { 0x0016FFFF, 1, LPC.LNKE, Zero },
+ Package () { 0x0016FFFF, 2, LPC.LNKF, Zero },
+ Package () { 0x0016FFFF, 3, LPC.LNKG, Zero },
+
+ Package () { 0x0017FFFF, 0, LPC.LNKE, Zero },
+ Package () { 0x0017FFFF, 1, LPC.LNKF, Zero },
+ Package () { 0x0017FFFF, 2, LPC.LNKG, Zero },
+ Package () { 0x0017FFFF, 3, LPC.LNKH, Zero },
+
+ Package () { 0x0018FFFF, 0, LPC.LNKF, Zero },
+ Package () { 0x0018FFFF, 1, LPC.LNKG, Zero },
+ Package () { 0x0018FFFF, 2, LPC.LNKH, Zero },
+ Package () { 0x0018FFFF, 3, LPC.LNKA, Zero },
+
+ Package () { 0x0019FFFF, 0, LPC.LNKG, Zero },
+ Package () { 0x0019FFFF, 1, LPC.LNKH, Zero },
+ Package () { 0x0019FFFF, 2, LPC.LNKA, Zero },
+ Package () { 0x0019FFFF, 3, LPC.LNKB, Zero },
+
+ Package () { 0x001AFFFF, 0, LPC.LNKH, Zero },
+ Package () { 0x001AFFFF, 1, LPC.LNKA, Zero },
+ Package () { 0x001AFFFF, 2, LPC.LNKB, Zero },
+ Package () { 0x001AFFFF, 3, LPC.LNKC, Zero },
+
+ Package () { 0x001BFFFF, 0, LPC.LNKA, Zero },
+ Package () { 0x001BFFFF, 1, LPC.LNKB, Zero },
+ Package () { 0x001BFFFF, 2, LPC.LNKC, Zero },
+ Package () { 0x001BFFFF, 3, LPC.LNKD, Zero },
+
+ Package () { 0x001CFFFF, 0, LPC.LNKB, Zero },
+ Package () { 0x001CFFFF, 1, LPC.LNKC, Zero },
+ Package () { 0x001CFFFF, 2, LPC.LNKD, Zero },
+ Package () { 0x001CFFFF, 3, LPC.LNKE, Zero },
+
+ Package () { 0x001DFFFF, 0, LPC.LNKC, Zero },
+ Package () { 0x001DFFFF, 1, LPC.LNKD, Zero },
+ Package () { 0x001DFFFF, 2, LPC.LNKE, Zero },
+ Package () { 0x001DFFFF, 3, LPC.LNKF, Zero },
+
+ Package () { 0x001EFFFF, 0, LPC.LNKD, Zero },
+ Package () { 0x001EFFFF, 1, LPC.LNKE, Zero },
+ Package () { 0x001EFFFF, 2, LPC.LNKF, Zero },
+ Package () { 0x001EFFFF, 3, LPC.LNKG, Zero },
+
+ Package () { 0x001FFFFF, 0, LPC.LNKE, Zero },
+ Package () { 0x001FFFFF, 1, LPC.LNKF, Zero },
+ Package () { 0x001FFFFF, 2, LPC.LNKG, Zero },
+ Package () { 0x001FFFFF, 3, LPC.LNKH, Zero }
+ })
+ Name (APRT, Package ()
+ {
+ Package () { 0x0000FFFF, 0, Zero, 0x15 },
+ Package () { 0x0000FFFF, 1, Zero, 0x16 },
+ Package () { 0x0000FFFF, 2, Zero, 0x17 },
+ Package () { 0x0000FFFF, 3, Zero, 0x10 },
+
+ Package () { 0x0001FFFF, 0, Zero, 0x16 },
+ Package () { 0x0001FFFF, 1, Zero, 0x17 },
+ Package () { 0x0001FFFF, 2, Zero, 0x10 },
+ Package () { 0x0001FFFF, 3, Zero, 0x11 },
+
+ Package () { 0x0002FFFF, 0, Zero, 0x17 },
+ Package () { 0x0002FFFF, 1, Zero, 0x10 },
+ Package () { 0x0002FFFF, 2, Zero, 0x11 },
+ Package () { 0x0002FFFF, 3, Zero, 0x12 },
+
+ Package () { 0x0003FFFF, 0, Zero, 0x10 },
+ Package () { 0x0003FFFF, 1, Zero, 0x11 },
+ Package () { 0x0003FFFF, 2, Zero, 0x12 },
+ Package () { 0x0003FFFF, 3, Zero, 0x13 },
+
+ Package () { 0x0004FFFF, 0, Zero, 0x11 },
+ Package () { 0x0004FFFF, 1, Zero, 0x12 },
+ Package () { 0x0004FFFF, 2, Zero, 0x13 },
+ Package () { 0x0004FFFF, 3, Zero, 0x14 },
+
+ Package () { 0x0005FFFF, 0, Zero, 0x12 },
+ Package () { 0x0005FFFF, 1, Zero, 0x13 },
+ Package () { 0x0005FFFF, 2, Zero, 0x14 },
+ Package () { 0x0005FFFF, 3, Zero, 0x15 },
+
+ Package () { 0x0006FFFF, 0, Zero, 0x13 },
+ Package () { 0x0006FFFF, 1, Zero, 0x14 },
+ Package () { 0x0006FFFF, 2, Zero, 0x15 },
+ Package () { 0x0006FFFF, 3, Zero, 0x16 },
+
+ Package () { 0x0007FFFF, 0, Zero, 0x14 },
+ Package () { 0x0007FFFF, 1, Zero, 0x15 },
+ Package () { 0x0007FFFF, 2, Zero, 0x16 },
+ Package () { 0x0007FFFF, 3, Zero, 0x17 },
+
+ Package () { 0x0008FFFF, 0, Zero, 0x15 },
+ Package () { 0x0008FFFF, 1, Zero, 0x16 },
+ Package () { 0x0008FFFF, 2, Zero, 0x17 },
+ Package () { 0x0008FFFF, 3, Zero, 0x10 },
+
+ Package () { 0x0009FFFF, 0, Zero, 0x16 },
+ Package () { 0x0009FFFF, 1, Zero, 0x17 },
+ Package () { 0x0009FFFF, 2, Zero, 0x10 },
+ Package () { 0x0009FFFF, 3, Zero, 0x11 },
+
+ Package () { 0x000AFFFF, 0, Zero, 0x17 },
+ Package () { 0x000AFFFF, 1, Zero, 0x10 },
+ Package () { 0x000AFFFF, 2, Zero, 0x11 },
+ Package () { 0x000AFFFF, 3, Zero, 0x12 },
+
+ Package () { 0x000BFFFF, 0, Zero, 0x10 },
+ Package () { 0x000BFFFF, 1, Zero, 0x11 },
+ Package () { 0x000BFFFF, 2, Zero, 0x12 },
+ Package () { 0x000BFFFF, 3, Zero, 0x13 },
+
+ Package () { 0x000CFFFF, 0, Zero, 0x11 },
+ Package () { 0x000CFFFF, 1, Zero, 0x12 },
+ Package () { 0x000CFFFF, 2, Zero, 0x13 },
+ Package () { 0x000CFFFF, 3, Zero, 0x14 },
+
+ Package () { 0x000DFFFF, 0, Zero, 0x12 },
+ Package () { 0x000DFFFF, 1, Zero, 0x13 },
+ Package () { 0x000DFFFF, 2, Zero, 0x14 },
+ Package () { 0x000DFFFF, 3, Zero, 0x15 },
+
+ Package () { 0x000EFFFF, 0, Zero, 0x13 },
+ Package () { 0x000EFFFF, 1, Zero, 0x14 },
+ Package () { 0x000EFFFF, 2, Zero, 0x15 },
+ Package () { 0x000EFFFF, 3, Zero, 0x16 },
+
+ Package () { 0x000FFFFF, 0, Zero, 0x14 },
+ Package () { 0x000FFFFF, 1, Zero, 0x15 },
+ Package () { 0x000FFFFF, 2, Zero, 0x16 },
+ Package () { 0x000FFFFF, 3, Zero, 0x17 },
+
+ Package () { 0x0010FFFF, 0, Zero, 0x15 },
+ Package () { 0x0010FFFF, 1, Zero, 0x16 },
+ Package () { 0x0010FFFF, 2, Zero, 0x17 },
+ Package () { 0x0010FFFF, 3, Zero, 0x10 },
+
+ Package () { 0x0011FFFF, 0, Zero, 0x16 },
+ Package () { 0x0011FFFF, 1, Zero, 0x17 },
+ Package () { 0x0011FFFF, 2, Zero, 0x10 },
+ Package () { 0x0011FFFF, 3, Zero, 0x11 },
+
+ Package () { 0x0012FFFF, 0, Zero, 0x17 },
+ Package () { 0x0012FFFF, 1, Zero, 0x10 },
+ Package () { 0x0012FFFF, 2, Zero, 0x11 },
+ Package () { 0x0012FFFF, 3, Zero, 0x12 },
+
+ Package () { 0x0013FFFF, 0, Zero, 0x10 },
+ Package () { 0x0013FFFF, 1, Zero, 0x11 },
+ Package () { 0x0013FFFF, 2, Zero, 0x12 },
+ Package () { 0x0013FFFF, 3, Zero, 0x13 },
+
+ Package () { 0x0014FFFF, 0, Zero, 0x11 },
+ Package () { 0x0014FFFF, 1, Zero, 0x12 },
+ Package () { 0x0014FFFF, 2, Zero, 0x13 },
+ Package () { 0x0014FFFF, 3, Zero, 0x14 },
+
+ Package () { 0x0015FFFF, 0, Zero, 0x12 },
+ Package () { 0x0015FFFF, 1, Zero, 0x13 },
+ Package () { 0x0015FFFF, 2, Zero, 0x14 },
+ Package () { 0x0015FFFF, 3, Zero, 0x15 },
+
+ Package () { 0x0016FFFF, 0, Zero, 0x13 },
+ Package () { 0x0016FFFF, 1, Zero, 0x14 },
+ Package () { 0x0016FFFF, 2, Zero, 0x15 },
+ Package () { 0x0016FFFF, 3, Zero, 0x16 },
+
+ Package () { 0x0017FFFF, 0, Zero, 0x14 },
+ Package () { 0x0017FFFF, 1, Zero, 0x15 },
+ Package () { 0x0017FFFF, 2, Zero, 0x16 },
+ Package () { 0x0017FFFF, 3, Zero, 0x17 },
+
+ Package () { 0x0018FFFF, 0, Zero, 0x15 },
+ Package () { 0x0018FFFF, 1, Zero, 0x16 },
+ Package () { 0x0018FFFF, 2, Zero, 0x17 },
+ Package () { 0x0018FFFF, 3, Zero, 0x10 },
+
+ Package () { 0x0019FFFF, 0, Zero, 0x16 },
+ Package () { 0x0019FFFF, 1, Zero, 0x17 },
+ Package () { 0x0019FFFF, 2, Zero, 0x10 },
+ Package () { 0x0019FFFF, 3, Zero, 0x11 },
+
+ Package () { 0x001AFFFF, 0, Zero, 0x17 },
+ Package () { 0x001AFFFF, 1, Zero, 0x10 },
+ Package () { 0x001AFFFF, 2, Zero, 0x11 },
+ Package () { 0x001AFFFF, 3, Zero, 0x12 },
+
+ Package () { 0x001BFFFF, 0, Zero, 0x10 },
+ Package () { 0x001BFFFF, 1, Zero, 0x11 },
+ Package () { 0x001BFFFF, 2, Zero, 0x12 },
+ Package () { 0x001BFFFF, 3, Zero, 0x13 },
+
+ Package () { 0x001CFFFF, 0, Zero, 0x11 },
+ Package () { 0x001CFFFF, 1, Zero, 0x12 },
+ Package () { 0x001CFFFF, 2, Zero, 0x13 },
+ Package () { 0x001CFFFF, 3, Zero, 0x14 },
+
+ Package () { 0x001DFFFF, 0, Zero, 0x12 },
+ Package () { 0x001DFFFF, 1, Zero, 0x13 },
+ Package () { 0x001DFFFF, 2, Zero, 0x14 },
+ Package () { 0x001DFFFF, 3, Zero, 0x15 },
+
+ Package () { 0x001EFFFF, 0, Zero, 0x13 },
+ Package () { 0x001EFFFF, 1, Zero, 0x14 },
+ Package () { 0x001EFFFF, 2, Zero, 0x15 },
+ Package () { 0x001EFFFF, 3, Zero, 0x16 },
+
+ Package () { 0x001FFFFF, 0, Zero, 0x14 },
+ Package () { 0x001FFFFF, 1, Zero, 0x15 },
+ Package () { 0x001FFFFF, 2, Zero, 0x16 },
+ Package () { 0x001FFFFF, 3, Zero, 0x17 }
+ })
+ Method (_PRT, 0, NotSerialized)
+ {
+ If (PICM)
+ {
+ Return (APRT)
+ }
+ Else
+ {
+ Return (PPRT)
+ }
+ }
+
+ Device (LPC)
+ {
+ Name (_ADR, 0x001F0000)
+ OperationRegion (LPCR, PCI_Config, Zero, 0x0100)
+ Field (LPCR, AnyAcc, NoLock, Preserve)
+ {
+ Offset (0x60),
+ PIRA, 8,
+ PIRB, 8,
+ PIRC, 8,
+ PIRD, 8,
+ Offset (0x68),
+ PIRE, 8,
+ PIRF, 8,
+ PIRG, 8,
+ PIRH, 8
+ }
+
+ Device (KBD)
+ {
+ Name (_HID, EISAID ("PNP0303"))
+ Name (_CID, EISAID ("PNP030B"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0060, // Range Minimum
+ 0x0060, // Range Maximum
+ 0x00, // Alignment
+ 0x01, // Length
+ )
+ IO (Decode16,
+ 0x0064, // Range Minimum
+ 0x0064, // Range Maximum
+ 0x00, // Alignment
+ 0x01, // Length
+ )
+ IRQNoFlags ()
+ {1}
+ })
+ }
+
+ Device (MOU)
+ {
+ Name (_HID, EISAID ("PNP0F03"))
+ Name (_CID, EISAID ("PNP0F13"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IRQNoFlags ()
+ {12}
+ })
+ }
+
+ Method (PIRV, 1, NotSerialized)
+ {
+ If (And (Arg0, 0x80))
+ {
+ Return (Zero)
+ }
+
+ And (Arg0, 0x0F, Local0)
+ If (LLess (Local0, 0x03))
+ {
+ Return (Zero)
+ }
+
+ If (LEqual (Local0, 0x08))
+ {
+ Return (Zero)
+ }
+
+ If (LEqual (Local0, 0x0D))
+ {
+ Return (Zero)
+ }
+
+ Return (One)
+ }
+
+ Device (LNKA)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, One)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRA))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB01, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB01, One, CIRA)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRA, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRA)
+ }
+ Else
+ {
+ Store (Zero, CIRA)
+ }
+
+ Return (CB01)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRA)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRA)
+ FindSetRightBit (SIRA, Local0)
+ Store (Decrement (Local0), PIRA)
+ }
+ }
+
+ Device (LNKB)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x02)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRB))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB02, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB02, One, CIRB)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRB, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRB)
+ }
+ Else
+ {
+ Store (Zero, CIRB)
+ }
+
+ Return (CB02)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRB)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRB)
+ FindSetRightBit (SIRB, Local0)
+ Store (Decrement (Local0), PIRB)
+ }
+ }
+
+ Device (LNKC)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x03)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRC))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB03, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB03, One, CIRC)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRC, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRC)
+ }
+ Else
+ {
+ Store (Zero, CIRC)
+ }
+
+ Return (CB03)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRC)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRC)
+ FindSetRightBit (SIRC, Local0)
+ Store (Decrement (Local0), PIRC)
+ }
+ }
+
+ Device (LNKD)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x04)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRD))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB04, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB04, One, CIRD)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRD, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRD)
+ }
+ Else
+ {
+ Store (Zero, CIRD)
+ }
+
+ Return (CB04)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRD)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRD)
+ FindSetRightBit (SIRD, Local0)
+ Store (Decrement (Local0), PIRD)
+ }
+ }
+
+ Device (LNKE)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x05)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRE))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB05, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB05, One, CIRE)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRE, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRE)
+ }
+ Else
+ {
+ Store (Zero, CIRE)
+ }
+
+ Return (CB05)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRE)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRE)
+ FindSetRightBit (SIRE, Local0)
+ Store (Decrement (Local0), PIRE)
+ }
+ }
+
+ Device (LNKF)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x06)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRF))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB06, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB06, One, CIRF)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRF, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRF)
+ }
+ Else
+ {
+ Store (Zero, CIRF)
+ }
+
+ Return (CB06)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRF)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRF)
+ FindSetRightBit (SIRF, Local0)
+ Store (Decrement (Local0), PIRF)
+ }
+ }
+
+ Device (LNKG)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x07)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRG))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB07, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB07, One, CIRG)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRG, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRG)
+ }
+ Else
+ {
+ Store (Zero, CIRG)
+ }
+
+ Return (CB07)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRG)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRG)
+ FindSetRightBit (SIRG, Local0)
+ Store (Decrement (Local0), PIRG)
+ }
+ }
+
+ Device (LNKH)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x08)
+ Method (_STA, 0, NotSerialized)
+ {
+ If (PIRV (PIRH))
+ {
+ Return (0x0B)
+ }
+ Else
+ {
+ Return (0x09)
+ }
+ }
+
+ Name (_PRS, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {3,4,5,6,7,9,10,11,12,14,15}
+ })
+ Name (CB08, ResourceTemplate ()
+ {
+ IRQ (Level, ActiveLow, Shared, )
+ {}
+ })
+ CreateWordField (CB08, One, CIRH)
+ Method (_CRS, 0, NotSerialized)
+ {
+ And (PIRH, 0x8F, Local0)
+ If (PIRV (Local0))
+ {
+ ShiftLeft (One, Local0, CIRH)
+ }
+ Else
+ {
+ Store (Zero, CIRH)
+ }
+
+ Return (CB08)
+ }
+
+ Method (_DIS, 0, NotSerialized)
+ {
+ Store (0x80, PIRH)
+ }
+
+ Method (_SRS, 1, NotSerialized)
+ {
+ CreateWordField (Arg0, One, SIRH)
+ FindSetRightBit (SIRH, Local0)
+ Store (Decrement (Local0), PIRH)
+ }
+ }
+
+ Device (SIO)
+ {
+ Name (_HID, EisaId ("PNP0C02"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0220, // Range Minimum
+ 0x0220, // Range Maximum
+ 0x01, // Alignment
+ 0x04, // Length
+ )
+ IO (Decode16,
+ 0x0224, // Range Minimum
+ 0x0224, // Range Maximum
+ 0x01, // Alignment
+ 0x04, // Length
+ )
+ Memory32Fixed (ReadWrite,
+ 0xE0000000, // Address Base
+ 0x10000000, // Address Length
+ )
+ IO (Decode16,
+ 0x04D0, // Range Minimum
+ 0x04D0, // Range Maximum
+ 0x01, // Alignment
+ 0x02, // Length
+ )
+ IO (Decode16,
+ 0x0061, // Range Minimum
+ 0x0061, // Range Maximum
+ 0x01, // Alignment
+ 0x01, // Length
+ )
+ IO (Decode16,
+ 0x0400, // Range Minimum
+ 0x0400, // Range Maximum
+ 0x01, // Alignment
+ 0x08, // Length
+ )
+ IO (Decode16,
+ 0x00B2, // Range Minimum
+ 0x00B2, // Range Maximum
+ 0x01, // Alignment
+ 0x01, // Length
+ )
+ IO (Decode16,
+ 0x0084, // Range Minimum
+ 0x0084, // Range Maximum
+ 0x01, // Alignment
+ 0x01, // Length
+ )
+ IO (Decode16,
+ 0x0072, // Range Minimum
+ 0x0072, // Range Maximum
+ 0x01, // Alignment
+ 0x06, // Length
+ )
+ })
+ }
+
+ Device (COM1)
+ {
+ Name (_HID, EisaId ("PNP0501"))
+ Name (_UID, One)
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x03F8, // Range Minimum
+ 0x03F8, // Range Maximum
+ 0x01, // Alignment
+ 0x08, // Length
+ )
+ IRQNoFlags ()
+ {4}
+ })
+ }
+
+ Device (COM2)
+ {
+ Name (_HID, EisaId ("PNP0501"))
+ Name (_UID, 0x02)
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x02F8, // Range Minimum
+ 0x02F8, // Range Maximum
+ 0x01, // Alignment
+ 0x08, // Length
+ )
+ IRQNoFlags ()
+ {3}
+ })
+ }
+
+ Device (RTC)
+ {
+ Name (_HID, EisaId ("PNP0B00"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0070, // Range Minimum
+ 0x0070, // Range Maximum
+ 0x00, // Alignment
+ 0x02, // Length
+ )
+ IRQNoFlags ()
+ {8}
+ IO (Decode16,
+ 0x0072, // Range Minimum
+ 0x0072, // Range Maximum
+ 0x02, // Alignment
+ 0x06, // Length
+ )
+ })
+ }
+
+ Device (PIC)
+ {
+ Name (_HID, EisaId ("PNP0000"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0020, // Range Minimum
+ 0x0020, // Range Maximum
+ 0x01, // Alignment
+ 0x02, // Length
+ )
+ IO (Decode16,
+ 0x00A0, // Range Minimum
+ 0x00A0, // Range Maximum
+ 0x01, // Alignment
+ 0x02, // Length
+ )
+ IRQNoFlags ()
+ {2}
+ })
+ }
+
+ Device (TIMR)
+ {
+ Name (_HID, EisaId ("PNP0100"))
+ Name (_CRS, ResourceTemplate ()
+ {
+ IO (Decode16,
+ 0x0040, // Range Minimum
+ 0x0040, // Range Maximum
+ 0x01, // Alignment
+ 0x04, // Length
+ )
+ IRQNoFlags ()
+ {0}
+ })
+ }
+ }
+ }
+ }
+
+ Scope (_SB.PC00)
+ {
+ Device (HPET)
+ {
+ Name (_HID, EisaId ("PNP0103"))
+ Name (_UID, Zero)
+ Name (_CRS, ResourceTemplate ()
+ {
+ Memory32Fixed (ReadWrite,
+ 0xFED00000, // Address Base
+ 0x00000400, // Address Length
+ )
+ })
+ }
+ }
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facp.aslc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facp.aslc
new file mode 100644
index 00000000000..a2df7daf0fe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facp.aslc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#include "Platform.h"
+
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('B','V','F','A','C','P',' ',' ')
+
+EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE FACP = {
+ {
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE),
+ EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION,
+ 0, // to make sum of entire table == 0
+ {EFI_ACPI_OEM_ID}, // OEMID is a 6 bytes long field
+ EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long)
+ EFI_ACPI_OEM_REVISION, // OEM revision number
+ EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID
+ EFI_ACPI_CREATOR_REVISION // ASL compiler revision number
+ },
+ 0, // Physical addesss of FACS
+ 0, // Physical address of DSDT
+ INT_MODEL, // System Interrupt Model
+ RESERVED, // reserved
+ SCI_INT_VECTOR, // System vector of SCI interrupt
+ SMI_CMD_IO_PORT, // Port address of SMI command port
+ ACPI_ENABLE, // value to write to port smi_cmd to enable ACPI
+ ACPI_DISABLE, // value to write to port smi_cmd to disable ACPI
+ S4BIOS_REQ, // Value to write to SMI CMD port to enter the S4BIOS state
+ 0, // PState control
+ PM1a_EVT_BLK, // Port address of Power Mgt 1a Event Reg Blk
+ PM1b_EVT_BLK, // Port address of Power Mgt 1b Event Reg Blk
+ PM1a_CNT_BLK, // Port address of Power Mgt 1a Ctrl Reg Blk
+ PM1b_CNT_BLK, // Port address of Power Mgt 1b Ctrl Reg Blk
+ PM2_CNT_BLK, // Port address of Power Mgt 2 Ctrl Reg Blk
+ PM_TMR_BLK, // Port address of Power Mgt Timer Ctrl Reg Blk
+ GPE0_BLK, // Port addr of General Purpose Event 0 Reg Blk
+ GPE1_BLK, // Port addr of General Purpose Event 1 Reg Blk
+ PM1_EVT_LEN, // Byte Length of ports at pm1X_evt_blk
+ PM1_CNT_LEN, // Byte Length of ports at pm1X_cnt_blk
+ PM2_CNT_LEN, // Byte Length of ports at pm2_cnt_blk
+ PM_TM_LEN, // Byte Length of ports at pm_tm_blk
+ GPE0_BLK_LEN, // Byte Length of ports at gpe0_blk
+ GPE1_BLK_LEN, // Byte Length of ports at gpe1_blk
+ GPE1_BASE, // offset in gpe model where gpe1 events start
+ 0, // _CST support
+ P_LVL2_LAT, // worst case HW latency to enter/exit C2 state
+ P_LVL3_LAT, // worst case HW latency to enter/exit C3 state
+ FLUSH_SIZE, // Size of area read to flush caches
+ FLUSH_STRIDE, // Stride used in flushing caches
+ DUTY_OFFSET, // bit location of duty cycle field in p_cnt reg
+ DUTY_WIDTH, // bit width of duty cycle field in p_cnt reg
+ DAY_ALRM, // index to day-of-month alarm in RTC CMOS RAM
+ MON_ALRM, // index to month-of-year alarm in RTC CMOS RAM
+ CENTURY, // index to century in RTC CMOS RAM
+ IAPC_BOOT_ARCH, // Boot architecture flag
+ RESERVED, // reserved
+ FACP_FLAGS,
+ FACP_RESET_REG,
+ FACP_RESET_VAL,
+};
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&FACP;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facs.aslc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facs.aslc
new file mode 100644
index 00000000000..8046ee3a634
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Facs.aslc
@@ -0,0 +1,80 @@
+/** @file
+ FACS Table
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/Acpi.h>
+
+EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE FACS = {
+ EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE,
+ sizeof (EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE),
+
+ //
+ // Hardware Signature will be updated at runtime
+ //
+ 0x00000000,
+ 0x00,
+ 0x00,
+ 0x00,
+ {
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE,
+ EFI_ACPI_RESERVED_BYTE
+ }
+};
+
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&FACS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc
new file mode 100644
index 00000000000..32e0d147c24
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Hpet.aslc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#include <IndustryStandard/HighPrecisionEventTimerTable.h>
+
+#include "Platform.h"
+
+#define EFI_ACPI_HPET_DESCRIPTION_TABLE_SIGNATURE SIGNATURE_32('H', 'P', 'E', 'T')
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('B','V','H','P','E','T',' ',' ')
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// ACPI HPET structure
+//
+typedef struct {
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_HEADER Header;
+} EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+//
+// HPET Description Table
+//
+EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_DESCRIPTION_TABLE Hpet = {
+ {
+ {
+ EFI_ACPI_HPET_DESCRIPTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_DESCRIPTION_TABLE),
+ EFI_ACPI_HIGH_PRECISION_EVENT_TIMER_TABLE_REVISION,
+ 0x00, // Checksum will be updated at runtime
+ {EFI_ACPI_OEM_ID},
+ EFI_ACPI_OEM_TABLE_ID,
+ EFI_ACPI_OEM_REVISION,
+ EFI_ACPI_CREATOR_ID,
+ EFI_ACPI_CREATOR_REVISION
+ },
+
+ //
+ // HPET specific fields
+ //
+ 0x0000A400, // EventTimerBlockId
+ {
+ EFI_ACPI_2_0_SYSTEM_MEMORY,
+ 0,
+ 0,
+ EFI_ACPI_RESERVED_BYTE,
+ 0xFED00000,
+ },
+ 0 // HpetNumber
+ }
+};
+
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&Hpet;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Madt.aslc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Madt.aslc
new file mode 100644
index 00000000000..9b64a8a1b7d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Madt.aslc
@@ -0,0 +1,145 @@
+/** @file
+ MADT Table
+
+ This file contains a structure definition for the ACPI 1.0 Multiple APIC
+ Description Table (MADT).
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2014, Pluribus Networks, Inc.
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/Acpi.h>
+#include <Platform.h>
+
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('B','V','M','A','D','T',' ',' ')
+
+//
+// Local APIC address
+//
+#define EFI_ACPI_LOCAL_APIC_ADDRESS 0xFEE00000
+
+//
+// Multiple APIC Flags are defined in AcpiX.0.h
+//
+#define EFI_ACPI_1_0_MULTIPLE_APIC_FLAGS (EFI_ACPI_1_0_PCAT_COMPAT)
+
+//
+// Define the number of each table type.
+// This is where the table layout is modified.
+//
+#define EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT 1
+#define EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT 1
+#define EFI_ACPI_IO_APIC_COUNT 1
+
+//
+// Ensure proper structure formats
+//
+#pragma pack (1)
+
+//
+// ACPI 1.0 MADT structure
+//
+typedef struct {
+ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER Header;
+
+#if EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT > 0
+ EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE LocalApic[EFI_ACPI_PROCESSOR_LOCAL_APIC_COUNT];
+#endif
+
+#if EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT > 0
+ EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE Iso[EFI_ACPI_INTERRUPT_SOURCE_OVERRIDE_COUNT];
+#endif
+
+#if EFI_ACPI_IO_APIC_COUNT > 0
+ EFI_ACPI_1_0_IO_APIC_STRUCTURE IoApic[EFI_ACPI_IO_APIC_COUNT];
+#endif
+
+} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE;
+
+#pragma pack ()
+
+//
+// Multiple APIC Description Table
+//
+EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE Madt = {
+ {
+ {
+ EFI_ACPI_1_0_APIC_SIGNATURE,
+ sizeof (EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE),
+ EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION,
+ 0x00, // Checksum will be updated at runtime
+ {EFI_ACPI_OEM_ID},
+ EFI_ACPI_OEM_TABLE_ID,
+ EFI_ACPI_OEM_REVISION,
+ EFI_ACPI_CREATOR_ID,
+ EFI_ACPI_CREATOR_REVISION
+ },
+
+ //
+ // MADT specific fields
+ //
+ EFI_ACPI_LOCAL_APIC_ADDRESS,
+ EFI_ACPI_1_0_MULTIPLE_APIC_FLAGS,
+ },
+
+ //
+ // Processor Local APIC Structure
+ //
+ {
+ {
+ EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC, // Type
+ sizeof (EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE), // Length
+ 0x00, // Processor ID
+ 0x00, // Local APIC ID
+ 0x00000001 // Flags - Enabled by default
+ }
+ },
+
+ //
+ // Interrupt Source Override Structure
+ //
+ {
+ {
+ //
+ // IRQ0=>IRQ2 Interrupt Source Override Structure
+ //
+ EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE, // Type
+ sizeof (EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE),// Length
+ 0x00, // Bus - ISA
+ 0x00, // Source - IRQ0
+ 0x00000002, // Global System Interrupt - IRQ2
+ 0x0005 // Flags - Conforms to specifications of the bus
+ },
+ },
+
+ //
+ // IO APIC Structure
+ //
+ {
+ {
+ EFI_ACPI_1_0_IO_APIC, // Type
+ sizeof (EFI_ACPI_1_0_IO_APIC_STRUCTURE), // Length
+ 0x01, // IO APIC ID
+ EFI_ACPI_RESERVED_BYTE, // Reserved
+ 0xFEC00000, // IO APIC Address (physical)
+ 0x00000000 // Global System Interrupt Base
+ }
+ },
+};
+
+
+VOID*
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&Madt;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc
new file mode 100644
index 00000000000..54936dd7f64
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Mcfg.aslc
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#include "Platform.h"
+
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('B','V','M','C','F','G',' ',' ')
+
+#pragma pack(1)
+
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT64 Reserved0;
+ UINT64 BaseAddress;
+ UINT16 PciSegmentGroupNumber;
+ UINT8 StartBusNumber;
+ UINT8 EndBusNumber;
+ UINT32 Reserved1;
+} EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE;
+
+#pragma pack()
+
+EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE MCFG = {
+ {
+ EFI_ACPI_2_0_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE),
+ EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION,
+ 0, // to make sum of entire table == 0
+ {EFI_ACPI_OEM_ID}, // OEMID is a 6 bytes long field
+ EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long)
+ EFI_ACPI_OEM_REVISION, // OEM revision number
+ EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID
+ EFI_ACPI_CREATOR_REVISION // ASL compiler revision number
+ },
+ 0, // Reserved
+ 0x00000000E0000000, // BaseAddress
+ 0x0000, // PciSegmentGroupNumber
+ 0, // StartBusNumber
+ 255, // EndBusNumber
+ 0 // Reserved
+};
+
+
+VOID *
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&MCFG;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Platform.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Platform.h
new file mode 100644
index 00000000000..806b874e62e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Platform.h
@@ -0,0 +1,72 @@
+/** @file
+ Platform specific defines for constructing ACPI tables
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2014, Pluribus Networks, Inc.
+ Copyright (c) 2012, 2013, Red Hat, Inc.
+ Copyright (c) 2008, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _Platform_h_INCLUDED_
+#define _Platform_h_INCLUDED_
+
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+#include <IndustryStandard/SerialPortConsoleRedirectionTable.h>
+
+//
+// ACPI table information used to initialize tables.
+//
+#define EFI_ACPI_OEM_ID 'B','H','Y','V','E',' ' // OEMID 6 bytes long
+#define EFI_ACPI_OEM_REVISION 0x1
+#define EFI_ACPI_CREATOR_ID SIGNATURE_32('B','H','Y','V')
+#define EFI_ACPI_CREATOR_REVISION 0x00000001
+
+#define INT_MODEL 0x01
+#define SCI_INT_VECTOR 0x0009
+#define SMI_CMD_IO_PORT 0xB2
+#define ACPI_ENABLE 0xA0
+#define ACPI_DISABLE 0xA1
+#define S4BIOS_REQ 0x00
+#define PM1a_EVT_BLK 0x00000400 /* TNXXX */
+#define PM1b_EVT_BLK 0x00000000
+#define PM1a_CNT_BLK 0x00000404 /* TNXXX */
+#define PM1b_CNT_BLK 0x00000000
+#define PM2_CNT_BLK 0x00000000
+#define PM_TMR_BLK 0x00000408
+#define GPE0_BLK 0x00000000
+#define GPE1_BLK 0x00000000
+#define PM1_EVT_LEN 0x04
+#define PM1_CNT_LEN 0x02
+#define PM2_CNT_LEN 0x00
+#define PM_TM_LEN 0x04
+#define GPE0_BLK_LEN 0x00
+#define GPE1_BLK_LEN 0x00
+#define GPE1_BASE 0x00
+#define RESERVED 0x00
+#define P_LVL2_LAT 0x0000
+#define P_LVL3_LAT 0x0000
+#define FLUSH_SIZE 0x0000
+#define FLUSH_STRIDE 0x0000
+#define DUTY_OFFSET 0x00
+#define DUTY_WIDTH 0x00
+#define DAY_ALRM 0x00
+#define MON_ALRM 0x00
+#define CENTURY 0x32
+#define IAPC_BOOT_ARCH 0x12 /* 8042 present, disable PCIe ASPM */
+#define FACP_FLAGS (EFI_ACPI_1_0_WBINVD | EFI_ACPI_1_0_PROC_C1 | \
+ EFI_ACPI_1_0_SLP_BUTTON | EFI_ACPI_1_0_TMR_VAL_EXT | \
+ EFI_ACPI_2_0_RESET_REG_SUP | \
+ EFI_ACPI_3_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE)
+#define FACP_RESET_REG { \
+ EFI_ACPI_3_0_SYSTEM_IO, /* Address Space ID */ \
+ 8, /* Bit Width */ \
+ 0, /* Bit Offset */ \
+ EFI_ACPI_3_0_BYTE, /* Byte Access */ \
+ 0xCF9 /* I/O Port */ \
+}
+#define FACP_RESET_VAL 0x6
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc
new file mode 100644
index 00000000000..9538610d964
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Spcr.aslc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2015, Nahanni Systems, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#include "Platform.h"
+
+#define EFI_ACPI_OEM_TABLE_ID SIGNATURE_64('B','V','S','P','C','R',' ',' ')
+
+EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE SPCR = {
+ {
+ EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE,
+ sizeof (EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE),
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION,
+ 0, // to make sum of entire table == 0
+ {EFI_ACPI_OEM_ID}, // OEMID is a 6 bytes long field
+ EFI_ACPI_OEM_TABLE_ID, // OEM table identification(8 bytes long)
+ EFI_ACPI_OEM_REVISION, // OEM revision number
+ EFI_ACPI_CREATOR_ID, // ASL compiler vendor ID
+ EFI_ACPI_CREATOR_REVISION // ASL compiler revision number
+ },
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERFACE_TYPE_16550,
+ { 0 }, // Reserved
+ { // BaseAddress
+ 0x01, // AddressSpaceId
+ 0x08, // RegisterBitWidth
+ 0x00, // RegisterBitOffset
+ 0x00, // Reserved
+ 0x03F8 // Address (COM1)
+ },
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_INTERRUPT_TYPE_8259,
+ 4, // Irq
+ 0, // GlobalSystemInterrupt
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_BAUD_RATE_115200,
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_PARITY_NO_PARITY,
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_STOP_BITS_1,
+ 0x03, // FlowControl: RTS/CTS | DCD
+ EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_TERMINAL_TYPE_VT_UTF8,
+ 0, // Language
+ 0, // PciDeviceId
+ 0, // PciVendorId
+ 0, // PciBusNumber
+ 0, // PciDeviceNumber
+ 0, // PciFunctionNumber
+ 0, // PciFlags
+ 0, // PciSegment
+ 0 // Reserved
+};
+
+
+VOID *
+ReferenceAcpiTable (
+ VOID
+ )
+{
+ //
+ // Reference the table being generated to prevent the optimizer from removing the
+ // data structure from the exeutable
+ //
+ return (VOID*)&SPCR;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl
new file mode 100644
index 00000000000..f7246467797
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/AcpiTables/Ssdt.asl
@@ -0,0 +1,15 @@
+/** @file
+ Placeholder for runtime-generated objects.
+
+ This empty table provides only a header for dynamic copying and extension,
+ and a trigger for QemuInstallAcpiSsdtTable().
+
+ Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (C) 2012 Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DefinitionBlock ("Ssdt.aml", "SSDT", 1, "REDHAT", "OVMF ", 1) {
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveDefines.fdf.inc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveDefines.fdf.inc
new file mode 100644
index 00000000000..a8be0c757b8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveDefines.fdf.inc
@@ -0,0 +1,85 @@
+## @file
+# FDF include file that defines the main macros and sets the dependent PCDs.
+#
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+DEFINE BLOCK_SIZE = 0x1000
+
+#
+# A firmware binary built with FD_SIZE_IN_KB=1024, and a firmware binary built
+# with FD_SIZE_IN_KB=2048, use the same variable store layout.
+#
+# Setting FD_SIZE_IN_KB to 4096 results in a different (much larger) variable
+# store structure that is incompatible with both of the above-mentioned
+# firmware binaries.
+#
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+DEFINE VARS_SIZE = 0x20000
+DEFINE VARS_BLOCKS = 0x20
+DEFINE VARS_LIVE_SIZE = 0xE000
+DEFINE VARS_SPARE_SIZE = 0x10000
+!endif
+
+!if $(FD_SIZE_IN_KB) == 1024
+DEFINE FW_BASE_ADDRESS = 0xFFF00000
+DEFINE FW_SIZE = 0x00100000
+DEFINE FW_BLOCKS = 0x100
+DEFINE CODE_BASE_ADDRESS = 0xFFF20000
+DEFINE CODE_SIZE = 0x000E0000
+DEFINE CODE_BLOCKS = 0xE0
+DEFINE FVMAIN_SIZE = 0x000CC000
+DEFINE SECFV_OFFSET = 0x000EC000
+DEFINE SECFV_SIZE = 0x14000
+!endif
+
+!if $(FD_SIZE_IN_KB) == 2048
+DEFINE FW_BASE_ADDRESS = 0xFFE00000
+DEFINE FW_SIZE = 0x00200000
+DEFINE FW_BLOCKS = 0x200
+DEFINE CODE_BASE_ADDRESS = 0xFFE20000
+DEFINE CODE_SIZE = 0x001E0000
+DEFINE CODE_BLOCKS = 0x1E0
+DEFINE FVMAIN_SIZE = 0x001AC000
+DEFINE SECFV_OFFSET = 0x001CC000
+DEFINE SECFV_SIZE = 0x34000
+!endif
+
+!if $(FD_SIZE_IN_KB) == 4096
+DEFINE VARS_SIZE = 0x84000
+DEFINE VARS_BLOCKS = 0x84
+DEFINE VARS_LIVE_SIZE = 0x40000
+DEFINE VARS_SPARE_SIZE = 0x42000
+
+DEFINE FW_BASE_ADDRESS = 0xFFC00000
+DEFINE FW_SIZE = 0x00400000
+DEFINE FW_BLOCKS = 0x400
+DEFINE CODE_BASE_ADDRESS = 0xFFC84000
+DEFINE CODE_SIZE = 0x0037C000
+DEFINE CODE_BLOCKS = 0x37C
+DEFINE FVMAIN_SIZE = 0x00348000
+DEFINE SECFV_OFFSET = 0x003CC000
+DEFINE SECFV_SIZE = 0x34000
+!endif
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress = $(FW_BASE_ADDRESS)
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize = $(FW_SIZE)
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareBlockSize = $(BLOCK_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase = $(FW_BASE_ADDRESS)
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize = $(VARS_LIVE_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageVariableBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize = $(BLOCK_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize = $(BLOCK_SIZE)
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwSpareBase = gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageFtwWorkingBase + gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = $(VARS_SPARE_SIZE)
+
+DEFINE MEMFD_BASE_ADDRESS = 0x800000
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
new file mode 100644
index 00000000000..802d3bfe46e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
@@ -0,0 +1,66 @@
+## @file
+# GOP driver
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Portions copyright (c) 2011, Apple Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = EmuGopDxe
+ FILE_GUID = 1b290126-5760-424e-8aa2-3faf4d0d7978
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = InitializeEmuGop
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+# DRIVER_BINDING = gEmuGopDriverBinding
+# COMPONENT_NAME = gEmuGopComponentName
+#
+
+[Sources]
+ ComponentName.c
+ Gop.h
+ GopDriver.c
+ GopScreen.c
+ VbeShim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ BltLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ PciLib
+ PcdLib
+ PrintLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiGraphicsOutputProtocolGuid # PROTOCOL BY_START
+ gEfiDevicePathProtocolGuid # PROTOCOL TO_START
+ gEfiPciIoProtocolGuid # PROTOCOL TO_START
+
+[Pcd]
+# gOptionRomPkgTokenSpaceGuid.PcdDriverSupportedEfiVersion
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c
new file mode 100644
index 00000000000..9008ffafefc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/ComponentName.c
@@ -0,0 +1,201 @@
+/** @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+**/
+
+#include "Gop.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gEmuGopComponentName = {
+ EmuGopComponentNameGetDriverName,
+ EmuGopComponentNameGetControllerName,
+ "eng"
+};
+
+//
+// EFI Component Name 2 Protocol
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gEmuGopComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) EmuGopComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) EmuGopComponentNameGetControllerName,
+ "en"
+};
+
+
+EFI_UNICODE_STRING_TABLE mEmuGopDriverNameTable[] = {
+ { "eng", L"Emulator GOP Driver" },
+ { NULL , NULL }
+};
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the driver.
+
+ This function retrieves the user readable name of a driver in the form of a
+ Unicode string. If the driver specified by This has a user readable name in
+ the language specified by Language, then a pointer to the driver name is
+ returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
+ by This does not support the language specified by Language,
+ then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified
+ in RFC 4646 or ISO 639-2 language code format.
+
+ @param DriverName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by
+ This and the language specified by Language was
+ returned in DriverName.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mEmuGopDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gEmuGopComponentName)
+ );
+}
+
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by a driver.
+
+ This function retrieves the user readable name of the controller specified by
+ ControllerHandle and ChildHandle in the form of a Unicode string. If the
+ driver specified by This has a user readable name in the language specified by
+ Language, then a pointer to the controller name is returned in ControllerName,
+ and EFI_SUCCESS is returned. If the driver specified by This is not currently
+ managing the controller specified by ControllerHandle and ChildHandle,
+ then EFI_UNSUPPORTED is returned. If the driver specified by This does not
+ support the language specified by Language, then EFI_UNSUPPORTED is returned.
+
+ @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
+ EFI_COMPONENT_NAME_PROTOCOL instance.
+
+ @param ControllerHandle[in] The handle of a controller that the driver
+ specified by This is managing. This handle
+ specifies the controller whose name is to be
+ returned.
+
+ @param ChildHandle[in] The handle of the child controller to retrieve
+ the name of. This is an optional parameter that
+ may be NULL. It will be NULL for device
+ drivers. It will also be NULL for a bus drivers
+ that wish to retrieve the name of the bus
+ controller. It will not be NULL for a bus
+ driver that wishes to retrieve the name of a
+ child controller.
+
+ @param Language[in] A pointer to a Null-terminated ASCII string
+ array indicating the language. This is the
+ language of the driver name that the caller is
+ requesting, and it must match one of the
+ languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up
+ to the driver writer. Language is specified in
+ RFC 4646 or ISO 639-2 language code format.
+
+ @param ControllerName[out] A pointer to the Unicode string to return.
+ This Unicode string is the name of the
+ controller specified by ControllerHandle and
+ ChildHandle in the language specified by
+ Language from the point of view of the driver
+ specified by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user readable name in
+ the language specified by Language for the
+ driver specified by This was returned in
+ DriverName.
+
+ @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
+ EFI_HANDLE.
+
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently
+ managing the controller specified by
+ ControllerHandle and ChildHandle.
+
+ @retval EFI_UNSUPPORTED The driver specified by This does not support
+ the language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h
new file mode 100644
index 00000000000..a792d2bba79
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/Gop.h
@@ -0,0 +1,149 @@
+/*++ @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _GOP_H_
+#define _GOP_H_
+
+#include <Uefi.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/DevicePath.h>
+
+#include <Guid/EventGroup.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <IndustryStandard/Pci.h>
+
+#define GRAPHICS_OUTPUT_INVALID_MODE_NUMBER 0xffff
+
+typedef struct {
+ UINT32 HorizontalResolution;
+ UINT32 VerticalResolution;
+ UINT32 ColorDepth;
+ UINT32 RefreshRate;
+} GOP_MODE_DATA;
+
+#define PIXEL_RED_SHIFT 0
+#define PIXEL_GREEN_SHIFT 3
+#define PIXEL_BLUE_SHIFT 6
+
+#define PIXEL_RED_MASK (BIT7 | BIT6 | BIT5)
+#define PIXEL_GREEN_MASK (BIT4 | BIT3 | BIT2)
+#define PIXEL_BLUE_MASK (BIT1 | BIT0)
+
+#define PIXEL_TO_COLOR_BYTE(pixel, mask, shift) ((UINT8) ((pixel & mask) << shift))
+#define PIXEL_TO_RED_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_RED_MASK, PIXEL_RED_SHIFT)
+#define PIXEL_TO_GREEN_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_GREEN_MASK, PIXEL_GREEN_SHIFT)
+#define PIXEL_TO_BLUE_BYTE(pixel) PIXEL_TO_COLOR_BYTE(pixel, PIXEL_BLUE_MASK, PIXEL_BLUE_SHIFT)
+
+#define RGB_BYTES_TO_PIXEL(Red, Green, Blue) \
+ (UINT8) ( (((Red) >> PIXEL_RED_SHIFT) & PIXEL_RED_MASK) | \
+ (((Green) >> PIXEL_GREEN_SHIFT) & PIXEL_GREEN_MASK) | \
+ (((Blue) >> PIXEL_BLUE_SHIFT) & PIXEL_BLUE_MASK) )
+
+#define PIXEL24_RED_MASK 0x00ff0000
+#define PIXEL24_GREEN_MASK 0x0000ff00
+#define PIXEL24_BLUE_MASK 0x000000ff
+
+extern EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gEmuGopComponentName;
+
+#define EMU_UGA_CLASS_NAME L"EmuGopWindow"
+
+#define GOP_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('G', 'o', 'p', 'N')
+typedef struct {
+ UINT64 Signature;
+
+ EFI_HANDLE Handle;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_GRAPHICS_OUTPUT_PROTOCOL GraphicsOutput;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ EFI_UNICODE_STRING_TABLE *ControllerNameTable;
+
+ //
+ // GOP Private Data for QueryMode ()
+ //
+ GOP_MODE_DATA *ModeData;
+
+ UINT64 FbAddr;
+ UINT32 FbSize;
+} GOP_PRIVATE_DATA;
+
+
+#define GOP_PRIVATE_DATA_FROM_THIS(a) \
+ CR(a, GOP_PRIVATE_DATA, GraphicsOutput, GOP_PRIVATE_DATA_SIGNATURE)
+
+typedef struct {
+ UINT32 FbSize;
+ UINT16 Width;
+ UINT16 Height;
+ UINT16 Depth;
+ UINT16 RefreshRate;
+} BHYVE_FBUF_MEMREGS;
+
+//
+// Global Protocol Variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gEmuGopComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gEmuGopComponentName2;
+
+//
+// Gop Hardware abstraction internal worker functions
+//
+EFI_STATUS
+EmuGopConstructor (
+ IN GOP_PRIVATE_DATA *Private
+ );
+
+EFI_STATUS
+EmuGopDestructor (
+ IN GOP_PRIVATE_DATA *Private
+ );
+
+VOID
+EFIAPI
+ShutdownGopEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+BhyveSetGraphicsMode (
+ GOP_PRIVATE_DATA *Private,
+ UINT16 Width,
+ UINT16 Height,
+ UINT16 Depth
+ );
+
+VOID
+BhyveGetMemregs (
+ GOP_PRIVATE_DATA *Private,
+ BHYVE_FBUF_MEMREGS *Memregs
+ );
+
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ );
+
+#endif /* _GOP_H_ */
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c
new file mode 100644
index 00000000000..7f723e889d7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c
@@ -0,0 +1,543 @@
+/*++ @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Gop.h"
+#include <IndustryStandard/Acpi.h>
+
+STATIC VOID
+BhyveGetGraphicsMode (
+ EFI_PCI_IO_PROTOCOL *PciIo,
+ UINT16 *Width,
+ UINT16 *Height,
+ UINT16 *Depth
+ );
+
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+EmuGopDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+ UINT16 Width, Height, Depth;
+
+ //
+ // Open the IO Abstraction(s) needed to perform the supported test
+ //
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // See if this is a PCI Framebuffer Controller by looking at the Command register and
+ // Class Code Register
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ goto Done;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (Pci.Hdr.VendorId == 0xFB5D && Pci.Hdr.DeviceId == 0x40FB) {
+ DEBUG((DEBUG_INFO, "BHYVE framebuffer device detected\n"));
+ Status = EFI_SUCCESS;
+
+ BhyveGetGraphicsMode(PciIo, &Width, &Height, &Depth);
+ PcdSet32S (PcdVideoHorizontalResolution, Width);
+ PcdSet32S (PcdVideoVerticalResolution, Height);
+ }
+
+Done:
+ //
+ // Close the PCI I/O Protocol
+ //
+ gBS->CloseProtocol (
+ Handle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Handle
+ );
+
+ return Status;
+}
+
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
+ )
+{
+ BHYVE_FBUF_MEMREGS Memregs;
+ GOP_PRIVATE_DATA *Private;
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;
+
+ //
+ // Allocate Private context data for SGO inteface.
+ //
+ Private = NULL;
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (GOP_PRIVATE_DATA),
+ (VOID **)&Private
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ // Set up context record
+ //
+ Private->Signature = GOP_PRIVATE_DATA_SIGNATURE;
+ Private->Handle = Handle;
+ Private->ControllerNameTable = NULL;
+
+ //
+ // Open PCI I/O Protocol
+ //
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **) &Private->PciIo,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Check if fbuf mmio BAR is present
+ //
+ MmioDesc = NULL;
+ Status = Private->PciIo->GetBarAttributes (
+ Private->PciIo,
+ PCI_BAR_IDX0,
+ NULL,
+ (VOID**) &MmioDesc
+ );
+ if (EFI_ERROR (Status) ||
+ MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((DEBUG_INFO, "BHYVE GOP: No mmio bar\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "BHYVE GOP: Using mmio bar @ 0x%lx\n",
+ MmioDesc->AddrRangeMin));
+ BhyveGetMemregs(Private, &Memregs);
+ Private->FbSize = Memregs.FbSize;
+ }
+ if (MmioDesc != NULL) {
+ FreePool (MmioDesc);
+ }
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Check if fbuf frame-buffer BAR is present
+ //
+ MmioDesc = NULL;
+ Status = Private->PciIo->GetBarAttributes (
+ Private->PciIo,
+ PCI_BAR_IDX1,
+ NULL,
+ (VOID**) &MmioDesc
+ );
+ if (EFI_ERROR (Status) ||
+ MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((DEBUG_INFO, "BHYVE GOP: No frame-buffer bar\n"));
+ } else {
+ DEBUG ((DEBUG_INFO, "BHYVE GOP: Using frame-buffer bar @ 0x%lx\n",
+ MmioDesc->AddrRangeMin));
+ Private->FbAddr = MmioDesc->AddrRangeMin;
+ // XXX assert BAR is >= size
+ }
+
+ if (MmioDesc != NULL) {
+ FreePool (MmioDesc);
+ }
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ DEBUG ((DEBUG_INFO, "BHYVE GOP: Framebuf addr 0x%lx, size %x\n",
+ Private->FbAddr, Private->FbSize));
+
+ Status = EmuGopConstructor (Private);
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ //
+ // Publish the Gop interface to the world
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Private->Handle,
+ &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
+ NULL
+ );
+
+ DEBUG((DEBUG_INFO, "BHYVE framebuffer device started\n"));
+
+ //
+ // Install int10 handler
+ //
+#ifndef CSM_ENABLE
+ InstallVbeShim (L"Framebuffer", Private->FbAddr);
+#endif
+
+Done:
+ if (EFI_ERROR (Status)) {
+ if (Private != NULL) {
+ //
+ // On Error Free back private data
+ //
+ if (Private->ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (Private->ControllerNameTable);
+ }
+
+ gBS->FreePool (Private);
+ }
+ }
+
+ return Status;
+}
+
+
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE Handle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_STATUS Status;
+ GOP_PRIVATE_DATA *Private;
+
+ DEBUG((DEBUG_INFO, "BHYVE framebuffer device stopping\n"));
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID **)&GraphicsOutput,
+ This->DriverBindingHandle,
+ Handle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If the GOP interface does not exist the driver is not started
+ //
+ return EFI_NOT_STARTED;
+ }
+
+ //
+ // Get our private context information
+ //
+ Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput);
+
+ //
+ // Remove the SGO interface from the system
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Private->Handle,
+ &gEfiGraphicsOutputProtocolGuid, &Private->GraphicsOutput,
+ NULL
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Shutdown the hardware
+ //
+ Status = EmuGopDestructor (Private);
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ gBS->CloseProtocol (
+ Handle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ Private->Handle
+ );
+
+ //
+ // Free our instance data
+ //
+ FreeUnicodeStringTable (Private->ControllerNameTable);
+
+ gBS->FreePool (Private);
+
+ }
+
+ return Status;
+}
+
+
+///
+/// This protocol provides the services required to determine if a driver supports a given controller.
+/// If a controller is supported, then it also provides routines to start and stop the controller.
+///
+EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding = {
+ EmuGopDriverBindingSupported,
+ EmuGopDriverBindingStart,
+ EmuGopDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+
+
+/**
+ The user Entry Point for module EmuGop. The user code starts with this function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeEmuGop (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gEmuGopDriverBinding,
+ ImageHandle,
+ &gEmuGopComponentName,
+ &gEmuGopComponentName2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+
+ return Status;
+}
+
+STATIC VOID
+BhyveGetGraphicsMode (
+ EFI_PCI_IO_PROTOCOL *PciIo,
+ UINT16 *Width,
+ UINT16 *Height,
+ UINT16 *Depth
+ )
+{
+ BHYVE_FBUF_MEMREGS BhyveRegs;
+ UINT64 Offset;
+ EFI_STATUS Status;
+
+
+ Offset = (UINT64)&BhyveRegs.Width - (UINT64)&BhyveRegs;
+
+ Status = PciIo->Mem.Read (
+ PciIo,
+ EfiPciIoWidthUint16,
+ PCI_BAR_IDX0,
+ Offset,
+ 3,
+ &BhyveRegs.Width
+ );
+
+ *Width = BhyveRegs.Width;
+ *Height = BhyveRegs.Height;
+ *Depth = BhyveRegs.Depth;
+
+ DEBUG ((DEBUG_INFO, "BHYVE Get Graphics Mode: w %d, h %d\n", *Width, *Height));
+
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+BhyveSetGraphicsMode (
+ GOP_PRIVATE_DATA *Private,
+ UINT16 Width,
+ UINT16 Height,
+ UINT16 Depth
+ )
+{
+ BHYVE_FBUF_MEMREGS BhyveRegs;
+ UINT64 Offset;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "BHYVE Set Graphics Mode: w %d, h %d\n", Width, Height));
+
+ BhyveRegs.Width = Width;
+ BhyveRegs.Height = Height;
+ BhyveRegs.Depth = Depth;
+ Offset = (UINT64)&BhyveRegs.Width - (UINT64)&BhyveRegs;
+
+ Status = Private->PciIo->Mem.Write (
+ Private->PciIo,
+ EfiPciIoWidthUint16,
+ PCI_BAR_IDX0,
+ Offset,
+ 3,
+ &BhyveRegs.Width
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+VOID
+BhyveGetMemregs (
+ GOP_PRIVATE_DATA *Private,
+ BHYVE_FBUF_MEMREGS *Memregs
+ )
+{
+ EFI_STATUS Status;
+
+ Status = Private->PciIo->Mem.Read (
+ Private->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ 0,
+ 3,
+ Memregs
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "BHYVE Get Memregs, size %d width %d height %d\n",
+ Memregs->FbSize, Memregs->Width, Memregs->Height));
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c
new file mode 100644
index 00000000000..8dedf4b6b12
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/GopScreen.c
@@ -0,0 +1,393 @@
+/*++ @file
+
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+Copyright (c) 2015, Nahanni Systems, Inc.
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Portions copyright (c) 2010 - 2011, Apple Inc. All rights reserved.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ EmuGopScreen.c
+
+Abstract:
+
+ This file produces the graphics abstration of UGA. It is called by
+ EmuGopDriver.c file which deals with the EFI 1.1 driver model.
+ This file just does graphics.
+
+**/
+
+#include "Gop.h"
+#include <Library/FrameBufferBltLib.h>
+
+
+EFI_EVENT mGopScreenExitBootServicesEvent;
+
+GOP_MODE_DATA mGopModeData[] = {
+ { 0, 0, 32, 0 }, // Filled in with user-spec'd resolution
+ { 1024, 768, 32, 0 },
+ { 800, 600, 32, 0 },
+ { 640, 480, 32, 0 }
+ };
+
+STATIC
+VOID
+BhyveGopCompleteModeInfo (
+ IN GOP_MODE_DATA *ModeData,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info
+ )
+{
+ Info->Version = 0;
+ if (ModeData->ColorDepth == 8) {
+ Info->PixelFormat = PixelBitMask;
+ Info->PixelInformation.RedMask = PIXEL_RED_MASK;
+ Info->PixelInformation.GreenMask = PIXEL_GREEN_MASK;
+ Info->PixelInformation.BlueMask = PIXEL_BLUE_MASK;
+ Info->PixelInformation.ReservedMask = 0;
+ } else if (ModeData->ColorDepth == 24) {
+ Info->PixelFormat = PixelBitMask;
+ Info->PixelInformation.RedMask = PIXEL24_RED_MASK;
+ Info->PixelInformation.GreenMask = PIXEL24_GREEN_MASK;
+ Info->PixelInformation.BlueMask = PIXEL24_BLUE_MASK;
+ Info->PixelInformation.ReservedMask = 0;
+ } else if (ModeData->ColorDepth == 32) {
+ DEBUG ((DEBUG_INFO, "%dx%d PixelBlueGreenRedReserved8BitPerColor\n",
+ ModeData->HorizontalResolution, ModeData->VerticalResolution));
+ Info->PixelFormat = PixelBlueGreenRedReserved8BitPerColor;
+ }
+ Info->PixelsPerScanLine = Info->HorizontalResolution;
+}
+
+
+/**
+ Returns information for an available graphics mode that the graphics device
+ and the set of active video output devices supports.
+
+ @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
+ @param ModeNumber The mode number to return information on.
+ @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer.
+ @param Info A pointer to callee allocated buffer that returns information about ModeNumber.
+
+ @retval EFI_SUCCESS Mode information returned.
+ @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small.
+ @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode.
+ @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
+ @retval EFI_INVALID_PARAMETER One of the input args was NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopQuerytMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber,
+ OUT UINTN *SizeOfInfo,
+ OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info
+ )
+{
+ GOP_PRIVATE_DATA *Private;
+ GOP_MODE_DATA *ModeData;
+
+ Private = GOP_PRIVATE_DATA_FROM_THIS (This);
+
+ if (Info == NULL || SizeOfInfo == NULL || (UINTN) ModeNumber >= This->Mode->MaxMode) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+ if (*Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ *SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+
+ ModeData = &Private->ModeData[ModeNumber];
+ (*Info)->Version = 0;
+ (*Info)->HorizontalResolution = ModeData->HorizontalResolution;
+ (*Info)->VerticalResolution = ModeData->VerticalResolution;
+ (*Info)->PixelFormat = PixelBitMask;
+ (*Info)->PixelsPerScanLine = (*Info)->HorizontalResolution;
+ BhyveGopCompleteModeInfo(ModeData, *Info);
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Set the video device into the specified mode and clears the visible portions of
+ the output display to black.
+
+ @param This The EFI_GRAPHICS_OUTPUT_PROTOCOL instance.
+ @param ModeNumber Abstraction that defines the current video mode.
+
+ @retval EFI_SUCCESS The graphics mode specified by ModeNumber was selected.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the request.
+ @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
+
+**/
+
+FRAME_BUFFER_CONFIGURE *fbconf;
+
+EFI_STATUS
+EFIAPI
+EmuGopSetMode (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN UINT32 ModeNumber
+ )
+{
+ GOP_PRIVATE_DATA *Private;
+ GOP_MODE_DATA *ModeData;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL Fill;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info;
+
+ UINTN confsize = 0;
+ fbconf = NULL;
+
+ Private = GOP_PRIVATE_DATA_FROM_THIS (This);
+
+ if (ModeNumber >= This->Mode->MaxMode) {
+ // Tell bhyve that we are switching out of vesa
+ BhyveSetGraphicsMode(Private, 0, 0, 0);
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "BHYVE GopSetMode %d\n", ModeNumber));
+
+ ModeData = &Private->ModeData[ModeNumber];
+ This->Mode->Mode = ModeNumber;
+ Private->GraphicsOutput.Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+ Private->GraphicsOutput.Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+ Private->GraphicsOutput.Mode->Info->PixelsPerScanLine = ModeData->HorizontalResolution;
+
+ Info = This->Mode->Info;
+ BhyveGopCompleteModeInfo(ModeData, Info);
+
+ This->Mode->Info->HorizontalResolution = ModeData->HorizontalResolution;
+ This->Mode->Info->VerticalResolution = ModeData->VerticalResolution;
+ This->Mode->SizeOfInfo = sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+ This->Mode->FrameBufferBase = Private->GraphicsOutput.Mode->FrameBufferBase;
+
+ /*
+ This->Mode->FrameBufferSize = Info->HorizontalResolution * Info->VerticalResolution
+ * ((ModeData->ColorDepth + 7) / 8);
+ */
+ This->Mode->FrameBufferSize = Private->FbSize;
+ DEBUG ((DEBUG_INFO, "BHYVE GOP FrameBufferBase: 0x%x, FrameBufferSize: 0x%x\n", This->Mode->FrameBufferBase, This->Mode->FrameBufferSize));
+
+ BhyveSetGraphicsMode(Private, (UINT16)ModeData->HorizontalResolution, (UINT16)ModeData->VerticalResolution, (UINT16)ModeData->ColorDepth);
+
+ RETURN_STATUS ret = FrameBufferBltConfigure (
+ (VOID*)(UINTN) This->Mode->FrameBufferBase,
+ This->Mode->Info, fbconf, &confsize
+ );
+ if (ret == EFI_BUFFER_TOO_SMALL || ret == EFI_INVALID_PARAMETER) {
+ fbconf = AllocatePool(confsize);
+ ret = FrameBufferBltConfigure(
+ (VOID*)(UINTN)This->Mode->FrameBufferBase,
+ This->Mode->Info, fbconf, &confsize);
+ ASSERT(ret == EFI_SUCCESS);
+ }
+
+ Fill.Red = 0;
+ Fill.Green = 0;
+ Fill.Blue = 0;
+ This->Blt (
+ This,
+ &Fill,
+ EfiBltVideoFill,
+ 0,
+ 0,
+ 0,
+ 0,
+ ModeData->HorizontalResolution,
+ ModeData->VerticalResolution,
+ ModeData->HorizontalResolution * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ );
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Blt a rectangle of pixels on the graphics screen. Blt stands for BLock Transfer.
+
+ @param This Protocol instance pointer.
+ @param BltBuffer Buffer containing data to blit into video buffer. This
+ buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)
+ @param BltOperation Operation to perform on BlitBuffer and video memory
+ @param SourceX X coordinate of source for the BltBuffer.
+ @param SourceY Y coordinate of source for the BltBuffer.
+ @param DestinationX X coordinate of destination for the BltBuffer.
+ @param DestinationY Y coordinate of destination for the BltBuffer.
+ @param Width Width of rectangle in BltBuffer in pixels.
+ @param Height Hight of rectangle in BltBuffer in pixels.
+ @param Delta OPTIONAL
+
+ @retval EFI_SUCCESS The Blt operation completed.
+ @retval EFI_INVALID_PARAMETER BltOperation is not valid.
+ @retval EFI_DEVICE_ERROR A hardware error occurred writting to the video buffer.
+
+**/
+EFI_STATUS
+EFIAPI
+EmuGopBlt (
+ IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This,
+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL
+ IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation,
+ IN UINTN SourceX,
+ IN UINTN SourceY,
+ IN UINTN DestinationX,
+ IN UINTN DestinationY,
+ IN UINTN Width,
+ IN UINTN Height,
+ IN UINTN Delta OPTIONAL
+ )
+{
+ EFI_TPL OriginalTPL;
+ EFI_STATUS Status;
+
+ if ((UINT32)BltOperation >= EfiGraphicsOutputBltOperationMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width == 0 || Height == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
+ // We would not want a timer based event (Cursor, ...) to come in while we are
+ // doing this operation.
+ //
+ OriginalTPL = gBS->RaiseTPL (TPL_NOTIFY);
+
+ switch (BltOperation) {
+ case EfiBltVideoToBltBuffer:
+ case EfiBltBufferToVideo:
+ case EfiBltVideoFill:
+ case EfiBltVideoToVideo:
+ Status = FrameBufferBlt (
+ fbconf,
+ BltBuffer,
+ BltOperation,
+ SourceX,
+ SourceY,
+ DestinationX,
+ DestinationY,
+ Width,
+ Height,
+ Delta
+ );
+ break;
+
+ default:
+ Status = EFI_INVALID_PARAMETER;
+ ASSERT (FALSE);
+ }
+
+ gBS->RestoreTPL (OriginalTPL);
+
+ return Status;
+}
+
+
+//
+// Construction and Destruction functions
+//
+
+EFI_STATUS
+EmuGopConstructor (
+ GOP_PRIVATE_DATA *Private
+ )
+{
+ // Set mode 0 to be the requested resolution
+ mGopModeData[0].HorizontalResolution = PcdGet32 ( PcdVideoHorizontalResolution);
+ mGopModeData[0].VerticalResolution = PcdGet32 ( PcdVideoVerticalResolution );
+
+ Private->ModeData = mGopModeData;
+
+ Private->GraphicsOutput.QueryMode = EmuGopQuerytMode;
+ Private->GraphicsOutput.SetMode = EmuGopSetMode;
+ Private->GraphicsOutput.Blt = EmuGopBlt;
+
+ //
+ // Allocate buffer for Graphics Output Protocol mode information
+ //
+ Private->GraphicsOutput.Mode = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE));
+ if (Private->GraphicsOutput.Mode == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Private->GraphicsOutput.Mode->Info = AllocatePool (sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION));
+ if (Private->GraphicsOutput.Mode->Info == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+
+ DEBUG ((DEBUG_INFO, "BHYVE Gop Constructor\n"));
+
+ Private->GraphicsOutput.Mode->MaxMode = sizeof(mGopModeData) / sizeof(GOP_MODE_DATA);
+ //
+ // Till now, we have no idea about the window size.
+ //
+ Private->GraphicsOutput.Mode->Mode = GRAPHICS_OUTPUT_INVALID_MODE_NUMBER;
+ Private->GraphicsOutput.Mode->Info->Version = 0;
+ Private->GraphicsOutput.Mode->Info->HorizontalResolution = 0;
+ Private->GraphicsOutput.Mode->Info->VerticalResolution = 0;
+ Private->GraphicsOutput.Mode->Info->PixelFormat = PixelBitMask;
+ Private->GraphicsOutput.Mode->SizeOfInfo = sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION);
+ Private->GraphicsOutput.Mode->FrameBufferBase = (EFI_PHYSICAL_ADDRESS) Private->FbAddr;
+ Private->GraphicsOutput.Mode->FrameBufferSize = Private->FbSize;
+
+ return EFI_SUCCESS;
+}
+
+
+
+EFI_STATUS
+EmuGopDestructor (
+ GOP_PRIVATE_DATA *Private
+ )
+{
+ //
+ // Free graphics output protocol occupied resource
+ //
+ if (Private->GraphicsOutput.Mode != NULL) {
+ if (Private->GraphicsOutput.Mode->Info != NULL) {
+ FreePool (Private->GraphicsOutput.Mode->Info);
+ }
+ FreePool (Private->GraphicsOutput.Mode);
+ Private->GraphicsOutput.Mode = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+ShutdownGopEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+/*++
+
+Routine Description:
+
+ This is the UGA screen's callback notification function for exit-boot-services.
+ All we do here is call EmuGopDestructor().
+
+Arguments:
+
+ Event - not used
+ Context - pointer to the Private structure.
+
+Returns:
+
+ None.
+
+**/
+{
+ EmuGopDestructor (Context);
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm
new file mode 100644
index 00000000000..83f0de13fad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.asm
@@ -0,0 +1,342 @@
+;------------------------------------------------------------------------------
+; @file
+; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
+; default VGA driver to switch to 1024x768x32.
+;
+; Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+; Copyright (C) 2015, Nahanni Systems, Inc.
+; Copyright (C) 2014, Red Hat, Inc.
+; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+;
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+; enable this macro for debug messages
+%define DEBUG
+
+%macro DebugLog 1
+%ifdef DEBUG
+ push si
+ mov si, %1
+ call PrintStringSi
+ pop si
+%endif
+%endmacro
+
+
+BITS 16
+ORG 0
+
+VbeInfo:
+TIMES 256 nop
+
+VbeModeInfo:
+VbeMode1:
+TIMES 50 nop
+VbeMode2:
+TIMES 50 nop
+VbeMode3:
+TIMES 50 nop
+VbeMode4:
+TIMES 50 nop
+TIMES 56 nop ; filler for 256 bytes
+
+Handler:
+ cmp ax, 0x4f00
+ je GetInfo
+ cmp ax, 0x4f01
+ je GetModeInfo
+ cmp ax, 0x4f02
+ je SetMode
+ cmp ax, 0x4f03
+ je GetMode
+ cmp ax, 0x4f10
+ je GetPmCapabilities
+ cmp ax, 0x4f15
+ je ReadEdid
+ cmp ah, 0x00
+ je SetModeLegacy
+ DebugLog StrUnkownFunction
+Hang:
+ jmp Hang
+
+
+GetInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetInfo
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, VbeInfo
+ ; source (ds:si) set now
+
+ mov cx, 256
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+GetModeInfo:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrEnterGetModeInfo
+
+ and cx, ~0x4000 ; clear potentially set LFB bit in mode number
+
+ cmp cx, 0x013f
+ je gKnownMode1
+ cmp cx, 0x0140
+ je gKnownMode2
+ cmp cx, 0x0141
+ je gKnownMode3
+
+ DebugLog StrUnkownMode
+ jmp Hang
+gKnownMode1:
+ DebugLog StrMode1
+ mov si, VbeMode1
+ jmp CopyModeInfo
+gKnownMode2:
+ DebugLog StrMode2
+ mov si, VbeMode2
+ jmp CopyModeInfo
+gKnownMode3:
+ DebugLog StrMode3
+ mov si, VbeMode3
+ jmp CopyModeInfo
+gKnownMode4:
+ DebugLog StrMode4
+ mov si, VbeMode4
+ jmp CopyModeInfo
+
+CopyModeInfo:
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ ;mov si, VbeModeInfo
+ ; source (ds:si) set now
+
+ ;mov cx, 256
+ mov cx, 50
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+SetMode:
+ push dx
+ push ax
+
+ DebugLog StrEnterSetMode
+
+ and bx, ~0x4000 ; clear potentially set LFB bit in mode number
+ cmp bx, 0x013f
+ je KnownMode1
+ cmp bx, 0x0140
+ je KnownMode2
+ cmp bx, 0x0141
+ je KnownMode3
+ DebugLog StrUnkownMode
+ jmp Hang
+KnownMode1:
+ DebugLog StrMode1
+ jmp SetModeDone
+KnownMode2:
+ DebugLog StrMode2
+ jmp SetModeDone
+KnownMode3:
+ DebugLog StrMode3
+ jmp SetModeDone
+KnownMode4:
+ DebugLog StrMode4
+
+SetModeDone:
+ mov [CurMode], bl
+ mov [CurMode+1], bh
+ pop ax
+ pop dx
+ jmp Success
+
+
+GetMode:
+ DebugLog StrEnterGetMode
+ mov bl, [CurMode]
+ mov bh, [CurMode+1]
+ jmp Success
+
+
+GetPmCapabilities:
+ DebugLog StrGetPmCapabilities
+ mov bx, 0x0080
+ jmp Success
+
+
+ReadEdid:
+ push es
+ push di
+ push ds
+ push si
+ push cx
+
+ DebugLog StrReadEdid
+
+ ; target (es:di) set on input
+ push cs
+ pop ds
+ mov si, Edid
+ ; source (ds:si) set now
+
+ mov cx, 128
+ cld
+ rep movsb
+
+ pop cx
+ pop si
+ pop ds
+ pop di
+ pop es
+ jmp Success
+
+
+SetModeLegacy:
+ DebugLog StrEnterSetModeLegacy
+
+ cmp al, 0x03
+ je sKnownMode3
+ cmp al, 0x12
+ je sKnownMode4
+ DebugLog StrUnkownMode
+ jmp Hang
+sKnownMode3:
+ DebugLog StrLegacyMode3
+ mov al, 0 ; 0x30
+ jmp SetModeLegacyDone
+sKnownMode4:
+ mov al, 0 ;0x20
+SetModeLegacyDone:
+ DebugLog StrExitSuccess
+ iret
+
+
+Success:
+ DebugLog StrExitSuccess
+ mov ax, 0x004f
+ iret
+
+
+Unsupported:
+ DebugLog StrExitUnsupported
+ mov ax, 0x024f
+ iret
+
+
+%ifdef DEBUG
+PrintStringSi:
+ pusha
+ push ds ; save original
+ push cs
+ pop ds
+ mov dx, 0x220 ; bhyve debug cons port
+ mov ax, 0
+PrintStringSiLoop:
+ lodsb
+ cmp al, 0
+ je PrintStringSiDone
+ out dx, al
+ jmp PrintStringSiLoop
+PrintStringSiDone:
+ pop ds ; restore original
+ popa
+ ret
+
+
+StrExitSuccess:
+ db 'vOk', 0x0d, 0x0a, 0
+
+StrExitUnsupported:
+ db 'vUnsupported', 0x0d, 0x0a, 0
+
+StrUnkownFunction:
+ db 'vUnknown Function', 0x0d, 0x0a, 0
+
+StrEnterGetInfo:
+ db 'vGetInfo', 0x0d, 0x0a, 0
+
+StrEnterGetModeInfo:
+ db 'vGetModeInfo', 0x0d, 0x0a, 0
+
+StrEnterGetMode:
+ db 'vGetMode', 0x0d, 0x0a, 0
+
+StrEnterSetMode:
+ db 'vSetMode', 0x0d, 0x0a, 0
+
+StrEnterSetModeLegacy:
+ db 'vSetModeLegacy', 0x0d, 0x0a, 0
+
+StrUnkownMode:
+ db 'vUnkown Mode', 0x0d, 0x0a, 0
+
+StrGetPmCapabilities:
+ db 'vGetPmCapabilities', 0x0d, 0x0a, 0
+
+StrReadEdid:
+ db 'vReadEdid', 0x0d, 0x0a, 0
+
+StrLegacyMode3:
+ db 'vLegacyMode3', 0x0d, 0x0a, 0
+
+
+StrMode1:
+ db 'mode_640x480x32', 0x0d, 0x0a, 0
+StrMode2:
+ db 'mode_800x600x32', 0x0d, 0x0a, 0
+StrMode3:
+ db 'mode_1024x768x32', 0x0d, 0x0a, 0
+StrMode4:
+ db 'mode_unused', 0x0d, 0x0a, 0
+%endif
+
+CurMode:
+ db 0x00, 0x00
+
+;
+; EDID stores monitor information. For now, just send back an null item.
+;
+Edid:
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c
new file mode 100644
index 00000000000..1805c373e8c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.c
@@ -0,0 +1,259 @@
+/** @file
+ Install a fake VGABIOS service handler (real mode Int10h) for the buggy
+ Windows 2008 R2 SP1 UEFI guest.
+
+ The handler is never meant to be directly executed by a VCPU; it's there for
+ the internal real mode emulator of Windows 2008 R2 SP1.
+
+ The code is based on Ralf Brown's Interrupt List:
+ <http://www.cs.cmu.edu/~ralf/files.html>
+ <http://www.ctyme.com/rbrown.htm>
+
+ Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (C) 2015, Nahanni Systems, Inc.
+ Copyright (C) 2014, Red Hat, Inc.
+ Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/LegacyVgaBios.h>
+#include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/PrintLib.h>
+
+#include "Gop.h"
+#include "VbeShim.h"
+
+#pragma pack (1)
+typedef struct {
+ UINT16 Offset;
+ UINT16 Segment;
+} IVT_ENTRY;
+#pragma pack ()
+
+//
+// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
+// Advanced Settings dialog. It should be short.
+//
+STATIC CONST CHAR8 mProductRevision[] = "2.0";
+
+#define NUM_VBE_MODES 3
+STATIC CONST UINT16 vbeModeIds[] = {
+ 0x13f, // 640x480x32
+ 0x140, // 800x600x32
+ 0x141 // 1024x768x32
+};
+
+// Modes can be toggled with bit-0
+#define VBE_MODE_ENABLED 0x00BB
+#define VBE_MODE_DISABLED 0x00BA
+
+STATIC VBE2_MODE_INFO vbeModes[] = {
+ { // 0x13f 640x480x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 640*4,
+ // Width, Height..., Vbe3
+ 640, 480, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ },
+ { // 0x140 800x600x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_DISABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 800*4,
+ // Width, Height..., Vbe3
+ 800, 600, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ },
+ { // 0x141 1024x768x32
+
+ // ModeAttr - BytesPerScanLine
+ VBE_MODE_ENABLED, 0x07, 0x00, 0x40, 0x40, 0xA000, 0x00, 0x0000, 1024*4,
+ // Width, Height..., Vbe3
+ 1024, 768, 16, 8, 1, 32, 1, 0x06, 0, 0, 1,
+ // Masks
+ 0x08, 0x10, 0x08, 0x08, 0x08, 0x00, 0x08, 0x18, 0x00,
+ // Framebuffer
+ 0xdeadbeef, 0x0000, 0x0000
+ }
+};
+
+/**
+ Install the VBE Info and VBE Mode Info structures, and the VBE service
+ handler routine in the C segment. Point the real-mode Int10h interrupt vector
+ to the handler. The only advertised mode is 1024x768x32.
+
+ @param[in] CardName Name of the video card to be exposed in the
+ Product Name field of the VBE Info structure.
+ @param[in] FrameBufferBase Guest-physical base address of the video card's
+ frame buffer.
+**/
+VOID
+InstallVbeShim (
+ IN CONST CHAR16 *CardName,
+ IN EFI_PHYSICAL_ADDRESS FrameBufferBase
+ )
+{
+ EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
+ UINTN Segment0Pages;
+ IVT_ENTRY *Int0x10;
+ EFI_STATUS Status;
+ UINTN Pam1Address;
+ UINT8 Pam1;
+ UINTN SegmentCPages;
+ VBE_INFO *VbeInfoFull;
+ VBE_INFO_BASE *VbeInfo;
+ UINT8 *Ptr;
+ UINTN Printed;
+ VBE_MODE_INFO *VbeModeInfo;
+ UINTN i;
+
+ Segment0 = 0x00000;
+ SegmentC = 0xC0000;
+ SegmentF = 0xF0000;
+
+ //
+ // Attempt to cover the real mode IVT with an allocation. This is a UEFI
+ // driver, hence the arch protocols have been installed previously. Among
+ // those, the CPU arch protocol has configured the IDT, so we can overwrite
+ // the IVT used in real mode.
+ //
+ // The allocation request may fail, eg. if LegacyBiosDxe has already run.
+ //
+ Segment0Pages = 1;
+ Int0x10 = (IVT_ENTRY *)(UINTN)Segment0 + 0x10;
+ Status = gBS->AllocatePages (AllocateAddress, EfiBootServicesCode,
+ Segment0Pages, &Segment0);
+
+ if (EFI_ERROR (Status)) {
+ EFI_PHYSICAL_ADDRESS Handler;
+
+ //
+ // Check if a video BIOS handler has been installed previously -- we
+ // shouldn't override a real video BIOS with our shim, nor our own shim if
+ // it's already present.
+ //
+ Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
+ if (Handler >= SegmentC && Handler < SegmentF) {
+ DEBUG ((DEBUG_VERBOSE, "%a: Video BIOS handler found at %04x:%04x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+ return;
+ }
+
+ //
+ // Otherwise we'll overwrite the Int10h vector, even though we may not own
+ // the page at zero.
+ //
+ DEBUG ((DEBUG_VERBOSE, "%a: failed to allocate page at zero: %r\n",
+ __FUNCTION__, Status));
+ } else {
+ //
+ // We managed to allocate the page at zero. SVN r14218 guarantees that it
+ // is NUL-filled.
+ //
+ ASSERT (Int0x10->Segment == 0x0000);
+ ASSERT (Int0x10->Offset == 0x0000);
+ }
+
+ //
+ // Put the shim in place first.
+ //
+ Pam1Address = PCI_LIB_ADDRESS (0, 0, 0, 0x5A);
+ //
+ // low nibble covers 0xC0000 to 0xC3FFF
+ // high nibble covers 0xC4000 to 0xC7FFF
+ // bit1 in each nibble is Write Enable
+ // bit0 in each nibble is Read Enable
+ //
+ Pam1 = PciRead8 (Pam1Address);
+ PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0));
+
+ //
+ // We never added memory space durig PEI or DXE for the C segment, so we
+ // don't need to (and can't) allocate from there. Also, guest operating
+ // systems will see a hole in the UEFI memory map there.
+ //
+ SegmentCPages = 4;
+
+ ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
+ CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim);
+
+ //
+ // Fill in the VBE INFO structure.
+ //
+ VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
+ VbeInfo = &VbeInfoFull->Base;
+ Ptr = VbeInfoFull->Buffer;
+
+ CopyMem (VbeInfo->Signature, "VESA", 4);
+ VbeInfo->VesaVersion = 0x0200;
+
+ VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, "FBSD", 5);
+ Ptr += 5;
+
+ VbeInfo->Capabilities = BIT1 | BIT0; // DAC can be switched into 8-bit mode
+
+ VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ for (i = 0; i < NUM_VBE_MODES; i ++) {
+ *(UINT16*)Ptr = vbeModeIds[i]; // mode number
+ Ptr += 2;
+ }
+ *(UINT16*)Ptr = 0xFFFF; // mode list terminator
+ Ptr += 2;
+
+ VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
+ VbeInfo->OemSoftwareVersion = 0x0200;
+
+ VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, "FBSD", 5);
+ Ptr += 5;
+
+ VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ Printed = AsciiSPrint ((CHAR8 *)Ptr,
+ sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer), "%s",
+ CardName);
+ Ptr += Printed + 1;
+
+ VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)((UINTN)Ptr-SegmentC);
+ CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
+ Ptr += sizeof mProductRevision;
+
+ ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
+ ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
+
+ //
+ // Fill in the VBE MODE INFO structure list
+ //
+ VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
+ Ptr = (UINT8 *)VbeModeInfo;
+ for (i = 0; i < NUM_VBE_MODES; i++) {
+ vbeModes[i].LfbAddress = (UINT32)FrameBufferBase;
+ CopyMem (Ptr, &vbeModes[i], 0x32);
+ Ptr += 0x32;
+ }
+
+ ZeroMem (Ptr, 56); // Clear remaining bytes
+
+ //
+ // Clear Write Enable (bit1), keep Read Enable (bit0) set
+ //
+ PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0);
+
+ //
+ // Second, point the Int10h vector at the shim.
+ //
+ Int0x10->Segment = (UINT16) ((UINT32)SegmentC >> 4);
+ Int0x10->Offset = (UINT16) ((UINTN) (VbeModeInfo + 1) - SegmentC);
+
+ DEBUG ((DEBUG_INFO, "%a: VBE shim installed to %x:%x\n",
+ __FUNCTION__, Int0x10->Segment, Int0x10->Offset));
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h
new file mode 100644
index 00000000000..1d2aeae4267
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.h
@@ -0,0 +1,912 @@
+//
+// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
+//
+#ifndef _VBE_SHIM_H_
+#define _VBE_SHIM_H_
+STATIC CONST UINT8 mVbeShim[] = {
+ /* 00000000 nop */ 0x90,
+ /* 00000001 nop */ 0x90,
+ /* 00000002 nop */ 0x90,
+ /* 00000003 nop */ 0x90,
+ /* 00000004 nop */ 0x90,
+ /* 00000005 nop */ 0x90,
+ /* 00000006 nop */ 0x90,
+ /* 00000007 nop */ 0x90,
+ /* 00000008 nop */ 0x90,
+ /* 00000009 nop */ 0x90,
+ /* 0000000A nop */ 0x90,
+ /* 0000000B nop */ 0x90,
+ /* 0000000C nop */ 0x90,
+ /* 0000000D nop */ 0x90,
+ /* 0000000E nop */ 0x90,
+ /* 0000000F nop */ 0x90,
+ /* 00000010 nop */ 0x90,
+ /* 00000011 nop */ 0x90,
+ /* 00000012 nop */ 0x90,
+ /* 00000013 nop */ 0x90,
+ /* 00000014 nop */ 0x90,
+ /* 00000015 nop */ 0x90,
+ /* 00000016 nop */ 0x90,
+ /* 00000017 nop */ 0x90,
+ /* 00000018 nop */ 0x90,
+ /* 00000019 nop */ 0x90,
+ /* 0000001A nop */ 0x90,
+ /* 0000001B nop */ 0x90,
+ /* 0000001C nop */ 0x90,
+ /* 0000001D nop */ 0x90,
+ /* 0000001E nop */ 0x90,
+ /* 0000001F nop */ 0x90,
+ /* 00000020 nop */ 0x90,
+ /* 00000021 nop */ 0x90,
+ /* 00000022 nop */ 0x90,
+ /* 00000023 nop */ 0x90,
+ /* 00000024 nop */ 0x90,
+ /* 00000025 nop */ 0x90,
+ /* 00000026 nop */ 0x90,
+ /* 00000027 nop */ 0x90,
+ /* 00000028 nop */ 0x90,
+ /* 00000029 nop */ 0x90,
+ /* 0000002A nop */ 0x90,
+ /* 0000002B nop */ 0x90,
+ /* 0000002C nop */ 0x90,
+ /* 0000002D nop */ 0x90,
+ /* 0000002E nop */ 0x90,
+ /* 0000002F nop */ 0x90,
+ /* 00000030 nop */ 0x90,
+ /* 00000031 nop */ 0x90,
+ /* 00000032 nop */ 0x90,
+ /* 00000033 nop */ 0x90,
+ /* 00000034 nop */ 0x90,
+ /* 00000035 nop */ 0x90,
+ /* 00000036 nop */ 0x90,
+ /* 00000037 nop */ 0x90,
+ /* 00000038 nop */ 0x90,
+ /* 00000039 nop */ 0x90,
+ /* 0000003A nop */ 0x90,
+ /* 0000003B nop */ 0x90,
+ /* 0000003C nop */ 0x90,
+ /* 0000003D nop */ 0x90,
+ /* 0000003E nop */ 0x90,
+ /* 0000003F nop */ 0x90,
+ /* 00000040 nop */ 0x90,
+ /* 00000041 nop */ 0x90,
+ /* 00000042 nop */ 0x90,
+ /* 00000043 nop */ 0x90,
+ /* 00000044 nop */ 0x90,
+ /* 00000045 nop */ 0x90,
+ /* 00000046 nop */ 0x90,
+ /* 00000047 nop */ 0x90,
+ /* 00000048 nop */ 0x90,
+ /* 00000049 nop */ 0x90,
+ /* 0000004A nop */ 0x90,
+ /* 0000004B nop */ 0x90,
+ /* 0000004C nop */ 0x90,
+ /* 0000004D nop */ 0x90,
+ /* 0000004E nop */ 0x90,
+ /* 0000004F nop */ 0x90,
+ /* 00000050 nop */ 0x90,
+ /* 00000051 nop */ 0x90,
+ /* 00000052 nop */ 0x90,
+ /* 00000053 nop */ 0x90,
+ /* 00000054 nop */ 0x90,
+ /* 00000055 nop */ 0x90,
+ /* 00000056 nop */ 0x90,
+ /* 00000057 nop */ 0x90,
+ /* 00000058 nop */ 0x90,
+ /* 00000059 nop */ 0x90,
+ /* 0000005A nop */ 0x90,
+ /* 0000005B nop */ 0x90,
+ /* 0000005C nop */ 0x90,
+ /* 0000005D nop */ 0x90,
+ /* 0000005E nop */ 0x90,
+ /* 0000005F nop */ 0x90,
+ /* 00000060 nop */ 0x90,
+ /* 00000061 nop */ 0x90,
+ /* 00000062 nop */ 0x90,
+ /* 00000063 nop */ 0x90,
+ /* 00000064 nop */ 0x90,
+ /* 00000065 nop */ 0x90,
+ /* 00000066 nop */ 0x90,
+ /* 00000067 nop */ 0x90,
+ /* 00000068 nop */ 0x90,
+ /* 00000069 nop */ 0x90,
+ /* 0000006A nop */ 0x90,
+ /* 0000006B nop */ 0x90,
+ /* 0000006C nop */ 0x90,
+ /* 0000006D nop */ 0x90,
+ /* 0000006E nop */ 0x90,
+ /* 0000006F nop */ 0x90,
+ /* 00000070 nop */ 0x90,
+ /* 00000071 nop */ 0x90,
+ /* 00000072 nop */ 0x90,
+ /* 00000073 nop */ 0x90,
+ /* 00000074 nop */ 0x90,
+ /* 00000075 nop */ 0x90,
+ /* 00000076 nop */ 0x90,
+ /* 00000077 nop */ 0x90,
+ /* 00000078 nop */ 0x90,
+ /* 00000079 nop */ 0x90,
+ /* 0000007A nop */ 0x90,
+ /* 0000007B nop */ 0x90,
+ /* 0000007C nop */ 0x90,
+ /* 0000007D nop */ 0x90,
+ /* 0000007E nop */ 0x90,
+ /* 0000007F nop */ 0x90,
+ /* 00000080 nop */ 0x90,
+ /* 00000081 nop */ 0x90,
+ /* 00000082 nop */ 0x90,
+ /* 00000083 nop */ 0x90,
+ /* 00000084 nop */ 0x90,
+ /* 00000085 nop */ 0x90,
+ /* 00000086 nop */ 0x90,
+ /* 00000087 nop */ 0x90,
+ /* 00000088 nop */ 0x90,
+ /* 00000089 nop */ 0x90,
+ /* 0000008A nop */ 0x90,
+ /* 0000008B nop */ 0x90,
+ /* 0000008C nop */ 0x90,
+ /* 0000008D nop */ 0x90,
+ /* 0000008E nop */ 0x90,
+ /* 0000008F nop */ 0x90,
+ /* 00000090 nop */ 0x90,
+ /* 00000091 nop */ 0x90,
+ /* 00000092 nop */ 0x90,
+ /* 00000093 nop */ 0x90,
+ /* 00000094 nop */ 0x90,
+ /* 00000095 nop */ 0x90,
+ /* 00000096 nop */ 0x90,
+ /* 00000097 nop */ 0x90,
+ /* 00000098 nop */ 0x90,
+ /* 00000099 nop */ 0x90,
+ /* 0000009A nop */ 0x90,
+ /* 0000009B nop */ 0x90,
+ /* 0000009C nop */ 0x90,
+ /* 0000009D nop */ 0x90,
+ /* 0000009E nop */ 0x90,
+ /* 0000009F nop */ 0x90,
+ /* 000000A0 nop */ 0x90,
+ /* 000000A1 nop */ 0x90,
+ /* 000000A2 nop */ 0x90,
+ /* 000000A3 nop */ 0x90,
+ /* 000000A4 nop */ 0x90,
+ /* 000000A5 nop */ 0x90,
+ /* 000000A6 nop */ 0x90,
+ /* 000000A7 nop */ 0x90,
+ /* 000000A8 nop */ 0x90,
+ /* 000000A9 nop */ 0x90,
+ /* 000000AA nop */ 0x90,
+ /* 000000AB nop */ 0x90,
+ /* 000000AC nop */ 0x90,
+ /* 000000AD nop */ 0x90,
+ /* 000000AE nop */ 0x90,
+ /* 000000AF nop */ 0x90,
+ /* 000000B0 nop */ 0x90,
+ /* 000000B1 nop */ 0x90,
+ /* 000000B2 nop */ 0x90,
+ /* 000000B3 nop */ 0x90,
+ /* 000000B4 nop */ 0x90,
+ /* 000000B5 nop */ 0x90,
+ /* 000000B6 nop */ 0x90,
+ /* 000000B7 nop */ 0x90,
+ /* 000000B8 nop */ 0x90,
+ /* 000000B9 nop */ 0x90,
+ /* 000000BA nop */ 0x90,
+ /* 000000BB nop */ 0x90,
+ /* 000000BC nop */ 0x90,
+ /* 000000BD nop */ 0x90,
+ /* 000000BE nop */ 0x90,
+ /* 000000BF nop */ 0x90,
+ /* 000000C0 nop */ 0x90,
+ /* 000000C1 nop */ 0x90,
+ /* 000000C2 nop */ 0x90,
+ /* 000000C3 nop */ 0x90,
+ /* 000000C4 nop */ 0x90,
+ /* 000000C5 nop */ 0x90,
+ /* 000000C6 nop */ 0x90,
+ /* 000000C7 nop */ 0x90,
+ /* 000000C8 nop */ 0x90,
+ /* 000000C9 nop */ 0x90,
+ /* 000000CA nop */ 0x90,
+ /* 000000CB nop */ 0x90,
+ /* 000000CC nop */ 0x90,
+ /* 000000CD nop */ 0x90,
+ /* 000000CE nop */ 0x90,
+ /* 000000CF nop */ 0x90,
+ /* 000000D0 nop */ 0x90,
+ /* 000000D1 nop */ 0x90,
+ /* 000000D2 nop */ 0x90,
+ /* 000000D3 nop */ 0x90,
+ /* 000000D4 nop */ 0x90,
+ /* 000000D5 nop */ 0x90,
+ /* 000000D6 nop */ 0x90,
+ /* 000000D7 nop */ 0x90,
+ /* 000000D8 nop */ 0x90,
+ /* 000000D9 nop */ 0x90,
+ /* 000000DA nop */ 0x90,
+ /* 000000DB nop */ 0x90,
+ /* 000000DC nop */ 0x90,
+ /* 000000DD nop */ 0x90,
+ /* 000000DE nop */ 0x90,
+ /* 000000DF nop */ 0x90,
+ /* 000000E0 nop */ 0x90,
+ /* 000000E1 nop */ 0x90,
+ /* 000000E2 nop */ 0x90,
+ /* 000000E3 nop */ 0x90,
+ /* 000000E4 nop */ 0x90,
+ /* 000000E5 nop */ 0x90,
+ /* 000000E6 nop */ 0x90,
+ /* 000000E7 nop */ 0x90,
+ /* 000000E8 nop */ 0x90,
+ /* 000000E9 nop */ 0x90,
+ /* 000000EA nop */ 0x90,
+ /* 000000EB nop */ 0x90,
+ /* 000000EC nop */ 0x90,
+ /* 000000ED nop */ 0x90,
+ /* 000000EE nop */ 0x90,
+ /* 000000EF nop */ 0x90,
+ /* 000000F0 nop */ 0x90,
+ /* 000000F1 nop */ 0x90,
+ /* 000000F2 nop */ 0x90,
+ /* 000000F3 nop */ 0x90,
+ /* 000000F4 nop */ 0x90,
+ /* 000000F5 nop */ 0x90,
+ /* 000000F6 nop */ 0x90,
+ /* 000000F7 nop */ 0x90,
+ /* 000000F8 nop */ 0x90,
+ /* 000000F9 nop */ 0x90,
+ /* 000000FA nop */ 0x90,
+ /* 000000FB nop */ 0x90,
+ /* 000000FC nop */ 0x90,
+ /* 000000FD nop */ 0x90,
+ /* 000000FE nop */ 0x90,
+ /* 000000FF nop */ 0x90,
+ /* 00000100 nop */ 0x90,
+ /* 00000101 nop */ 0x90,
+ /* 00000102 nop */ 0x90,
+ /* 00000103 nop */ 0x90,
+ /* 00000104 nop */ 0x90,
+ /* 00000105 nop */ 0x90,
+ /* 00000106 nop */ 0x90,
+ /* 00000107 nop */ 0x90,
+ /* 00000108 nop */ 0x90,
+ /* 00000109 nop */ 0x90,
+ /* 0000010A nop */ 0x90,
+ /* 0000010B nop */ 0x90,
+ /* 0000010C nop */ 0x90,
+ /* 0000010D nop */ 0x90,
+ /* 0000010E nop */ 0x90,
+ /* 0000010F nop */ 0x90,
+ /* 00000110 nop */ 0x90,
+ /* 00000111 nop */ 0x90,
+ /* 00000112 nop */ 0x90,
+ /* 00000113 nop */ 0x90,
+ /* 00000114 nop */ 0x90,
+ /* 00000115 nop */ 0x90,
+ /* 00000116 nop */ 0x90,
+ /* 00000117 nop */ 0x90,
+ /* 00000118 nop */ 0x90,
+ /* 00000119 nop */ 0x90,
+ /* 0000011A nop */ 0x90,
+ /* 0000011B nop */ 0x90,
+ /* 0000011C nop */ 0x90,
+ /* 0000011D nop */ 0x90,
+ /* 0000011E nop */ 0x90,
+ /* 0000011F nop */ 0x90,
+ /* 00000120 nop */ 0x90,
+ /* 00000121 nop */ 0x90,
+ /* 00000122 nop */ 0x90,
+ /* 00000123 nop */ 0x90,
+ /* 00000124 nop */ 0x90,
+ /* 00000125 nop */ 0x90,
+ /* 00000126 nop */ 0x90,
+ /* 00000127 nop */ 0x90,
+ /* 00000128 nop */ 0x90,
+ /* 00000129 nop */ 0x90,
+ /* 0000012A nop */ 0x90,
+ /* 0000012B nop */ 0x90,
+ /* 0000012C nop */ 0x90,
+ /* 0000012D nop */ 0x90,
+ /* 0000012E nop */ 0x90,
+ /* 0000012F nop */ 0x90,
+ /* 00000130 nop */ 0x90,
+ /* 00000131 nop */ 0x90,
+ /* 00000132 nop */ 0x90,
+ /* 00000133 nop */ 0x90,
+ /* 00000134 nop */ 0x90,
+ /* 00000135 nop */ 0x90,
+ /* 00000136 nop */ 0x90,
+ /* 00000137 nop */ 0x90,
+ /* 00000138 nop */ 0x90,
+ /* 00000139 nop */ 0x90,
+ /* 0000013A nop */ 0x90,
+ /* 0000013B nop */ 0x90,
+ /* 0000013C nop */ 0x90,
+ /* 0000013D nop */ 0x90,
+ /* 0000013E nop */ 0x90,
+ /* 0000013F nop */ 0x90,
+ /* 00000140 nop */ 0x90,
+ /* 00000141 nop */ 0x90,
+ /* 00000142 nop */ 0x90,
+ /* 00000143 nop */ 0x90,
+ /* 00000144 nop */ 0x90,
+ /* 00000145 nop */ 0x90,
+ /* 00000146 nop */ 0x90,
+ /* 00000147 nop */ 0x90,
+ /* 00000148 nop */ 0x90,
+ /* 00000149 nop */ 0x90,
+ /* 0000014A nop */ 0x90,
+ /* 0000014B nop */ 0x90,
+ /* 0000014C nop */ 0x90,
+ /* 0000014D nop */ 0x90,
+ /* 0000014E nop */ 0x90,
+ /* 0000014F nop */ 0x90,
+ /* 00000150 nop */ 0x90,
+ /* 00000151 nop */ 0x90,
+ /* 00000152 nop */ 0x90,
+ /* 00000153 nop */ 0x90,
+ /* 00000154 nop */ 0x90,
+ /* 00000155 nop */ 0x90,
+ /* 00000156 nop */ 0x90,
+ /* 00000157 nop */ 0x90,
+ /* 00000158 nop */ 0x90,
+ /* 00000159 nop */ 0x90,
+ /* 0000015A nop */ 0x90,
+ /* 0000015B nop */ 0x90,
+ /* 0000015C nop */ 0x90,
+ /* 0000015D nop */ 0x90,
+ /* 0000015E nop */ 0x90,
+ /* 0000015F nop */ 0x90,
+ /* 00000160 nop */ 0x90,
+ /* 00000161 nop */ 0x90,
+ /* 00000162 nop */ 0x90,
+ /* 00000163 nop */ 0x90,
+ /* 00000164 nop */ 0x90,
+ /* 00000165 nop */ 0x90,
+ /* 00000166 nop */ 0x90,
+ /* 00000167 nop */ 0x90,
+ /* 00000168 nop */ 0x90,
+ /* 00000169 nop */ 0x90,
+ /* 0000016A nop */ 0x90,
+ /* 0000016B nop */ 0x90,
+ /* 0000016C nop */ 0x90,
+ /* 0000016D nop */ 0x90,
+ /* 0000016E nop */ 0x90,
+ /* 0000016F nop */ 0x90,
+ /* 00000170 nop */ 0x90,
+ /* 00000171 nop */ 0x90,
+ /* 00000172 nop */ 0x90,
+ /* 00000173 nop */ 0x90,
+ /* 00000174 nop */ 0x90,
+ /* 00000175 nop */ 0x90,
+ /* 00000176 nop */ 0x90,
+ /* 00000177 nop */ 0x90,
+ /* 00000178 nop */ 0x90,
+ /* 00000179 nop */ 0x90,
+ /* 0000017A nop */ 0x90,
+ /* 0000017B nop */ 0x90,
+ /* 0000017C nop */ 0x90,
+ /* 0000017D nop */ 0x90,
+ /* 0000017E nop */ 0x90,
+ /* 0000017F nop */ 0x90,
+ /* 00000180 nop */ 0x90,
+ /* 00000181 nop */ 0x90,
+ /* 00000182 nop */ 0x90,
+ /* 00000183 nop */ 0x90,
+ /* 00000184 nop */ 0x90,
+ /* 00000185 nop */ 0x90,
+ /* 00000186 nop */ 0x90,
+ /* 00000187 nop */ 0x90,
+ /* 00000188 nop */ 0x90,
+ /* 00000189 nop */ 0x90,
+ /* 0000018A nop */ 0x90,
+ /* 0000018B nop */ 0x90,
+ /* 0000018C nop */ 0x90,
+ /* 0000018D nop */ 0x90,
+ /* 0000018E nop */ 0x90,
+ /* 0000018F nop */ 0x90,
+ /* 00000190 nop */ 0x90,
+ /* 00000191 nop */ 0x90,
+ /* 00000192 nop */ 0x90,
+ /* 00000193 nop */ 0x90,
+ /* 00000194 nop */ 0x90,
+ /* 00000195 nop */ 0x90,
+ /* 00000196 nop */ 0x90,
+ /* 00000197 nop */ 0x90,
+ /* 00000198 nop */ 0x90,
+ /* 00000199 nop */ 0x90,
+ /* 0000019A nop */ 0x90,
+ /* 0000019B nop */ 0x90,
+ /* 0000019C nop */ 0x90,
+ /* 0000019D nop */ 0x90,
+ /* 0000019E nop */ 0x90,
+ /* 0000019F nop */ 0x90,
+ /* 000001A0 nop */ 0x90,
+ /* 000001A1 nop */ 0x90,
+ /* 000001A2 nop */ 0x90,
+ /* 000001A3 nop */ 0x90,
+ /* 000001A4 nop */ 0x90,
+ /* 000001A5 nop */ 0x90,
+ /* 000001A6 nop */ 0x90,
+ /* 000001A7 nop */ 0x90,
+ /* 000001A8 nop */ 0x90,
+ /* 000001A9 nop */ 0x90,
+ /* 000001AA nop */ 0x90,
+ /* 000001AB nop */ 0x90,
+ /* 000001AC nop */ 0x90,
+ /* 000001AD nop */ 0x90,
+ /* 000001AE nop */ 0x90,
+ /* 000001AF nop */ 0x90,
+ /* 000001B0 nop */ 0x90,
+ /* 000001B1 nop */ 0x90,
+ /* 000001B2 nop */ 0x90,
+ /* 000001B3 nop */ 0x90,
+ /* 000001B4 nop */ 0x90,
+ /* 000001B5 nop */ 0x90,
+ /* 000001B6 nop */ 0x90,
+ /* 000001B7 nop */ 0x90,
+ /* 000001B8 nop */ 0x90,
+ /* 000001B9 nop */ 0x90,
+ /* 000001BA nop */ 0x90,
+ /* 000001BB nop */ 0x90,
+ /* 000001BC nop */ 0x90,
+ /* 000001BD nop */ 0x90,
+ /* 000001BE nop */ 0x90,
+ /* 000001BF nop */ 0x90,
+ /* 000001C0 nop */ 0x90,
+ /* 000001C1 nop */ 0x90,
+ /* 000001C2 nop */ 0x90,
+ /* 000001C3 nop */ 0x90,
+ /* 000001C4 nop */ 0x90,
+ /* 000001C5 nop */ 0x90,
+ /* 000001C6 nop */ 0x90,
+ /* 000001C7 nop */ 0x90,
+ /* 000001C8 nop */ 0x90,
+ /* 000001C9 nop */ 0x90,
+ /* 000001CA nop */ 0x90,
+ /* 000001CB nop */ 0x90,
+ /* 000001CC nop */ 0x90,
+ /* 000001CD nop */ 0x90,
+ /* 000001CE nop */ 0x90,
+ /* 000001CF nop */ 0x90,
+ /* 000001D0 nop */ 0x90,
+ /* 000001D1 nop */ 0x90,
+ /* 000001D2 nop */ 0x90,
+ /* 000001D3 nop */ 0x90,
+ /* 000001D4 nop */ 0x90,
+ /* 000001D5 nop */ 0x90,
+ /* 000001D6 nop */ 0x90,
+ /* 000001D7 nop */ 0x90,
+ /* 000001D8 nop */ 0x90,
+ /* 000001D9 nop */ 0x90,
+ /* 000001DA nop */ 0x90,
+ /* 000001DB nop */ 0x90,
+ /* 000001DC nop */ 0x90,
+ /* 000001DD nop */ 0x90,
+ /* 000001DE nop */ 0x90,
+ /* 000001DF nop */ 0x90,
+ /* 000001E0 nop */ 0x90,
+ /* 000001E1 nop */ 0x90,
+ /* 000001E2 nop */ 0x90,
+ /* 000001E3 nop */ 0x90,
+ /* 000001E4 nop */ 0x90,
+ /* 000001E5 nop */ 0x90,
+ /* 000001E6 nop */ 0x90,
+ /* 000001E7 nop */ 0x90,
+ /* 000001E8 nop */ 0x90,
+ /* 000001E9 nop */ 0x90,
+ /* 000001EA nop */ 0x90,
+ /* 000001EB nop */ 0x90,
+ /* 000001EC nop */ 0x90,
+ /* 000001ED nop */ 0x90,
+ /* 000001EE nop */ 0x90,
+ /* 000001EF nop */ 0x90,
+ /* 000001F0 nop */ 0x90,
+ /* 000001F1 nop */ 0x90,
+ /* 000001F2 nop */ 0x90,
+ /* 000001F3 nop */ 0x90,
+ /* 000001F4 nop */ 0x90,
+ /* 000001F5 nop */ 0x90,
+ /* 000001F6 nop */ 0x90,
+ /* 000001F7 nop */ 0x90,
+ /* 000001F8 nop */ 0x90,
+ /* 000001F9 nop */ 0x90,
+ /* 000001FA nop */ 0x90,
+ /* 000001FB nop */ 0x90,
+ /* 000001FC nop */ 0x90,
+ /* 000001FD nop */ 0x90,
+ /* 000001FE nop */ 0x90,
+ /* 000001FF nop */ 0x90,
+ /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
+ /* 00000203 jz 0x237 */ 0x74, 0x32,
+ /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
+ /* 00000208 jz 0x257 */ 0x74, 0x4D,
+ /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
+ /* 0000020D jz word 0x2c8 */ 0x0F, 0x84, 0xB7, 0x00,
+ /* 00000211 cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
+ /* 00000214 jz word 0x325 */ 0x0F, 0x84, 0x0D, 0x01,
+ /* 00000218 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
+ /* 0000021B jz word 0x337 */ 0x0F, 0x84, 0x18, 0x01,
+ /* 0000021F cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
+ /* 00000222 jz word 0x344 */ 0x0F, 0x84, 0x1E, 0x01,
+ /* 00000226 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
+ /* 00000229 jz word 0x363 */ 0x0F, 0x84, 0x36, 0x01,
+ /* 0000022D push si */ 0x56,
+ /* 0000022E mov si,0x3d7 */ 0xBE, 0xD7, 0x03,
+ /* 00000231 call word 0x3ad */ 0xE8, 0x79, 0x01,
+ /* 00000234 pop si */ 0x5E,
+ /* 00000235 jmp short 0x235 */ 0xEB, 0xFE,
+ /* 00000237 push es */ 0x06,
+ /* 00000238 push di */ 0x57,
+ /* 00000239 push ds */ 0x1E,
+ /* 0000023A push si */ 0x56,
+ /* 0000023B push cx */ 0x51,
+ /* 0000023C push si */ 0x56,
+ /* 0000023D mov si,0x3eb */ 0xBE, 0xEB, 0x03,
+ /* 00000240 call word 0x3ad */ 0xE8, 0x6A, 0x01,
+ /* 00000243 pop si */ 0x5E,
+ /* 00000244 push cs */ 0x0E,
+ /* 00000245 pop ds */ 0x1F,
+ /* 00000246 mov si,0x0 */ 0xBE, 0x00, 0x00,
+ /* 00000249 mov cx,0x100 */ 0xB9, 0x00, 0x01,
+ /* 0000024C cld */ 0xFC,
+ /* 0000024D rep movsb */ 0xF3, 0xA4,
+ /* 0000024F pop cx */ 0x59,
+ /* 00000250 pop si */ 0x5E,
+ /* 00000251 pop ds */ 0x1F,
+ /* 00000252 pop di */ 0x5F,
+ /* 00000253 pop es */ 0x07,
+ /* 00000254 jmp word 0x395 */ 0xE9, 0x3E, 0x01,
+ /* 00000257 push es */ 0x06,
+ /* 00000258 push di */ 0x57,
+ /* 00000259 push ds */ 0x1E,
+ /* 0000025A push si */ 0x56,
+ /* 0000025B push cx */ 0x51,
+ /* 0000025C push si */ 0x56,
+ /* 0000025D mov si,0x3f6 */ 0xBE, 0xF6, 0x03,
+ /* 00000260 call word 0x3ad */ 0xE8, 0x4A, 0x01,
+ /* 00000263 pop si */ 0x5E,
+ /* 00000264 and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
+ /* 00000268 cmp cx,0x13f */ 0x81, 0xF9, 0x3F, 0x01,
+ /* 0000026C jz 0x284 */ 0x74, 0x16,
+ /* 0000026E cmp cx,0x140 */ 0x81, 0xF9, 0x40, 0x01,
+ /* 00000272 jz 0x291 */ 0x74, 0x1D,
+ /* 00000274 cmp cx,0x141 */ 0x81, 0xF9, 0x41, 0x01,
+ /* 00000278 jz 0x29e */ 0x74, 0x24,
+ /* 0000027A push si */ 0x56,
+ /* 0000027B mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 0000027E call word 0x3ad */ 0xE8, 0x2C, 0x01,
+ /* 00000281 pop si */ 0x5E,
+ /* 00000282 jmp short 0x235 */ 0xEB, 0xB1,
+ /* 00000284 push si */ 0x56,
+ /* 00000285 mov si,0x46b */ 0xBE, 0x6B, 0x04,
+ /* 00000288 call word 0x3ad */ 0xE8, 0x22, 0x01,
+ /* 0000028B pop si */ 0x5E,
+ /* 0000028C mov si,0x100 */ 0xBE, 0x00, 0x01,
+ /* 0000028F jmp short 0x2b8 */ 0xEB, 0x27,
+ /* 00000291 push si */ 0x56,
+ /* 00000292 mov si,0x47d */ 0xBE, 0x7D, 0x04,
+ /* 00000295 call word 0x3ad */ 0xE8, 0x15, 0x01,
+ /* 00000298 pop si */ 0x5E,
+ /* 00000299 mov si,0x132 */ 0xBE, 0x32, 0x01,
+ /* 0000029C jmp short 0x2b8 */ 0xEB, 0x1A,
+ /* 0000029E push si */ 0x56,
+ /* 0000029F mov si,0x48f */ 0xBE, 0x8F, 0x04,
+ /* 000002A2 call word 0x3ad */ 0xE8, 0x08, 0x01,
+ /* 000002A5 pop si */ 0x5E,
+ /* 000002A6 mov si,0x164 */ 0xBE, 0x64, 0x01,
+ /* 000002A9 jmp short 0x2b8 */ 0xEB, 0x0D,
+ /* 000002AB push si */ 0x56,
+ /* 000002AC mov si,0x4a2 */ 0xBE, 0xA2, 0x04,
+ /* 000002AF call word 0x3ad */ 0xE8, 0xFB, 0x00,
+ /* 000002B2 pop si */ 0x5E,
+ /* 000002B3 mov si,0x196 */ 0xBE, 0x96, 0x01,
+ /* 000002B6 jmp short 0x2b8 */ 0xEB, 0x00,
+ /* 000002B8 push cs */ 0x0E,
+ /* 000002B9 pop ds */ 0x1F,
+ /* 000002BA mov cx,0x32 */ 0xB9, 0x32, 0x00,
+ /* 000002BD cld */ 0xFC,
+ /* 000002BE rep movsb */ 0xF3, 0xA4,
+ /* 000002C0 pop cx */ 0x59,
+ /* 000002C1 pop si */ 0x5E,
+ /* 000002C2 pop ds */ 0x1F,
+ /* 000002C3 pop di */ 0x5F,
+ /* 000002C4 pop es */ 0x07,
+ /* 000002C5 jmp word 0x395 */ 0xE9, 0xCD, 0x00,
+ /* 000002C8 push dx */ 0x52,
+ /* 000002C9 push ax */ 0x50,
+ /* 000002CA push si */ 0x56,
+ /* 000002CB mov si,0x410 */ 0xBE, 0x10, 0x04,
+ /* 000002CE call word 0x3ad */ 0xE8, 0xDC, 0x00,
+ /* 000002D1 pop si */ 0x5E,
+ /* 000002D2 and bx,0xbfff */ 0x81, 0xE3, 0xFF, 0xBF,
+ /* 000002D6 cmp bx,0x13f */ 0x81, 0xFB, 0x3F, 0x01,
+ /* 000002DA jz 0x2f3 */ 0x74, 0x17,
+ /* 000002DC cmp bx,0x140 */ 0x81, 0xFB, 0x40, 0x01,
+ /* 000002E0 jz 0x2fd */ 0x74, 0x1B,
+ /* 000002E2 cmp bx,0x141 */ 0x81, 0xFB, 0x41, 0x01,
+ /* 000002E6 jz 0x307 */ 0x74, 0x1F,
+ /* 000002E8 push si */ 0x56,
+ /* 000002E9 mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 000002EC call word 0x3ad */ 0xE8, 0xBE, 0x00,
+ /* 000002EF pop si */ 0x5E,
+ /* 000002F0 jmp word 0x235 */ 0xE9, 0x42, 0xFF,
+ /* 000002F3 push si */ 0x56,
+ /* 000002F4 mov si,0x46b */ 0xBE, 0x6B, 0x04,
+ /* 000002F7 call word 0x3ad */ 0xE8, 0xB3, 0x00,
+ /* 000002FA pop si */ 0x5E,
+ /* 000002FB jmp short 0x319 */ 0xEB, 0x1C,
+ /* 000002FD push si */ 0x56,
+ /* 000002FE mov si,0x47d */ 0xBE, 0x7D, 0x04,
+ /* 00000301 call word 0x3ad */ 0xE8, 0xA9, 0x00,
+ /* 00000304 pop si */ 0x5E,
+ /* 00000305 jmp short 0x319 */ 0xEB, 0x12,
+ /* 00000307 push si */ 0x56,
+ /* 00000308 mov si,0x48f */ 0xBE, 0x8F, 0x04,
+ /* 0000030B call word 0x3ad */ 0xE8, 0x9F, 0x00,
+ /* 0000030E pop si */ 0x5E,
+ /* 0000030F jmp short 0x319 */ 0xEB, 0x08,
+ /* 00000311 push si */ 0x56,
+ /* 00000312 mov si,0x4a2 */ 0xBE, 0xA2, 0x04,
+ /* 00000315 call word 0x3ad */ 0xE8, 0x95, 0x00,
+ /* 00000318 pop si */ 0x5E,
+ /* 00000319 mov [0x4b0],bl */ 0x88, 0x1E, 0xB0, 0x04,
+ /* 0000031D mov [0x4b1],bh */ 0x88, 0x3E, 0xB1, 0x04,
+ /* 00000321 pop ax */ 0x58,
+ /* 00000322 pop dx */ 0x5A,
+ /* 00000323 jmp short 0x395 */ 0xEB, 0x70,
+ /* 00000325 push si */ 0x56,
+ /* 00000326 mov si,0x405 */ 0xBE, 0x05, 0x04,
+ /* 00000329 call word 0x3ad */ 0xE8, 0x81, 0x00,
+ /* 0000032C pop si */ 0x5E,
+ /* 0000032D mov bl,[0x4b0] */ 0x8A, 0x1E, 0xB0, 0x04,
+ /* 00000331 mov bh,[0x4b1] */ 0x8A, 0x3E, 0xB1, 0x04,
+ /* 00000335 jmp short 0x395 */ 0xEB, 0x5E,
+ /* 00000337 push si */ 0x56,
+ /* 00000338 mov si,0x43b */ 0xBE, 0x3B, 0x04,
+ /* 0000033B call word 0x3ad */ 0xE8, 0x6F, 0x00,
+ /* 0000033E pop si */ 0x5E,
+ /* 0000033F mov bx,0x80 */ 0xBB, 0x80, 0x00,
+ /* 00000342 jmp short 0x395 */ 0xEB, 0x51,
+ /* 00000344 push es */ 0x06,
+ /* 00000345 push di */ 0x57,
+ /* 00000346 push ds */ 0x1E,
+ /* 00000347 push si */ 0x56,
+ /* 00000348 push cx */ 0x51,
+ /* 00000349 push si */ 0x56,
+ /* 0000034A mov si,0x450 */ 0xBE, 0x50, 0x04,
+ /* 0000034D call word 0x3ad */ 0xE8, 0x5D, 0x00,
+ /* 00000350 pop si */ 0x5E,
+ /* 00000351 push cs */ 0x0E,
+ /* 00000352 pop ds */ 0x1F,
+ /* 00000353 mov si,0x4b2 */ 0xBE, 0xB2, 0x04,
+ /* 00000356 mov cx,0x80 */ 0xB9, 0x80, 0x00,
+ /* 00000359 cld */ 0xFC,
+ /* 0000035A rep movsb */ 0xF3, 0xA4,
+ /* 0000035C pop cx */ 0x59,
+ /* 0000035D pop si */ 0x5E,
+ /* 0000035E pop ds */ 0x1F,
+ /* 0000035F pop di */ 0x5F,
+ /* 00000360 pop es */ 0x07,
+ /* 00000361 jmp short 0x395 */ 0xEB, 0x32,
+ /* 00000363 push si */ 0x56,
+ /* 00000364 mov si,0x41b */ 0xBE, 0x1B, 0x04,
+ /* 00000367 call word 0x3ad */ 0xE8, 0x43, 0x00,
+ /* 0000036A pop si */ 0x5E,
+ /* 0000036B cmp al,0x3 */ 0x3C, 0x03,
+ /* 0000036D jz 0x37e */ 0x74, 0x0F,
+ /* 0000036F cmp al,0x12 */ 0x3C, 0x12,
+ /* 00000371 jz 0x38a */ 0x74, 0x17,
+ /* 00000373 push si */ 0x56,
+ /* 00000374 mov si,0x42c */ 0xBE, 0x2C, 0x04,
+ /* 00000377 call word 0x3ad */ 0xE8, 0x33, 0x00,
+ /* 0000037A pop si */ 0x5E,
+ /* 0000037B jmp word 0x235 */ 0xE9, 0xB7, 0xFE,
+ /* 0000037E push si */ 0x56,
+ /* 0000037F mov si,0x45c */ 0xBE, 0x5C, 0x04,
+ /* 00000382 call word 0x3ad */ 0xE8, 0x28, 0x00,
+ /* 00000385 pop si */ 0x5E,
+ /* 00000386 mov al,0x0 */ 0xB0, 0x00,
+ /* 00000388 jmp short 0x38c */ 0xEB, 0x02,
+ /* 0000038A mov al,0x0 */ 0xB0, 0x00,
+ /* 0000038C push si */ 0x56,
+ /* 0000038D mov si,0x3c2 */ 0xBE, 0xC2, 0x03,
+ /* 00000390 call word 0x3ad */ 0xE8, 0x1A, 0x00,
+ /* 00000393 pop si */ 0x5E,
+ /* 00000394 iretw */ 0xCF,
+ /* 00000395 push si */ 0x56,
+ /* 00000396 mov si,0x3c2 */ 0xBE, 0xC2, 0x03,
+ /* 00000399 call word 0x3ad */ 0xE8, 0x11, 0x00,
+ /* 0000039C pop si */ 0x5E,
+ /* 0000039D mov ax,0x4f */ 0xB8, 0x4F, 0x00,
+ /* 000003A0 iretw */ 0xCF,
+ /* 000003A1 push si */ 0x56,
+ /* 000003A2 mov si,0x3c8 */ 0xBE, 0xC8, 0x03,
+ /* 000003A5 call word 0x3ad */ 0xE8, 0x05, 0x00,
+ /* 000003A8 pop si */ 0x5E,
+ /* 000003A9 mov ax,0x24f */ 0xB8, 0x4F, 0x02,
+ /* 000003AC iretw */ 0xCF,
+ /* 000003AD pushaw */ 0x60,
+ /* 000003AE push ds */ 0x1E,
+ /* 000003AF push cs */ 0x0E,
+ /* 000003B0 pop ds */ 0x1F,
+ /* 000003B1 mov dx,0x220 */ 0xBA, 0x20, 0x02,
+ /* 000003B4 mov ax,0x0 */ 0xB8, 0x00, 0x00,
+ /* 000003B7 lodsb */ 0xAC,
+ /* 000003B8 cmp al,0x0 */ 0x3C, 0x00,
+ /* 000003BA jz 0x3bf */ 0x74, 0x03,
+ /* 000003BC out dx,al */ 0xEE,
+ /* 000003BD jmp short 0x3b7 */ 0xEB, 0xF8,
+ /* 000003BF pop ds */ 0x1F,
+ /* 000003C0 popaw */ 0x61,
+ /* 000003C1 ret */ 0xC3,
+ /* 000003C2 jna 0x413 */ 0x76, 0x4F,
+ /* 000003C4 imul cx,[di],byte +0xa */ 0x6B, 0x0D, 0x0A,
+ /* 000003C7 add [bp+0x55],dh */ 0x00, 0x76, 0x55,
+ /* 000003CA outsb */ 0x6E,
+ /* 000003CB jnc 0x442 */ 0x73, 0x75,
+ /* 000003CD jo 0x43f */ 0x70, 0x70,
+ /* 000003CF outsw */ 0x6F,
+ /* 000003D0 jc 0x446 */ 0x72, 0x74,
+ /* 000003D2 fs or ax,0xa */ 0x65, 0x64, 0x0D, 0x0A, 0x00,
+ /* 000003D7 jna 0x42e */ 0x76, 0x55,
+ /* 000003D9 outsb */ 0x6E,
+ /* 000003DA imul bp,[bp+0x6f],byte +0x77 */ 0x6B, 0x6E, 0x6F, 0x77,
+ /* 000003DE outsb */ 0x6E,
+ /* 000003DF and [bp+0x75],al */ 0x20, 0x46, 0x75,
+ /* 000003E2 outsb */ 0x6E,
+ /* 000003E3 arpl [si+0x69],si */ 0x63, 0x74, 0x69,
+ /* 000003E6 outsw */ 0x6F,
+ /* 000003E7 outsb */ 0x6E,
+ /* 000003E8 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 000003EB jna 0x434 */ 0x76, 0x47,
+ /* 000003ED gs jz 0x439 */ 0x65, 0x74, 0x49,
+ /* 000003F0 outsb */ 0x6E,
+ /* 000003F1 outsd */ 0x66, 0x6F,
+ /* 000003F3 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 000003F6 jna 0x43f */ 0x76, 0x47,
+ /* 000003F8 gs jz 0x448 */ 0x65, 0x74, 0x4D,
+ /* 000003FB outsw */ 0x6F,
+ /* 000003FC gs dec cx */ 0x64, 0x65, 0x49,
+ /* 000003FF outsb */ 0x6E,
+ /* 00000400 outsd */ 0x66, 0x6F,
+ /* 00000402 or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 00000405 jna 0x44e */ 0x76, 0x47,
+ /* 00000407 gs jz 0x457 */ 0x65, 0x74, 0x4D,
+ /* 0000040A outsw */ 0x6F,
+ /* 0000040B gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 00000410 jna 0x465 */ 0x76, 0x53,
+ /* 00000412 gs jz 0x462 */ 0x65, 0x74, 0x4D,
+ /* 00000415 outsw */ 0x6F,
+ /* 00000416 gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 0000041B jna 0x470 */ 0x76, 0x53,
+ /* 0000041D gs jz 0x46d */ 0x65, 0x74, 0x4D,
+ /* 00000420 outsw */ 0x6F,
+ /* 00000421 gs dec sp */ 0x64, 0x65, 0x4C,
+ /* 00000424 gs a32 popaw */ 0x65, 0x67, 0x61,
+ /* 00000427 arpl [bx+di+0xd],di */ 0x63, 0x79, 0x0D,
+ /* 0000042A or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000042C jna 0x483 */ 0x76, 0x55,
+ /* 0000042E outsb */ 0x6E,
+ /* 0000042F imul bp,[bx+0x77],byte +0x6e */ 0x6B, 0x6F, 0x77, 0x6E,
+ /* 00000433 and [di+0x6f],cl */ 0x20, 0x4D, 0x6F,
+ /* 00000436 gs or ax,0xa */ 0x64, 0x65, 0x0D, 0x0A, 0x00,
+ /* 0000043B jna 0x484 */ 0x76, 0x47,
+ /* 0000043D gs jz 0x490 */ 0x65, 0x74, 0x50,
+ /* 00000440 insw */ 0x6D,
+ /* 00000441 inc bx */ 0x43,
+ /* 00000442 popaw */ 0x61,
+ /* 00000443 jo 0x4a6 */ 0x70, 0x61,
+ /* 00000445 bound bp,[bx+di+0x6c] */ 0x62, 0x69, 0x6C,
+ /* 00000448 imul si,[si+0x69],word 0x7365 */ 0x69, 0x74, 0x69, 0x65, 0x73,
+ /* 0000044D or ax,0xa */ 0x0D, 0x0A, 0x00,
+ /* 00000450 jna 0x4a4 */ 0x76, 0x52,
+ /* 00000452 gs popaw */ 0x65, 0x61,
+ /* 00000454 fs inc bp */ 0x64, 0x45,
+ /* 00000456 imul sp,[fs:si+0xd],word 0xa */ 0x64, 0x69, 0x64, 0x0D, 0x0A, 0x00,
+ /* 0000045C jna 0x4aa */ 0x76, 0x4C,
+ /* 0000045E gs a32 popaw */ 0x65, 0x67, 0x61,
+ /* 00000461 arpl [bx+di+0x4d],di */ 0x63, 0x79, 0x4D,
+ /* 00000464 outsw */ 0x6F,
+ /* 00000465 xor cx,[gs:di] */ 0x64, 0x65, 0x33, 0x0D,
+ /* 00000469 or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000046B insw */ 0x6D,
+ /* 0000046C outsw */ 0x6F,
+ /* 0000046D gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000470 ss xor al,0x30 */ 0x36, 0x34, 0x30,
+ /* 00000473 js 0x4a9 */ 0x78, 0x34,
+ /* 00000475 cmp [bx+si],dh */ 0x38, 0x30,
+ /* 00000477 js 0x4ac */ 0x78, 0x33,
+ /* 00000479 xor cl,[di] */ 0x32, 0x0D,
+ /* 0000047B or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000047D insw */ 0x6D,
+ /* 0000047E outsw */ 0x6F,
+ /* 0000047F gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000482 cmp [bx+si],dh */ 0x38, 0x30,
+ /* 00000484 xor [bx+si+0x36],bh */ 0x30, 0x78, 0x36,
+ /* 00000487 xor [bx+si],dh */ 0x30, 0x30,
+ /* 00000489 js 0x4be */ 0x78, 0x33,
+ /* 0000048B xor cl,[di] */ 0x32, 0x0D,
+ /* 0000048D or al,[bx+si] */ 0x0A, 0x00,
+ /* 0000048F insw */ 0x6D,
+ /* 00000490 outsw */ 0x6F,
+ /* 00000491 gs pop di */ 0x64, 0x65, 0x5F,
+ /* 00000494 xor [bx+si],si */ 0x31, 0x30,
+ /* 00000496 xor dh,[si] */ 0x32, 0x34,
+ /* 00000498 js 0x4d1 */ 0x78, 0x37,
+ /* 0000049A cmp [ss:bx+si+0x33],bh */ 0x36, 0x38, 0x78, 0x33,
+ /* 0000049E xor cl,[di] */ 0x32, 0x0D,
+ /* 000004A0 or al,[bx+si] */ 0x0A, 0x00,
+ /* 000004A2 insw */ 0x6D,
+ /* 000004A3 outsw */ 0x6F,
+ /* 000004A4 gs pop di */ 0x64, 0x65, 0x5F,
+ /* 000004A7 jnz 0x517 */ 0x75, 0x6E,
+ /* 000004A9 jnz 0x51e */ 0x75, 0x73,
+ /* 000004AB fs or ax,0xa */ 0x65, 0x64, 0x0D, 0x0A, 0x00,
+ /* 000004B0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004B8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004BA add [bx+si],al */ 0x00, 0x00,
+ /* 000004BC add [bx+si],al */ 0x00, 0x00,
+ /* 000004BE add [bx+si],al */ 0x00, 0x00,
+ /* 000004C0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004C8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004CA add [bx+si],al */ 0x00, 0x00,
+ /* 000004CC add [bx+si],al */ 0x00, 0x00,
+ /* 000004CE add [bx+si],al */ 0x00, 0x00,
+ /* 000004D0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004D8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004DA add [bx+si],al */ 0x00, 0x00,
+ /* 000004DC add [bx+si],al */ 0x00, 0x00,
+ /* 000004DE add [bx+si],al */ 0x00, 0x00,
+ /* 000004E0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004E8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004EA add [bx+si],al */ 0x00, 0x00,
+ /* 000004EC add [bx+si],al */ 0x00, 0x00,
+ /* 000004EE add [bx+si],al */ 0x00, 0x00,
+ /* 000004F0 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F2 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F4 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F6 add [bx+si],al */ 0x00, 0x00,
+ /* 000004F8 add [bx+si],al */ 0x00, 0x00,
+ /* 000004FA add [bx+si],al */ 0x00, 0x00,
+ /* 000004FC add [bx+si],al */ 0x00, 0x00,
+ /* 000004FE add [bx+si],al */ 0x00, 0x00,
+ /* 00000500 add [bx+si],al */ 0x00, 0x00,
+ /* 00000502 add [bx+si],al */ 0x00, 0x00,
+ /* 00000504 add [bx+si],al */ 0x00, 0x00,
+ /* 00000506 add [bx+si],al */ 0x00, 0x00,
+ /* 00000508 add [bx+si],al */ 0x00, 0x00,
+ /* 0000050A add [bx+si],al */ 0x00, 0x00,
+ /* 0000050C add [bx+si],al */ 0x00, 0x00,
+ /* 0000050E add [bx+si],al */ 0x00, 0x00,
+ /* 00000510 add [bx+si],al */ 0x00, 0x00,
+ /* 00000512 add [bx+si],al */ 0x00, 0x00,
+ /* 00000514 add [bx+si],al */ 0x00, 0x00,
+ /* 00000516 add [bx+si],al */ 0x00, 0x00,
+ /* 00000518 add [bx+si],al */ 0x00, 0x00,
+ /* 0000051A add [bx+si],al */ 0x00, 0x00,
+ /* 0000051C add [bx+si],al */ 0x00, 0x00,
+ /* 0000051E add [bx+si],al */ 0x00, 0x00,
+ /* 00000520 add [bx+si],al */ 0x00, 0x00,
+ /* 00000522 add [bx+si],al */ 0x00, 0x00,
+ /* 00000524 add [bx+si],al */ 0x00, 0x00,
+ /* 00000526 add [bx+si],al */ 0x00, 0x00,
+ /* 00000528 add [bx+si],al */ 0x00, 0x00,
+ /* 0000052A add [bx+si],al */ 0x00, 0x00,
+ /* 0000052C add [bx+si],al */ 0x00, 0x00,
+ /* 0000052E add [bx+si],al */ 0x00, 0x00,
+ /* 00000530 add [bx+si],al */ 0x00, 0x00,
+ /* 00000532 add [bx+si],al */ 0x00, 0x00,
+};
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh
new file mode 100644
index 00000000000..5d65053582f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveRfbDxe/VbeShim.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+###
+# @file
+# Shell script to assemble and dump the fake Int10h handler from NASM source to
+# a C array.
+#
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+###
+
+set -e -u
+
+STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
+
+#
+# Install exit handler -- remove temporary files.
+#
+exit_handler()
+{
+ rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
+ "$STEM".bytes
+}
+trap exit_handler EXIT
+
+#
+# Assemble the source file.
+#
+nasm -o "$STEM".bin -- "$STEM".asm
+
+#
+# Disassemble it, in order to get a binary dump associated with the source.
+# (ndisasm doesn't recognize the "--" end-of-options delimiter.)
+#
+ndisasm "$STEM".bin >"$STEM".disasm
+
+#
+# Create three files, each with one column of the disassembly.
+#
+# The first column contains the offsets, and it starts the comment.
+#
+cut -c 1-8 -- "$STEM".disasm \
+| sed -e 's,^, /* ,' >"$STEM".offsets
+
+#
+# The second column contains the assembly-language instructions, and it closes
+# the comment. We first pad it to 30 characters.
+#
+cut -c 29- -- "$STEM".disasm \
+| sed -e 's,$, ,' \
+ -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
+
+#
+# The third column contains the bytes corresponding to the instruction,
+# represented as C integer constants. First strip trailing whitespace from the
+# middle column of the input disassembly, then process pairs of nibbles.
+#
+cut -c 11-28 -- "$STEM".disasm \
+| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' | sed 's/0x ,//g' >"$STEM".bytes
+
+#
+# Write the output file, recombining the columns. The output should have CRLF
+# line endings.
+#
+{
+ printf '//\n'
+ printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
+ "$(basename -- "$0")"
+ printf '//\n'
+ printf '#ifndef _VBE_SHIM_H_\n'
+ printf '#define _VBE_SHIM_H_\n'
+ printf 'STATIC CONST UINT8 mVbeShim[] = {\n'
+ paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
+ printf '};\n'
+ printf '#endif\n'
+} \
+| unix2dos >"$STEM".h
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.dsc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.dsc
new file mode 100644
index 00000000000..a7a953684ad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -0,0 +1,864 @@
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+#
+# Defines Section - statements that will be processed to create a Makefile.
+#
+################################################################################
+[Defines]
+ PLATFORM_NAME = Bhyve
+ PLATFORM_GUID = 562b76ee-ceb2-4f4f-adfe-a4c8dc46e4ff
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 1.30
+ OUTPUT_DIRECTORY = Build/BhyveX64
+ SUPPORTED_ARCHITECTURES = X64
+ BUILD_TARGETS = NOOPT|DEBUG|RELEASE
+ SKUID_IDENTIFIER = DEFAULT
+ FLASH_DEFINITION = OvmfPkg/Bhyve/BhyveX64.fdf
+
+ #
+ # Defines for default states. These can be changed on the command line.
+ # -D FLAG=VALUE
+ #
+ DEFINE SECURE_BOOT_ENABLE = FALSE
+ DEFINE SMM_REQUIRE = FALSE
+ DEFINE SOURCE_DEBUG_ENABLE = FALSE
+ DEFINE TPM_ENABLE = FALSE
+ DEFINE TPM_CONFIG_ENABLE = FALSE
+
+ #
+ # Network definition
+ #
+ DEFINE NETWORK_TLS_ENABLE = FALSE
+ DEFINE NETWORK_IP6_ENABLE = FALSE
+ DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
+ DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = TRUE
+
+!include NetworkPkg/NetworkDefines.dsc.inc
+
+ #
+ # Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
+ # one of the supported values, in place of any of the convenience macros, is
+ # permitted.
+ #
+!ifdef $(FD_SIZE_1MB)
+ DEFINE FD_SIZE_IN_KB = 1024
+!else
+!ifdef $(FD_SIZE_2MB)
+ DEFINE FD_SIZE_IN_KB = 2048
+!else
+!ifdef $(FD_SIZE_4MB)
+ DEFINE FD_SIZE_IN_KB = 4096
+!else
+ DEFINE FD_SIZE_IN_KB = 4096
+!endif
+!endif
+!endif
+
+[BuildOptions]
+ GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
+ INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+ MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(TOOL_CHAIN_TAG) != "CLANGPDB"
+ GCC:*_*_*_CC_FLAGS = -mno-mmx -mno-sse
+!endif
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ MSFT:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+ GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+ INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
+!endif
+ RELEASE_*_*_GENFW_FLAGS = --zero
+
+ #
+ # Disable deprecated APIs.
+ #
+ MSFT:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
+ INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
+ GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+
+!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.
+#
+################################################################################
+[SkuIds]
+ 0|DEFAULT
+
+################################################################################
+#
+# Library Class section - list of all Library Classes needed by this Platform.
+#
+################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLibBhyve.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
+ SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
+ BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
+ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
+ PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+ PciCapLib|OvmfPkg/Library/BasePciCapLib/BasePciCapLib.inf
+ PciCapPciSegmentLib|OvmfPkg/Library/BasePciCapPciSegmentLib/BasePciCapPciSegmentLib.inf
+ PciCapPciIoLib|OvmfPkg/Library/UefiPciCapPciIoLib/UefiPciCapPciIoLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
+ MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+ NvVarsFileLib|OvmfPkg/Library/NvVarsFileLib/NvVarsFileLib.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+ SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
+ SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
+ QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibNull.inf
+ QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/BaseQemuFwCfgS3LibNull.inf
+ BhyveFwCtlLib|OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
+ VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
+
+ CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
+ FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
+ DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
+!else
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
+ DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+!endif
+
+ ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibBhyve.inf
+ LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+
+ IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+!if $(NETWORK_TLS_ENABLE) == TRUE
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
+!else
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+!endif
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ PlatformSecureLib|OvmfPkg/Bhyve/Library/PlatformSecureLib/PlatformSecureLib.inf
+ AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+!else
+ AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
+!endif
+ VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
+
+ #
+ # Network libraries
+ #
+!include NetworkPkg/NetworkLibs.dsc.inc
+
+!if $(NETWORK_TLS_ENABLE) == TRUE
+ TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
+!endif
+
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+ S3BootScriptLib|MdeModulePkg/Library/PiDxeS3BootScriptLib/DxeS3BootScriptLib.inf
+ SmbusLib|MdePkg/Library/BaseSmbusLibNull/BaseSmbusLibNull.inf
+ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
+ XenPlatformLib|OvmfPkg/Library/XenPlatformLib/XenPlatformLib.inf
+
+
+!if $(TPM_ENABLE) == TRUE
+ Tpm2CommandLib|SecurityPkg/Library/Tpm2CommandLib/Tpm2CommandLib.inf
+ Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibQemu/DxeTcg2PhysicalPresenceLib.inf
+ Tcg2PpVendorLib|SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
+ TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
+!else
+ Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf
+ TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+!endif
+
+[LibraryClasses.common]
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+
+[LibraryClasses.common.SEC]
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPort.inf
+!endif
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/BaseExtractGuidedSectionLib/BaseExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+
+[LibraryClasses.common.PEI_CORE]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
+ PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+ MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ ResourcePublicationLib|MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+ ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+
+!if $(TPM_ENABLE) == TRUE
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
+!endif
+
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+
+[LibraryClasses.common.DXE_CORE]
+ HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+
+[LibraryClasses.common.DXE_RUNTIME_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+
+[LibraryClasses.common.UEFI_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.DXE_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PlatformBootManagerLib|OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformBootManagerLibBhyve.inf
+ PlatformBmPrintScLib|OvmfPkg/Library/PlatformBmPrintScLib/PlatformBmPrintScLib.inf
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxDxeLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
+!endif
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+ MpInitLib|UefiCpuPkg/Library/MpInitLibUp/MpInitLibUp.inf
+!if $(TPM_ENABLE) == TRUE
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
+!endif
+
+[LibraryClasses.common.UEFI_APPLICATION]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.DXE_SMM_DRIVER]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+ MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
+ SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SmmDebugAgentLib.inf
+!endif
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+[LibraryClasses.common.SMM_CORE]
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ SmmCorePlatformHookLib|MdeModulePkg/Library/SmmCorePlatformHookLibNull/SmmCorePlatformHookLibNull.inf
+ MemoryAllocationLib|MdeModulePkg/Library/PiSmmCoreMemoryAllocationLib/PiSmmCoreMemoryAllocationLib.inf
+ ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
+ HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
+ SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
+ SmmServicesTableLib|MdeModulePkg/Library/PiSmmCoreSmmServicesTableLib/PiSmmCoreSmmServicesTableLib.inf
+!ifdef $(DEBUG_ON_SERIAL_PORT)
+ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
+!else
+ DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformDebugLibIoPort.inf
+!endif
+ PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
+
+################################################################################
+#
+# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
+#
+################################################################################
+[PcdsFeatureFlag]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdInstallAcpiSdtProtocol|TRUE
+
+[PcdsFixedAtBuild]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
+ gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
+!if $(NETWORK_TLS_ENABLE) == FALSE
+ # match PcdFlashNvStorageVariableSize purely for convenience
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0xe000
+!endif
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x8400
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x8400
+!if $(NETWORK_TLS_ENABLE) == FALSE
+ # match PcdFlashNvStorageVariableSize purely for convenience
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x40000
+!endif
+!endif
+!if $(NETWORK_TLS_ENABLE) == TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x80000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVolatileVariableSize|0x40000
+!endif
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+
+ gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
+
+ # DEBUG_INIT 0x00000001 // Initialization
+ # DEBUG_WARN 0x00000002 // Warnings
+ # DEBUG_LOAD 0x00000004 // Load events
+ # DEBUG_FS 0x00000008 // EFI File system
+ # DEBUG_POOL 0x00000010 // Alloc & Free (pool)
+ # DEBUG_PAGE 0x00000020 // Alloc & Free (page)
+ # DEBUG_INFO 0x00000040 // Informational debug messages
+ # DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers
+ # DEBUG_VARIABLE 0x00000100 // Variable
+ # DEBUG_BM 0x00000400 // Boot Manager
+ # DEBUG_BLKIO 0x00001000 // BlkIo Driver
+ # DEBUG_NET 0x00004000 // SNP Driver
+ # DEBUG_UNDI 0x00010000 // UNDI Driver
+ # DEBUG_LOADFILE 0x00020000 // LoadFile
+ # DEBUG_EVENT 0x00080000 // Event messages
+ # DEBUG_GCD 0x00100000 // Global Coherency Database changes
+ # DEBUG_CACHE 0x00200000 // Memory range cachability changes
+ # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may
+ # // significantly impact boot performance
+ # DEBUG_ERROR 0x80000000 // Error
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+!else
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+!endif
+
+ # This PCD is used to set the base address of the PCI express hierarchy. It
+ # is only consulted when OVMF runs on Q35. In that case it is programmed into
+ # the PCIEXBAR register.
+ #
+ # On Q35 machine types that QEMU intends to support in the long term, QEMU
+ # never lets the RAM below 4 GB exceed 2816 MB.
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0xB0000000
+
+!if $(SOURCE_DEBUG_ENABLE) == TRUE
+ gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
+!endif
+
+ #
+ # Network Pcds
+ #
+!include NetworkPkg/NetworkPcds.dsc.inc
+
+ # Point to the MdeModulePkg/Application/UiApp/UiApp.inf
+ gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConInConnectOnDemand|FALSE
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVendor|L"BHYVE"
+ gUefiOvmfPkgTokenSpaceGuid.PcdDebugIoPort|0x2F8
+
+################################################################################
+#
+# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
+#
+################################################################################
+
+[PcdsDynamicDefault]
+ # only set when
+ # ($(SMM_REQUIRE) == FALSE)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|800
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|600
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable|FALSE
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId|0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x800000000
+
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
+
+ # Set video resolution for text setup.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|640
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|480
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosVersion|0x0208
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSmbiosDocRev|0x0
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated|FALSE
+
+ # Noexec settings for DXE.
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE
+
+ # UefiCpuPkg PCDs related to initial AP bringup and general AP management.
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000
+
+ # Set memory encryption mask
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy|0x00
+
+!if $(TPM_ENABLE) == TRUE
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+!endif
+
+ # MdeModulePkg resolution sets up the system display resolution
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|0
+
+[PcdsDynamicHii]
+!if $(TPM_ENABLE) == TRUE && $(TPM_CONFIG_ENABLE) == TRUE
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x0|"1.3"|NV,BS
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev|L"TCG2_VERSION"|gTcg2ConfigFormSetGuid|0x8|3|NV,BS
+!endif
+
+################################################################################
+#
+# Components Section - list of all EDK II Modules needed by this Platform.
+#
+################################################################################
+[Components]
+ OvmfPkg/Bhyve/ResetVector/ResetVector.inf
+
+ #
+ # SEC Phase modules
+ #
+ OvmfPkg/Sec/SecMain.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ #
+ # PEI Phase modules
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+
+ OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
+ UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf {
+ <LibraryClasses>
+ }
+
+!if $(TPM_ENABLE) == TRUE
+ OvmfPkg/Bhyve/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+ SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
+ <LibraryClasses>
+ HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterPei.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
+ }
+!endif
+
+ #
+ # DXE Phase modules
+ #
+ MdeModulePkg/Core/Dxe/DxeMain.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ }
+
+ MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+ MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+
+ MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+
+ MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf {
+ <LibraryClasses>
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf
+!endif
+!if $(TPM_ENABLE) == TRUE
+ NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf
+!endif
+ }
+
+ MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+ UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+ UefiCpuPkg/CpuDxe/CpuDxe.inf
+ PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+ OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
+ OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
+ MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
+ <LibraryClasses>
+ PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
+ NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
+ }
+ MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+ MdeModulePkg/Universal/Metronome/Metronome.inf
+ PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+ MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+ MdeModulePkg/Universal/BdsDxe/BdsDxe.inf {
+ <LibraryClasses>
+!ifdef $(CSM_ENABLE)
+ NULL|OvmfPkg/Bhyve/Csm/CsmSupportLib/CsmSupportLib.inf
+ NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf
+!endif
+ }
+ MdeModulePkg/Logo/LogoDxe.inf
+ MdeModulePkg/Application/UiApp/UiApp.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
+ NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
+!ifdef $(CSM_ENABLE)
+ NULL|OvmfPkg/Csm/LegacyBootManagerLib/LegacyBootManagerLib.inf
+ NULL|OvmfPkg/Csm/LegacyBootMaintUiLib/LegacyBootMaintUiLib.inf
+!endif
+ }
+ OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+ OvmfPkg/Virtio10Dxe/Virtio10.inf
+ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+ OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+ OvmfPkg/VirtioRngDxe/VirtioRng.inf
+ MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+ MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+ MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+ MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+ MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+ MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+ MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf {
+ <LibraryClasses>
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+ MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+ MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+ MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+ MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+ FatPkg/EnhancedFatDxe/Fat.inf
+ MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+ MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+ OvmfPkg/SataControllerDxe/SataControllerDxe.inf
+ MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+ MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+ MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+ MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+ MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+ OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf {
+ <LibraryClasses>
+ BltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+
+ #
+ # ISA Support
+ #
+ OvmfPkg/SioBusDxe/SioBusDxe.inf
+ MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+ MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+ MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+
+ #
+ # SMBIOS Support
+ #
+ MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+ OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+ #
+ # ACPI Support
+ #
+ MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+ OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
+ OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
+ MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+ MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+ MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+
+ #
+ # Network Support
+ #
+!include NetworkPkg/NetworkComponents.dsc.inc
+
+!if $(NETWORK_TLS_ENABLE) == TRUE
+ NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf {
+ <LibraryClasses>
+ NULL|OvmfPkg/Bhyve/Library/TlsAuthConfigLib/TlsAuthConfigLib.inf
+ }
+!endif
+ OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+!ifdef $(CSM_ENABLE)
+ IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ }
+!endif
+# OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+!ifdef $(CSM_ENABLE)
+ OvmfPkg/Bhyve/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+
+!if $(TOOL_CHAIN_TAG) != "XCODE5"
+ ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
+!endif
+ ShellPkg/Application/Shell/Shell.inf {
+ <LibraryClasses>
+ ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+!if $(NETWORK_IP6_ENABLE) == TRUE
+ NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
+!endif
+ HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+
+ <PcdsFixedAtBuild>
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|8000
+ }
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+ OvmfPkg/EnrollDefaultKeys/EnrollDefaultKeys.inf
+!endif
+
+ OvmfPkg/PlatformDxe/Platform.inf
+ OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+ OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+
+
+ #
+ # Variable driver stack (non-SMM)
+ #
+ OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+ OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf {
+ <LibraryClasses>
+ PlatformFvbLib|OvmfPkg/Library/EmuVariableFvbLib/EmuVariableFvbLib.inf
+ }
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ }
+
+
+ #
+ # TPM support
+ #
+!if $(TPM_ENABLE) == TRUE
+ SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf {
+ <LibraryClasses>
+ Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
+ NULL|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
+ HashLib|SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha1/HashInstanceLibSha1.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha256/HashInstanceLibSha256.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha384/HashInstanceLibSha384.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSha512/HashInstanceLibSha512.inf
+ NULL|SecurityPkg/Library/HashInstanceLibSm3/HashInstanceLibSm3.inf
+ }
+!if $(TPM_CONFIG_ENABLE) == TRUE
+ SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
+!endif
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.fdf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.fdf
new file mode 100644
index 00000000000..53160694373
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/BhyveX64.fdf
@@ -0,0 +1,490 @@
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) 2014, Pluribus Networks, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+################################################################################
+
+[Defines]
+!include OvmfPkg/Bhyve/BhyveDefines.fdf.inc
+
+#
+# Build the variable store and the firmware code as one unified flash device
+# image.
+#
+[FD.BHYVE]
+BaseAddress = $(FW_BASE_ADDRESS)
+Size = $(FW_SIZE)
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(FW_BLOCKS)
+
+!include VarStore.fdf.inc
+
+$(VARS_SIZE)|$(FVMAIN_SIZE)
+FV = FVMAIN_COMPACT
+
+$(SECFV_OFFSET)|$(SECFV_SIZE)
+FV = SECFV
+
+#
+# Build the variable store and the firmware code as separate flash device
+# images.
+#
+[FD.BHYVE_VARS]
+BaseAddress = $(FW_BASE_ADDRESS)
+Size = $(VARS_SIZE)
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(VARS_BLOCKS)
+
+!include VarStore.fdf.inc
+
+[FD.BHYVE_CODE]
+BaseAddress = $(CODE_BASE_ADDRESS)
+Size = $(CODE_SIZE)
+ErasePolarity = 1
+BlockSize = $(BLOCK_SIZE)
+NumBlocks = $(CODE_BLOCKS)
+
+0x00000000|$(FVMAIN_SIZE)
+FV = FVMAIN_COMPACT
+
+$(FVMAIN_SIZE)|$(SECFV_SIZE)
+FV = SECFV
+
+################################################################################
+
+[FD.MEMFD]
+BaseAddress = $(MEMFD_BASE_ADDRESS)
+Size = 0xC00000
+ErasePolarity = 1
+BlockSize = 0x10000
+NumBlocks = 0xC0
+
+0x000000|0x006000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+
+0x006000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
+
+0x007000|0x001000
+gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+
+0x010000|0x010000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+
+0x020000|0x0E0000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+FV = PEIFV
+
+0x100000|0xB00000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+FV = DXEFV
+
+################################################################################
+
+[FV.SECFV]
+FvNameGuid = 763BED0D-DE9F-48F5-81F1-3E90E1B1A015
+BlockSize = 0x1000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+#
+# SEC Phase modules
+#
+# The code in this FV handles the initial firmware startup, and
+# decompresses the PEI and DXE FVs which handles the rest of the boot sequence.
+#
+INF OvmfPkg/Sec/SecMain.inf
+
+INF RuleOverride=RESET_VECTOR OvmfPkg/Bhyve/ResetVector/ResetVector.inf
+
+################################################################################
+[FV.PEIFV]
+FvNameGuid = 6938079B-B503-4E3D-9D24-B28337A25806
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+}
+
+#
+# PEI Phase modules
+#
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
+INF OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+!if $(SMM_REQUIRE) == TRUE
+INF OvmfPkg/Bhyve/SmmAccess/SmmAccessPei.inf
+!endif
+
+!if $(TPM_ENABLE) == TRUE
+INF OvmfPkg/Bhyve/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+!endif
+
+################################################################################
+
+[FV.DXEFV]
+FvForceRebase = FALSE
+FvNameGuid = 7CB8BDC9-F8EB-4F34-AAEA-3EE4AF6516A1
+BlockSize = 0x10000
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+APRIORI DXE {
+ INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+ INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+ INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+!if $(SMM_REQUIRE) == FALSE
+ INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+!endif
+}
+
+#
+# DXE Phase modules
+#
+INF MdeModulePkg/Core/Dxe/DxeMain.inf
+
+INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
+INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+
+INF MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
+INF MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
+INF MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
+INF UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
+INF UefiCpuPkg/CpuDxe/CpuDxe.inf
+INF PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
+INF OvmfPkg/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupport.inf
+INF OvmfPkg/PciHotPlugInitDxe/PciHotPlugInit.inf
+INF MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf
+INF MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
+INF MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
+INF MdeModulePkg/Universal/Metronome/Metronome.inf
+INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+
+INF OvmfPkg/VirtioPciDeviceDxe/VirtioPciDeviceDxe.inf
+INF OvmfPkg/Virtio10Dxe/Virtio10.inf
+INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf
+INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf
+INF OvmfPkg/VirtioRngDxe/VirtioRng.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
+ INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
+!endif
+
+INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+INF MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
+INF MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
+INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
+INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
+INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+INF MdeModulePkg/Universal/DriverHealthManagerDxe/DriverHealthManagerDxe.inf
+INF MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
+INF MdeModulePkg/Application/UiApp/UiApp.inf
+INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
+INF MdeModulePkg/Universal/PrintDxe/PrintDxe.inf
+INF MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
+INF MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
+INF MdeModulePkg/Universal/Disk/RamDiskDxe/RamDiskDxe.inf
+INF MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
+INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+INF OvmfPkg/SataControllerDxe/SataControllerDxe.inf
+INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
+INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
+INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
+INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
+INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
+INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
+INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
+
+
+INF OvmfPkg/SioBusDxe/SioBusDxe.inf
+INF MdeModulePkg/Bus/Pci/PciSioSerialDxe/PciSioSerialDxe.inf
+INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
+INF MdeModulePkg/Bus/Isa/Ps2MouseDxe/Ps2MouseDxe.inf
+
+INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
+INF OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
+
+INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
+INF OvmfPkg/Bhyve/AcpiPlatformDxe/AcpiPlatformDxe.inf
+INF RuleOverride=ACPITABLE OvmfPkg/Bhyve/AcpiTables/AcpiTables.inf
+INF MdeModulePkg/Universal/Acpi/S3SaveStateDxe/S3SaveStateDxe.inf
+INF MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/BootScriptExecutorDxe.inf
+INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
+
+INF FatPkg/EnhancedFatDxe/Fat.inf
+INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+
+!if $(TOOL_CHAIN_TAG) != "XCODE5"
+INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+!endif
+INF ShellPkg/Application/Shell/Shell.inf
+
+INF MdeModulePkg/Logo/LogoDxe.inf
+
+#
+# Network modules
+#
+!if $(E1000_ENABLE)
+ FILE DRIVER = 5D695E11-9B3F-4b83-B25F-4A8D5D69BE07 {
+ SECTION PE32 = Intel3.5/EFIX64/E3522X2.EFI
+ }
+!endif
+!include NetworkPkg/Network.fdf.inc
+ INF OvmfPkg/VirtioNetDxe/VirtioNet.inf
+
+!ifdef $(CSM_ENABLE)
+INF IntelFrameworkModulePkg/Csm/BiosThunk/VideoDxe/VideoDxe.inf
+!endif
+#INF OvmfPkg/Csm/LegacyBiosDxe/LegacyBiosDxe.inf
+!ifdef $(CSM_ENABLE)
+INF RuleOverride=CSM OvmfPkg/Bhyve/Csm/BhyveCsm16/BhyveCsm16.inf
+!endif
+
+INF OvmfPkg/PlatformDxe/Platform.inf
+INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+INF OvmfPkg/IoMmuDxe/IoMmuDxe.inf
+INF OvmfPkg/Bhyve/BhyveRfbDxe/BhyveRfbDxe.inf
+
+!if $(SMM_REQUIRE) == TRUE
+INF OvmfPkg/Bhyve/SmmAccess/SmmAccess2Dxe.inf
+INF OvmfPkg/Bhyve/SmmControl2Dxe/SmmControl2Dxe.inf
+INF UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+INF MdeModulePkg/Core/PiSmmCore/PiSmmIpl.inf
+INF MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf
+INF UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+INF MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.inf
+INF UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+
+#
+# Variable driver stack (SMM)
+#
+INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesSmm.inf
+INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteSmm.inf
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
+
+!else
+
+#
+# Variable driver stack (non-SMM)
+#
+INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+INF OvmfPkg/EmuVariableFvbRuntimeDxe/Fvb.inf
+INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
+!endif
+
+#
+# TPM support
+#
+!if $(TPM_ENABLE) == TRUE
+INF SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+!if $(TPM_CONFIG_ENABLE) == TRUE
+INF SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigDxe.inf
+!endif
+!endif
+
+################################################################################
+
+[FV.FVMAIN_COMPACT]
+FvNameGuid = 48DB5E17-707C-472D-91CD-1613E7EF51B0
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+
+FILE FV_IMAGE = 9E21FD93-9C72-4c15-8C4B-E77F1DB2D792 {
+ SECTION GUIDED EE4E5898-3914-4259-9D6E-DC7BD79403CF PROCESSING_REQUIRED = TRUE {
+ #
+ # These firmware volumes will have files placed in them uncompressed,
+ # and then both firmware volumes will be compressed in a single
+ # compression operation in order to achieve better overall compression.
+ #
+ SECTION FV_IMAGE = PEIFV
+ SECTION FV_IMAGE = DXEFV
+ }
+ }
+
+!include FvmainCompactScratchEnd.fdf.inc
+
+################################################################################
+
+[Rule.Common.SEC]
+ FILE SEC = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ VERSION STRING ="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_CORE]
+ FILE DXE_CORE = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ RAW ACPI Optional |.acpi
+ RAW ASL Optional |.aml
+ }
+
+[Rule.Common.DXE_RUNTIME_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_DRIVER.BINARY]
+ FILE DRIVER = $(NAMED_GUID) {
+ DXE_DEPEX DXE_DEPEX Optional |.depex
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.UEFI_APPLICATION.BINARY]
+ FILE APPLICATION = $(NAMED_GUID) {
+ PE32 PE32 |.efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.USER_DEFINED.ACPITABLE]
+ FILE FREEFORM = 7E374E25-8E01-4FEE-87F2-390C23C606CD {
+ RAW ACPI |.acpi
+ RAW ASL |.aml
+ }
+
+[Rule.Common.USER_DEFINED.CSM]
+ FILE FREEFORM = $(NAMED_GUID) {
+ RAW BIN |.bin
+ }
+
+[Rule.Common.SEC.RESET_VECTOR]
+ FILE RAW = $(NAMED_GUID) {
+ RAW BIN Align = 16 |.bin
+ }
+
+[Rule.Common.SMM_CORE]
+ FILE SMM_CORE = $(NAMED_GUID) {
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
+
+[Rule.Common.DXE_SMM_DRIVER]
+ FILE SMM = $(NAMED_GUID) {
+ SMM_DEPEX SMM_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
+ }
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc
new file mode 100644
index 00000000000..780741f1ce3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/FvmainCompactScratchEnd.fdf.inc
@@ -0,0 +1,65 @@
+## @file
+# This FDF include file computes the end of the scratch buffer used in
+# DecompressMemFvs() [OvmfPkg/Sec/SecMain.c]. It is based on the decompressed
+# (ie. original) size of the LZMA-compressed section of the one FFS file in
+# the FVMAIN_COMPACT firmware volume.
+#
+# Copyright (C) 2015, Red Hat, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+# The GUID EE4E5898-3914-4259-9D6E-DC7BD79403CF means "LzmaCustomDecompress".
+# The decompressed output will have the following structure (see the file
+# "9E21FD93-9C72-4c15-8C4B-E77F1DB2D792SEC1.guided.dummy" in the
+# Build/Ovmf*/*/FV/Ffs/9E21FD93-9C72-4c15-8C4B-E77F1DB2D792/ directory):
+#
+# Size Contents
+# ------------------- --------------------------------------------------------
+# 4 EFI_COMMON_SECTION_HEADER, stating size 124 (0x7C) and
+# type 0x19 (EFI_SECTION_RAW). The purpose of this section
+# is to pad the start of PEIFV to 128 bytes.
+# 120 Zero bytes (padding).
+#
+# 4 EFI_COMMON_SECTION_HEADER, stating size
+# (PcdOvmfPeiMemFvSize + 4), and type 0x17
+# (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdOvmfPeiMemFvSize PEIFV. Note that the above sizes pad the offset of this
+# object to 128 bytes. See also the "guided.dummy.txt"
+# file in the same directory.
+#
+# 4 EFI_COMMON_SECTION_HEADER, stating size 12 (0xC) and
+# type 0x19 (EFI_SECTION_RAW). The purpose of this section
+# is to pad the start of DXEFV to 16 bytes.
+# 8 Zero bytes (padding).
+#
+# 4 EFI_COMMON_SECTION_HEADER, stating size
+# (PcdOvmfDxeMemFvSize + 4), and type 0x17
+# (EFI_SECTION_FIRMWARE_VOLUME_IMAGE).
+# PcdOvmfDxeMemFvSize DXEFV. Note that the above sizes pad the offset of this
+# object to 16 bytes. See also the "guided.dummy.txt" file
+# in the same directory.
+#
+# The total size after decompression is (128 + PcdOvmfPeiMemFvSize + 16 +
+# PcdOvmfDxeMemFvSize).
+
+DEFINE OUTPUT_SIZE = (128 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize + 16 + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize)
+
+# LzmaCustomDecompressLib uses a constant scratch buffer size of 64KB; see
+# SCRATCH_BUFFER_REQUEST_SIZE in
+# "MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaDecompress.c".
+
+DEFINE DECOMP_SCRATCH_SIZE = 0x00010000
+
+# Note: when we use PcdOvmfDxeMemFvBase in this context, BaseTools have not yet
+# offset it with MEMFD's base address. For that reason we have to do it manually.
+#
+# The calculation below mirrors DecompressMemFvs() [OvmfPkg/Sec/SecMain.c].
+
+DEFINE OUTPUT_BASE = ($(MEMFD_BASE_ADDRESS) + gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase + 0x00100000)
+DEFINE DECOMP_SCRATCH_BASE_UNALIGNED = ($(OUTPUT_BASE) + $(OUTPUT_SIZE))
+DEFINE DECOMP_SCRATCH_BASE_ALIGNMENT = 0x000FFFFF
+DEFINE DECOMP_SCRATCH_BASE_MASK = 0xFFF00000
+DEFINE DECOMP_SCRATCH_BASE = (($(DECOMP_SCRATCH_BASE_UNALIGNED) + $(DECOMP_SCRATCH_BASE_ALIGNMENT)) & $(DECOMP_SCRATCH_BASE_MASK))
+
+SET gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd = $(DECOMP_SCRATCH_BASE) + $(DECOMP_SCRATCH_SIZE)
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/License.txt b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/License.txt
new file mode 100644
index 00000000000..507ed7d68b4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/License.txt
@@ -0,0 +1,68 @@
+Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (C) 2018, Red Hat, Inc.
+Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
+Copyright (C) 2016, Red Hat, Inc.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+Copyright (c) 2015 Nahanni Systems
+Copyright (C) 2015, Red Hat, Inc.
+Copyright (C) 2014, Red Hat, Inc.
+Copyright (c) 2014, Pluribus Networks, Inc.
+Copyright (C) 2013, Red Hat, Inc.
+Copyright (c) 2012, 2013, Red Hat, Inc.
+Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+Portions copyright (c) 2011, Apple Inc. All rights reserved.
+Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
+
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+Subject to the terms and conditions of this license, each copyright holder
+and contributor hereby grants to those receiving rights under this license
+a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+(except for failure to satisfy the conditions of this license) patent
+license to make, have made, use, offer to sell, sell, import, and otherwise
+transfer this software, where such license applies only to those patent
+claims, already acquired or hereafter acquired, licensable by such copyright
+holder or contributor that are necessarily infringed by:
+
+(a) their Contribution(s) (the licensed copyrights of copyright holders and
+ non-copyrightable additions of contributors, in source or binary form)
+ alone; or
+
+(b) combination of their Contribution(s) with the work of authorship to
+ which such Contribution(s) was added by such copyright holder or
+ contributor, if, at the time the Contribution is added, such addition
+ causes such combination to be necessarily infringed. The patent license
+ shall not apply to any other combinations which include the
+ Contribution.
+
+Except as expressly stated above, no rights or licenses from any copyright
+holder or contributor is granted under this license, whether expressly, by
+implication, estoppel or otherwise.
+
+DISCLAIMER
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/AmdSev.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/AmdSev.c
new file mode 100644
index 00000000000..f447cd319a5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/AmdSev.c
@@ -0,0 +1,98 @@
+/**@file
+ Initialize Secure Encrypted Virtualization (SEV) support
+
+ Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+//
+// The package level header files this module uses
+//
+#include <IndustryStandard/Q35MchIch9.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PcdLib.h>
+#include <PiPei.h>
+#include <Register/Intel/SmramSaveStateMap.h>
+
+#include "Platform.h"
+
+/**
+
+ Function checks if SEV support is available, if present then it sets
+ the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
+
+ **/
+VOID
+AmdSevInitialize (
+ VOID
+ )
+{
+ UINT64 EncryptionMask;
+ RETURN_STATUS PcdStatus;
+
+ //
+ // Check if SEV is enabled
+ //
+ if (!MemEncryptSevIsEnabled ()) {
+ return;
+ }
+
+ //
+ // Set Memory Encryption Mask PCD
+ //
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();
+ PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
+
+ //
+ // Set Pcd to Deny the execution of option ROM when security
+ // violation.
+ //
+ PcdStatus = PcdSet32S (PcdOptionRomImageVerificationPolicy, 0x4);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ //
+ // When SMM is required, cover the pages containing the initial SMRAM Save
+ // State Map with a memory allocation HOB:
+ //
+ // There's going to be a time interval between our decrypting those pages for
+ // SMBASE relocation and re-encrypting the same pages after SMBASE
+ // relocation. We shall ensure that the DXE phase stay away from those pages
+ // until after re-encryption, in order to prevent an information leak to the
+ // hypervisor.
+ //
+ if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {
+ RETURN_STATUS LocateMapStatus;
+ UINTN MapPagesBase;
+ UINTN MapPagesCount;
+
+ LocateMapStatus = MemEncryptSevLocateInitialSmramSaveStateMapPages (
+ &MapPagesBase,
+ &MapPagesCount
+ );
+ ASSERT_RETURN_ERROR (LocateMapStatus);
+
+ if (mQ35SmramAtDefaultSmbase) {
+ //
+ // The initial SMRAM Save State Map has been covered as part of a larger
+ // reserved memory allocation in InitializeRamRegions().
+ //
+ ASSERT (SMM_DEFAULT_SMBASE <= MapPagesBase);
+ ASSERT (
+ (MapPagesBase + EFI_PAGES_TO_SIZE (MapPagesCount) <=
+ SMM_DEFAULT_SMBASE + MCH_DEFAULT_SMBASE_SIZE)
+ );
+ } else {
+ BuildMemoryAllocationHob (
+ MapPagesBase, // BaseAddress
+ EFI_PAGES_TO_SIZE (MapPagesCount), // Length
+ EfiBootServicesData // MemoryType
+ );
+ }
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/ClearCache.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/ClearCache.c
new file mode 100644
index 00000000000..eaaab8733fb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/ClearCache.c
@@ -0,0 +1,111 @@
+/**@file
+ Install a callback to clear cache on all processors.
+ This is for conformance with the TCG "Platform Reset Attack Mitigation
+ Specification". Because clearing the CPU caches at boot doesn't impact
+ performance significantly, do it unconditionally, for simplicity's
+ sake.
+
+ Copyright (C) 2018, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/CacheMaintenanceLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/MpServices.h>
+
+#include "Platform.h"
+
+/**
+ Invalidate data & instruction caches.
+ All APs execute this function in parallel. The BSP executes the function
+ separately.
+
+ @param[in,out] WorkSpace Pointer to the input/output argument workspace
+ shared by all processors.
+**/
+STATIC
+VOID
+EFIAPI
+ClearCache (
+ IN OUT VOID *WorkSpace
+ )
+{
+ WriteBackInvalidateDataCache ();
+ InvalidateInstructionCache ();
+}
+
+/**
+ Notification function called when EFI_PEI_MP_SERVICES_PPI becomes available.
+
+ @param[in] PeiServices Indirect reference to the PEI Services Table.
+ @param[in] NotifyDescriptor Address of the notification descriptor data
+ structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @return Status of the notification. The status code returned from this
+ function is ignored.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ClearCacheOnMpServicesAvailable (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_PEI_MP_SERVICES_PPI *MpServices;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a: %a\n", gEfiCallerBaseName, __FUNCTION__));
+
+ //
+ // Clear cache on all the APs in parallel.
+ //
+ MpServices = Ppi;
+ Status = MpServices->StartupAllAPs (
+ (CONST EFI_PEI_SERVICES **)PeiServices,
+ MpServices,
+ ClearCache, // Procedure
+ FALSE, // SingleThread
+ 0, // TimeoutInMicroSeconds: inf.
+ NULL // ProcedureArgument
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_STARTED) {
+ DEBUG ((DEBUG_ERROR, "%a: StartupAllAps(): %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ //
+ // Now clear cache on the BSP too.
+ //
+ ClearCache (NULL);
+ return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EFI_PEI_MP_SERVICES_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServicesNotify = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiMpServicesPpiGuid, // Guid
+ ClearCacheOnMpServicesAvailable // Notify
+};
+
+VOID
+InstallClearCacheCallback (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesNotifyPpi (&mMpServicesNotify);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: failed to set up MP Services callback: %r\n",
+ __FUNCTION__, Status));
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.c
new file mode 100644
index 00000000000..2d0f158733a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.c
@@ -0,0 +1,58 @@
+/** @file
+ PC/AT CMOS access routines
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "Cmos.h"
+#include "Library/IoLib.h"
+
+/**
+ Reads 8-bits of CMOS data.
+
+ Reads the 8-bits of CMOS data at the location specified by Index.
+ The 8-bit read value is returned.
+
+ @param Index The CMOS location to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+ IN UINTN Index
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ return IoRead8 (0x71);
+}
+
+
+/**
+ Writes 8-bits of CMOS data.
+
+ Writes 8-bits of CMOS data to the location specified by Index
+ with the value specified by Value and returns Value.
+
+ @param Index The CMOS location to write.
+ @param Value The value to write to CMOS.
+
+ @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+ IN UINTN Index,
+ IN UINT8 Value
+ )
+{
+ IoWrite8 (0x70, (UINT8) Index);
+ IoWrite8 (0x71, Value);
+ return Value;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.h
new file mode 100644
index 00000000000..d3a7845ba39
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Cmos.h
@@ -0,0 +1,50 @@
+/** @file
+ PC/AT CMOS access routines
+
+ Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CMOS_H_
+#define _CMOS_H_
+
+/**
+ Reads 8-bits of CMOS data.
+
+ Reads the 8-bits of CMOS data at the location specified by Index.
+ The 8-bit read value is returned.
+
+ @param Index The CMOS location to read.
+
+ @return The value read.
+
+**/
+UINT8
+EFIAPI
+CmosRead8 (
+ IN UINTN Index
+ );
+
+/**
+ Writes 8-bits of CMOS data.
+
+ Writes 8-bits of CMOS data to the location specified by Index
+ with the value specified by Value and returns Value.
+
+ @param Index The CMOS location to write.
+ @param Value The value to write to CMOS.
+
+ @return The value written to CMOS.
+
+**/
+UINT8
+EFIAPI
+CmosWrite8 (
+ IN UINTN Index,
+ IN UINT8 Value
+ );
+
+
+#endif /* _CMOS_H_ */
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c
new file mode 100644
index 00000000000..c07313ce515
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/FeatureControl.c
@@ -0,0 +1,21 @@
+/**@file
+ Install a callback when necessary for setting the Feature Control MSR on all
+ processors.
+
+ Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (C) 2016, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Platform.h"
+
+VOID
+InstallFeatureControlCallback (
+ VOID
+ )
+{
+ //
+ // Nothing to do.
+ //
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Fv.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Fv.c
new file mode 100644
index 00000000000..50cff64241f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Fv.c
@@ -0,0 +1,94 @@
+/** @file
+ Build FV related hobs for platform.
+
+ Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiPei.h"
+#include "Platform.h"
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+
+
+/**
+ Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+ and DXE know about them.
+
+ @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.
+
+**/
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ )
+{
+ BOOLEAN SecureS3Needed;
+
+ DEBUG ((DEBUG_INFO, "Platform PEI Firmware Volume Initialization\n"));
+
+ //
+ // Create a memory allocation HOB for the PEI FV.
+ //
+ // Allocate as ACPI NVS is S3 is supported
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdOvmfPeiMemFvBase),
+ PcdGet32 (PcdOvmfPeiMemFvSize),
+ mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+
+ //
+ // Let DXE know about the DXE FV
+ //
+ BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 (PcdOvmfDxeMemFvSize));
+
+ SecureS3Needed = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire);
+
+ //
+ // Create a memory allocation HOB for the DXE FV.
+ //
+ // If "secure" S3 is needed, then SEC will decompress both PEI and DXE
+ // firmware volumes at S3 resume too, hence we need to keep away the OS from
+ // DXEFV as well. Otherwise we only need to keep away DXE itself from the
+ // DXEFV area.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdOvmfDxeMemFvBase),
+ PcdGet32 (PcdOvmfDxeMemFvSize),
+ SecureS3Needed ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+
+ //
+ // Additionally, said decompression will use temporary memory above the end
+ // of DXEFV, so let's keep away the OS from there too.
+ //
+ if (SecureS3Needed) {
+ UINT32 DxeMemFvEnd;
+
+ DxeMemFvEnd = PcdGet32 (PcdOvmfDxeMemFvBase) +
+ PcdGet32 (PcdOvmfDxeMemFvSize);
+ BuildMemoryAllocationHob (
+ DxeMemFvEnd,
+ PcdGet32 (PcdOvmfDecompressionScratchEnd) - DxeMemFvEnd,
+ EfiACPIMemoryNVS
+ );
+ }
+
+ //
+ // Let PEI know about the DXE FV so it can find the DXE Core
+ //
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ (VOID *)(UINTN) PcdGet32 (PcdOvmfDxeMemFvBase),
+ PcdGet32 (PcdOvmfDxeMemFvSize),
+ NULL,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/MemDetect.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
new file mode 100644
index 00000000000..eddbcdd53cf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/MemDetect.c
@@ -0,0 +1,627 @@
+/**@file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ MemDetect.c
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <IndustryStandard/E820.h>
+#include <IndustryStandard/Q35MchIch9.h>
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/MtrrLib.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+UINT8 mPhysMemAddressWidth;
+
+STATIC UINT32 mS3AcpiReservedMemoryBase;
+STATIC UINT32 mS3AcpiReservedMemorySize;
+
+STATIC UINT16 mQ35TsegMbytes;
+
+BOOLEAN mQ35SmramAtDefaultSmbase = FALSE;
+
+VOID
+Q35TsegMbytesInitialization (
+ VOID
+ )
+{
+ UINT16 ExtendedTsegMbytes;
+ RETURN_STATUS PcdStatus;
+
+ if (mHostBridgeDevId != INTEL_Q35_MCH_DEVICE_ID) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: no TSEG (SMRAM) on host bridge DID=0x%04x; "
+ "only DID=0x%04x (Q35) is supported\n",
+ __FUNCTION__,
+ mHostBridgeDevId,
+ INTEL_Q35_MCH_DEVICE_ID
+ ));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+
+ //
+ // Check if QEMU offers an extended TSEG.
+ //
+ // This can be seen from writing MCH_EXT_TSEG_MB_QUERY to the MCH_EXT_TSEG_MB
+ // register, and reading back the register.
+ //
+ // On a QEMU machine type that does not offer an extended TSEG, the initial
+ // write overwrites whatever value a malicious guest OS may have placed in
+ // the (unimplemented) register, before entering S3 or rebooting.
+ // Subsequently, the read returns MCH_EXT_TSEG_MB_QUERY unchanged.
+ //
+ // On a QEMU machine type that offers an extended TSEG, the initial write
+ // triggers an update to the register. Subsequently, the value read back
+ // (which is guaranteed to differ from MCH_EXT_TSEG_MB_QUERY) tells us the
+ // number of megabytes.
+ //
+ PciWrite16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB), MCH_EXT_TSEG_MB_QUERY);
+ ExtendedTsegMbytes = PciRead16 (DRAMC_REGISTER_Q35 (MCH_EXT_TSEG_MB));
+ if (ExtendedTsegMbytes == MCH_EXT_TSEG_MB_QUERY) {
+ mQ35TsegMbytes = PcdGet16 (PcdQ35TsegMbytes);
+ return;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: QEMU offers an extended TSEG (%d MB)\n",
+ __FUNCTION__,
+ ExtendedTsegMbytes
+ ));
+ PcdStatus = PcdSet16S (PcdQ35TsegMbytes, ExtendedTsegMbytes);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ mQ35TsegMbytes = ExtendedTsegMbytes;
+}
+
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+ VOID
+ )
+{
+ UINT8 Cmos0x34;
+ UINT8 Cmos0x35;
+
+ //
+ // CMOS 0x34/0x35 specifies the system memory above 16 MB.
+ // * CMOS(0x35) is the high byte
+ // * CMOS(0x34) is the low byte
+ // * The size is specified in 64kb chunks
+ // * Since this is memory above 16MB, the 16MB must be added
+ // into the calculation to get the total memory size.
+ //
+
+ Cmos0x34 = (UINT8) CmosRead8 (0x34);
+ Cmos0x35 = (UINT8) CmosRead8 (0x35);
+
+ return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
+}
+
+
+STATIC
+UINT64
+GetSystemMemorySizeAbove4gb (
+ )
+{
+ UINT32 Size;
+ UINTN CmosIndex;
+
+ //
+ // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
+ // * CMOS(0x5d) is the most significant size byte
+ // * CMOS(0x5c) is the middle size byte
+ // * CMOS(0x5b) is the least significant size byte
+ // * The size is specified in 64kb chunks
+ //
+
+ Size = 0;
+ for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
+ Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
+ }
+
+ return LShiftU64 (Size, 16);
+}
+
+
+/**
+ Return the highest address that DXE could possibly use, plus one.
+**/
+STATIC
+UINT64
+GetFirstNonAddress (
+ VOID
+ )
+{
+ UINT64 FirstNonAddress;
+ UINT64 Pci64Base, Pci64Size;
+ RETURN_STATUS PcdStatus;
+
+ FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();
+
+ //
+ // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
+ // resources to 32-bit anyway. See DegradeResource() in
+ // "PciResourceSupport.c".
+ //
+#ifdef MDE_CPU_IA32
+ if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ return FirstNonAddress;
+ }
+#endif
+
+ //
+ // Otherwise, in order to calculate the highest address plus one, we must
+ // consider the 64-bit PCI host aperture too. Fetch the default size.
+ //
+ Pci64Size = PcdGet64 (PcdPciMmio64Size);
+
+ if (Pci64Size == 0) {
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ DEBUG ((DEBUG_INFO, "%a: disabling 64-bit PCI host aperture\n",
+ __FUNCTION__));
+ PcdStatus = PcdSet64S (PcdPciMmio64Size, 0);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ }
+
+ //
+ // There's nothing more to do; the amount of memory above 4GB fully
+ // determines the highest address plus one. The memory hotplug area (see
+ // below) plays no role for the firmware in this case.
+ //
+ return FirstNonAddress;
+ }
+
+ //
+ // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
+ // that the host can map it with 1GB hugepages. Follow suit.
+ //
+ Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
+ Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);
+
+ //
+ // The 64-bit PCI host aperture should also be "naturally" aligned. The
+ // alignment is determined by rounding the size of the aperture down to the
+ // next smaller or equal power of two. That is, align the aperture by the
+ // largest BAR size that can fit into it.
+ //
+ Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ //
+ // The core PciHostBridgeDxe driver will automatically add this range to
+ // the GCD memory space map through our PciHostBridgeLib instance; here we
+ // only need to set the PCDs.
+ //
+ PcdStatus = PcdSet64S (PcdPciMmio64Base, Pci64Base);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdPciMmio64Size, Pci64Size);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ DEBUG ((DEBUG_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",
+ __FUNCTION__, Pci64Base, Pci64Size));
+ }
+
+ //
+ // The useful address space ends with the 64-bit PCI host aperture.
+ //
+ FirstNonAddress = Pci64Base + Pci64Size;
+ return FirstNonAddress;
+}
+
+
+/**
+ Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
+**/
+VOID
+AddressWidthInitialization (
+ VOID
+ )
+{
+ UINT64 FirstNonAddress;
+
+ //
+ // As guest-physical memory size grows, the permanent PEI RAM requirements
+ // are dominated by the identity-mapping page tables built by the DXE IPL.
+ // The DXL IPL keys off of the physical address bits advertized in the CPU
+ // HOB. To conserve memory, we calculate the minimum address width here.
+ //
+ FirstNonAddress = GetFirstNonAddress ();
+ mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
+
+ //
+ // If FirstNonAddress is not an integral power of two, then we need an
+ // additional bit.
+ //
+ if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
+ ++mPhysMemAddressWidth;
+ }
+
+ //
+ // The minimum address width is 36 (covers up to and excluding 64 GB, which
+ // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
+ // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
+ // can simply assert that here, since 48 bits are good enough for 256 TB.
+ //
+ if (mPhysMemAddressWidth <= 36) {
+ mPhysMemAddressWidth = 36;
+ }
+ ASSERT (mPhysMemAddressWidth <= 48);
+}
+
+
+/**
+ Calculate the cap for the permanent PEI memory.
+**/
+STATIC
+UINT32
+GetPeiMemoryCap (
+ VOID
+ )
+{
+ BOOLEAN Page1GSupport;
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINT32 Pml4Entries;
+ UINT32 PdpEntries;
+ UINTN TotalPages;
+
+ //
+ // If DXE is 32-bit, then just return the traditional 64 MB cap.
+ //
+#ifdef MDE_CPU_IA32
+ if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
+ return SIZE_64MB;
+ }
+#endif
+
+ //
+ // Dependent on physical address width, PEI memory allocations can be
+ // dominated by the page tables built for 64-bit DXE. So we key the cap off
+ // of those. The code below is based on CreateIdentityMappingPageTables() in
+ // "MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c".
+ //
+ Page1GSupport = FALSE;
+ if (PcdGetBool (PcdUse1GPageTable)) {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+ }
+
+ if (mPhysMemAddressWidth <= 39) {
+ Pml4Entries = 1;
+ PdpEntries = 1 << (mPhysMemAddressWidth - 30);
+ ASSERT (PdpEntries <= 0x200);
+ } else {
+ Pml4Entries = 1 << (mPhysMemAddressWidth - 39);
+ ASSERT (Pml4Entries <= 0x200);
+ PdpEntries = 512;
+ }
+
+ TotalPages = Page1GSupport ? Pml4Entries + 1 :
+ (PdpEntries + 1) * Pml4Entries + 1;
+ ASSERT (TotalPages <= 0x40201);
+
+ //
+ // Add 64 MB for miscellaneous allocations. Note that for
+ // mPhysMemAddressWidth values close to 36, the cap will actually be
+ // dominated by this increment.
+ //
+ return (UINT32)(EFI_PAGES_TO_SIZE (TotalPages) + SIZE_64MB);
+}
+
+
+/**
+ Publish PEI core memory
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS MemoryBase;
+ UINT64 MemorySize;
+ UINT32 LowerMemorySize;
+ UINT32 PeiMemoryCap;
+
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // TSEG is chipped from the end of low RAM
+ //
+ LowerMemorySize -= mQ35TsegMbytes * SIZE_1MB;
+ }
+
+ //
+ // If S3 is supported, then the S3 permanent PEI memory is placed next,
+ // downwards. Its size is primarily dictated by CpuMpPei. The formula below
+ // is an approximation.
+ //
+ if (mS3Supported) {
+ mS3AcpiReservedMemorySize = SIZE_512KB +
+ mMaxCpuCount *
+ PcdGet32 (PcdCpuApStackSize);
+ mS3AcpiReservedMemoryBase = LowerMemorySize - mS3AcpiReservedMemorySize;
+ LowerMemorySize = mS3AcpiReservedMemoryBase;
+ }
+
+ if (mBootMode == BOOT_ON_S3_RESUME) {
+ MemoryBase = mS3AcpiReservedMemoryBase;
+ MemorySize = mS3AcpiReservedMemorySize;
+ } else {
+ PeiMemoryCap = GetPeiMemoryCap ();
+ DEBUG ((DEBUG_INFO, "%a: mPhysMemAddressWidth=%d PeiMemoryCap=%u KB\n",
+ __FUNCTION__, mPhysMemAddressWidth, PeiMemoryCap >> 10));
+
+ //
+ // Determine the range of memory to use during PEI
+ //
+ // Technically we could lay the permanent PEI RAM over SEC's temporary
+ // decompression and scratch buffer even if "secure S3" is needed, since
+ // their lifetimes don't overlap. However, PeiFvInitialization() will cover
+ // RAM up to PcdOvmfDecompressionScratchEnd with an EfiACPIMemoryNVS memory
+ // allocation HOB, and other allocations served from the permanent PEI RAM
+ // shouldn't overlap with that HOB.
+ //
+ MemoryBase = mS3Supported && FeaturePcdGet (PcdSmmSmramRequire) ?
+ PcdGet32 (PcdOvmfDecompressionScratchEnd) :
+ PcdGet32 (PcdOvmfDxeMemFvBase) + PcdGet32 (PcdOvmfDxeMemFvSize);
+ MemorySize = LowerMemorySize - MemoryBase;
+ if (MemorySize > PeiMemoryCap) {
+ MemoryBase = LowerMemorySize - PeiMemoryCap;
+ MemorySize = PeiMemoryCap;
+ }
+ }
+
+ //
+ // Publish this memory to the PEI Core
+ //
+ Status = PublishSystemMemory(MemoryBase, MemorySize);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+
+/**
+ Peform Memory Detection for QEMU / KVM
+
+**/
+STATIC
+VOID
+QemuInitializeRam (
+ VOID
+ )
+{
+ UINT64 LowerMemorySize;
+ UINT64 UpperMemorySize;
+ MTRR_SETTINGS MtrrSettings;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a called\n", __FUNCTION__));
+
+ //
+ // Determine total memory size available
+ //
+ LowerMemorySize = GetSystemMemorySizeBelow4gb ();
+ UpperMemorySize = GetSystemMemorySizeAbove4gb ();
+
+ if (mBootMode == BOOT_ON_S3_RESUME) {
+ //
+ // Create the following memory HOB as an exception on the S3 boot path.
+ //
+ // Normally we'd create memory HOBs only on the normal boot path. However,
+ // CpuMpPei specifically needs such a low-memory HOB on the S3 path as
+ // well, for "borrowing" a subset of it temporarily, for the AP startup
+ // vector.
+ //
+ // CpuMpPei saves the original contents of the borrowed area in permanent
+ // PEI RAM, in a backup buffer allocated with the normal PEI services.
+ // CpuMpPei restores the original contents ("returns" the borrowed area) at
+ // End-of-PEI. End-of-PEI in turn is emitted by S3Resume2Pei before
+ // transferring control to the OS's wakeup vector in the FACS.
+ //
+ // We expect any other PEIMs that "borrow" memory similarly to CpuMpPei to
+ // restore the original contents. Furthermore, we expect all such PEIMs
+ // (CpuMpPei included) to claim the borrowed areas by producing memory
+ // allocation HOBs, and to honor preexistent memory allocation HOBs when
+ // looking for an area to borrow.
+ //
+ AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+ } else {
+ //
+ // Create memory HOBs
+ //
+ AddMemoryRangeHob (0, BASE_512KB + BASE_128KB);
+
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ UINT32 TsegSize;
+
+ TsegSize = mQ35TsegMbytes * SIZE_1MB;
+ AddMemoryRangeHob (BASE_1MB, LowerMemorySize - TsegSize);
+ AddReservedMemoryBaseSizeHob (LowerMemorySize - TsegSize, TsegSize,
+ TRUE);
+ } else {
+ AddMemoryRangeHob (BASE_1MB, LowerMemorySize);
+ }
+
+ if (UpperMemorySize != 0) {
+ AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize);
+ }
+ }
+
+ //
+ // We'd like to keep the following ranges uncached:
+ // - [640 KB, 1 MB)
+ // - [LowerMemorySize, 4 GB)
+ //
+ // Everything else should be WB. Unfortunately, programming the inverse (ie.
+ // keeping the default UC, and configuring the complement set of the above as
+ // WB) is not reliable in general, because the end of the upper RAM can have
+ // practically any alignment, and we may not have enough variable MTRRs to
+ // cover it exactly.
+ //
+ if (IsMtrrSupported ()) {
+ MtrrGetAllMtrrs (&MtrrSettings);
+
+ //
+ // MTRRs disabled, fixed MTRRs disabled, default type is uncached
+ //
+ ASSERT ((MtrrSettings.MtrrDefType & BIT11) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & BIT10) == 0);
+ ASSERT ((MtrrSettings.MtrrDefType & 0xFF) == 0);
+
+ //
+ // flip default type to writeback
+ //
+ SetMem (&MtrrSettings.Fixed, sizeof MtrrSettings.Fixed, 0x06);
+ ZeroMem (&MtrrSettings.Variables, sizeof MtrrSettings.Variables);
+ MtrrSettings.MtrrDefType |= BIT11 | BIT10 | 6;
+ MtrrSetAllMtrrs (&MtrrSettings);
+
+ //
+ // Set memory range from 640KB to 1MB to uncacheable
+ //
+ Status = MtrrSetMemoryAttribute (BASE_512KB + BASE_128KB,
+ BASE_1MB - (BASE_512KB + BASE_128KB), CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set memory range from the "top of lower RAM" (RAM below 4GB) to 4GB as
+ // uncacheable
+ //
+ Status = MtrrSetMemoryAttribute (LowerMemorySize,
+ SIZE_4GB - LowerMemorySize, CacheUncacheable);
+ ASSERT_EFI_ERROR (Status);
+ }
+}
+
+/**
+ Publish system RAM and reserve memory regions
+
+**/
+VOID
+InitializeRamRegions (
+ VOID
+ )
+{
+ QemuInitializeRam ();
+
+ if (mS3Supported && mBootMode != BOOT_ON_S3_RESUME) {
+ //
+ // This is the memory range that will be used for PEI on S3 resume
+ //
+ BuildMemoryAllocationHob (
+ mS3AcpiReservedMemoryBase,
+ mS3AcpiReservedMemorySize,
+ EfiACPIMemoryNVS
+ );
+
+ //
+ // Cover the initial RAM area used as stack and temporary PEI heap.
+ //
+ // This is reserved as ACPI NVS so it can be used on S3 resume.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet32 (PcdOvmfSecPeiTempRamBase),
+ PcdGet32 (PcdOvmfSecPeiTempRamSize),
+ EfiACPIMemoryNVS
+ );
+
+ //
+ // SEC stores its table of GUIDed section handlers here.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet64 (PcdGuidedExtractHandlerTableAddress),
+ PcdGet32 (PcdGuidedExtractHandlerTableSize),
+ EfiACPIMemoryNVS
+ );
+
+#ifdef MDE_CPU_X64
+ //
+ // Reserve the initial page tables built by the reset vector code.
+ //
+ // Since this memory range will be used by the Reset Vector on S3
+ // resume, it must be reserved as ACPI NVS.
+ //
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecPageTablesBase),
+ (UINT64)(UINTN) PcdGet32 (PcdOvmfSecPageTablesSize),
+ EfiACPIMemoryNVS
+ );
+#endif
+ }
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+ //
+ // Reserve the lock box storage area
+ //
+ // Since this memory range will be used on S3 resume, it must be
+ // reserved as ACPI NVS.
+ //
+ // If S3 is unsupported, then various drivers might still write to the
+ // LockBox area. We ought to prevent DXE from serving allocation requests
+ // such that they would overlap the LockBox storage.
+ //
+ ZeroMem (
+ (VOID*)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),
+ (UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize)
+ );
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageBase),
+ (UINT64)(UINTN) PcdGet32 (PcdOvmfLockBoxStorageSize),
+ mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+ }
+
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ UINT32 TsegSize;
+
+ //
+ // Make sure the TSEG area that we reported as a reserved memory resource
+ // cannot be used for reserved memory allocations.
+ //
+ TsegSize = mQ35TsegMbytes * SIZE_1MB;
+ BuildMemoryAllocationHob (
+ GetSystemMemorySizeBelow4gb() - TsegSize,
+ TsegSize,
+ EfiReservedMemoryType
+ );
+ }
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.c
new file mode 100644
index 00000000000..e6f7b6d8254
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.c
@@ -0,0 +1,608 @@
+/**@file
+ Platform PEI driver
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2011, Andrei Warkentin <andreiw@motorola.com>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Ppi/MasterBootMode.h>
+#include <IndustryStandard/Pci22.h>
+#include <OvmfPlatforms.h>
+
+#include "Platform.h"
+#include "Cmos.h"
+
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+ { EfiACPIMemoryNVS, 0x004 },
+ { EfiACPIReclaimMemory, 0x008 },
+ { EfiReservedMemoryType, 0x004 },
+ { EfiRuntimeServicesData, 0x024 },
+ { EfiRuntimeServicesCode, 0x030 },
+ { EfiBootServicesCode, 0x180 },
+ { EfiBootServicesData, 0xF00 },
+ { EfiMaxMemoryType, 0x000 }
+};
+
+
+EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
+ {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+ }
+};
+
+
+UINT16 mHostBridgeDevId;
+
+EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+BOOLEAN mS3Supported = FALSE;
+
+UINT32 mMaxCpuCount;
+
+VOID
+AddIoMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_MAPPED_IO,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize,
+ BOOLEAN Cacheable
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ (Cacheable ?
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE :
+ 0
+ ) |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+VOID
+AddIoMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddIoMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+
+VOID
+MemMapInitialization (
+ VOID
+ )
+{
+ UINT64 PciIoBase;
+ UINT64 PciIoSize;
+ RETURN_STATUS PcdStatus;
+
+ PciIoBase = 0xC000;
+ PciIoSize = 0x4000;
+
+ //
+ // Create Memory Type Information HOB
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultMemoryTypeInformation,
+ sizeof(mDefaultMemoryTypeInformation)
+ );
+
+ //
+ // Video memory + Legacy BIOS region
+ //
+ AddIoMemoryRangeHob (0x0A0000, BASE_1MB);
+
+ if (TRUE) {
+ UINT32 TopOfLowRam;
+ UINT64 PciExBarBase;
+ UINT32 PciBase;
+ UINT32 PciSize;
+
+ TopOfLowRam = GetSystemMemorySizeBelow4gb ();
+ PciExBarBase = 0;
+ if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+ //
+ // The MMCONFIG area is expected to fall between the top of low RAM and
+ // the base of the 32-bit PCI host aperture.
+ //
+ PciExBarBase = FixedPcdGet64 (PcdPciExpressBaseAddress);
+ ASSERT (TopOfLowRam <= PciExBarBase);
+ ASSERT (PciExBarBase <= MAX_UINT32 - SIZE_256MB);
+ PciBase = (UINT32)(PciExBarBase + SIZE_256MB);
+ } else {
+ PciBase = (TopOfLowRam < BASE_2GB) ? BASE_2GB : TopOfLowRam;
+ }
+
+ //
+ // address purpose size
+ // ------------ -------- -------------------------
+ // max(top, 2g) PCI MMIO 0xFC000000 - max(top, 2g)
+ // 0xFC000000 gap 44 MB
+ // 0xFEC00000 IO-APIC 4 KB
+ // 0xFEC01000 gap 1020 KB
+ // 0xFED00000 HPET 1 KB
+ // 0xFED00400 gap 111 KB
+ // 0xFED1C000 gap (PIIX4) / RCRB (ICH9) 16 KB
+ // 0xFED20000 gap 896 KB
+ // 0xFEE00000 LAPIC 1 MB
+ //
+ PciSize = 0xFC000000 - PciBase;
+ AddIoMemoryBaseSizeHob (PciBase, PciSize);
+ PcdStatus = PcdSet64S (PcdPciMmio32Base, PciBase);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdPciMmio32Size, PciSize);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ AddIoMemoryBaseSizeHob (0xFEC00000, SIZE_4KB);
+ AddIoMemoryBaseSizeHob (0xFED00000, SIZE_1KB);
+ if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+ AddIoMemoryBaseSizeHob (ICH9_ROOT_COMPLEX_BASE, SIZE_16KB);
+ //
+ // Note: there should be an
+ //
+ // AddIoMemoryBaseSizeHob (PciExBarBase, SIZE_256MB);
+ //
+ // call below, just like the one above for RCBA. However, Linux insists
+ // that the MMCONFIG area be marked in the E820 or UEFI memory map as
+ // "reserved memory" -- Linux does not content itself with a simple gap
+ // in the memory map wherever the MCFG ACPI table points to.
+ //
+ // This appears to be a safety measure. The PCI Firmware Specification
+ // (rev 3.1) says in 4.1.2. "MCFG Table Description": "The resources can
+ // *optionally* be returned in [...] EFIGetMemoryMap as reserved memory
+ // [...]". (Emphasis added here.)
+ //
+ // Normally we add memory resource descriptor HOBs in
+ // QemuInitializeRam(), and pre-allocate from those with memory
+ // allocation HOBs in InitializeRamRegions(). However, the MMCONFIG area
+ // is most definitely not RAM; so, as an exception, cover it with
+ // uncacheable reserved memory right here.
+ //
+ AddReservedMemoryBaseSizeHob (PciExBarBase, SIZE_256MB, FALSE);
+ BuildMemoryAllocationHob (PciExBarBase, SIZE_256MB,
+ EfiReservedMemoryType);
+ }
+ AddIoMemoryBaseSizeHob (PcdGet32(PcdCpuLocalApicBaseAddress), SIZE_1MB);
+
+ //
+ // On Q35, the IO Port space is available for PCI resource allocations from
+ // 0x6000 up.
+ //
+ if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+ PciIoBase = 0x6000;
+ PciIoSize = 0xA000;
+ ASSERT ((ICH9_PMBASE_VALUE & 0xF000) < PciIoBase);
+ }
+ }
+
+ //
+ // Add PCI IO Port space available for PCI resource allocations.
+ //
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_IO,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED,
+ PciIoBase,
+ PciIoSize
+ );
+ PcdStatus = PcdSet64S (PcdPciIoBase, PciIoBase);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdPciIoSize, PciIoSize);
+ ASSERT_RETURN_ERROR (PcdStatus);
+}
+
+VOID
+NoexecDxeInitialization (
+ VOID
+ )
+{
+}
+
+VOID
+PciExBarInitialization (
+ VOID
+ )
+{
+ union {
+ UINT64 Uint64;
+ UINT32 Uint32[2];
+ } PciExBarBase;
+
+ //
+ // We only support the 256MB size for the MMCONFIG area:
+ // 256 buses * 32 devices * 8 functions * 4096 bytes config space.
+ //
+ // The masks used below enforce the Q35 requirements that the MMCONFIG area
+ // be (a) correctly aligned -- here at 256 MB --, (b) located under 64 GB.
+ //
+ // Note that (b) also ensures that the minimum address width we have
+ // determined in AddressWidthInitialization(), i.e., 36 bits, will suffice
+ // for DXE's page tables to cover the MMCONFIG area.
+ //
+ PciExBarBase.Uint64 = FixedPcdGet64 (PcdPciExpressBaseAddress);
+ ASSERT ((PciExBarBase.Uint32[1] & MCH_PCIEXBAR_HIGHMASK) == 0);
+ ASSERT ((PciExBarBase.Uint32[0] & MCH_PCIEXBAR_LOWMASK) == 0);
+
+ //
+ // Clear the PCIEXBAREN bit first, before programming the high register.
+ //
+ PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW), 0);
+
+ //
+ // Program the high register. Then program the low register, setting the
+ // MMCONFIG area size and enabling decoding at once.
+ //
+ PciWrite32 (DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_HIGH), PciExBarBase.Uint32[1]);
+ PciWrite32 (
+ DRAMC_REGISTER_Q35 (MCH_PCIEXBAR_LOW),
+ PciExBarBase.Uint32[0] | MCH_PCIEXBAR_BUS_FF | MCH_PCIEXBAR_EN
+ );
+}
+
+VOID
+MiscInitialization (
+ VOID
+ )
+{
+ UINTN PmCmd;
+ UINTN Pmba;
+ UINT32 PmbaAndVal;
+ UINT32 PmbaOrVal;
+ UINTN AcpiCtlReg;
+ UINT8 AcpiEnBit;
+ RETURN_STATUS PcdStatus;
+
+ //
+ // Disable A20 Mask
+ //
+ IoOr8 (0x92, BIT1);
+
+ //
+ // Build the CPU HOB with guest RAM size dependent address width and 16-bits
+ // of IO space. (Side note: unlike other HOBs, the CPU HOB is needed during
+ // S3 resume as well, so we build it unconditionally.)
+ //
+ BuildCpuHob (mPhysMemAddressWidth, 16);
+
+ //
+ // Determine platform type and save Host Bridge DID to PCD
+ //
+ switch (mHostBridgeDevId) {
+ case 0x7432: // BHYVE (AMD hostbridge)
+ case 0x1275: // BHYVE (Intel hostbridge)
+ case INTEL_82441_DEVICE_ID:
+ PmCmd = POWER_MGMT_REGISTER_PIIX4 (PCI_COMMAND_OFFSET);
+ Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+ PmbaAndVal = ~(UINT32)PIIX4_PMBA_MASK;
+ PmbaOrVal = PIIX4_PMBA_VALUE;
+ AcpiCtlReg = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMREGMISC);
+ AcpiEnBit = PIIX4_PMREGMISC_PMIOSE;
+ break;
+ case INTEL_Q35_MCH_DEVICE_ID:
+ PmCmd = POWER_MGMT_REGISTER_Q35 (PCI_COMMAND_OFFSET);
+ Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
+ PmbaAndVal = ~(UINT32)ICH9_PMBASE_MASK;
+ PmbaOrVal = ICH9_PMBASE_VALUE;
+ AcpiCtlReg = POWER_MGMT_REGISTER_Q35 (ICH9_ACPI_CNTL);
+ AcpiEnBit = ICH9_ACPI_CNTL_ACPI_EN;
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__, mHostBridgeDevId));
+ ASSERT (FALSE);
+ return;
+ }
+ PcdStatus = PcdSet16S (PcdOvmfHostBridgePciDevId, mHostBridgeDevId);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ //
+ // If the appropriate IOspace enable bit is set, assume the ACPI PMBA
+ // has been configured (e.g., by Xen) and skip the setup here.
+ // This matches the logic in AcpiTimerLibConstructor ().
+ //
+ if ((PciRead8 (AcpiCtlReg) & AcpiEnBit) == 0) {
+ //
+ // The PEI phase should be exited with fully accessibe ACPI PM IO space:
+ // 1. set PMBA
+ //
+ PciAndThenOr32 (Pmba, PmbaAndVal, PmbaOrVal);
+
+ //
+ // 2. set PCICMD/IOSE
+ //
+ PciOr8 (PmCmd, EFI_PCI_COMMAND_IO_SPACE);
+
+ //
+ // 3. set ACPI PM IO enable bit (PMREGMISC:PMIOSE or ACPI_CNTL:ACPI_EN)
+ //
+ PciOr8 (AcpiCtlReg, AcpiEnBit);
+ }
+
+ if (mHostBridgeDevId == INTEL_Q35_MCH_DEVICE_ID) {
+ //
+ // Set Root Complex Register Block BAR
+ //
+ PciWrite32 (
+ POWER_MGMT_REGISTER_Q35 (ICH9_RCBA),
+ ICH9_ROOT_COMPLEX_BASE | ICH9_RCBA_EN
+ );
+
+ //
+ // Set PCI Express Register Range Base Address
+ //
+ PciExBarInitialization ();
+ }
+}
+
+
+VOID
+BootModeInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (CmosRead8 (0xF) == 0xFE) {
+ mBootMode = BOOT_ON_S3_RESUME;
+ }
+ CmosWrite8 (0xF, 0x00);
+
+ Status = PeiServicesSetBootMode (mBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesInstallPpi (mPpiBootMode);
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+VOID
+ReserveEmuVariableNvStore (
+ )
+{
+ EFI_PHYSICAL_ADDRESS VariableStore;
+ RETURN_STATUS PcdStatus;
+
+ //
+ // Allocate storage for NV variables early on so it will be
+ // at a consistent address. Since VM memory is preserved
+ // across reboots, this allows the NV variable storage to survive
+ // a VM reboot.
+ //
+ VariableStore =
+ (EFI_PHYSICAL_ADDRESS)(UINTN)
+ AllocateRuntimePages (
+ EFI_SIZE_TO_PAGES (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize))
+ );
+ DEBUG ((DEBUG_INFO,
+ "Reserved variable store memory: 0x%lX; size: %dkb\n",
+ VariableStore,
+ (2 * PcdGet32 (PcdFlashNvStorageFtwSpareSize)) / 1024
+ ));
+ PcdStatus = PcdSet64S (PcdEmuVariableNvStoreReserved, VariableStore);
+ ASSERT_RETURN_ERROR (PcdStatus);
+}
+
+
+VOID
+DebugDumpCmos (
+ VOID
+ )
+{
+ UINT32 Loop;
+
+ DEBUG ((DEBUG_INFO, "CMOS:\n"));
+
+ for (Loop = 0; Loop < 0x80; Loop++) {
+ if ((Loop % 0x10) == 0) {
+ DEBUG ((DEBUG_INFO, "%02x:", Loop));
+ }
+ DEBUG ((DEBUG_INFO, " %02x", CmosRead8 (Loop)));
+ if ((Loop % 0x10) == 0xf) {
+ DEBUG ((DEBUG_INFO, "\n"));
+ }
+ }
+}
+
+
+VOID
+S3Verification (
+ VOID
+ )
+{
+#if defined (MDE_CPU_X64)
+ if (FeaturePcdGet (PcdSmmSmramRequire) && mS3Supported) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: S3Resume2Pei doesn't support X64 PEI + SMM yet.\n", __FUNCTION__));
+ DEBUG ((DEBUG_ERROR,
+ "%a: Please disable S3 on the QEMU command line (see the README),\n",
+ __FUNCTION__));
+ DEBUG ((DEBUG_ERROR,
+ "%a: or build OVMF with \"OvmfPkgIa32X64.dsc\".\n", __FUNCTION__));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+#endif
+}
+
+
+/**
+ Fetch the number of boot CPUs from QEMU and expose it to UefiCpuPkg modules.
+ Set the mMaxCpuCount variable.
+**/
+VOID
+MaxCpuCountInitialization (
+ VOID
+ )
+{
+ UINT16 ProcessorCount = 0;
+ RETURN_STATUS PcdStatus;
+
+ //
+ // If the fw_cfg key or fw_cfg entirely is unavailable, load mMaxCpuCount
+ // from the PCD default. No change to PCDs.
+ //
+ if (ProcessorCount == 0) {
+ mMaxCpuCount = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ return;
+ }
+ //
+ // Otherwise, set mMaxCpuCount to the value reported by QEMU.
+ //
+ mMaxCpuCount = ProcessorCount;
+ //
+ // Additionally, tell UefiCpuPkg modules (a) the exact number of VCPUs, (b)
+ // to wait, in the initial AP bringup, exactly as long as it takes for all of
+ // the APs to report in. For this, we set the longest representable timeout
+ // (approx. 71 minutes).
+ //
+ PcdStatus = PcdSet32S (PcdCpuMaxLogicalProcessorNumber, ProcessorCount);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet32S (PcdCpuApInitTimeOutInMicroSeconds, MAX_UINT32);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ DEBUG ((DEBUG_INFO, "%a: QEMU reports %d processor(s)\n", __FUNCTION__,
+ ProcessorCount));
+}
+
+
+/**
+ Perform Platform PEI initialization.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatform (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
+
+ //
+ // Initialize Local APIC Timer hardware and disable Local APIC Timer
+ // interrupts before initializing the Debug Agent and the debug timer is
+ // enabled.
+ //
+ InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
+ DisableApicTimerInterrupt ();
+
+ DebugDumpCmos ();
+
+ BootModeInitialization ();
+ AddressWidthInitialization ();
+ MaxCpuCountInitialization ();
+
+ //
+ // Query Host Bridge DID
+ //
+ mHostBridgeDevId = PciRead16 (OVMF_HOSTBRIDGE_DID);
+
+ if (FeaturePcdGet (PcdSmmSmramRequire)) {
+ Q35TsegMbytesInitialization ();
+ }
+
+ PublishPeiMemory ();
+
+ InitializeRamRegions ();
+
+ if (mBootMode != BOOT_ON_S3_RESUME) {
+ if (!FeaturePcdGet (PcdSmmSmramRequire)) {
+ ReserveEmuVariableNvStore ();
+ }
+ PeiFvInitialization ();
+ MemMapInitialization ();
+ NoexecDxeInitialization ();
+ }
+
+ InstallClearCacheCallback ();
+ AmdSevInitialize ();
+ MiscInitialization ();
+ InstallFeatureControlCallback ();
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.h
new file mode 100644
index 00000000000..331d25cba9c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/Platform.h
@@ -0,0 +1,137 @@
+/** @file
+ Platform PEI module include file.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _PLATFORM_PEI_H_INCLUDED_
+#define _PLATFORM_PEI_H_INCLUDED_
+
+#include <IndustryStandard/E820.h>
+
+VOID
+AddIoMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddIoMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize,
+ BOOLEAN Cacheable
+ );
+
+VOID
+AddressWidthInitialization (
+ VOID
+ );
+
+VOID
+Q35TsegMbytesInitialization (
+ VOID
+ );
+
+VOID
+Q35SmramAtDefaultSmbaseInitialization (
+ VOID
+ );
+
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ );
+
+UINT32
+GetSystemMemorySizeBelow4gb (
+ VOID
+ );
+
+VOID
+QemuUc32BaseInitialization (
+ VOID
+ );
+
+VOID
+InitializeRamRegions (
+ VOID
+ );
+
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ );
+
+VOID
+MemTypeInfoInitialization (
+ VOID
+ );
+
+VOID
+InstallFeatureControlCallback (
+ VOID
+ );
+
+VOID
+InstallClearCacheCallback (
+ VOID
+ );
+
+EFI_STATUS
+InitializeXen (
+ VOID
+ );
+
+BOOLEAN
+XenDetect (
+ VOID
+ );
+
+VOID
+AmdSevInitialize (
+ VOID
+ );
+
+extern BOOLEAN mXen;
+
+VOID
+XenPublishRamRegions (
+ VOID
+ );
+
+extern EFI_BOOT_MODE mBootMode;
+
+extern BOOLEAN mS3Supported;
+
+extern UINT8 mPhysMemAddressWidth;
+
+extern UINT32 mMaxCpuCount;
+
+extern UINT16 mHostBridgeDevId;
+
+extern BOOLEAN mQ35SmramAtDefaultSmbase;
+
+extern UINT32 mQemuUc32Base;
+
+#endif // _PLATFORM_PEI_H_INCLUDED_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
new file mode 100644
index 00000000000..652b30713c0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/PlatformPei/PlatformPei.inf
@@ -0,0 +1,113 @@
+## @file
+# Platform PEI driver
+#
+# This module provides platform specific function to detect boot mode.
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = PlatformPei
+ FILE_GUID = aa89d903-345b-4ab2-9abf-030b5efb5d50
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializePlatform
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ AmdSev.c
+ ClearCache.c
+ Cmos.c
+ Cmos.h
+ FeatureControl.c
+ Fv.c
+ MemDetect.c
+ Platform.c
+ Platform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+
+[LibraryClasses]
+ BaseLib
+ CacheMaintenanceLib
+ DebugLib
+ HobLib
+ IoLib
+ LocalApicLib
+ MemEncryptSevLib
+ MtrrLib
+ PciLib
+ PeimEntryPoint
+ PeiServicesLib
+ PeiServicesTablePointerLib
+ PcdLib
+ ResourcePublicationLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciIoSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Base
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio32Size
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base
+ gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDecompressionScratchEnd
+ gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes
+ gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+ gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
+ gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+
+[FeaturePcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid
+ gEfiPeiMpServicesPpiGuid
+
+[Depex]
+ TRUE
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia16/Real16ToFlat32.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia16/Real16ToFlat32.asm
new file mode 100644
index 00000000000..6d1e832db9a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia16/Real16ToFlat32.asm
@@ -0,0 +1,143 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 16 bit real mode into 32 bit flat protected mode
+;
+; Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>. All rights reserved.<BR>
+; Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+%define SEC_DEFAULT_CR0 0x00000023
+%define SEC_DEFAULT_CR4 0x640
+
+BITS 16
+
+;
+; Modified: EAX, EBX
+;
+; @param[out] DS Selector allowing flat access to all addresses
+; @param[out] ES Selector allowing flat access to all addresses
+; @param[out] FS Selector allowing flat access to all addresses
+; @param[out] GS Selector allowing flat access to all addresses
+; @param[out] SS Selector allowing flat access to all addresses
+;
+TransitionFromReal16To32BitFlat:
+
+ debugShowPostCode POSTCODE_16BIT_MODE
+
+ cli
+
+ mov bx, 0xf000
+ mov ds, bx
+
+ mov bx, ADDR16_OF(gdtr)
+
+o32 lgdt [cs:bx]
+
+ mov eax, SEC_DEFAULT_CR0
+ mov cr0, eax
+
+ jmp LINEAR_CODE_SEL:dword ADDR_OF(jumpTo32BitAndLandHere)
+BITS 32
+jumpTo32BitAndLandHere:
+
+ mov eax, SEC_DEFAULT_CR4
+ mov cr4, eax
+
+ debugShowPostCode POSTCODE_32BIT_MODE
+
+ mov ax, LINEAR_SEL
+ mov ds, ax
+ mov es, ax
+ mov fs, ax
+ mov gs, ax
+ mov ss, ax
+
+ OneTimeCallRet TransitionFromReal16To32BitFlat
+
+ALIGN 2
+
+gdtr:
+ dw GDT_END - GDT_BASE - 1 ; GDT limit
+ dd ADDR_OF(GDT_BASE)
+
+ALIGN 16
+
+;
+; Macros for GDT entries
+;
+
+%define PRESENT_FLAG(p) (p << 7)
+%define DPL(dpl) (dpl << 5)
+%define SYSTEM_FLAG(s) (s << 4)
+%define DESC_TYPE(t) (t)
+
+; Type: data, expand-up, writable, accessed
+%define DATA32_TYPE 3
+
+; Type: execute, readable, expand-up, accessed
+%define CODE32_TYPE 0xb
+
+; Type: execute, readable, expand-up, accessed
+%define CODE64_TYPE 0xb
+
+%define GRANULARITY_FLAG(g) (g << 7)
+%define DEFAULT_SIZE32(d) (d << 6)
+%define CODE64_FLAG(l) (l << 5)
+%define UPPER_LIMIT(l) (l)
+
+;
+; The Global Descriptor Table (GDT)
+;
+
+GDT_BASE:
+; null descriptor
+NULL_SEL equ $-GDT_BASE
+ DW 0 ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB 0 ; sys flag, dpl, type
+ DB 0 ; limit 19:16, flags
+ DB 0 ; base 31:24
+
+; linear data segment descriptor
+LINEAR_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(DATA32_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+
+; linear code segment descriptor
+LINEAR_CODE_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(1)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+
+%ifdef ARCH_X64
+; linear code (64-bit) segment descriptor
+LINEAR_CODE64_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE64_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(1)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+%endif
+
+; linear code segment descriptor
+LINEAR_CODE16_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+
+GDT_END:
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia32/PageTables64.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia32/PageTables64.asm
new file mode 100644
index 00000000000..147d7c828b0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/Ia32/PageTables64.asm
@@ -0,0 +1,149 @@
+;------------------------------------------------------------------------------
+; @file
+; Sets the CR3 register for 64-bit paging
+;
+; Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS 32
+
+%define PAGE_PRESENT 0x01
+%define PAGE_READ_WRITE 0x02
+%define PAGE_USER_SUPERVISOR 0x04
+%define PAGE_WRITE_THROUGH 0x08
+%define PAGE_CACHE_DISABLE 0x010
+%define PAGE_ACCESSED 0x020
+%define PAGE_DIRTY 0x040
+%define PAGE_PAT 0x080
+%define PAGE_GLOBAL 0x0100
+%define PAGE_2M_MBO 0x080
+%define PAGE_2M_PAT 0x01000
+
+%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
+ PAGE_ACCESSED + \
+ PAGE_DIRTY + \
+ PAGE_READ_WRITE + \
+ PAGE_PRESENT)
+
+%define PAGE_PDP_ATTR (PAGE_ACCESSED + \
+ PAGE_READ_WRITE + \
+ PAGE_PRESENT)
+
+; Check if Secure Encrypted Virtualization (SEV) feature is enabled
+;
+; If SEV is enabled then EAX will be at least 32
+; If SEV is disabled then EAX will be zero.
+;
+CheckSevFeature:
+ ; Check if we have a valid (0x8000_001F) CPUID leaf
+ mov eax, 0x80000000
+ cpuid
+
+ ; This check should fail on Intel or Non SEV AMD CPUs. In future if
+ ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
+ ; same bit definition.
+ cmp eax, 0x8000001f
+ jl NoSev
+
+ ; Check for memory encryption feature:
+ ; CPUID Fn8000_001F[EAX] - Bit 1
+ ;
+ mov eax, 0x8000001f
+ cpuid
+ bt eax, 1
+ jnc NoSev
+
+ ; Check if memory encryption is enabled
+ ; MSR_0xC0010131 - Bit 0 (SEV enabled)
+ mov ecx, 0xc0010131
+ rdmsr
+ bt eax, 0
+ jnc NoSev
+
+ ; Get pte bit position to enable memory encryption
+ ; CPUID Fn8000_001F[EBX] - Bits 5:0
+ ;
+ mov eax, ebx
+ and eax, 0x3f
+ jmp SevExit
+
+NoSev:
+ xor eax, eax
+
+SevExit:
+ OneTimeCallRet CheckSevFeature
+
+;
+; Modified: EAX, EBX, ECX, EDX
+;
+SetCr3ForPageTables64:
+
+ OneTimeCall CheckSevFeature
+ xor edx, edx
+ test eax, eax
+ jz SevNotActive
+
+ ; If SEV is enabled, C-bit is always above 31
+ sub eax, 32
+ bts edx, eax
+
+SevNotActive:
+
+ ;
+ ; For OVMF, build some initial page tables at
+ ; PcdOvmfSecPageTablesBase - (PcdOvmfSecPageTablesBase + 0x6000).
+ ;
+ ; This range should match with PcdOvmfSecPageTablesSize which is
+ ; declared in the FDF files.
+ ;
+ ; At the end of PEI, the pages tables will be rebuilt into a
+ ; more permanent location by DxeIpl.
+ ;
+
+ mov ecx, 6 * 0x1000 / 4
+ xor eax, eax
+clearPageTablesMemoryLoop:
+ mov dword[ecx * 4 + PT_ADDR (0) - 4], eax
+ loop clearPageTablesMemoryLoop
+
+ ;
+ ; Top level Page Directory Pointers (1 * 512GB entry)
+ ;
+ mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
+ mov dword[PT_ADDR (4)], edx
+
+ ;
+ ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
+ ;
+ mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
+ mov dword[PT_ADDR (0x1004)], edx
+ mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
+ mov dword[PT_ADDR (0x100C)], edx
+ mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
+ mov dword[PT_ADDR (0x1014)], edx
+ mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
+ mov dword[PT_ADDR (0x101C)], edx
+
+ ;
+ ; Page Table Entries (2048 * 2MB entries => 4GB)
+ ;
+ mov ecx, 0x800
+pageTableEntriesLoop:
+ mov eax, ecx
+ dec eax
+ shl eax, 21
+ add eax, PAGE_2M_PDE_ATTR
+ mov [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
+ mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
+ loop pageTableEntriesLoop
+
+ ;
+ ; Set CR3 now that the paging structures are available
+ ;
+ mov eax, PT_ADDR (0)
+ mov cr3, eax
+
+ OneTimeCallRet SetCr3ForPageTables64
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.inf
new file mode 100644
index 00000000000..7976cc54327
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.inf
@@ -0,0 +1,38 @@
+## @file
+# Reset Vector
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = ResetVector
+ FILE_GUID = 1BA0062E-C779-4582-8566-336AE8F78F09
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.1
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ ResetVector.nasmb
+
+[Packages]
+ OvmfPkg/OvmfPkg.dec
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[BuildOptions]
+ *_*_IA32_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/
+ *_*_X64_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.nasmb b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.nasmb
new file mode 100644
index 00000000000..e0cb2a6fcbd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/ResetVector/ResetVector.nasmb
@@ -0,0 +1,68 @@
+;------------------------------------------------------------------------------
+; @file
+; This file includes all other code files to assemble the reset vector code
+;
+; Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>.
+; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+;
+; If neither ARCH_IA32 nor ARCH_X64 are defined, then try to include
+; Base.h to use the C pre-processor to determine the architecture.
+;
+%ifndef ARCH_IA32
+ %ifndef ARCH_X64
+ #include <Base.h>
+ #if defined (MDE_CPU_IA32)
+ %define ARCH_IA32
+ #elif defined (MDE_CPU_X64)
+ %define ARCH_X64
+ #endif
+ %endif
+%endif
+
+%ifdef ARCH_IA32
+ %ifdef ARCH_X64
+ %error "Only one of ARCH_IA32 or ARCH_X64 can be defined."
+ %endif
+%elifdef ARCH_X64
+%else
+ %error "Either ARCH_IA32 or ARCH_X64 must be defined."
+%endif
+
+%include "CommonMacros.inc"
+
+%include "PostCodes.inc"
+
+%ifdef DEBUG_PORT80
+ %include "Port80Debug.asm"
+%elifdef DEBUG_SERIAL
+ %include "SerialDebug.asm"
+%else
+ %include "DebugDisabled.asm"
+%endif
+
+%include "Ia32/SearchForBfvBase.asm"
+%include "Ia32/SearchForSecEntry.asm"
+
+%ifdef ARCH_X64
+ #include <AutoGen.h>
+
+ %if (FixedPcdGet32 (PcdOvmfSecPageTablesSize) != 0x6000)
+ %error "This implementation inherently depends on PcdOvmfSecPageTablesSize"
+ %endif
+
+ %define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
+%include "Ia32/Flat32ToFlat64.asm"
+%include "Ia32/PageTables64.asm"
+%endif
+
+%include "Ia16/Real16ToFlat32.asm"
+%include "Ia16/Init16.asm"
+
+%include "Main.asm"
+
+%include "Ia16/ResetVectorVtf0.asm"
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c
new file mode 100644
index 00000000000..1ba5947c77e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/Bhyve.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ * Copyright (c) 2014, Pluribus Networks, Inc.
+ *
+ * SPDX-License-Identifier: BSD-2-Clause-Patent
+ */
+
+#include "SmbiosPlatformDxe.h"
+
+#define BHYVE_SMBIOS_PHYSICAL_ADDRESS 0x000F0000
+#define BHYVE_SMBIOS_PHYSICAL_END 0x000FFFFF
+
+/**
+ Locates the bhyve SMBIOS data if it exists
+
+ @return SMBIOS_TABLE_ENTRY_POINT Address of bhyve SMBIOS data
+
+**/
+SMBIOS_TABLE_ENTRY_POINT *
+GetBhyveSmbiosTables (
+ VOID
+ )
+{
+ UINT8 *BhyveSmbiosPtr;
+ SMBIOS_TABLE_ENTRY_POINT *BhyveSmbiosEntryPointStructure;
+
+ for (BhyveSmbiosPtr = (UINT8*)(UINTN) BHYVE_SMBIOS_PHYSICAL_ADDRESS;
+ BhyveSmbiosPtr < (UINT8*)(UINTN) BHYVE_SMBIOS_PHYSICAL_END;
+ BhyveSmbiosPtr += 0x10) {
+
+ BhyveSmbiosEntryPointStructure = (SMBIOS_TABLE_ENTRY_POINT *) BhyveSmbiosPtr;
+
+ if (!AsciiStrnCmp ((CHAR8 *) BhyveSmbiosEntryPointStructure->AnchorString, "_SM_", 4) &&
+ !AsciiStrnCmp ((CHAR8 *) BhyveSmbiosEntryPointStructure->IntermediateAnchorString, "_DMI_", 5) &&
+ IsEntryPointStructureValid (BhyveSmbiosEntryPointStructure)) {
+
+ return BhyveSmbiosEntryPointStructure;
+
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c
new file mode 100644
index 00000000000..2ba0474b037
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.c
@@ -0,0 +1,245 @@
+/** @file
+ This driver installs SMBIOS information for OVMF
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SmbiosPlatformDxe.h"
+
+#define TYPE0_STRINGS \
+ "EFI Development Kit II / OVMF\0" /* Vendor */ \
+ "0.0.0\0" /* BiosVersion */ \
+ "02/06/2015\0" /* BiosReleaseDate */
+//
+// Type definition and contents of the default Type 0 SMBIOS table.
+//
+#pragma pack(1)
+typedef struct {
+ SMBIOS_TABLE_TYPE0 Base;
+ UINT8 Strings[sizeof(TYPE0_STRINGS)];
+} OVMF_TYPE0;
+#pragma pack()
+
+STATIC CONST OVMF_TYPE0 mOvmfDefaultType0 = {
+ {
+ // SMBIOS_STRUCTURE Hdr
+ {
+ EFI_SMBIOS_TYPE_BIOS_INFORMATION, // UINT8 Type
+ sizeof (SMBIOS_TABLE_TYPE0), // UINT8 Length
+ },
+ 1, // SMBIOS_TABLE_STRING Vendor
+ 2, // SMBIOS_TABLE_STRING BiosVersion
+ 0xE800,// UINT16 BiosSegment
+ 3, // SMBIOS_TABLE_STRING BiosReleaseDate
+ 0, // UINT8 BiosSize
+ { // MISC_BIOS_CHARACTERISTICS BiosCharacteristics
+ 0, // Reserved :2
+ 0, // Unknown :1
+ 1, // BiosCharacteristicsNotSupported :1
+ // Remaining BiosCharacteristics bits left unset :60
+ },
+ { // BIOSCharacteristicsExtensionBytes[2]
+ 0, // BiosReserved
+ 0x1C // SystemReserved = VirtualMachineSupported |
+ // UefiSpecificationSupported |
+ // TargetContentDistributionEnabled
+ },
+ 0, // UINT8 SystemBiosMajorRelease
+ 0, // UINT8 SystemBiosMinorRelease
+ 0xFF, // UINT8 EmbeddedControllerFirmwareMajorRelease
+ 0xFF // UINT8 EmbeddedControllerFirmwareMinorRelease
+ },
+ // Text strings (unformatted area)
+ TYPE0_STRINGS
+};
+
+
+/**
+ Validates the SMBIOS entry point structure
+
+ @param EntryPointStructure SMBIOS entry point structure
+
+ @retval TRUE The entry point structure is valid
+ @retval FALSE The entry point structure is not valid
+
+**/
+BOOLEAN
+IsEntryPointStructureValid (
+ IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure
+ )
+{
+ UINTN Index;
+ UINT8 Length;
+ UINT8 Checksum;
+ UINT8 *BytePtr;
+
+ BytePtr = (UINT8*) EntryPointStructure;
+ Length = EntryPointStructure->EntryPointLength;
+ Checksum = 0;
+
+ for (Index = 0; Index < Length; Index++) {
+ Checksum = Checksum + (UINT8) BytePtr[Index];
+ }
+
+ if (Checksum != 0) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+/**
+ Get SMBIOS record length.
+
+ @param SmbiosTable SMBIOS pointer.
+
+**/
+UINTN
+SmbiosTableLength (
+ IN SMBIOS_STRUCTURE_POINTER SmbiosTable
+ )
+{
+ CHAR8 *AChar;
+ UINTN Length;
+
+ AChar = (CHAR8 *)(SmbiosTable.Raw + SmbiosTable.Hdr->Length);
+
+ //
+ // Each structure shall be terminated by a double-null (SMBIOS spec.7.1)
+ //
+ while ((*AChar != 0) || (*(AChar + 1) != 0)) {
+ AChar ++;
+ }
+ Length = ((UINTN)AChar - (UINTN)SmbiosTable.Raw + 2);
+
+ return Length;
+}
+
+
+/**
+ Install all structures from the given SMBIOS structures block
+
+ @param Smbios SMBIOS protocol
+ @param TableAddress SMBIOS tables starting address
+
+**/
+EFI_STATUS
+InstallAllStructures (
+ IN EFI_SMBIOS_PROTOCOL *Smbios,
+ IN UINT8 *TableAddress
+ )
+{
+ EFI_STATUS Status;
+ SMBIOS_STRUCTURE_POINTER SmbiosTable;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ BOOLEAN NeedSmbiosType0;
+
+ SmbiosTable.Raw = TableAddress;
+ if (SmbiosTable.Raw == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ NeedSmbiosType0 = TRUE;
+
+ while (SmbiosTable.Hdr->Type != 127) {
+ //
+ // Log the SMBIOS data for this structure
+ //
+ SmbiosHandle = SmbiosTable.Hdr->Handle;
+ Status = Smbios->Add (
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER*) SmbiosTable.Raw
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (SmbiosTable.Hdr->Type == 0) {
+ NeedSmbiosType0 = FALSE;
+ }
+
+ //
+ // Get the next structure address
+ //
+ SmbiosTable.Raw = (UINT8 *)(SmbiosTable.Raw + SmbiosTableLength (SmbiosTable));
+ }
+
+ if (NeedSmbiosType0) {
+ //
+ // Add OVMF default Type 0 (BIOS Information) table
+ //
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (
+ Smbios,
+ NULL,
+ &SmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER*) &mOvmfDefaultType0
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Installs SMBIOS information for OVMF
+
+ @param ImageHandle Module's image handle
+ @param SystemTable Pointer of EFI_SYSTEM_TABLE
+
+ @retval EFI_SUCCESS Smbios data successfully installed
+ @retval Other Smbios data was not installed
+
+**/
+EFI_STATUS
+EFIAPI
+SmbiosTablePublishEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure;
+ UINT8 *SmbiosTables = NULL;
+
+ //
+ // Find the SMBIOS protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiSmbiosProtocolGuid,
+ NULL,
+ (VOID**)&Smbios
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Add bhyve SMBIOS data
+ //
+ EntryPointStructure = GetBhyveSmbiosTables ();
+ if (EntryPointStructure != NULL) {
+ SmbiosTables = (UINT8*)(UINTN)EntryPointStructure->TableAddress;
+ }
+
+ if (SmbiosTables != NULL) {
+ Status = InstallAllStructures (Smbios, SmbiosTables);
+
+ //
+ // Free SmbiosTables if allocated by Qemu (i.e., NOT by Xen):
+ //
+ if (EntryPointStructure == NULL) {
+ FreePool (SmbiosTables);
+ }
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h
new file mode 100644
index 00000000000..d6ea62ba4d1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.h
@@ -0,0 +1,51 @@
+/** @file
+ This driver installs SMBIOS information for OVMF
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMBIOS_PLATFORM_DXE_H_
+#define _SMBIOS_PLATFORM_DXE_H_
+
+#include <PiDxe.h>
+#include <Protocol/Smbios.h>
+#include <IndustryStandard/SmBios.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+
+/**
+ Locates the bhyve SMBIOS data if it exists
+
+ @return SMBIOS_TABLE_ENTRY_POINT Address of bhyve SMBIOS data
+
+**/
+SMBIOS_TABLE_ENTRY_POINT *
+GetBhyveSmbiosTables (
+ VOID
+ );
+
+
+/**
+ Validates the SMBIOS entry point structure
+
+ @param EntryPointStructure SMBIOS entry point structure
+
+ @retval TRUE The entry point structure is valid
+ @retval FALSE The entry point structure is not valid
+
+**/
+BOOLEAN
+IsEntryPointStructureValid (
+ IN SMBIOS_TABLE_ENTRY_POINT *EntryPointStructure
+ );
+
+#endif /* _SMBIOS_PLATFORM_DXE_H_ */
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
new file mode 100644
index 00000000000..ffad1bd3388
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/SmbiosPlatformDxe/SmbiosPlatformDxe.inf
@@ -0,0 +1,55 @@
+## @file
+# This driver installs SMBIOS information for bhyve
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2011, Bei Guan <gbtju85@gmail.com>
+# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = SmbiosPlatformDxe
+ FILE_GUID = e2d8a63c-c239-484f-bb21-2917843cc382
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+
+ ENTRY_POINT = SmbiosTablePublishEntry
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC ARM AARCH64
+#
+
+[Sources]
+ Bhyve.c
+ SmbiosPlatformDxe.h
+ SmbiosPlatformDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ MemoryAllocationLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdQemuSmbiosValidated
+
+[Protocols]
+ gEfiSmbiosProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/VarStore.fdf.inc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/VarStore.fdf.inc
new file mode 100644
index 00000000000..9fcc9eda650
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Bhyve/VarStore.fdf.inc
@@ -0,0 +1,115 @@
+## @file
+# FDF include file with Layout Regions that define an empty variable store.
+#
+# Copyright (C) 2014, Red Hat, Inc.
+# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x00000000|0x0000e000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00000000|0x00040000
+!endif
+#NV_VARIABLE_STORE
+DATA = {
+ ## This is the EFI_FIRMWARE_VOLUME_HEADER
+ # ZeroVector []
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ # FileSystemGuid: gEfiSystemNvDataFvGuid =
+ # { 0xFFF12B8D, 0x7696, 0x4C8B,
+ # { 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50 }}
+ 0x8D, 0x2B, 0xF1, 0xFF, 0x96, 0x76, 0x8B, 0x4C,
+ 0xA9, 0x85, 0x27, 0x47, 0x07, 0x5B, 0x4F, 0x50,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+ # FvLength: 0x20000
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+ # FvLength: 0x84000
+ 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+!endif
+ # Signature "_FVH" # Attributes
+ 0x5f, 0x46, 0x56, 0x48, 0xff, 0xfe, 0x04, 0x00,
+ # HeaderLength
+ 0x48, 0x00,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+ # CheckSum
+ 0x19, 0xF9,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+ # CheckSum
+ 0xAF, 0xB8,
+!endif
+ # ExtHeaderOffset #Reserved #Revision
+ 0x00, 0x00, 0x00, 0x02,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+ # Blockmap[0]: 0x20 Blocks * 0x1000 Bytes / Block
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+ # Blockmap[0]: 0x84 Blocks * 0x1000 Bytes / Block
+ 0x84, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+!endif
+ # Blockmap[1]: End
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ ## This is the VARIABLE_STORE_HEADER
+ # It is compatible with SECURE_BOOT_ENABLE == FALSE as well.
+ # Signature: gEfiAuthenticatedVariableGuid =
+ # { 0xaaf32c78, 0x947b, 0x439a,
+ # { 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92 }}
+ 0x78, 0x2c, 0xf3, 0xaa, 0x7b, 0x94, 0x9a, 0x43,
+ 0xa1, 0x80, 0x2e, 0x14, 0x4e, 0xc3, 0x77, 0x92,
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+ # Size: 0xe000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+ # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0xdfb8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0xDF, 0x00, 0x00,
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+ # Size: 0x40000 (gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize) -
+ # 0x48 (size of EFI_FIRMWARE_VOLUME_HEADER) = 0x3ffb8
+ # This can speed up the Variable Dispatch a bit.
+ 0xB8, 0xFF, 0x03, 0x00,
+!endif
+ # FORMATTED: 0x5A #HEALTHY: 0xFE #Reserved: UINT16 #Reserved1: UINT32
+ 0x5A, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x0000e000|0x00001000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00040000|0x00001000
+!endif
+#NV_EVENT_LOG
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x0000f000|0x00001000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00041000|0x00001000
+!endif
+#NV_FTW_WORKING
+DATA = {
+ # EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
+ # { 0x9e58292b, 0x7c68, 0x497d, { 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95 }}
+ 0x2b, 0x29, 0x58, 0x9e, 0x68, 0x7c, 0x7d, 0x49,
+ 0xa0, 0xce, 0x65, 0x0, 0xfd, 0x9f, 0x1b, 0x95,
+ # Crc:UINT32 #WorkingBlockValid:1, WorkingBlockInvalid:1, Reserved
+ 0x2c, 0xaf, 0x2c, 0x64, 0xFE, 0xFF, 0xFF, 0xFF,
+ # WriteQueueSize: UINT64
+ 0xE0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+}
+
+!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
+0x00010000|0x00010000
+!endif
+!if $(FD_SIZE_IN_KB) == 4096
+0x00042000|0x00042000
+!endif
+#NV_FTW_SPARE
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
index 47313af2a1e..51b1496cb75 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
@@ -10,12 +10,15 @@
#include <IndustryStandard/Q35MchIch9.h> // ICH9_APM_CNT
#include <IndustryStandard/QemuCpuHotplug.h> // QEMU_CPUHP_CMD_GET_PENDING
#include <Library/BaseLib.h> // CpuDeadLoop()
+#include <Library/CpuLib.h> // CpuSleep()
#include <Library/DebugLib.h> // ASSERT()
#include <Library/MmServicesTableLib.h> // gMmst
#include <Library/PcdLib.h> // PcdGetBool()
#include <Library/SafeIntLib.h> // SafeUintnSub()
+#include <Pcd/CpuHotEjectData.h> // CPU_HOT_EJECT_DATA
#include <Protocol/MmCpuIo.h> // EFI_MM_CPU_IO_PROTOCOL
#include <Protocol/SmmCpuService.h> // EFI_SMM_CPU_SERVICE_PROTOCOL
+#include <Register/Intel/ArchitecturalMsr.h> // MSR_IA32_APIC_BASE_REGISTER
#include <Uefi/UefiBaseType.h> // EFI_STATUS
#include "ApicId.h" // APIC_ID
@@ -32,11 +35,12 @@ STATIC EFI_MM_CPU_IO_PROTOCOL *mMmCpuIo;
//
STATIC EFI_SMM_CPU_SERVICE_PROTOCOL *mMmCpuService;
//
-// This structure is a communication side-channel between the
+// These structures serve as communication side-channels between the
// EFI_SMM_CPU_SERVICE_PROTOCOL consumer (i.e., this driver) and provider
// (i.e., PiSmmCpuDxeSmm).
//
STATIC CPU_HOT_PLUG_DATA *mCpuHotPlugData;
+STATIC CPU_HOT_EJECT_DATA *mCpuHotEjectData;
//
// SMRAM arrays for fetching the APIC IDs of processors with pending events (of
// known event types), for the time of just one MMI.
@@ -45,13 +49,16 @@ STATIC CPU_HOT_PLUG_DATA *mCpuHotPlugData;
// don't want to allocate SMRAM at OS runtime, and potentially fail (or
// fragment the SMRAM map).
//
-// These arrays provide room for ("possible CPU count" minus one) APIC IDs
-// each, as we don't expect every possible CPU to appear, or disappear, in a
-// single MMI. The numbers of used (populated) elements in the arrays are
+// The first array stores APIC IDs for hot-plug events, the second and the
+// third store APIC IDs and QEMU CPU Selectors (both indexed similarly) for
+// hot-unplug events. All of these provide room for "possible CPU count" minus
+// one elements as we don't expect every possible CPU to appear, or disappear,
+// in a single MMI. The numbers of used (populated) elements in the arrays are
// determined on every MMI separately.
//
STATIC APIC_ID *mPluggedApicIds;
STATIC APIC_ID *mToUnplugApicIds;
+STATIC UINT32 *mToUnplugSelectors;
//
// Address of the non-SMRAM reserved memory page that contains the Post-SMM Pen
// for hot-added CPUs.
@@ -62,6 +69,426 @@ STATIC UINT32 mPostSmmPenAddress;
//
STATIC EFI_HANDLE mDispatchHandle;
+/**
+ Process CPUs that have been hot-added, per QemuCpuhpCollectApicIds().
+
+ For each such CPU, relocate the SMBASE, and report the CPU to PiSmmCpuDxeSmm
+ via EFI_SMM_CPU_SERVICE_PROTOCOL. If the supposedly hot-added CPU is already
+ known, skip it silently.
+
+ @param[in] PluggedApicIds The APIC IDs of the CPUs that have been
+ hot-plugged.
+
+ @param[in] PluggedCount The number of filled-in APIC IDs in
+ PluggedApicIds.
+
+ @retval EFI_SUCCESS CPUs corresponding to all the APIC IDs are
+ populated.
+
+ @retval EFI_OUT_OF_RESOURCES Out of APIC ID space in "mCpuHotPlugData".
+
+ @return Error codes propagated from SmbaseRelocate()
+ and mMmCpuService->AddProcessor().
+**/
+STATIC
+EFI_STATUS
+ProcessHotAddedCpus (
+ IN APIC_ID *PluggedApicIds,
+ IN UINT32 PluggedCount
+ )
+{
+ EFI_STATUS Status;
+ UINT32 PluggedIdx;
+ UINT32 NewSlot;
+
+ //
+ // The Post-SMM Pen need not be reinstalled multiple times within a single
+ // root MMI handling. Even reinstalling once per root MMI is only prudence;
+ // in theory installing the pen in the driver's entry point function should
+ // suffice.
+ //
+ SmbaseReinstallPostSmmPen (mPostSmmPenAddress);
+
+ PluggedIdx = 0;
+ NewSlot = 0;
+ while (PluggedIdx < PluggedCount) {
+ APIC_ID NewApicId;
+ UINT32 CheckSlot;
+ UINTN NewProcessorNumberByProtocol;
+
+ NewApicId = PluggedApicIds[PluggedIdx];
+
+ //
+ // Check if the supposedly hot-added CPU is already known to us.
+ //
+ for (CheckSlot = 0;
+ CheckSlot < mCpuHotPlugData->ArrayLength;
+ CheckSlot++) {
+ if (mCpuHotPlugData->ApicId[CheckSlot] == NewApicId) {
+ break;
+ }
+ }
+ if (CheckSlot < mCpuHotPlugData->ArrayLength) {
+ DEBUG ((DEBUG_VERBOSE, "%a: APIC ID " FMT_APIC_ID " was hot-plugged "
+ "before; ignoring it\n", __FUNCTION__, NewApicId));
+ PluggedIdx++;
+ continue;
+ }
+
+ //
+ // Find the first empty slot in CPU_HOT_PLUG_DATA.
+ //
+ while (NewSlot < mCpuHotPlugData->ArrayLength &&
+ mCpuHotPlugData->ApicId[NewSlot] != MAX_UINT64) {
+ NewSlot++;
+ }
+ if (NewSlot == mCpuHotPlugData->ArrayLength) {
+ DEBUG ((DEBUG_ERROR, "%a: no room for APIC ID " FMT_APIC_ID "\n",
+ __FUNCTION__, NewApicId));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Store the APIC ID of the new processor to the slot.
+ //
+ mCpuHotPlugData->ApicId[NewSlot] = NewApicId;
+
+ //
+ // Relocate the SMBASE of the new CPU.
+ //
+ Status = SmbaseRelocate (NewApicId, mCpuHotPlugData->SmBase[NewSlot],
+ mPostSmmPenAddress);
+ if (EFI_ERROR (Status)) {
+ goto RevokeNewSlot;
+ }
+
+ //
+ // Add the new CPU with EFI_SMM_CPU_SERVICE_PROTOCOL.
+ //
+ Status = mMmCpuService->AddProcessor (mMmCpuService, NewApicId,
+ &NewProcessorNumberByProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: AddProcessor(" FMT_APIC_ID "): %r\n",
+ __FUNCTION__, NewApicId, Status));
+ goto RevokeNewSlot;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: hot-added APIC ID " FMT_APIC_ID ", SMBASE 0x%Lx, "
+ "EFI_SMM_CPU_SERVICE_PROTOCOL assigned number %Lu\n", __FUNCTION__,
+ NewApicId, (UINT64)mCpuHotPlugData->SmBase[NewSlot],
+ (UINT64)NewProcessorNumberByProtocol));
+
+ NewSlot++;
+ PluggedIdx++;
+ }
+
+ //
+ // We've processed this batch of hot-added CPUs.
+ //
+ return EFI_SUCCESS;
+
+RevokeNewSlot:
+ mCpuHotPlugData->ApicId[NewSlot] = MAX_UINT64;
+
+ return Status;
+}
+
+/**
+ EjectCpu needs to know the BSP at SMI exit at a point when
+ some of the EFI_SMM_CPU_SERVICE_PROTOCOL state has been torn
+ down.
+ Reuse the logic from OvmfPkg::PlatformSmmBspElection() to
+ do that.
+
+ @retval TRUE If the CPU executing this function is the BSP.
+
+ @retval FALSE If the CPU executing this function is an AP.
+**/
+STATIC
+BOOLEAN
+CheckIfBsp (
+ VOID
+ )
+{
+ MSR_IA32_APIC_BASE_REGISTER ApicBaseMsr;
+ BOOLEAN IsBsp;
+
+ ApicBaseMsr.Uint64 = AsmReadMsr64 (MSR_IA32_APIC_BASE);
+ IsBsp = (BOOLEAN)(ApicBaseMsr.Bits.BSP == 1);
+ return IsBsp;
+}
+
+/**
+ CPU Hot-eject handler, called from SmmCpuFeaturesRendezvousExit()
+ on each CPU at exit from SMM.
+
+ If, the executing CPU is neither the BSP, nor being ejected, nothing
+ to be done.
+ If, the executing CPU is being ejected, wait in a halted loop
+ until ejected.
+ If, the executing CPU is the BSP, set QEMU CPU status to eject
+ for CPUs being ejected.
+
+ @param[in] ProcessorNum ProcessorNum denotes the CPU exiting SMM,
+ and will be used as an index into
+ CPU_HOT_EJECT_DATA->QemuSelectorMap. It is
+ identical to the processor handle number in
+ EFI_SMM_CPU_SERVICE_PROTOCOL.
+**/
+VOID
+EFIAPI
+EjectCpu (
+ IN UINTN ProcessorNum
+ )
+{
+ UINT64 QemuSelector;
+
+ if (CheckIfBsp ()) {
+ UINT32 Idx;
+
+ for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {
+ QemuSelector = mCpuHotEjectData->QemuSelectorMap[Idx];
+
+ if (QemuSelector != CPU_EJECT_QEMU_SELECTOR_INVALID) {
+ //
+ // This to-be-ejected-CPU has already received the BSP's SMI exit
+ // signal and will execute SmmCpuFeaturesRendezvousExit()
+ // followed by this callback or is already penned in the
+ // CpuSleep() loop below.
+ //
+ // Tell QEMU to context-switch it out.
+ //
+ QemuCpuhpWriteCpuSelector (mMmCpuIo, (UINT32) QemuSelector);
+ QemuCpuhpWriteCpuStatus (mMmCpuIo, QEMU_CPUHP_STAT_EJECT);
+
+ //
+ // Now that we've ejected the CPU corresponding to QemuSelectorMap[Idx],
+ // clear its eject status to ensure that an invalid future SMI does
+ // not end up trying a spurious eject or a newly hotplugged CPU does
+ // not get penned in the CpuSleep() loop.
+ //
+ // Note that the QemuCpuhpWriteCpuStatus() command above is a write to
+ // a different address space and uses the EFI_MM_CPU_IO_PROTOCOL.
+ //
+ // This means that we are guaranteed that the following assignment
+ // will not be reordered before the eject. And, so we can safely
+ // do this write here.
+ //
+ mCpuHotEjectData->QemuSelectorMap[Idx] =
+ CPU_EJECT_QEMU_SELECTOR_INVALID;
+
+ DEBUG ((DEBUG_INFO, "%a: Unplugged ProcessorNum %u, "
+ "QemuSelector %Lu\n", __FUNCTION__, Idx, QemuSelector));
+ }
+ }
+
+ //
+ // We are done until the next hot-unplug; clear the handler.
+ //
+ // mCpuHotEjectData->Handler is a NOP for any CPU not under ejection.
+ // So, once we are done with all the ejections, we can safely reset it
+ // here since any CPU dereferencing it would only see either the old
+ // or the new value (since it is aligned at a natural boundary.)
+ //
+ mCpuHotEjectData->Handler = NULL;
+ return;
+ }
+
+ //
+ // Reached only on APs
+ //
+
+ //
+ // mCpuHotEjectData->QemuSelectorMap[ProcessorNum] is updated
+ // on the BSP in the ongoing SMI at two places:
+ //
+ // - UnplugCpus() where the BSP determines if a CPU is under ejection
+ // or not. As a comment in UnplugCpus() at set-up, and in
+ // SmmCpuFeaturesRendezvousExit() where it is dereferenced describe,
+ // any such updates are guaranteed to be ordered-before the
+ // dereference below.
+ //
+ // - EjectCpu() on the BSP (above) updates QemuSelectorMap[ProcessorNum]
+ // for a CPU once it's ejected.
+ //
+ // The CPU under ejection: might be executing anywhere between the
+ // AllCpusInSync loop in SmiRendezvous(), to about to dereference
+ // QemuSelectorMap[ProcessorNum].
+ // As described in the comment above where we do the reset, this
+ // is not a problem since the ejected CPU never sees the after value.
+ // CPUs not-under ejection: never see any changes so they are fine.
+ //
+ QemuSelector = mCpuHotEjectData->QemuSelectorMap[ProcessorNum];
+ if (QemuSelector == CPU_EJECT_QEMU_SELECTOR_INVALID) {
+ return;
+ }
+
+ //
+ // APs being unplugged get here from SmmCpuFeaturesRendezvousExit()
+ // after having been cleared to exit the SMI and so have no SMM
+ // processing remaining.
+ //
+ // Keep them penned here until the BSP tells QEMU to eject them.
+ //
+ for (;;) {
+ DisableInterrupts ();
+ CpuSleep ();
+ }
+}
+
+/**
+ Process to be hot-unplugged CPUs, per QemuCpuhpCollectApicIds().
+
+ For each such CPU, report the CPU to PiSmmCpuDxeSmm via
+ EFI_SMM_CPU_SERVICE_PROTOCOL and stash the QEMU Cpu Selectors for later
+ ejection. If the to be hot-unplugged CPU is unknown, skip it silently.
+
+ Additonally, if we do stash any Cpu Selectors, also install a CPU eject
+ handler which would handle the ejection.
+
+ @param[in] ToUnplugApicIds The APIC IDs of the CPUs that are about to be
+ hot-unplugged.
+
+ @param[in] ToUnplugSelectors The QEMU Selectors of the CPUs that are about to
+ be hot-unplugged.
+
+ @param[in] ToUnplugCount The number of filled-in APIC IDs in
+ ToUnplugApicIds.
+
+ @retval EFI_ALREADY_STARTED For the ProcessorNum that
+ EFI_SMM_CPU_SERVICE_PROTOCOL had assigned to
+ one of the APIC IDs in ToUnplugApicIds,
+ mCpuHotEjectData->QemuSelectorMap already has
+ the QemuSelector value stashed. (This should
+ never happen.)
+
+ @retval EFI_SUCCESS Known APIC IDs have been removed from SMM data
+ structures.
+
+ @return Error codes propagated from
+ mMmCpuService->RemoveProcessor().
+**/
+STATIC
+EFI_STATUS
+UnplugCpus (
+ IN APIC_ID *ToUnplugApicIds,
+ IN UINT32 *ToUnplugSelectors,
+ IN UINT32 ToUnplugCount
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ToUnplugIdx;
+ UINT32 EjectCount;
+ UINTN ProcessorNum;
+
+ ToUnplugIdx = 0;
+ EjectCount = 0;
+ while (ToUnplugIdx < ToUnplugCount) {
+ APIC_ID RemoveApicId;
+ UINT32 QemuSelector;
+
+ RemoveApicId = ToUnplugApicIds[ToUnplugIdx];
+ QemuSelector = ToUnplugSelectors[ToUnplugIdx];
+
+ //
+ // mCpuHotPlugData->ApicId maps ProcessorNum -> ApicId. Use RemoveApicId
+ // to find the corresponding ProcessorNum for the CPU to be removed.
+ //
+ // With this we can establish a 3 way mapping:
+ // APIC_ID -- ProcessorNum -- QemuSelector
+ //
+ // We stash the ProcessorNum -> QemuSelector mapping so it can later be
+ // used for CPU hot-eject in SmmCpuFeaturesRendezvousExit() context (where
+ // we only have ProcessorNum available.)
+ //
+
+ for (ProcessorNum = 0;
+ ProcessorNum < mCpuHotPlugData->ArrayLength;
+ ProcessorNum++) {
+ if (mCpuHotPlugData->ApicId[ProcessorNum] == RemoveApicId) {
+ break;
+ }
+ }
+
+ //
+ // Ignore the unplug if APIC ID not found
+ //
+ if (ProcessorNum == mCpuHotPlugData->ArrayLength) {
+ DEBUG ((DEBUG_VERBOSE, "%a: did not find APIC ID " FMT_APIC_ID
+ " to unplug\n", __FUNCTION__, RemoveApicId));
+ ToUnplugIdx++;
+ continue;
+ }
+
+ //
+ // Mark ProcessorNum for removal from SMM data structures
+ //
+ Status = mMmCpuService->RemoveProcessor (mMmCpuService, ProcessorNum);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: RemoveProcessor(" FMT_APIC_ID "): %r\n",
+ __FUNCTION__, RemoveApicId, Status));
+ return Status;
+ }
+
+ if (mCpuHotEjectData->QemuSelectorMap[ProcessorNum] !=
+ CPU_EJECT_QEMU_SELECTOR_INVALID) {
+ //
+ // mCpuHotEjectData->QemuSelectorMap[ProcessorNum] is set to
+ // CPU_EJECT_QEMU_SELECTOR_INVALID when mCpuHotEjectData->QemuSelectorMap
+ // is allocated, and once the subject processsor is ejected.
+ //
+ // Additionally, mMmCpuService->RemoveProcessor(ProcessorNum) invalidates
+ // mCpuHotPlugData->ApicId[ProcessorNum], so a given ProcessorNum can
+ // never match more than one APIC ID -- nor, by transitivity, designate
+ // more than one QemuSelector -- in a single invocation of UnplugCpus().
+ //
+ DEBUG ((DEBUG_ERROR, "%a: ProcessorNum %Lu maps to QemuSelector %Lu, "
+ "cannot also map to %u\n", __FUNCTION__, (UINT64)ProcessorNum,
+ mCpuHotEjectData->QemuSelectorMap[ProcessorNum], QemuSelector));
+
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Stash the QemuSelector so we can do the actual ejection later.
+ //
+ mCpuHotEjectData->QemuSelectorMap[ProcessorNum] = (UINT64)QemuSelector;
+
+ DEBUG ((DEBUG_INFO, "%a: Started hot-unplug on ProcessorNum %Lu, APIC ID "
+ FMT_APIC_ID ", QemuSelector %u\n", __FUNCTION__, (UINT64)ProcessorNum,
+ RemoveApicId, QemuSelector));
+
+ EjectCount++;
+ ToUnplugIdx++;
+ }
+
+ if (EjectCount != 0) {
+ //
+ // We have processors to be ejected; install the handler.
+ //
+ mCpuHotEjectData->Handler = EjectCpu;
+
+ //
+ // The BSP and APs load mCpuHotEjectData->Handler, and
+ // mCpuHotEjectData->QemuSelectorMap[] in SmmCpuFeaturesRendezvousExit()
+ // and EjectCpu().
+ //
+ // The comment in SmmCpuFeaturesRendezvousExit() details how we use
+ // the AllCpusInSync control-dependency to ensure that any loads are
+ // ordered-after the stores above.
+ //
+ // Ensure that the stores above are ordered-before the AllCpusInSync store
+ // by using a MemoryFence() with release semantics.
+ //
+ MemoryFence ();
+ }
+
+ //
+ // We've removed this set of APIC IDs from SMM data structures and
+ // have installed an ejection handler if needed.
+ //
+ return EFI_SUCCESS;
+}
/**
CPU Hotplug MMI handler function.
@@ -122,8 +549,6 @@ CpuHotplugMmi (
UINT8 ApmControl;
UINT32 PluggedCount;
UINT32 ToUnplugCount;
- UINT32 PluggedIdx;
- UINT32 NewSlot;
//
// Assert that we are entering this function due to our root MMI handler
@@ -168,79 +593,25 @@ CpuHotplugMmi (
mPluggedApicIds,
&PluggedCount,
mToUnplugApicIds,
+ mToUnplugSelectors,
&ToUnplugCount
);
if (EFI_ERROR (Status)) {
goto Fatal;
}
- if (ToUnplugCount > 0) {
- DEBUG ((DEBUG_ERROR, "%a: hot-unplug is not supported yet\n",
- __FUNCTION__));
- goto Fatal;
- }
-
- //
- // Process hot-added CPUs.
- //
- // The Post-SMM Pen need not be reinstalled multiple times within a single
- // root MMI handling. Even reinstalling once per root MMI is only prudence;
- // in theory installing the pen in the driver's entry point function should
- // suffice.
- //
- SmbaseReinstallPostSmmPen (mPostSmmPenAddress);
- PluggedIdx = 0;
- NewSlot = 0;
- while (PluggedIdx < PluggedCount) {
- APIC_ID NewApicId;
- UINTN NewProcessorNumberByProtocol;
-
- NewApicId = mPluggedApicIds[PluggedIdx];
- //
- // Find the first empty slot in CPU_HOT_PLUG_DATA.
- //
- while (NewSlot < mCpuHotPlugData->ArrayLength &&
- mCpuHotPlugData->ApicId[NewSlot] != MAX_UINT64) {
- NewSlot++;
- }
- if (NewSlot == mCpuHotPlugData->ArrayLength) {
- DEBUG ((DEBUG_ERROR, "%a: no room for APIC ID " FMT_APIC_ID "\n",
- __FUNCTION__, NewApicId));
- goto Fatal;
- }
-
- //
- // Store the APIC ID of the new processor to the slot.
- //
- mCpuHotPlugData->ApicId[NewSlot] = NewApicId;
-
- //
- // Relocate the SMBASE of the new CPU.
- //
- Status = SmbaseRelocate (NewApicId, mCpuHotPlugData->SmBase[NewSlot],
- mPostSmmPenAddress);
+ if (PluggedCount > 0) {
+ Status = ProcessHotAddedCpus (mPluggedApicIds, PluggedCount);
if (EFI_ERROR (Status)) {
- goto RevokeNewSlot;
+ goto Fatal;
}
+ }
- //
- // Add the new CPU with EFI_SMM_CPU_SERVICE_PROTOCOL.
- //
- Status = mMmCpuService->AddProcessor (mMmCpuService, NewApicId,
- &NewProcessorNumberByProtocol);
+ if (ToUnplugCount > 0) {
+ Status = UnplugCpus (mToUnplugApicIds, mToUnplugSelectors, ToUnplugCount);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: AddProcessor(" FMT_APIC_ID "): %r\n",
- __FUNCTION__, NewApicId, Status));
- goto RevokeNewSlot;
+ goto Fatal;
}
-
- DEBUG ((DEBUG_INFO, "%a: hot-added APIC ID " FMT_APIC_ID ", SMBASE 0x%Lx, "
- "EFI_SMM_CPU_SERVICE_PROTOCOL assigned number %Lu\n", __FUNCTION__,
- NewApicId, (UINT64)mCpuHotPlugData->SmBase[NewSlot],
- (UINT64)NewProcessorNumberByProtocol));
-
- NewSlot++;
- PluggedIdx++;
}
//
@@ -248,9 +619,6 @@ CpuHotplugMmi (
//
return EFI_SUCCESS;
-RevokeNewSlot:
- mCpuHotPlugData->ApicId[NewSlot] = MAX_UINT64;
-
Fatal:
ASSERT (FALSE);
CpuDeadLoop ();
@@ -272,7 +640,9 @@ CpuHotplugEntry (
)
{
EFI_STATUS Status;
+ UINTN Len;
UINTN Size;
+ UINTN SizeSel;
//
// This module should only be included when SMM support is required.
@@ -309,9 +679,14 @@ CpuHotplugEntry (
//
// Our DEPEX on EFI_SMM_CPU_SERVICE_PROTOCOL guarantees that PiSmmCpuDxeSmm
- // has pointed PcdCpuHotPlugDataAddress to CPU_HOT_PLUG_DATA in SMRAM.
+ // has pointed:
+ // - PcdCpuHotPlugDataAddress to CPU_HOT_PLUG_DATA in SMRAM,
+ // - PcdCpuHotEjectDataAddress to CPU_HOT_EJECT_DATA in SMRAM, if the
+ // possible CPU count is greater than 1.
//
mCpuHotPlugData = (VOID *)(UINTN)PcdGet64 (PcdCpuHotPlugDataAddress);
+ mCpuHotEjectData = (VOID *)(UINTN)PcdGet64 (PcdCpuHotEjectDataAddress);
+
if (mCpuHotPlugData == NULL) {
Status = EFI_NOT_FOUND;
DEBUG ((DEBUG_ERROR, "%a: CPU_HOT_PLUG_DATA: %r\n", __FUNCTION__, Status));
@@ -323,11 +698,25 @@ CpuHotplugEntry (
if (mCpuHotPlugData->ArrayLength == 1) {
return EFI_UNSUPPORTED;
}
+
+ if (mCpuHotEjectData == NULL) {
+ Status = EFI_NOT_FOUND;
+ } else if (mCpuHotPlugData->ArrayLength != mCpuHotEjectData->ArrayLength) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = EFI_SUCCESS;
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: CPU_HOT_EJECT_DATA: %r\n", __FUNCTION__, Status));
+ goto Fatal;
+ }
+
//
// Allocate the data structures that depend on the possible CPU count.
//
- if (RETURN_ERROR (SafeUintnSub (mCpuHotPlugData->ArrayLength, 1, &Size)) ||
- RETURN_ERROR (SafeUintnMult (sizeof (APIC_ID), Size, &Size))) {
+ if (RETURN_ERROR (SafeUintnSub (mCpuHotPlugData->ArrayLength, 1, &Len)) ||
+ RETURN_ERROR (SafeUintnMult (sizeof (APIC_ID), Len, &Size)) ||
+ RETURN_ERROR (SafeUintnMult (sizeof (UINT32), Len, &SizeSel))) {
Status = EFI_ABORTED;
DEBUG ((DEBUG_ERROR, "%a: invalid CPU_HOT_PLUG_DATA\n", __FUNCTION__));
goto Fatal;
@@ -344,6 +733,12 @@ CpuHotplugEntry (
DEBUG ((DEBUG_ERROR, "%a: MmAllocatePool(): %r\n", __FUNCTION__, Status));
goto ReleasePluggedApicIds;
}
+ Status = gMmst->MmAllocatePool (EfiRuntimeServicesData, SizeSel,
+ (VOID **)&mToUnplugSelectors);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: MmAllocatePool(): %r\n", __FUNCTION__, Status));
+ goto ReleaseToUnplugApicIds;
+ }
//
// Allocate the Post-SMM Pen for hot-added CPUs.
@@ -351,7 +746,7 @@ CpuHotplugEntry (
Status = SmbaseAllocatePostSmmPen (&mPostSmmPenAddress,
SystemTable->BootServices);
if (EFI_ERROR (Status)) {
- goto ReleaseToUnplugApicIds;
+ goto ReleaseToUnplugSelectors;
}
//
@@ -411,6 +806,10 @@ ReleasePostSmmPen:
SmbaseReleasePostSmmPen (mPostSmmPenAddress, SystemTable->BootServices);
mPostSmmPenAddress = 0;
+ReleaseToUnplugSelectors:
+ gMmst->MmFreePool (mToUnplugSelectors);
+ mToUnplugSelectors = NULL;
+
ReleaseToUnplugApicIds:
gMmst->MmFreePool (mToUnplugApicIds);
mToUnplugApicIds = NULL;
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
index 45d86aea97c..6a68fe39a6d 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
@@ -40,6 +40,7 @@
[LibraryClasses]
BaseLib
BaseMemoryLib
+ CpuLib
DebugLib
LocalApicLib
MmServicesTableLib
@@ -54,6 +55,7 @@
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress ## CONSUMES
+ gUefiOvmfPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress ## CONSUMES
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase ## CONSUMES
[FeaturePcd]
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.c
index f07ead0526e..d9c30494e30 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.c
@@ -114,6 +114,28 @@ QemuCpuhpWriteCpuSelector (
}
VOID
+QemuCpuhpWriteCpuStatus (
+ IN CONST EFI_MM_CPU_IO_PROTOCOL *MmCpuIo,
+ IN UINT8 CpuStatus
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MmCpuIo->Io.Write (
+ MmCpuIo,
+ MM_IO_UINT8,
+ ICH9_CPU_HOTPLUG_BASE + QEMU_CPUHP_R_CPU_STAT,
+ 1,
+ &CpuStatus
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+ }
+}
+
+VOID
QemuCpuhpWriteCommand (
IN CONST EFI_MM_CPU_IO_PROTOCOL *MmCpuIo,
IN UINT8 Command
@@ -145,27 +167,30 @@ QemuCpuhpWriteCommand (
On error, the contents of the output parameters are undefined.
- @param[in] MmCpuIo The EFI_MM_CPU_IO_PROTOCOL instance for
- accessing IO Ports.
+ @param[in] MmCpuIo The EFI_MM_CPU_IO_PROTOCOL instance for
+ accessing IO Ports.
+
+ @param[in] PossibleCpuCount The number of possible CPUs in the system. Must
+ be positive.
- @param[in] PossibleCpuCount The number of possible CPUs in the system. Must
- be positive.
+ @param[in] ApicIdCount The number of elements each one of the
+ PluggedApicIds and ToUnplugApicIds arrays can
+ accommodate. Must be positive.
- @param[in] ApicIdCount The number of elements each one of the
- PluggedApicIds and ToUnplugApicIds arrays can
- accommodate. Must be positive.
+ @param[out] PluggedApicIds The APIC IDs of the CPUs that have been
+ hot-plugged.
- @param[out] PluggedApicIds The APIC IDs of the CPUs that have been
- hot-plugged.
+ @param[out] PluggedCount The number of filled-in APIC IDs in
+ PluggedApicIds.
- @param[out] PluggedCount The number of filled-in APIC IDs in
- PluggedApicIds.
+ @param[out] ToUnplugApicIds The APIC IDs of the CPUs that are about to be
+ hot-unplugged.
- @param[out] ToUnplugApicIds The APIC IDs of the CPUs that are about to be
- hot-unplugged.
+ @param[out] ToUnplugSelectors The QEMU Selectors of the CPUs that are about
+ to be hot-unplugged.
- @param[out] ToUnplugCount The number of filled-in APIC IDs in
- ToUnplugApicIds.
+ @param[out] ToUnplugCount The number of filled-in APIC IDs in
+ ToUnplugApicIds.
@retval EFI_INVALID_PARAMETER PossibleCpuCount is zero, or ApicIdCount is
zero.
@@ -187,6 +212,7 @@ QemuCpuhpCollectApicIds (
OUT APIC_ID *PluggedApicIds,
OUT UINT32 *PluggedCount,
OUT APIC_ID *ToUnplugApicIds,
+ OUT UINT32 *ToUnplugSelectors,
OUT UINT32 *ToUnplugCount
)
{
@@ -204,6 +230,7 @@ QemuCpuhpCollectApicIds (
UINT32 PendingSelector;
UINT8 CpuStatus;
APIC_ID *ExtendIds;
+ UINT32 *ExtendSels;
UINT32 *ExtendCount;
APIC_ID NewApicId;
@@ -245,10 +272,10 @@ QemuCpuhpCollectApicIds (
if ((CpuStatus & QEMU_CPUHP_STAT_INSERT) != 0) {
//
// The "insert" event guarantees the "enabled" status; plus it excludes
- // the "remove" event.
+ // the "fw_remove" event.
//
if ((CpuStatus & QEMU_CPUHP_STAT_ENABLED) == 0 ||
- (CpuStatus & QEMU_CPUHP_STAT_REMOVE) != 0) {
+ (CpuStatus & QEMU_CPUHP_STAT_FW_REMOVE) != 0) {
DEBUG ((DEBUG_ERROR, "%a: CurrentSelector=%u CpuStatus=0x%x: "
"inconsistent CPU status\n", __FUNCTION__, CurrentSelector,
CpuStatus));
@@ -259,33 +286,63 @@ QemuCpuhpCollectApicIds (
CurrentSelector));
ExtendIds = PluggedApicIds;
+ ExtendSels = NULL;
ExtendCount = PluggedCount;
- } else if ((CpuStatus & QEMU_CPUHP_STAT_REMOVE) != 0) {
- DEBUG ((DEBUG_VERBOSE, "%a: CurrentSelector=%u: remove\n", __FUNCTION__,
- CurrentSelector));
+ } else if ((CpuStatus & QEMU_CPUHP_STAT_FW_REMOVE) != 0) {
+ //
+ // "fw_remove" event guarantees "enabled".
+ //
+ if ((CpuStatus & QEMU_CPUHP_STAT_ENABLED) == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: CurrentSelector=%u CpuStatus=0x%x: "
+ "inconsistent CPU status\n", __FUNCTION__, CurrentSelector,
+ CpuStatus));
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%a: CurrentSelector=%u: fw_remove\n",
+ __FUNCTION__, CurrentSelector));
ExtendIds = ToUnplugApicIds;
+ ExtendSels = ToUnplugSelectors;
ExtendCount = ToUnplugCount;
+ } else if ((CpuStatus & QEMU_CPUHP_STAT_REMOVE) != 0) {
+ //
+ // Let the OSPM deal with the "remove" event.
+ //
+ DEBUG ((DEBUG_VERBOSE, "%a: CurrentSelector=%u: remove (ignored)\n",
+ __FUNCTION__, CurrentSelector));
+
+ ExtendIds = NULL;
+ ExtendSels = NULL;
+ ExtendCount = NULL;
} else {
DEBUG ((DEBUG_VERBOSE, "%a: CurrentSelector=%u: no event\n",
__FUNCTION__, CurrentSelector));
break;
}
- //
- // Save the APIC ID of the CPU with the pending event, to the corresponding
- // APIC ID array.
- //
- if (*ExtendCount == ApicIdCount) {
- DEBUG ((DEBUG_ERROR, "%a: APIC ID array too small\n", __FUNCTION__));
- return EFI_BUFFER_TOO_SMALL;
- }
- QemuCpuhpWriteCommand (MmCpuIo, QEMU_CPUHP_CMD_GET_ARCH_ID);
- NewApicId = QemuCpuhpReadCommandData (MmCpuIo);
- DEBUG ((DEBUG_VERBOSE, "%a: ApicId=" FMT_APIC_ID "\n", __FUNCTION__,
- NewApicId));
- ExtendIds[(*ExtendCount)++] = NewApicId;
+ ASSERT ((ExtendIds == NULL) == (ExtendCount == NULL));
+ ASSERT ((ExtendSels == NULL) || (ExtendIds != NULL));
+ if (ExtendIds != NULL) {
+ //
+ // Save the APIC ID of the CPU with the pending event, to the
+ // corresponding APIC ID array.
+ // For unplug events, also save the CurrentSelector.
+ //
+ if (*ExtendCount == ApicIdCount) {
+ DEBUG ((DEBUG_ERROR, "%a: APIC ID array too small\n", __FUNCTION__));
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ QemuCpuhpWriteCommand (MmCpuIo, QEMU_CPUHP_CMD_GET_ARCH_ID);
+ NewApicId = QemuCpuhpReadCommandData (MmCpuIo);
+ DEBUG ((DEBUG_VERBOSE, "%a: ApicId=" FMT_APIC_ID "\n", __FUNCTION__,
+ NewApicId));
+ if (ExtendSels != NULL) {
+ ExtendSels[(*ExtendCount)] = CurrentSelector;
+ }
+ ExtendIds[(*ExtendCount)++] = NewApicId;
+ }
//
// We've processed the CPU with (known) pending events, but we must never
// clear events. Therefore we need to advance past this CPU manually;
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.h
index 92ae6f906f3..89ab994067a 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/QemuCpuhp.h
@@ -42,6 +42,12 @@ QemuCpuhpWriteCpuSelector (
);
VOID
+QemuCpuhpWriteCpuStatus (
+ IN CONST EFI_MM_CPU_IO_PROTOCOL *MmCpuIo,
+ IN UINT8 CpuStatus
+ );
+
+VOID
QemuCpuhpWriteCommand (
IN CONST EFI_MM_CPU_IO_PROTOCOL *MmCpuIo,
IN UINT8 Command
@@ -55,6 +61,7 @@ QemuCpuhpCollectApicIds (
OUT APIC_ID *PluggedApicIds,
OUT UINT32 *PluggedCount,
OUT APIC_ID *ToUnplugApicIds,
+ OUT UINT32 *ToUnplugSelectors,
OUT UINT32 *ToUnplugCount
);
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/Smbase.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/Smbase.c
index dc5aefde738..36696739246 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/Smbase.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuHotplugSmm/Smbase.c
@@ -220,14 +220,37 @@ SmbaseRelocate (
//
// Boot the hot-added CPU.
//
- // If the OS is benign, and so the hot-added CPU is still in RESET state,
- // then the broadcast SMI is still pending for it; it will now launch
- // directly into SMM.
+ // There are 2*2 cases to consider:
//
- // If the OS is malicious, the hot-added CPU has been booted already, and so
- // it is already spinning on the APIC ID gate. In that case, the
- // INIT-SIPI-SIPI below will be ignored.
+ // (1) The CPU was hot-added before the SMI was broadcast.
//
+ // (1.1) The OS is benign.
+ //
+ // The hot-added CPU is in RESET state, with the broadcast SMI pending
+ // for it. The directed SMI below will be ignored (it's idempotent),
+ // and the INIT-SIPI-SIPI will launch the CPU directly into SMM.
+ //
+ // (1.2) The OS is malicious.
+ //
+ // The hot-added CPU has been booted, by the OS. Thus, the hot-added
+ // CPU is spinning on the APIC ID gate. In that case, both the SMI and
+ // the INIT-SIPI-SIPI below will be ignored.
+ //
+ // (2) The CPU was hot-added after the SMI was broadcast.
+ //
+ // (2.1) The OS is benign.
+ //
+ // The hot-added CPU is in RESET state, with no SMI pending for it. The
+ // directed SMI will latch the SMI for the CPU. Then the INIT-SIPI-SIPI
+ // will launch the CPU into SMM.
+ //
+ // (2.2) The OS is malicious.
+ //
+ // The hot-added CPU is executing OS code. The directed SMI will pull
+ // the hot-added CPU into SMM, where it will start spinning on the APIC
+ // ID gate. The INIT-SIPI-SIPI will be ignored.
+ //
+ SendSmiIpi (ApicId);
SendInitSipiSipi (ApicId, PenAddress);
//
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3Data.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
index eacbf9a7fb4..8c027841e21 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
@@ -23,7 +23,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
-#include <Library/IoLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/MtrrLib.h>
#include <Library/UefiBootServicesTableLib.h>
@@ -31,9 +30,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/MpService.h>
#include <Guid/EventGroup.h>
-#include <IndustryStandard/Q35MchIch9.h>
-#include <IndustryStandard/QemuCpuHotplug.h>
-
//
// Data structure used to allocate ACPI_CPU_DATA and its supporting structures
//
@@ -168,17 +164,12 @@ CpuS3DataInitialize (
EFI_MP_SERVICES_PROTOCOL *MpServices;
UINTN NumberOfCpus;
VOID *Stack;
- UINTN TableSize;
- CPU_REGISTER_TABLE *RegisterTable;
- UINTN Index;
- EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
UINTN GdtSize;
UINTN IdtSize;
VOID *Gdt;
VOID *Idt;
EFI_EVENT Event;
ACPI_CPU_DATA *OldAcpiCpuData;
- BOOLEAN FetchPossibleApicIds;
if (!PcdGetBool (PcdAcpiS3Enable)) {
return EFI_UNSUPPORTED;
@@ -193,13 +184,7 @@ CpuS3DataInitialize (
ASSERT (AcpiCpuDataEx != NULL);
AcpiCpuData = &AcpiCpuDataEx->AcpiCpuData;
- //
- // The "SMRAM at default SMBASE" feature guarantees that
- // QEMU_CPUHP_CMD_GET_ARCH_ID too is available.
- //
- FetchPossibleApicIds = PcdGetBool (PcdQ35SmramAtDefaultSmbase);
-
- if (FetchPossibleApicIds) {
+ if (PcdGetBool (PcdQ35SmramAtDefaultSmbase)) {
NumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
} else {
UINTN NumberOfEnabledProcessors;
@@ -271,59 +256,6 @@ CpuS3DataInitialize (
AcpiCpuData->PreSmmInitRegisterTable = OldAcpiCpuData->PreSmmInitRegisterTable;
AcpiCpuData->ApLocation = OldAcpiCpuData->ApLocation;
CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));
- } else {
- //
- // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
- //
- TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
- RegisterTable = (CPU_REGISTER_TABLE *)AllocateZeroPages (TableSize);
- ASSERT (RegisterTable != NULL);
-
- if (FetchPossibleApicIds) {
- //
- // Write a valid selector so that other hotplug registers can be
- // accessed.
- //
- IoWrite32 (ICH9_CPU_HOTPLUG_BASE + QEMU_CPUHP_W_CPU_SEL, 0);
- //
- // We'll be fetching the APIC IDs.
- //
- IoWrite8 (ICH9_CPU_HOTPLUG_BASE + QEMU_CPUHP_W_CMD,
- QEMU_CPUHP_CMD_GET_ARCH_ID);
- }
- for (Index = 0; Index < NumberOfCpus; Index++) {
- UINT32 InitialApicId;
-
- if (FetchPossibleApicIds) {
- IoWrite32 (ICH9_CPU_HOTPLUG_BASE + QEMU_CPUHP_W_CPU_SEL,
- (UINT32)Index);
- InitialApicId = IoRead32 (
- ICH9_CPU_HOTPLUG_BASE + QEMU_CPUHP_RW_CMD_DATA);
- } else {
- Status = MpServices->GetProcessorInfo (
- MpServices,
- Index,
- &ProcessorInfoBuffer
- );
- ASSERT_EFI_ERROR (Status);
- InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
- }
-
- DEBUG ((DEBUG_VERBOSE, "%a: Index=%05Lu ApicId=0x%08x\n", __FUNCTION__,
- (UINT64)Index, InitialApicId));
-
- RegisterTable[Index].InitialApicId = InitialApicId;
- RegisterTable[Index].TableLength = 0;
- RegisterTable[Index].AllocatedSize = 0;
- RegisterTable[Index].RegisterTableEntry = 0;
-
- RegisterTable[NumberOfCpus + Index].InitialApicId = InitialApicId;
- RegisterTable[NumberOfCpus + Index].TableLength = 0;
- RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;
- RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
- }
- AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
- AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
}
//
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf
index 5ba142b2999..1460b213f24 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf
@@ -42,7 +42,6 @@
BaseLib
BaseMemoryLib
DebugLib
- IoLib
MemoryAllocationLib
MtrrLib
UefiBootServicesTableLib
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
new file mode 100644
index 00000000000..23169958248
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Guid/ConfidentialComputingSecret.h
@@ -0,0 +1,28 @@
+ /** @file
+ UEFI Configuration Table for exposing the SEV Launch Secret location to UEFI
+ applications (boot loaders).
+
+ Copyright (C) 2020 James Bottomley, IBM Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+#ifndef CONFIDENTIAL_COMPUTING_SECRET_H_
+#define CONFIDENTIAL_COMPUTING_SECRET_H_
+
+#include <Uefi/UefiBaseType.h>
+
+#define CONFIDENTIAL_COMPUTING_SECRET_GUID \
+ { 0xadf956ad, \
+ 0xe98c, \
+ 0x484c, \
+ { 0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47 }, \
+ }
+
+typedef struct {
+ UINT64 Base;
+ UINT64 Size;
+} CONFIDENTIAL_COMPUTING_SECRET_LOCATION;
+
+extern EFI_GUID gConfidentialComputingSecretGuid;
+
+#endif // SEV_LAUNCH_SECRET_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/InstructionParsing.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/InstructionParsing.h
new file mode 100644
index 00000000000..2e9cfa7fb43
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/InstructionParsing.h
@@ -0,0 +1,83 @@
+/** @file
+ Instruction parsing support definitions.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __INSTRUCTION_PARSING_H__
+#define __INSTRUCTION_PARSING_H__
+
+#include <Base.h>
+#include <Uefi.h>
+
+//
+// Instruction REX prefix definition
+//
+typedef union {
+ struct {
+ UINT8 BitB:1;
+ UINT8 BitX:1;
+ UINT8 BitR:1;
+ UINT8 BitW:1;
+ UINT8 Rex:4;
+ } Bits;
+
+ UINT8 Uint8;
+} INSTRUCTION_REX_PREFIX;
+
+//
+// Instruction ModRM definition
+//
+typedef union {
+ struct {
+ UINT8 Rm:3;
+ UINT8 Reg:3;
+ UINT8 Mod:2;
+ } Bits;
+
+ UINT8 Uint8;
+} INSTRUCTION_MODRM;
+
+//
+// Instruction SIB definition
+//
+typedef union {
+ struct {
+ UINT8 Base:3;
+ UINT8 Index:3;
+ UINT8 Scale:2;
+ } Bits;
+
+ UINT8 Uint8;
+} INSTRUCTION_SIB;
+
+//
+// Legacy Instruction Prefixes
+//
+#define OVERRIDE_SEGMENT_CS 0x2E
+#define OVERRIDE_SEGMENT_DS 0x3E
+#define OVERRIDE_SEGMENT_ES 0x26
+#define OVERRIDE_SEGMENT_SS 0x36
+#define OVERRIDE_SEGMENT_FS 0x64
+#define OVERRIDE_SEGMENT_GS 0x65
+#define OVERRIDE_OPERAND_SIZE 0x66
+#define OVERRIDE_ADDRESS_SIZE 0x67
+#define LOCK_PREFIX 0xF0
+#define REPNZ_PREFIX 0xF2
+#define REPZ_PREFIX 0xF3
+
+//
+// REX Prefixes
+//
+#define REX_PREFIX_START 0x40
+#define REX_PREFIX_STOP 0x4F
+#define REX_64BIT_OPERAND_SIZE_MASK 0x08
+
+//
+// Two-byte Opcode Flag
+//
+#define TWO_BYTE_OPCODE_ESCAPE 0x0F
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/LsiScsi.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/LsiScsi.h
new file mode 100644
index 00000000000..7edff86d45a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/LsiScsi.h
@@ -0,0 +1,105 @@
+/** @file
+
+ Macros and type definitions for LSI 53C895A SCSI devices.
+
+ Copyright (C) 2020, SUSE LLC.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LSI_SCSI_H_
+#define _LSI_SCSI_H_
+
+//
+// Device ID
+//
+#define LSI_LOGIC_PCI_VENDOR_ID 0x1000
+#define LSI_53C895A_PCI_DEVICE_ID 0x0012
+
+//
+// LSI 53C895A Registers
+//
+#define LSI_REG_DSTAT 0x0C
+#define LSI_REG_ISTAT0 0x14
+#define LSI_REG_DSP 0x2C
+#define LSI_REG_SIST0 0x42
+#define LSI_REG_SIST1 0x43
+#define LSI_REG_CSBC 0xDC
+
+//
+// The status bits for DMA Status (DSTAT)
+//
+#define LSI_DSTAT_IID BIT0
+#define LSI_DSTAT_R BIT1
+#define LSI_DSTAT_SIR BIT2
+#define LSI_DSTAT_SSI BIT3
+#define LSI_DSTAT_ABRT BIT4
+#define LSI_DSTAT_BF BIT5
+#define LSI_DSTAT_MDPE BIT6
+#define LSI_DSTAT_DFE BIT7
+
+//
+// The status bits for Interrupt Status Zero (ISTAT0)
+//
+#define LSI_ISTAT0_DIP BIT0
+#define LSI_ISTAT0_SIP BIT1
+#define LSI_ISTAT0_INTF BIT2
+#define LSI_ISTAT0_CON BIT3
+#define LSI_ISTAT0_SEM BIT4
+#define LSI_ISTAT0_SIGP BIT5
+#define LSI_ISTAT0_SRST BIT6
+#define LSI_ISTAT0_ABRT BIT7
+
+//
+// The status bits for SCSI Interrupt Status Zero (SIST0)
+//
+#define LSI_SIST0_PAR BIT0
+#define LSI_SIST0_RST BIT1
+#define LSI_SIST0_UDC BIT2
+#define LSI_SIST0_SGE BIT3
+#define LSI_SIST0_RSL BIT4
+#define LSI_SIST0_SEL BIT5
+#define LSI_SIST0_CMP BIT6
+#define LSI_SIST0_MA BIT7
+
+//
+// The status bits for SCSI Interrupt Status One (SIST1)
+//
+#define LSI_SIST1_HTH BIT0
+#define LSI_SIST1_GEN BIT1
+#define LSI_SIST1_STO BIT2
+#define LSI_SIST1_R3 BIT3
+#define LSI_SIST1_SBMC BIT4
+#define LSI_SIST1_R5 BIT5
+#define LSI_SIST1_R6 BIT6
+#define LSI_SIST1_R7 BIT7
+
+//
+// LSI 53C895A Script Instructions
+//
+#define LSI_INS_TYPE_BLK 0x00000000
+#define LSI_INS_TYPE_IO BIT30
+#define LSI_INS_TYPE_TC BIT31
+
+#define LSI_INS_BLK_SCSIP_DAT_OUT 0x00000000
+#define LSI_INS_BLK_SCSIP_DAT_IN BIT24
+#define LSI_INS_BLK_SCSIP_CMD BIT25
+#define LSI_INS_BLK_SCSIP_STAT (BIT24 | BIT25)
+#define LSI_INS_BLK_SCSIP_MSG_OUT (BIT25 | BIT26)
+#define LSI_INS_BLK_SCSIP_MSG_IN (BIT24 | BIT25 | BIT26)
+
+#define LSI_INS_IO_OPC_SEL 0x00000000
+#define LSI_INS_IO_OPC_WAIT_RESEL BIT28
+
+#define LSI_INS_TC_CP BIT17
+#define LSI_INS_TC_JMP BIT19
+#define LSI_INS_TC_RA BIT23
+
+#define LSI_INS_TC_OPC_JMP 0x00000000
+#define LSI_INS_TC_OPC_INT (BIT27 | BIT28)
+
+#define LSI_INS_TC_SCSIP_DAT_OUT 0x00000000
+#define LSI_INS_TC_SCSIP_MSG_IN (BIT24 | BIT25 | BIT26)
+
+#endif // _LSI_SCSI_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/PageTable.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/PageTable.h
new file mode 100644
index 00000000000..897afb8e9c9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/PageTable.h
@@ -0,0 +1,161 @@
+/** @file
+
+ x86_64 Page Tables structures
+
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h
+
+**/
+
+#ifndef PAGE_TABLE_H_
+#define PAGE_TABLE_H_
+
+#include <Base.h>
+
+#pragma pack(1)
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1 = Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// Page Table Entry 4KB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1 = Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
+ // processor on access to page
+ UINT64 PAT:1; //
+ UINT64 Global:1; // 0 = Not global page, 1 = global page
+ // TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code,
+ // 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_4K_ENTRY;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
+ // processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page
+ // TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code,
+ // 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_ENTRY;
+
+//
+// Page Table Entry 1GB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory,
+ // 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching,
+ // 1 = Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed,
+ // 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
+ // processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page
+ // TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:17; // Must be zero;
+ UINT64 PageTableBaseAddress:22; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code,
+ // 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_1G_ENTRY;
+
+#pragma pack()
+
+#define IA32_PG_P BIT0
+#define IA32_PG_RW BIT1
+#define IA32_PG_PS BIT7
+
+#define PAGING_PAE_INDEX_MASK 0x1FF
+
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+
+#define PAGING_L1_ADDRESS_SHIFT 12
+#define PAGING_L2_ADDRESS_SHIFT 21
+#define PAGING_L3_ADDRESS_SHIFT 30
+#define PAGING_L4_ADDRESS_SHIFT 39
+
+#define PAGING_PML4E_NUMBER 4
+
+#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1)
+#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK)
+#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK)
+#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK)
+#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK)
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/QemuCpuHotplug.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/QemuCpuHotplug.h
index 0beab850432..1b0f9f6a983 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/QemuCpuHotplug.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/QemuCpuHotplug.h
@@ -34,6 +34,8 @@
#define QEMU_CPUHP_STAT_ENABLED BIT0
#define QEMU_CPUHP_STAT_INSERT BIT1
#define QEMU_CPUHP_STAT_REMOVE BIT2
+#define QEMU_CPUHP_STAT_EJECT BIT3
+#define QEMU_CPUHP_STAT_FW_REMOVE BIT4
#define QEMU_CPUHP_RW_CMD_DATA 0x8
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Virtio10.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Virtio10.h
index 3e41d61939e..5e13abd9f5d 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Virtio10.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Virtio10.h
@@ -17,6 +17,11 @@
// Subsystem Device IDs (to be) introduced in VirtIo 1.0
//
#define VIRTIO_SUBSYSTEM_GPU_DEVICE 16
+//
+// Subsystem Device IDs from the VirtIo spec at git commit 87fa6b5d8155;
+// <https://github.com/oasis-tcs/virtio-spec/tree/87fa6b5d8155>.
+//
+#define VIRTIO_SUBSYSTEM_FILESYSTEM 26
//
// Structures for parsing the VirtIo 1.0 specific PCI capabilities from the
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/VirtioFs.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/VirtioFs.h
new file mode 100644
index 00000000000..c87a32faabd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/VirtioFs.h
@@ -0,0 +1,454 @@
+/** @file
+ Type and macro definitions specific to the Virtio Filesystem device.
+
+ At the time of this writing, the latest released Virtio specification (v1.1)
+ does not include the virtio-fs device. The development version of the
+ specification defines it however; see the latest version at
+ <https://github.com/oasis-tcs/virtio-spec/blob/87fa6b5d8155/virtio-fs.tex>.
+
+ This header file is minimal, and only defines the types and macros that are
+ necessary for the OvmfPkg implementation.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef VIRTIO_FS_H_
+#define VIRTIO_FS_H_
+
+#include <IndustryStandard/Virtio.h>
+
+//
+// Lowest numbered queue for sending normal priority requests.
+//
+#define VIRTIO_FS_REQUEST_QUEUE 1
+
+//
+// Number of bytes in the "VIRTIO_FS_CONFIG.Tag" field.
+//
+#define VIRTIO_FS_TAG_BYTES 36
+
+//
+// Device configuration layout.
+//
+#pragma pack (1)
+typedef struct {
+ //
+ // The Tag field can be considered the filesystem label, or a mount point
+ // hint. It is UTF-8 encoded, and padded to full size with NUL bytes. If the
+ // encoded bytes take up the entire Tag field, then there is no NUL
+ // terminator.
+ //
+ UINT8 Tag[VIRTIO_FS_TAG_BYTES];
+ //
+ // The total number of request virtqueues exposed by the device (i.e.,
+ // excluding the "hiprio" queue).
+ //
+ UINT32 NumReqQueues;
+} VIRTIO_FS_CONFIG;
+#pragma pack ()
+
+//
+// FUSE-related definitions follow.
+//
+// From virtio-v1.1-cs01-87fa6b5d8155, 5.11 File System Device: "[...] The
+// driver acts as the FUSE client mounting the file system. The virtio file
+// system device provides the mechanism for transporting FUSE requests [...]"
+//
+// Unfortunately, the documentation of the FUSE wire protocol is lacking. The
+// Virtio spec (as of this writing) simply defers to
+// "include/uapi/linux/fuse.h" in the Linux kernel source -- see the reference
+// in virtio spec file "introduction.tex", at commit 87fa6b5d8155.
+//
+// Of course, "include/uapi/linux/fuse.h" is a moving target (the virtio spec
+// does not specify a particular FUSE interface version). The OvmfPkg code
+// targets version 7.31, because that's the lowest version that the QEMU
+// virtio-fs daemon supports at this time -- see QEMU commit 72c42e2d6551
+// ("virtiofsd: Trim out compatibility code", 2020-01-23).
+//
+// Correspondingly, Linux's "include/uapi/linux/fuse.h" is consulted as checked
+// out at commit (c6ff213fe5b8^) = d78092e4937d ("fuse: fix page dereference
+// after free", 2020-09-18); that is, right before commit c6ff213fe5b8 ("fuse:
+// add submount support to <uapi/linux/fuse.h>", 2020-09-18) introduces FUSE
+// interface version 7.32.
+//
+#define VIRTIO_FS_FUSE_MAJOR 7
+#define VIRTIO_FS_FUSE_MINOR 31
+
+//
+// The inode number of the root directory.
+//
+#define VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID 1
+
+//
+// Distinguished errno values.
+//
+#define VIRTIO_FS_FUSE_ERRNO_ENOENT (-2)
+
+//
+// File mode bitmasks.
+//
+#define VIRTIO_FS_FUSE_MODE_TYPE_MASK 0170000u
+#define VIRTIO_FS_FUSE_MODE_TYPE_REG 0100000u
+#define VIRTIO_FS_FUSE_MODE_TYPE_DIR 0040000u
+#define VIRTIO_FS_FUSE_MODE_PERM_RWXU 0000700u
+#define VIRTIO_FS_FUSE_MODE_PERM_RUSR 0000400u
+#define VIRTIO_FS_FUSE_MODE_PERM_WUSR 0000200u
+#define VIRTIO_FS_FUSE_MODE_PERM_XUSR 0000100u
+#define VIRTIO_FS_FUSE_MODE_PERM_RWXG 0000070u
+#define VIRTIO_FS_FUSE_MODE_PERM_RGRP 0000040u
+#define VIRTIO_FS_FUSE_MODE_PERM_WGRP 0000020u
+#define VIRTIO_FS_FUSE_MODE_PERM_XGRP 0000010u
+#define VIRTIO_FS_FUSE_MODE_PERM_RWXO 0000007u
+#define VIRTIO_FS_FUSE_MODE_PERM_ROTH 0000004u
+#define VIRTIO_FS_FUSE_MODE_PERM_WOTH 0000002u
+#define VIRTIO_FS_FUSE_MODE_PERM_XOTH 0000001u
+
+//
+// Flags for VirtioFsFuseOpSetAttr, in the VIRTIO_FS_FUSE_SETATTR_REQUEST.Valid
+// field.
+//
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_MODE BIT0
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_SIZE BIT3
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_ATIME BIT4
+#define VIRTIO_FS_FUSE_SETATTR_REQ_F_MTIME BIT5
+
+//
+// Flags for VirtioFsFuseOpOpen.
+//
+#define VIRTIO_FS_FUSE_OPEN_REQ_F_RDONLY 0
+#define VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR 2
+
+//
+// Flags for VirtioFsFuseOpInit.
+//
+#define VIRTIO_FS_FUSE_INIT_REQ_F_DO_READDIRPLUS BIT13
+
+/**
+ Macro for calculating the size of a directory stream entry.
+
+ The macro may evaluate Namelen multiple times.
+
+ The macro evaluates to a UINTN value that is safe to cast to UINT32.
+
+ @param[in] Namelen The size of the filename byte array that follows
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE in the directory
+ stream, as reported by
+ VIRTIO_FS_FUSE_STATFS_RESPONSE.Namelen or
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE.Namelen. The filename
+ byte array is not NUL-terminated.
+
+ @retval 0 Namelen was zero or greater than SIZE_4KB.
+
+ @return The number of bytes in the directory entry, including the
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE header.
+**/
+#define VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE(Namelen) \
+ ((Namelen) == 0 || (Namelen) > SIZE_4KB ? \
+ (UINTN)0 : \
+ ALIGN_VALUE ( \
+ sizeof (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE) + (UINTN)(Namelen), \
+ sizeof (UINT64) \
+ ) \
+ )
+
+//
+// Flags for VirtioFsFuseOpRename2.
+//
+#define VIRTIO_FS_FUSE_RENAME2_REQ_F_NOREPLACE BIT0
+
+//
+// FUSE operation codes.
+//
+typedef enum {
+ VirtioFsFuseOpLookup = 1,
+ VirtioFsFuseOpForget = 2,
+ VirtioFsFuseOpGetAttr = 3,
+ VirtioFsFuseOpSetAttr = 4,
+ VirtioFsFuseOpMkDir = 9,
+ VirtioFsFuseOpUnlink = 10,
+ VirtioFsFuseOpRmDir = 11,
+ VirtioFsFuseOpOpen = 14,
+ VirtioFsFuseOpRead = 15,
+ VirtioFsFuseOpWrite = 16,
+ VirtioFsFuseOpStatFs = 17,
+ VirtioFsFuseOpRelease = 18,
+ VirtioFsFuseOpFsync = 20,
+ VirtioFsFuseOpFlush = 25,
+ VirtioFsFuseOpInit = 26,
+ VirtioFsFuseOpOpenDir = 27,
+ VirtioFsFuseOpReleaseDir = 29,
+ VirtioFsFuseOpFsyncDir = 30,
+ VirtioFsFuseOpCreate = 35,
+ VirtioFsFuseOpReadDirPlus = 44,
+ VirtioFsFuseOpRename2 = 45,
+} VIRTIO_FS_FUSE_OPCODE;
+
+#pragma pack (1)
+//
+// Request-response headers common to all request types.
+//
+typedef struct {
+ UINT32 Len;
+ UINT32 Opcode;
+ UINT64 Unique;
+ UINT64 NodeId;
+ UINT32 Uid;
+ UINT32 Gid;
+ UINT32 Pid;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_REQUEST;
+
+typedef struct {
+ UINT32 Len;
+ INT32 Error;
+ UINT64 Unique;
+} VIRTIO_FS_FUSE_RESPONSE;
+
+//
+// Structure with which the Virtio Filesystem device reports a NodeId to the
+// FUSE client (i.e., to the Virtio Filesystem driver). This structure is a
+// part of the response headers for operations that inform the FUSE client of
+// an inode.
+//
+typedef struct {
+ UINT64 NodeId;
+ UINT64 Generation;
+ UINT64 EntryValid;
+ UINT64 AttrValid;
+ UINT32 EntryValidNsec;
+ UINT32 AttrValidNsec;
+} VIRTIO_FS_FUSE_NODE_RESPONSE;
+
+//
+// Structure describing the host-side attributes of an inode. This structure is
+// a part of the response headers for operations that inform the FUSE client of
+// an inode.
+//
+typedef struct {
+ UINT64 Ino;
+ UINT64 Size;
+ UINT64 Blocks;
+ UINT64 Atime;
+ UINT64 Mtime;
+ UINT64 Ctime;
+ UINT32 AtimeNsec;
+ UINT32 MtimeNsec;
+ UINT32 CtimeNsec;
+ UINT32 Mode;
+ UINT32 Nlink;
+ UINT32 Uid;
+ UINT32 Gid;
+ UINT32 Rdev;
+ UINT32 Blksize;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpForget.
+//
+typedef struct {
+ UINT64 NumberOfLookups;
+} VIRTIO_FS_FUSE_FORGET_REQUEST;
+
+//
+// Headers for VirtioFsFuseOpGetAttr (VIRTIO_FS_FUSE_GETATTR_RESPONSE is also
+// for VirtioFsFuseOpSetAttr).
+//
+typedef struct {
+ UINT32 GetAttrFlags;
+ UINT32 Dummy;
+ UINT64 FileHandle;
+} VIRTIO_FS_FUSE_GETATTR_REQUEST;
+
+typedef struct {
+ UINT64 AttrValid;
+ UINT32 AttrValidNsec;
+ UINT32 Dummy;
+} VIRTIO_FS_FUSE_GETATTR_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpSetAttr.
+//
+typedef struct {
+ UINT32 Valid;
+ UINT32 Padding;
+ UINT64 FileHandle;
+ UINT64 Size;
+ UINT64 LockOwner;
+ UINT64 Atime;
+ UINT64 Mtime;
+ UINT64 Ctime;
+ UINT32 AtimeNsec;
+ UINT32 MtimeNsec;
+ UINT32 CtimeNsec;
+ UINT32 Mode;
+ UINT32 Unused4;
+ UINT32 Uid;
+ UINT32 Gid;
+ UINT32 Unused5;
+} VIRTIO_FS_FUSE_SETATTR_REQUEST;
+
+//
+// Header for VirtioFsFuseOpMkDir.
+//
+typedef struct {
+ UINT32 Mode;
+ UINT32 Umask;
+} VIRTIO_FS_FUSE_MKDIR_REQUEST;
+
+//
+// Headers for VirtioFsFuseOpOpen and VirtioFsFuseOpOpenDir.
+//
+typedef struct {
+ UINT32 Flags;
+ UINT32 Unused;
+} VIRTIO_FS_FUSE_OPEN_REQUEST;
+
+typedef struct {
+ UINT64 FileHandle;
+ UINT32 OpenFlags;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_OPEN_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpRead and VirtioFsFuseOpReadDirPlus.
+//
+typedef struct {
+ UINT64 FileHandle;
+ UINT64 Offset;
+ UINT32 Size;
+ UINT32 ReadFlags;
+ UINT64 LockOwner;
+ UINT32 Flags;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_READ_REQUEST;
+
+//
+// Headers for VirtioFsFuseOpWrite.
+//
+typedef struct {
+ UINT64 FileHandle;
+ UINT64 Offset;
+ UINT32 Size;
+ UINT32 WriteFlags;
+ UINT64 LockOwner;
+ UINT32 Flags;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_WRITE_REQUEST;
+
+typedef struct {
+ UINT32 Size;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_WRITE_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpStatFs.
+//
+typedef struct {
+ UINT64 Blocks;
+ UINT64 Bfree;
+ UINT64 Bavail;
+ UINT64 Files;
+ UINT64 Ffree;
+ UINT32 Bsize;
+ UINT32 Namelen;
+ UINT32 Frsize;
+ UINT32 Padding;
+ UINT32 Spare[6];
+} VIRTIO_FS_FUSE_STATFS_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpRelease and VirtioFsFuseOpReleaseDir.
+//
+typedef struct {
+ UINT64 FileHandle;
+ UINT32 Flags;
+ UINT32 ReleaseFlags;
+ UINT64 LockOwner;
+} VIRTIO_FS_FUSE_RELEASE_REQUEST;
+
+//
+// Header for VirtioFsFuseOpFsync and VirtioFsFuseOpFsyncDir.
+//
+typedef struct {
+ UINT64 FileHandle;
+ UINT32 FsyncFlags;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_FSYNC_REQUEST;
+
+//
+// Header for VirtioFsFuseOpFlush.
+//
+typedef struct {
+ UINT64 FileHandle;
+ UINT32 Unused;
+ UINT32 Padding;
+ UINT64 LockOwner;
+} VIRTIO_FS_FUSE_FLUSH_REQUEST;
+
+//
+// Headers for VirtioFsFuseOpInit.
+//
+typedef struct {
+ UINT32 Major;
+ UINT32 Minor;
+ UINT32 MaxReadahead;
+ UINT32 Flags;
+} VIRTIO_FS_FUSE_INIT_REQUEST;
+
+typedef struct {
+ UINT32 Major;
+ UINT32 Minor;
+ UINT32 MaxReadahead;
+ UINT32 Flags;
+ UINT16 MaxBackground;
+ UINT16 CongestionThreshold;
+ UINT32 MaxWrite;
+ UINT32 TimeGran;
+ UINT16 MaxPages;
+ UINT16 MapAlignment;
+ UINT32 Unused[8];
+} VIRTIO_FS_FUSE_INIT_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpCreate.
+//
+typedef struct {
+ UINT32 Flags;
+ UINT32 Mode;
+ UINT32 Umask;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_CREATE_REQUEST;
+
+//
+// Header for VirtioFsFuseOpReadDirPlus.
+//
+// Diverging from the rest of the headers, this structure embeds other
+// structures. The reason is that a scatter list cannot be used to receive
+// NodeResp and AttrResp separately; the record below is followed by a variable
+// size filename byte array, and then such pairs are repeated a number of
+// times. Thus, later header start offsets depend on earlier filename array
+// sizes.
+//
+typedef struct {
+ VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
+ UINT64 NodeId;
+ UINT64 CookieForNextEntry;
+ UINT32 Namelen;
+ UINT32 Type;
+} VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE;
+
+//
+// Header for VirtioFsFuseOpRename2.
+//
+typedef struct {
+ UINT64 NewDir;
+ UINT32 Flags;
+ UINT32 Padding;
+} VIRTIO_FS_FUSE_RENAME2_REQUEST;
+#pragma pack ()
+
+#endif // VIRTIO_FS_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Xen/xen.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Xen/xen.h
index e71e38e85c3..2f158b04e57 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Xen/xen.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/IndustryStandard/Xen/xen.h
@@ -183,10 +183,10 @@ struct vcpu_time_info {
* The correct way to interact with the version number is similar to
* Linux's seqlock: see the implementations of read_seqbegin/read_seqretry.
*/
- UINT32 version;
+ UINT32 Version;
UINT32 pad0;
- UINT64 tsc_timestamp; /* TSC at last update of time vals. */
- UINT64 system_time; /* Time, in nanosecs, since boot. */
+ UINT64 TscTimestamp; /* TSC at last update of time vals. */
+ UINT64 SystemTime; /* Time, in nanosecs, since boot. */
/*
* Current system time:
* system_time +
@@ -194,11 +194,11 @@ struct vcpu_time_info {
* CPU frequency (Hz):
* ((10^9 << 32) / tsc_to_system_mul) >> tsc_shift
*/
- UINT32 tsc_to_system_mul;
- INT8 tsc_shift;
+ UINT32 TscToSystemMultiplier;
+ INT8 TscShift;
INT8 pad1[3];
}; /* 32 bytes */
-typedef struct vcpu_time_info vcpu_time_info_t;
+typedef struct vcpu_time_info XEN_VCPU_TIME_INFO;
struct vcpu_info {
/*
@@ -234,7 +234,7 @@ struct vcpu_info {
#endif /* XEN_HAVE_PV_UPCALL_MASK */
xen_ulong_t evtchn_pending_sel;
struct arch_vcpu_info arch;
- struct vcpu_time_info time;
+ struct vcpu_time_info Time;
}; /* 64 bytes (x86) */
#ifndef __XEN__
typedef struct vcpu_info vcpu_info_t;
@@ -250,7 +250,7 @@ typedef struct vcpu_info vcpu_info_t;
* of this structure remaining constant.
*/
struct shared_info {
- struct vcpu_info vcpu_info[XEN_LEGACY_MAX_VCPUS];
+ struct vcpu_info VcpuInfo[XEN_LEGACY_MAX_VCPUS];
/*
* A domain can create "event channels" on which it can send and receive
@@ -299,6 +299,7 @@ struct shared_info {
};
#ifndef __XEN__
typedef struct shared_info shared_info_t;
+typedef struct shared_info XEN_SHARED_INFO;
#endif
/* Turn a plain number into a C UINTN constant. */
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/BhyveFwCtlLib.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/BhyveFwCtlLib.h
new file mode 100644
index 00000000000..9a22cf65a1a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/BhyveFwCtlLib.h
@@ -0,0 +1,47 @@
+/** @file
+ bhyve firmware configuration access
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2015 Nahanni Systems
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _BHYVE_FW_CTL_LIB_
+#define _BHYVE_FW_CTL_LIB_
+
+/**
+ Sysctl-like interface to read host information via a dot-separated
+ ASCII OID.
+
+ The information is copied into the buffer specified by Item. The
+ size of the buffer is given by the location specified by Size
+ before the call, and that location gives the amount of data copied
+ after a successfull call, and after a call that returns a truncated
+ value with an error return of RETURN_BUFFER_TOO_SMALL.
+
+ The size of the available data can be determined by passing a NULL
+ argument for Item. The size will be returned in the location pointed
+ to by Size.
+
+ @param[] Name - ASCII OID name
+ @param[] Data - return buffer pointer
+ @param[] Size - pointer to length
+
+ @return RETURN_SUCCESS Valid data/len returned.
+ RETURN_UNSUPPORTED f/w interface not present.
+ RETURN_NOT_FOUND OID not found.
+ RETURN_BUFFER_TOO_SMALL Return message truncated.
+ RETURN_INVALID_PARAMETER Buffer too large.
+ RETURN_PROTOCOL_ERROR Unknown error from host.
+ **/
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGet (
+ IN CONST CHAR8 *Name,
+ OUT VOID *Item,
+ IN OUT UINTN *Size
+ );
+
+#endif /* _BHYVE_FW_CTL_LIB_ */
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/MemEncryptSevLib.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 024f56c0eeb..ca1981e4f1b 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -2,7 +2,7 @@
Define Secure Encrypted Virtualization (SEV) base library helper function
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -13,6 +13,71 @@
#include <Base.h>
+//
+// Define the maximum number of #VCs allowed (e.g. the level of nesting
+// that is allowed => 2 allows for 1 nested #VCs). I this value is changed,
+// be sure to increase the size of
+// gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+// in any FDF file using this PCD.
+//
+#define VMGEXIT_MAXIMUM_VC_COUNT 2
+
+//
+// Per-CPU data mapping structure
+// Use UINT32 for cached indicators and compare to a specific value
+// so that the hypervisor can't indicate a value is cached by just
+// writing random data to that area.
+//
+typedef struct {
+ UINT32 Dr7Cached;
+ UINT64 Dr7;
+
+ UINTN VcCount;
+ VOID *GhcbBackupPages;
+} SEV_ES_PER_CPU_DATA;
+
+//
+// Internal structure for holding SEV-ES information needed during SEC phase
+// and valid only during SEC phase and early PEI during platform
+// initialization.
+//
+// This structure is also used by assembler files:
+// OvmfPkg/ResetVector/ResetVector.nasmb
+// OvmfPkg/ResetVector/Ia32/PageTables64.asm
+// OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
+// any changes must stay in sync with its usage.
+//
+typedef struct _SEC_SEV_ES_WORK_AREA {
+ UINT8 SevEsEnabled;
+ UINT8 Reserved1[7];
+
+ UINT64 RandomData;
+
+ UINT64 EncryptionMask;
+} SEC_SEV_ES_WORK_AREA;
+
+//
+// Memory encryption address range states.
+//
+typedef enum {
+ MemEncryptSevAddressRangeUnencrypted,
+ MemEncryptSevAddressRangeEncrypted,
+ MemEncryptSevAddressRangeMixed,
+ MemEncryptSevAddressRangeError,
+} MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE;
+
+/**
+ Returns a boolean to indicate whether SEV-ES is enabled.
+
+ @retval TRUE SEV-ES is enabled
+ @retval FALSE SEV-ES is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevEsIsEnabled (
+ VOID
+ );
+
/**
Returns a boolean to indicate whether SEV is enabled
@@ -103,4 +168,39 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages (
OUT UINTN *BaseAddress,
OUT UINTN *NumberOfPages
);
+
+/**
+ Returns the SEV encryption mask.
+
+ @return The SEV pagetable encryption mask
+**/
+UINT64
+EFIAPI
+MemEncryptSevGetEncryptionMask (
+ VOID
+ );
+
+/**
+ Returns the encryption state of the specified virtual address range.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress Base address to check
+ @param[in] Length Length of virtual address range
+
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
+ unencrypted
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
+ encrypted
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
+ @retval MemEncryptSevAddressRangeError Address range is not mapped
+**/
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
+EFIAPI
+MemEncryptSevGetAddressRangeState (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ );
+
#endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/PciHostBridgeUtilityLib.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/PciHostBridgeUtilityLib.h
new file mode 100644
index 00000000000..c0da372ae87
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Library/PciHostBridgeUtilityLib.h
@@ -0,0 +1,185 @@
+/** @file
+ Provide common utility functions to PciHostBridgeLib instances in
+ ArmVirtPkg and OvmfPkg.
+
+ Copyright (C) 2016, Red Hat, Inc.
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, Huawei Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __PCI_HOST_BRIDGE_UTILITY_LIB_H__
+#define __PCI_HOST_BRIDGE_UTILITY_LIB_H__
+
+
+#include <Library/PciHostBridgeLib.h>
+
+
+/**
+ Utility function to initialize a PCI_ROOT_BRIDGE structure.
+
+ @param[in] Supports Supported attributes.
+
+ @param[in] Attributes Initial attributes.
+
+ @param[in] AllocAttributes Allocation attributes.
+
+ @param[in] DmaAbove4G DMA above 4GB memory.
+
+ @param[in] NoExtendedConfigSpace No Extended Config Space.
+
+ @param[in] RootBusNumber The bus number to store in RootBus.
+
+ @param[in] MaxSubBusNumber The inclusive maximum bus number that can
+ be assigned to any subordinate bus found
+ behind any PCI bridge hanging off this
+ root bus.
+
+ The caller is repsonsible for ensuring
+ that RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then
+ the root bus has no room for subordinate
+ buses.
+
+ @param[in] Io IO aperture.
+
+ @param[in] Mem MMIO aperture.
+
+ @param[in] MemAbove4G MMIO aperture above 4G.
+
+ @param[in] PMem Prefetchable MMIO aperture.
+
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
+
+ @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated
+ by the caller) that should be filled in by
+ this function.
+
+ @retval EFI_SUCCESS Initialization successful. A device path
+ consisting of an ACPI device path node,
+ with UID = RootBusNumber, has been
+ allocated and linked into RootBus.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+PciHostBridgeUtilityInitRootBridge (
+ IN UINT64 Supports,
+ IN UINT64 Attributes,
+ IN UINT64 AllocAttributes,
+ IN BOOLEAN DmaAbove4G,
+ IN BOOLEAN NoExtendedConfigSpace,
+ IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
+ IN PCI_ROOT_BRIDGE_APERTURE *Io,
+ IN PCI_ROOT_BRIDGE_APERTURE *Mem,
+ IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMem,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
+ OUT PCI_ROOT_BRIDGE *RootBus
+ );
+
+
+/**
+ Utility function to uninitialize a PCI_ROOT_BRIDGE structure set up with
+ PciHostBridgeUtilityInitRootBridge().
+
+ @param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
+ initialized with PciHostBridgeUtilityInitRootBridge(),
+ that should be uninitialized. This function doesn't free
+ RootBus.
+**/
+VOID
+EFIAPI
+PciHostBridgeUtilityUninitRootBridge (
+ IN PCI_ROOT_BRIDGE *RootBus
+ );
+
+
+/**
+ Utility function to return all the root bridge instances in an array.
+
+ @param[out] Count The number of root bridge instances.
+
+ @param[in] Attributes Initial attributes.
+
+ @param[in] AllocAttributes Allocation attributes.
+
+ @param[in] DmaAbove4G DMA above 4GB memory.
+
+ @param[in] NoExtendedConfigSpace No Extended Config Space.
+
+ @param[in] BusMin Minimum Bus number, inclusive.
+
+ @param[in] BusMax Maximum Bus number, inclusive.
+
+ @param[in] Io IO aperture.
+
+ @param[in] Mem MMIO aperture.
+
+ @param[in] MemAbove4G MMIO aperture above 4G.
+
+ @param[in] PMem Prefetchable MMIO aperture.
+
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
+
+ @return All the root bridge instances in an array.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeUtilityGetRootBridges (
+ OUT UINTN *Count,
+ IN UINT64 Attributes,
+ IN UINT64 AllocationAttributes,
+ IN BOOLEAN DmaAbove4G,
+ IN BOOLEAN NoExtendedConfigSpace,
+ IN UINTN BusMin,
+ IN UINTN BusMax,
+ IN PCI_ROOT_BRIDGE_APERTURE *Io,
+ IN PCI_ROOT_BRIDGE_APERTURE *Mem,
+ IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMem,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G
+ );
+
+
+/**
+ Utility function to free root bridge instances array from
+ PciHostBridgeUtilityGetRootBridges().
+
+ @param[in] Bridges The root bridge instances array.
+ @param[in] Count The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeUtilityFreeRootBridges (
+ IN PCI_ROOT_BRIDGE *Bridges,
+ IN UINTN Count
+ );
+
+
+/**
+ Utility function to inform the platform that the resource conflict happens.
+
+ @param[in] Configuration Pointer to PCI I/O and PCI memory resource
+ descriptors. The Configuration contains the
+ resources for all the root bridges. The resource
+ for each root bridge is terminated with END
+ descriptor and an additional END is appended
+ indicating the end of the entire resources. The
+ resource descriptor field values follow the
+ description in
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ .SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeUtilityResourceConflict (
+ IN VOID *Configuration
+ );
+
+
+#endif // __PCI_HOST_BRIDGE_UTILITY_LIB_H__
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Pcd/CpuHotEjectData.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Pcd/CpuHotEjectData.h
new file mode 100644
index 00000000000..01d7c8a99aa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Pcd/CpuHotEjectData.h
@@ -0,0 +1,60 @@
+/** @file
+ Definition for the CPU_HOT_EJECT_DATA structure, which shares
+ CPU hot-eject state between OVMF's SmmCpuFeaturesLib instance in
+ PiSmmCpuDxeSmm, and CpuHotplugSmm.
+
+ CPU_HOT_EJECT_DATA is allocated in SMRAM, and pointed-to by
+ PcdCpuHotEjectDataAddress.
+
+ PcdCpuHotEjectDataAddress is valid when SMM_REQUIRE is TRUE
+ and PcdCpuMaxLogicalProcessorNumber > 1.
+
+ Copyright (C) 2021, Oracle Corporation.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef CPU_HOT_EJECT_DATA_H_
+#define CPU_HOT_EJECT_DATA_H_
+
+/**
+ CPU Hot-eject handler, called from SmmCpuFeaturesRendezvousExit()
+ on each CPU at exit from SMM.
+
+ @param[in] ProcessorNum ProcessorNum denotes the CPU exiting SMM,
+ and will be used as an index into
+ CPU_HOT_EJECT_DATA->QemuSelectorMap. It is
+ identical to the processor handle in
+ EFI_SMM_CPU_SERVICE_PROTOCOL.
+**/
+typedef
+VOID
+(EFIAPI *CPU_HOT_EJECT_HANDLER) (
+ IN UINTN ProcessorNum
+ );
+
+//
+// CPU_EJECT_QEMU_SELECTOR_INVALID marks CPUs not being ejected in
+// CPU_HOT_EJECT_DATA->QemuSelectorMap.
+//
+// QEMU CPU Selector is UINT32, so we choose an invalid value larger
+// than that type.
+//
+#define CPU_EJECT_QEMU_SELECTOR_INVALID (MAX_UINT64)
+
+typedef struct {
+ //
+ // Maps ProcessorNum -> QemuSelector for pending hot-ejects
+ //
+ volatile UINT64 *QemuSelectorMap;
+ //
+ // Handler to do the CPU ejection
+ //
+ volatile CPU_HOT_EJECT_HANDLER Handler;
+ //
+ // Entries in the QemuSelectorMap
+ //
+ UINT32 ArrayLength;
+} CPU_HOT_EJECT_DATA;
+
+#endif // CPU_HOT_EJECT_DATA_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Protocol/Legacy8259.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Protocol/Legacy8259.h
index 12b9f43131e..65444086fa7 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Protocol/Legacy8259.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Include/Protocol/Legacy8259.h
@@ -58,7 +58,7 @@ typedef enum {
@param SlaveBase The base vector for the Slave PIC in the 8259 controller.
@retval EFI_SUCCESS The new bases were programmed.
- @retval EFI_DEVICE_ERROR A device error occured programming the vector bases.
+ @retval EFI_DEVICE_ERROR A device error occurred programming the vector bases.
**/
typedef
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index a9ba5da9e55..02770281c94 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -1,7 +1,7 @@
## @file
# Library provides the helper functions for SEV guest
#
-# Copyright (c) 2017 Advanced Micro Devices. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -10,11 +10,11 @@
[Defines]
INF_VERSION = 1.25
- BASE_NAME = MemEncryptSevLib
+ BASE_NAME = DxeMemEncryptSevLib
FILE_GUID = c1594631-3888-4be4-949f-9c630dbc842b
MODULE_TYPE = BASE
VERSION_STRING = 1.0
- LIBRARY_CLASS = MemEncryptSevLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
+ LIBRARY_CLASS = MemEncryptSevLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
#
# The following information is for reference only and not required by the build
@@ -29,15 +29,18 @@
OvmfPkg/OvmfPkg.dec
UefiCpuPkg/UefiCpuPkg.dec
+[Sources]
+ DxeMemEncryptSevLibInternal.c
+ PeiDxeMemEncryptSevLibInternal.c
+
[Sources.X64]
- MemEncryptSevLibInternal.c
X64/MemEncryptSevLib.c
+ X64/PeiDxeVirtualMemory.c
X64/VirtualMemory.c
X64/VirtualMemory.h
[Sources.IA32]
Ia32/MemEncryptSevLib.c
- MemEncryptSevLibInternal.c
[LibraryClasses]
BaseLib
@@ -49,3 +52,6 @@
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
new file mode 100644
index 00000000000..bc1d039a081
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -0,0 +1,145 @@
+/** @file
+
+ Secure Encrypted Virtualization (SEV) library helper function
+
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PcdLib.h>
+#include <Register/Amd/Cpuid.h>
+#include <Register/Amd/Msr.h>
+#include <Register/Cpuid.h>
+#include <Uefi/UefiBaseType.h>
+
+STATIC BOOLEAN mSevStatus = FALSE;
+STATIC BOOLEAN mSevEsStatus = FALSE;
+STATIC BOOLEAN mSevStatusChecked = FALSE;
+
+STATIC UINT64 mSevEncryptionMask = 0;
+STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
+
+/**
+ Reads and sets the status of SEV features.
+
+ **/
+STATIC
+VOID
+EFIAPI
+InternalMemEncryptSevStatus (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ MSR_SEV_STATUS_REGISTER Msr;
+ CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax;
+ BOOLEAN ReadSevMsr;
+ UINT64 EncryptionMask;
+
+ ReadSevMsr = FALSE;
+
+ EncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask);
+ if (EncryptionMask != 0) {
+ //
+ // The MSR has been read before, so it is safe to read it again and avoid
+ // having to validate the CPUID information.
+ //
+ ReadSevMsr = TRUE;
+ } else {
+ //
+ // Check if memory encryption leaf exist
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {
+ //
+ // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported)
+ //
+ AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+
+ if (Eax.Bits.SevBit) {
+ ReadSevMsr = TRUE;
+ }
+ }
+ }
+
+ if (ReadSevMsr) {
+ //
+ // Check MSR_0xC0010131 Bit 0 (Sev Enabled)
+ //
+ Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
+ if (Msr.Bits.SevBit) {
+ mSevStatus = TRUE;
+ }
+
+ //
+ // Check MSR_0xC0010131 Bit 1 (Sev-Es Enabled)
+ //
+ if (Msr.Bits.SevEsBit) {
+ mSevEsStatus = TRUE;
+ }
+ }
+
+ mSevStatusChecked = TRUE;
+}
+
+/**
+ Returns a boolean to indicate whether SEV-ES is enabled.
+
+ @retval TRUE SEV-ES is enabled
+ @retval FALSE SEV-ES is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevEsIsEnabled (
+ VOID
+ )
+{
+ if (!mSevStatusChecked) {
+ InternalMemEncryptSevStatus ();
+ }
+
+ return mSevEsStatus;
+}
+
+/**
+ Returns a boolean to indicate whether SEV is enabled.
+
+ @retval TRUE SEV is enabled
+ @retval FALSE SEV is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevIsEnabled (
+ VOID
+ )
+{
+ if (!mSevStatusChecked) {
+ InternalMemEncryptSevStatus ();
+ }
+
+ return mSevStatus;
+}
+
+/**
+ Returns the SEV encryption mask.
+
+ @return The SEV pagtable encryption mask
+**/
+UINT64
+EFIAPI
+MemEncryptSevGetEncryptionMask (
+ VOID
+ )
+{
+ if (!mSevEncryptionMaskSaved) {
+ mSevEncryptionMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask);
+ mSevEncryptionMaskSaved = TRUE;
+ }
+
+ return mSevEncryptionMask;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index 21c776979ee..060fd5fde96 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -2,7 +2,7 @@
Secure Encrypted Virtualization (SEV) library helper function
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -82,3 +82,32 @@ MemEncryptSevSetPageEncMask (
//
return RETURN_UNSUPPORTED;
}
+
+/**
+ Returns the encryption state of the specified virtual address range.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress Base address to check
+ @param[in] Length Length of virtual address range
+
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
+ unencrypted
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
+ encrypted
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
+ @retval MemEncryptSevAddressRangeError Address range is not mapped
+**/
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
+EFIAPI
+MemEncryptSevGetAddressRangeState (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ //
+ // Memory is always encrypted in 32-bit mode
+ //
+ return MemEncryptSevAddressRangeEncrypted;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
index 44e4975b93a..41ed7926da0 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
@@ -2,7 +2,7 @@
Secure Encrypted Virtualization (SEV) library helper function
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -12,81 +12,10 @@
#include <Library/DebugLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/PcdLib.h>
-#include <Register/Amd/Cpuid.h>
-#include <Register/Amd/Msr.h>
-#include <Register/Cpuid.h>
#include <Register/QemuSmramSaveStateMap.h>
#include <Register/SmramSaveStateMap.h>
#include <Uefi/UefiBaseType.h>
-STATIC BOOLEAN mSevStatus = FALSE;
-STATIC BOOLEAN mSevStatusChecked = FALSE;
-
-/**
-
- Returns a boolean to indicate whether SEV is enabled
-
- @retval TRUE SEV is enabled
- @retval FALSE SEV is not enabled
- **/
-STATIC
-BOOLEAN
-EFIAPI
-InternalMemEncryptSevIsEnabled (
- VOID
- )
-{
- UINT32 RegEax;
- MSR_SEV_STATUS_REGISTER Msr;
- CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax;
-
- //
- // Check if memory encryption leaf exist
- //
- AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
- if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {
- //
- // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported)
- //
- AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL);
-
- if (Eax.Bits.SevBit) {
- //
- // Check MSR_0xC0010131 Bit 0 (Sev Enabled)
- //
- Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
- if (Msr.Bits.SevBit) {
- return TRUE;
- }
- }
- }
-
- return FALSE;
-}
-
-/**
- Returns a boolean to indicate whether SEV is enabled
-
- @retval TRUE SEV is enabled
- @retval FALSE SEV is not enabled
-**/
-BOOLEAN
-EFIAPI
-MemEncryptSevIsEnabled (
- VOID
- )
-{
- if (mSevStatusChecked) {
- return mSevStatus;
- }
-
- mSevStatus = InternalMemEncryptSevIsEnabled();
- mSevStatusChecked = TRUE;
-
- return mSevStatus;
-}
-
-
/**
Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM
Save State Map.
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
new file mode 100644
index 00000000000..f60e1debe42
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -0,0 +1,57 @@
+## @file
+# Library provides the helper functions for SEV guest
+#
+# Copyright (c) 2020 Advanced Micro Devices. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 1.25
+ BASE_NAME = PeiMemEncryptSevLib
+ FILE_GUID = 15d9a694-3d2a-4184-9672-ba55c3070e07
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MemEncryptSevLib|PEIM
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[Sources]
+ PeiDxeMemEncryptSevLibInternal.c
+ PeiMemEncryptSevLibInternal.c
+
+[Sources.X64]
+ X64/MemEncryptSevLib.c
+ X64/PeiDxeVirtualMemory.c
+ X64/VirtualMemory.c
+ X64/VirtualMemory.h
+
+[Sources.IA32]
+ Ia32/MemEncryptSevLib.c
+
+[LibraryClasses]
+ BaseLib
+ CacheMaintenanceLib
+ CpuLib
+ DebugLib
+ MemoryAllocationLib
+ PcdLib
+
+[FeaturePcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
+
+[FixedPcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
new file mode 100644
index 00000000000..f449026f9d0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
@@ -0,0 +1,159 @@
+/** @file
+
+ Secure Encrypted Virtualization (SEV) library helper function
+
+ Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PcdLib.h>
+#include <Register/Amd/Cpuid.h>
+#include <Register/Amd/Msr.h>
+#include <Register/Cpuid.h>
+#include <Uefi/UefiBaseType.h>
+
+STATIC BOOLEAN mSevStatus = FALSE;
+STATIC BOOLEAN mSevEsStatus = FALSE;
+STATIC BOOLEAN mSevStatusChecked = FALSE;
+
+STATIC UINT64 mSevEncryptionMask = 0;
+STATIC BOOLEAN mSevEncryptionMaskSaved = FALSE;
+
+/**
+ Reads and sets the status of SEV features.
+
+ **/
+STATIC
+VOID
+EFIAPI
+InternalMemEncryptSevStatus (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ MSR_SEV_STATUS_REGISTER Msr;
+ CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax;
+ BOOLEAN ReadSevMsr;
+ SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
+
+ ReadSevMsr = FALSE;
+
+ SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+ if (SevEsWorkArea != NULL && SevEsWorkArea->EncryptionMask != 0) {
+ //
+ // The MSR has been read before, so it is safe to read it again and avoid
+ // having to validate the CPUID information.
+ //
+ ReadSevMsr = TRUE;
+ } else {
+ //
+ // Check if memory encryption leaf exist
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {
+ //
+ // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported)
+ //
+ AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+
+ if (Eax.Bits.SevBit) {
+ ReadSevMsr = TRUE;
+ }
+ }
+ }
+
+ if (ReadSevMsr) {
+ //
+ // Check MSR_0xC0010131 Bit 0 (Sev Enabled)
+ //
+ Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
+ if (Msr.Bits.SevBit) {
+ mSevStatus = TRUE;
+ }
+
+ //
+ // Check MSR_0xC0010131 Bit 1 (Sev-Es Enabled)
+ //
+ if (Msr.Bits.SevEsBit) {
+ mSevEsStatus = TRUE;
+ }
+ }
+
+ mSevStatusChecked = TRUE;
+}
+
+/**
+ Returns a boolean to indicate whether SEV-ES is enabled.
+
+ @retval TRUE SEV-ES is enabled
+ @retval FALSE SEV-ES is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevEsIsEnabled (
+ VOID
+ )
+{
+ if (!mSevStatusChecked) {
+ InternalMemEncryptSevStatus ();
+ }
+
+ return mSevEsStatus;
+}
+
+/**
+ Returns a boolean to indicate whether SEV is enabled.
+
+ @retval TRUE SEV is enabled
+ @retval FALSE SEV is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevIsEnabled (
+ VOID
+ )
+{
+ if (!mSevStatusChecked) {
+ InternalMemEncryptSevStatus ();
+ }
+
+ return mSevStatus;
+}
+
+/**
+ Returns the SEV encryption mask.
+
+ @return The SEV pagtable encryption mask
+**/
+UINT64
+EFIAPI
+MemEncryptSevGetEncryptionMask (
+ VOID
+ )
+{
+ if (!mSevEncryptionMaskSaved) {
+ SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
+
+ SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+ if (SevEsWorkArea != NULL) {
+ mSevEncryptionMask = SevEsWorkArea->EncryptionMask;
+ } else {
+ CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
+
+ //
+ // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
+ //
+ AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
+ mSevEncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
+ }
+
+ mSevEncryptionMaskSaved = TRUE;
+ }
+
+ return mSevEncryptionMask;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
new file mode 100644
index 00000000000..32fbbd52c30
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Library provides the helper functions for SEV guest
+#
+# Copyright (c) 2020 Advanced Micro Devices. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 1.25
+ BASE_NAME = SecMemEncryptSevLib
+ FILE_GUID = 046388b4-430e-4e61-88f6-51ea21db2632
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MemEncryptSevLib|SEC
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[Sources]
+ SecMemEncryptSevLibInternal.c
+
+[Sources.X64]
+ X64/MemEncryptSevLib.c
+ X64/SecVirtualMemory.c
+ X64/VirtualMemory.c
+ X64/VirtualMemory.h
+
+[Sources.IA32]
+ Ia32/MemEncryptSevLib.c
+
+[LibraryClasses]
+ BaseLib
+ CpuLib
+ DebugLib
+ PcdLib
+
+[FixedPcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
new file mode 100644
index 00000000000..404fa70a93f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -0,0 +1,155 @@
+/** @file
+
+ Secure Encrypted Virtualization (SEV) library helper function
+
+ Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PcdLib.h>
+#include <Register/Amd/Cpuid.h>
+#include <Register/Amd/Msr.h>
+#include <Register/Cpuid.h>
+#include <Uefi/UefiBaseType.h>
+
+/**
+ Reads and sets the status of SEV features.
+
+ **/
+STATIC
+UINT32
+EFIAPI
+InternalMemEncryptSevStatus (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax;
+ BOOLEAN ReadSevMsr;
+ SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
+
+ ReadSevMsr = FALSE;
+
+ SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+ if (SevEsWorkArea != NULL && SevEsWorkArea->EncryptionMask != 0) {
+ //
+ // The MSR has been read before, so it is safe to read it again and avoid
+ // having to validate the CPUID information.
+ //
+ ReadSevMsr = TRUE;
+ } else {
+ //
+ // Check if memory encryption leaf exist
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_MEMORY_ENCRYPTION_INFO) {
+ //
+ // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported)
+ //
+ AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL);
+
+ if (Eax.Bits.SevBit) {
+ ReadSevMsr = TRUE;
+ }
+ }
+ }
+
+ return ReadSevMsr ? AsmReadMsr32 (MSR_SEV_STATUS) : 0;
+}
+
+/**
+ Returns a boolean to indicate whether SEV-ES is enabled.
+
+ @retval TRUE SEV-ES is enabled
+ @retval FALSE SEV-ES is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevEsIsEnabled (
+ VOID
+ )
+{
+ MSR_SEV_STATUS_REGISTER Msr;
+
+ Msr.Uint32 = InternalMemEncryptSevStatus ();
+
+ return Msr.Bits.SevEsBit ? TRUE : FALSE;
+}
+
+/**
+ Returns a boolean to indicate whether SEV is enabled.
+
+ @retval TRUE SEV is enabled
+ @retval FALSE SEV is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevIsEnabled (
+ VOID
+ )
+{
+ MSR_SEV_STATUS_REGISTER Msr;
+
+ Msr.Uint32 = InternalMemEncryptSevStatus ();
+
+ return Msr.Bits.SevBit ? TRUE : FALSE;
+}
+
+/**
+ Returns the SEV encryption mask.
+
+ @return The SEV pagtable encryption mask
+**/
+UINT64
+EFIAPI
+MemEncryptSevGetEncryptionMask (
+ VOID
+ )
+{
+ CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
+ SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
+ UINT64 EncryptionMask;
+
+ SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+ if (SevEsWorkArea != NULL) {
+ EncryptionMask = SevEsWorkArea->EncryptionMask;
+ } else {
+ //
+ // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
+ //
+ AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
+ EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
+ }
+
+ return EncryptionMask;
+}
+
+/**
+ Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM
+ Save State Map.
+
+ @param[out] BaseAddress The base address of the lowest-address page that
+ covers the initial SMRAM Save State Map.
+
+ @param[out] NumberOfPages The number of pages in the page range that covers
+ the initial SMRAM Save State Map.
+
+ @retval RETURN_SUCCESS BaseAddress and NumberOfPages have been set on
+ output.
+
+ @retval RETURN_UNSUPPORTED SMM is unavailable.
+**/
+RETURN_STATUS
+EFIAPI
+MemEncryptSevLocateInitialSmramSaveStateMapPages (
+ OUT UINTN *BaseAddress,
+ OUT UINTN *NumberOfPages
+ )
+{
+ return RETURN_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index 6fc47f520c4..9cbe2c9bcc5 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -2,7 +2,7 @@
Secure Encrypted Virtualization (SEV) library helper function
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -88,3 +88,33 @@ MemEncryptSevSetPageEncMask (
Flush
);
}
+
+/**
+ Returns the encryption state of the specified virtual address range.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress Base address to check
+ @param[in] Length Length of virtual address range
+
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
+ unencrypted
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
+ encrypted
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
+ @retval MemEncryptSevAddressRangeError Address range is not mapped
+**/
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
+EFIAPI
+MemEncryptSevGetAddressRangeState (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ return InternalMemEncryptSevGetAddressRangeState (
+ Cr3BaseAddress,
+ BaseAddress,
+ Length
+ );
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
new file mode 100644
index 00000000000..0d69a9014b6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -0,0 +1,893 @@
+/** @file
+
+ Virtual Memory Management Services to set or clear the memory encryption bit
+
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
+
+**/
+
+#include <Library/CpuLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Register/Amd/Cpuid.h>
+#include <Register/Cpuid.h>
+
+#include "VirtualMemory.h"
+
+STATIC BOOLEAN mAddressEncMaskChecked = FALSE;
+STATIC UINT64 mAddressEncMask;
+STATIC PAGE_TABLE_POOL *mPageTablePool = NULL;
+
+typedef enum {
+ SetCBit,
+ ClearCBit
+} MAP_RANGE_MODE;
+
+/**
+ Return the pagetable memory encryption mask.
+
+ @return The pagetable memory encryption mask.
+
+**/
+UINT64
+EFIAPI
+InternalGetMemEncryptionAddressMask (
+ VOID
+ )
+{
+ UINT64 EncryptionMask;
+
+ if (mAddressEncMaskChecked) {
+ return mAddressEncMask;
+ }
+
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();
+
+ mAddressEncMask = EncryptionMask & PAGING_1G_ADDRESS_MASK_64;
+ mAddressEncMaskChecked = TRUE;
+
+ return mAddressEncMask;
+}
+
+/**
+ Initialize a buffer pool for page table use only.
+
+ To reduce the potential split operation on page table, the pages reserved for
+ page table should be allocated in the times of PAGE_TABLE_POOL_UNIT_PAGES and
+ at the boundary of PAGE_TABLE_POOL_ALIGNMENT. So the page pool is always
+ initialized with number of pages greater than or equal to the given
+ PoolPages.
+
+ Once the pages in the pool are used up, this method should be called again to
+ reserve at least another PAGE_TABLE_POOL_UNIT_PAGES. Usually this won't
+ happen often in practice.
+
+ @param[in] PoolPages The least page number of the pool to be created.
+
+ @retval TRUE The pool is initialized successfully.
+ @retval FALSE The memory is out of resource.
+**/
+STATIC
+BOOLEAN
+InitializePageTablePool (
+ IN UINTN PoolPages
+ )
+{
+ VOID *Buffer;
+
+ //
+ // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for
+ // header.
+ //
+ PoolPages += 1; // Add one page for header.
+ PoolPages = ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) *
+ PAGE_TABLE_POOL_UNIT_PAGES;
+ Buffer = AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
+ if (Buffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n"));
+ return FALSE;
+ }
+
+ //
+ // Link all pools into a list for easier track later.
+ //
+ if (mPageTablePool == NULL) {
+ mPageTablePool = Buffer;
+ mPageTablePool->NextPool = mPageTablePool;
+ } else {
+ ((PAGE_TABLE_POOL *)Buffer)->NextPool = mPageTablePool->NextPool;
+ mPageTablePool->NextPool = Buffer;
+ mPageTablePool = Buffer;
+ }
+
+ //
+ // Reserve one page for pool header.
+ //
+ mPageTablePool->FreePages = PoolPages - 1;
+ mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
+
+ return TRUE;
+}
+
+/**
+ This API provides a way to allocate memory for page table.
+
+ This API can be called more than once to allocate memory for page tables.
+
+ Allocates the number of 4KB pages 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 remaining 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.
+
+**/
+STATIC
+VOID *
+EFIAPI
+AllocatePageTableMemory (
+ IN UINTN Pages
+ )
+{
+ VOID *Buffer;
+
+ if (Pages == 0) {
+ return NULL;
+ }
+
+ //
+ // Renew the pool if necessary.
+ //
+ if (mPageTablePool == NULL ||
+ Pages > mPageTablePool->FreePages) {
+ if (!InitializePageTablePool (Pages)) {
+ return NULL;
+ }
+ }
+
+ Buffer = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
+
+ mPageTablePool->Offset += EFI_PAGES_TO_SIZE (Pages);
+ mPageTablePool->FreePages -= Pages;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a:%a: Buffer=0x%Lx Pages=%ld\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ Buffer,
+ Pages
+ ));
+
+ return Buffer;
+}
+
+
+/**
+ Split 2M page to 4K.
+
+ @param[in] PhysicalAddress Start physical address the 2M page
+ covered.
+ @param[in, out] PageEntry2M Pointer to 2M page entry.
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+
+**/
+STATIC
+VOID
+Split2MPageTo4K (
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN OUT UINT64 *PageEntry2M,
+ IN PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize
+ )
+{
+ PHYSICAL_ADDRESS PhysicalAddress4K;
+ UINTN IndexOfPageTableEntries;
+ PAGE_TABLE_4K_ENTRY *PageTableEntry;
+ PAGE_TABLE_4K_ENTRY *PageTableEntry1;
+ UINT64 AddressEncMask;
+
+ PageTableEntry = AllocatePageTableMemory(1);
+
+ PageTableEntry1 = PageTableEntry;
+
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();
+
+ ASSERT (PageTableEntry != NULL);
+ ASSERT (*PageEntry2M & AddressEncMask);
+
+ PhysicalAddress4K = PhysicalAddress;
+ for (IndexOfPageTableEntries = 0;
+ IndexOfPageTableEntries < 512;
+ (IndexOfPageTableEntries++,
+ PageTableEntry++,
+ PhysicalAddress4K += SIZE_4KB)) {
+ //
+ // Fill in the Page Table entries
+ //
+ PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
+ PageTableEntry->Bits.ReadWrite = 1;
+ PageTableEntry->Bits.Present = 1;
+ if ((PhysicalAddress4K >= StackBase) &&
+ (PhysicalAddress4K < StackBase + StackSize)) {
+ //
+ // Set Nx bit for stack.
+ //
+ PageTableEntry->Bits.Nx = 1;
+ }
+ }
+
+ //
+ // Fill in 2M page entry.
+ //
+ *PageEntry2M = ((UINT64)(UINTN)PageTableEntry1 |
+ IA32_PG_P | IA32_PG_RW | AddressEncMask);
+}
+
+/**
+ Set one page of page table pool memory to be read-only.
+
+ @param[in] PageTableBase Base address of page table (CR3).
+ @param[in] Address Start address of a page to be set as read-only.
+ @param[in] Level4Paging Level 4 paging flag.
+
+**/
+STATIC
+VOID
+SetPageTablePoolReadOnly (
+ IN UINTN PageTableBase,
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN BOOLEAN Level4Paging
+ )
+{
+ UINTN Index;
+ UINTN EntryIndex;
+ UINT64 AddressEncMask;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ UINT64 *PageTable;
+ UINT64 *NewPageTable;
+ UINT64 PageAttr;
+ UINT64 LevelSize[5];
+ UINT64 LevelMask[5];
+ UINTN LevelShift[5];
+ UINTN Level;
+ UINT64 PoolUnitSize;
+
+ ASSERT (PageTableBase != 0);
+
+ //
+ // Since the page table is always from page table pool, which is always
+ // located at the boundary of PcdPageTablePoolAlignment, we just need to
+ // set the whole pool unit to be read-only.
+ //
+ Address = Address & PAGE_TABLE_POOL_ALIGN_MASK;
+
+ LevelShift[1] = PAGING_L1_ADDRESS_SHIFT;
+ LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
+ LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
+ LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
+
+ LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
+ LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
+ LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
+ LevelMask[4] = PAGING_1G_ADDRESS_MASK_64;
+
+ LevelSize[1] = SIZE_4KB;
+ LevelSize[2] = SIZE_2MB;
+ LevelSize[3] = SIZE_1GB;
+ LevelSize[4] = SIZE_512GB;
+
+ AddressEncMask = InternalGetMemEncryptionAddressMask();
+ PageTable = (UINT64 *)(UINTN)PageTableBase;
+ PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
+
+ for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) {
+ Index = ((UINTN)RShiftU64 (Address, LevelShift[Level]));
+ Index &= PAGING_PAE_INDEX_MASK;
+
+ PageAttr = PageTable[Index];
+ if ((PageAttr & IA32_PG_PS) == 0) {
+ //
+ // Go to next level of table.
+ //
+ PageTable = (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask &
+ PAGING_4K_ADDRESS_MASK_64);
+ continue;
+ }
+
+ if (PoolUnitSize >= LevelSize[Level]) {
+ //
+ // Clear R/W bit if current page granularity is not larger than pool unit
+ // size.
+ //
+ if ((PageAttr & IA32_PG_RW) != 0) {
+ while (PoolUnitSize > 0) {
+ //
+ // PAGE_TABLE_POOL_UNIT_SIZE and PAGE_TABLE_POOL_ALIGNMENT are fit in
+ // one page (2MB). Then we don't need to update attributes for pages
+ // crossing page directory. ASSERT below is for that purpose.
+ //
+ ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64));
+
+ PageTable[Index] &= ~(UINT64)IA32_PG_RW;
+ PoolUnitSize -= LevelSize[Level];
+
+ ++Index;
+ }
+ }
+
+ break;
+
+ } else {
+ //
+ // The smaller granularity of page must be needed.
+ //
+ ASSERT (Level > 1);
+
+ NewPageTable = AllocatePageTableMemory (1);
+ ASSERT (NewPageTable != NULL);
+
+ PhysicalAddress = PageAttr & LevelMask[Level];
+ for (EntryIndex = 0;
+ EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64);
+ ++EntryIndex) {
+ NewPageTable[EntryIndex] = PhysicalAddress | AddressEncMask |
+ IA32_PG_P | IA32_PG_RW;
+ if (Level > 2) {
+ NewPageTable[EntryIndex] |= IA32_PG_PS;
+ }
+ PhysicalAddress += LevelSize[Level - 1];
+ }
+
+ PageTable[Index] = (UINT64)(UINTN)NewPageTable | AddressEncMask |
+ IA32_PG_P | IA32_PG_RW;
+ PageTable = NewPageTable;
+ }
+ }
+}
+
+/**
+ Prevent the memory pages used for page table from been overwritten.
+
+ @param[in] PageTableBase Base address of page table (CR3).
+ @param[in] Level4Paging Level 4 paging flag.
+
+**/
+STATIC
+VOID
+EnablePageTableProtection (
+ IN UINTN PageTableBase,
+ IN BOOLEAN Level4Paging
+ )
+{
+ PAGE_TABLE_POOL *HeadPool;
+ PAGE_TABLE_POOL *Pool;
+ UINT64 PoolSize;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ if (mPageTablePool == NULL) {
+ return;
+ }
+
+ //
+ // SetPageTablePoolReadOnly might update mPageTablePool. It's safer to
+ // remember original one in advance.
+ //
+ HeadPool = mPageTablePool;
+ Pool = HeadPool;
+ do {
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Pool;
+ PoolSize = Pool->Offset + EFI_PAGES_TO_SIZE (Pool->FreePages);
+
+ //
+ // The size of one pool must be multiple of PAGE_TABLE_POOL_UNIT_SIZE,
+ // which is one of page size of the processor (2MB by default). Let's apply
+ // the protection to them one by one.
+ //
+ while (PoolSize > 0) {
+ SetPageTablePoolReadOnly(PageTableBase, Address, Level4Paging);
+ Address += PAGE_TABLE_POOL_UNIT_SIZE;
+ PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
+ }
+
+ Pool = Pool->NextPool;
+ } while (Pool != HeadPool);
+
+}
+
+
+/**
+ Split 1G page to 2M.
+
+ @param[in] PhysicalAddress Start physical address the 1G page
+ covered.
+ @param[in, out] PageEntry1G Pointer to 1G page entry.
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+
+**/
+STATIC
+VOID
+Split1GPageTo2M (
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN OUT UINT64 *PageEntry1G,
+ IN PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize
+ )
+{
+ PHYSICAL_ADDRESS PhysicalAddress2M;
+ UINTN IndexOfPageDirectoryEntries;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ UINT64 AddressEncMask;
+
+ PageDirectoryEntry = AllocatePageTableMemory(1);
+
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();
+ ASSERT (PageDirectoryEntry != NULL);
+ ASSERT (*PageEntry1G & AddressEncMask);
+ //
+ // Fill in 1G page entry.
+ //
+ *PageEntry1G = ((UINT64)(UINTN)PageDirectoryEntry |
+ IA32_PG_P | IA32_PG_RW | AddressEncMask);
+
+ PhysicalAddress2M = PhysicalAddress;
+ for (IndexOfPageDirectoryEntries = 0;
+ IndexOfPageDirectoryEntries < 512;
+ (IndexOfPageDirectoryEntries++,
+ PageDirectoryEntry++,
+ PhysicalAddress2M += SIZE_2MB)) {
+ if ((PhysicalAddress2M < StackBase + StackSize) &&
+ ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
+ //
+ // Need to split this 2M page that covers stack range.
+ //
+ Split2MPageTo4K (
+ PhysicalAddress2M,
+ (UINT64 *)PageDirectoryEntry,
+ StackBase,
+ StackSize
+ );
+ } else {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M | AddressEncMask;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+}
+
+
+/**
+ Set or Clear the memory encryption bit
+
+ @param[in, out] PageTablePointer Page table entry pointer (PTE).
+ @param[in] Mode Set or Clear encryption bit
+
+**/
+STATIC VOID
+SetOrClearCBit(
+ IN OUT UINT64* PageTablePointer,
+ IN MAP_RANGE_MODE Mode
+ )
+{
+ UINT64 AddressEncMask;
+
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();
+
+ if (Mode == SetCBit) {
+ *PageTablePointer |= AddressEncMask;
+ } else {
+ *PageTablePointer &= ~AddressEncMask;
+ }
+
+}
+
+/**
+ Check the WP status in CR0 register. This bit is used to lock or unlock write
+ access to pages marked as read-only.
+
+ @retval TRUE Write protection is enabled.
+ @retval FALSE Write protection is disabled.
+**/
+STATIC
+BOOLEAN
+IsReadOnlyPageWriteProtected (
+ VOID
+ )
+{
+ return ((AsmReadCr0 () & BIT16) != 0);
+}
+
+
+/**
+ Disable Write Protect on pages marked as read-only.
+**/
+STATIC
+VOID
+DisableReadOnlyPageWriteProtect (
+ VOID
+ )
+{
+ AsmWriteCr0 (AsmReadCr0() & ~BIT16);
+}
+
+/**
+ Enable Write Protect on pages marked as read-only.
+**/
+STATIC
+VOID
+EnableReadOnlyPageWriteProtect (
+ VOID
+ )
+{
+ AsmWriteCr0 (AsmReadCr0() | BIT16);
+}
+
+
+/**
+ This function either sets or clears memory encryption bit for the memory
+ region specified by PhysicalAddress and Length from the current page table
+ context.
+
+ The function iterates through the PhysicalAddress one page at a time, and set
+ or clears the memory encryption mask in the page table. If it encounters
+ that a given physical address range is part of large page then it attempts to
+ change the attribute at one go (based on size), otherwise it splits the
+ large pages into smaller (e.g 2M page into 4K pages) and then try to set or
+ clear the encryption bit on the smallest page size.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a memory region.
+ @param[in] Length The length of memory region
+ @param[in] Mode Set or Clear mode
+ @param[in] CacheFlush Flush the caches before applying the
+ encryption mask
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute
+ is not supported
+**/
+STATIC
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDec (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length,
+ IN MAP_RANGE_MODE Mode,
+ IN BOOLEAN CacheFlush
+ )
+{
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+ PAGE_TABLE_ENTRY *PageDirectory2MEntry;
+ PAGE_TABLE_4K_ENTRY *PageTableEntry;
+ UINT64 PgTableMask;
+ UINT64 AddressEncMask;
+ BOOLEAN IsWpEnabled;
+ RETURN_STATUS Status;
+
+ //
+ // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings.
+ //
+ PageMapLevel4Entry = NULL;
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx Mode=%a CacheFlush=%u\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ Cr3BaseAddress,
+ PhysicalAddress,
+ (UINT64)Length,
+ (Mode == SetCBit) ? "Encrypt" : "Decrypt",
+ (UINT32)CacheFlush
+ ));
+
+ //
+ // Check if we have a valid memory encryption mask
+ //
+ AddressEncMask = InternalGetMemEncryptionAddressMask ();
+ if (!AddressEncMask) {
+ return RETURN_ACCESS_DENIED;
+ }
+
+ PgTableMask = AddressEncMask | EFI_PAGE_MASK;
+
+ if (Length == 0) {
+ return RETURN_INVALID_PARAMETER;
+ }
+
+ //
+ // We are going to change the memory encryption attribute from C=0 -> C=1 or
+ // vice versa Flush the caches to ensure that data is written into memory
+ // with correct C-bit
+ //
+ if (CacheFlush) {
+ WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Length);
+ }
+
+ //
+ // Make sure that the page table is changeable.
+ //
+ IsWpEnabled = IsReadOnlyPageWriteProtected ();
+ if (IsWpEnabled) {
+ DisableReadOnlyPageWriteProtect ();
+ }
+
+ Status = EFI_SUCCESS;
+
+ while (Length != 0)
+ {
+ //
+ // If Cr3BaseAddress is not specified then read the current CR3
+ //
+ if (Cr3BaseAddress == 0) {
+ Cr3BaseAddress = AsmReadCr3();
+ }
+
+ PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask);
+ PageMapLevel4Entry += PML4_OFFSET(PhysicalAddress);
+ if (!PageMapLevel4Entry->Bits.Present) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a:%a: bad PML4 for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ Status = RETURN_NO_MAPPING;
+ goto Done;
+ }
+
+ PageDirectory1GEntry = (VOID *)(
+ (PageMapLevel4Entry->Bits.PageTableBaseAddress <<
+ 12) & ~PgTableMask
+ );
+ PageDirectory1GEntry += PDP_OFFSET(PhysicalAddress);
+ if (!PageDirectory1GEntry->Bits.Present) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a:%a: bad PDPE for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ Status = RETURN_NO_MAPPING;
+ goto Done;
+ }
+
+ //
+ // If the MustBe1 bit is not 1, it's not actually a 1GB entry
+ //
+ if (PageDirectory1GEntry->Bits.MustBe1) {
+ //
+ // Valid 1GB page
+ // If we have at least 1GB to go, we can just update this entry
+ //
+ if ((PhysicalAddress & (BIT30 - 1)) == 0 && Length >= BIT30) {
+ SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode);
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a:%a: updated 1GB entry for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ PhysicalAddress += BIT30;
+ Length -= BIT30;
+ } else {
+ //
+ // We must split the page
+ //
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a:%a: splitting 1GB page for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ Split1GPageTo2M (
+ (UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress << 30,
+ (UINT64 *)PageDirectory1GEntry,
+ 0,
+ 0
+ );
+ continue;
+ }
+ } else {
+ //
+ // Actually a PDP
+ //
+ PageUpperDirectoryPointerEntry =
+ (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory1GEntry;
+ PageDirectory2MEntry =
+ (VOID *)(
+ (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress <<
+ 12) & ~PgTableMask
+ );
+ PageDirectory2MEntry += PDE_OFFSET(PhysicalAddress);
+ if (!PageDirectory2MEntry->Bits.Present) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a:%a: bad PDE for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ Status = RETURN_NO_MAPPING;
+ goto Done;
+ }
+ //
+ // If the MustBe1 bit is not a 1, it's not a 2MB entry
+ //
+ if (PageDirectory2MEntry->Bits.MustBe1) {
+ //
+ // Valid 2MB page
+ // If we have at least 2MB left to go, we can just update this entry
+ //
+ if ((PhysicalAddress & (BIT21-1)) == 0 && Length >= BIT21) {
+ SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode);
+ PhysicalAddress += BIT21;
+ Length -= BIT21;
+ } else {
+ //
+ // We must split up this page into 4K pages
+ //
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a:%a: splitting 2MB page for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ Split2MPageTo4K (
+ (UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress << 21,
+ (UINT64 *)PageDirectory2MEntry,
+ 0,
+ 0
+ );
+ continue;
+ }
+ } else {
+ PageDirectoryPointerEntry =
+ (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory2MEntry;
+ PageTableEntry =
+ (VOID *)(
+ (PageDirectoryPointerEntry->Bits.PageTableBaseAddress <<
+ 12) & ~PgTableMask
+ );
+ PageTableEntry += PTE_OFFSET(PhysicalAddress);
+ if (!PageTableEntry->Bits.Present) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a:%a: bad PTE for Physical=0x%Lx\n",
+ gEfiCallerBaseName,
+ __FUNCTION__,
+ PhysicalAddress
+ ));
+ Status = RETURN_NO_MAPPING;
+ goto Done;
+ }
+ SetOrClearCBit (&PageTableEntry->Uint64, Mode);
+ PhysicalAddress += EFI_PAGE_SIZE;
+ Length -= EFI_PAGE_SIZE;
+ }
+ }
+ }
+
+ //
+ // Protect the page table by marking the memory used for page table to be
+ // read-only.
+ //
+ if (IsWpEnabled) {
+ EnablePageTableProtection ((UINTN)PageMapLevel4Entry, TRUE);
+ }
+
+ //
+ // Flush TLB
+ //
+ CpuFlushTlb();
+
+Done:
+ //
+ // Restore page table write protection, if any.
+ //
+ if (IsWpEnabled) {
+ EnableReadOnlyPageWriteProtect ();
+ }
+
+ return Status;
+}
+
+/**
+ This function clears memory encryption bit for the memory region specified by
+ PhysicalAddress and Length from the current page table context.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a memory region.
+ @param[in] Length The length of memory region
+ @param[in] Flush Flush the caches before applying the
+ encryption mask
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encyrption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevSetMemoryDecrypted (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length,
+ IN BOOLEAN Flush
+ )
+{
+
+ return SetMemoryEncDec (
+ Cr3BaseAddress,
+ PhysicalAddress,
+ Length,
+ ClearCBit,
+ Flush
+ );
+}
+
+/**
+ This function sets memory encryption bit for the memory region specified by
+ PhysicalAddress and Length from the current page table context.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a memory region.
+ @param[in] Length The length of memory region
+ @param[in] Flush Flush the caches before applying the
+ encryption mask
+
+ @retval RETURN_SUCCESS The attributes were set for the memory
+ region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevSetMemoryEncrypted (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length,
+ IN BOOLEAN Flush
+ )
+{
+ return SetMemoryEncDec (
+ Cr3BaseAddress,
+ PhysicalAddress,
+ Length,
+ SetCBit,
+ Flush
+ );
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
new file mode 100644
index 00000000000..93830622dd7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/SecVirtualMemory.c
@@ -0,0 +1,100 @@
+/** @file
+
+ Virtual Memory Management Services to set or clear the memory encryption bit
+
+ Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/CpuLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+#include "VirtualMemory.h"
+
+/**
+ Return the pagetable memory encryption mask.
+
+ @return The pagetable memory encryption mask.
+
+**/
+UINT64
+EFIAPI
+InternalGetMemEncryptionAddressMask (
+ VOID
+ )
+{
+ UINT64 EncryptionMask;
+
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();
+ EncryptionMask &= PAGING_1G_ADDRESS_MASK_64;
+
+ return EncryptionMask;
+}
+
+/**
+ This function clears memory encryption bit for the memory region specified by
+ PhysicalAddress and Length from the current page table context.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a memory region.
+ @param[in] Length The length of memory region
+ @param[in] Flush Flush the caches before applying the
+ encryption mask
+
+ @retval RETURN_SUCCESS The attributes were cleared for the
+ memory region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Clearing the memory encyrption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevSetMemoryDecrypted (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length,
+ IN BOOLEAN Flush
+ )
+{
+ //
+ // This function is not available during SEC.
+ //
+ return RETURN_UNSUPPORTED;
+}
+
+/**
+ This function sets memory encryption bit for the memory region specified by
+ PhysicalAddress and Length from the current page table context.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] PhysicalAddress The physical address that is the start
+ address of a memory region.
+ @param[in] Length The length of memory region
+ @param[in] Flush Flush the caches before applying the
+ encryption mask
+
+ @retval RETURN_SUCCESS The attributes were set for the memory
+ region.
+ @retval RETURN_INVALID_PARAMETER Number of pages is zero.
+ @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute
+ is not supported
+**/
+RETURN_STATUS
+EFIAPI
+InternalMemEncryptSevSetMemoryEncrypted (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS PhysicalAddress,
+ IN UINTN Length,
+ IN BOOLEAN Flush
+ )
+{
+ //
+ // This function is not available during SEC.
+ //
+ return RETURN_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
index dcea0c5cf36..28a474a2473 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
@@ -1,683 +1,133 @@
/** @file
- Virtual Memory Management Services to set or clear the memory encryption bit
+ Virtual Memory Management Services to test an address range encryption state
- Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
- Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
-
**/
#include <Library/CpuLib.h>
-#include <Register/Amd/Cpuid.h>
-#include <Register/Cpuid.h>
+#include <Library/MemEncryptSevLib.h>
#include "VirtualMemory.h"
-STATIC BOOLEAN mAddressEncMaskChecked = FALSE;
-STATIC UINT64 mAddressEncMask;
-STATIC PAGE_TABLE_POOL *mPageTablePool = NULL;
-
-typedef enum {
- SetCBit,
- ClearCBit
-} MAP_RANGE_MODE;
-
-/**
- Get the memory encryption mask
-
- @param[out] EncryptionMask contains the pte mask.
-
-**/
-STATIC
-UINT64
-GetMemEncryptionAddressMask (
- VOID
- )
-{
- UINT64 EncryptionMask;
- CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
-
- if (mAddressEncMaskChecked) {
- return mAddressEncMask;
- }
-
- //
- // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
- //
- AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
- EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
-
- mAddressEncMask = EncryptionMask & PAGING_1G_ADDRESS_MASK_64;
- mAddressEncMaskChecked = TRUE;
-
- return mAddressEncMask;
-}
-
-/**
- Initialize a buffer pool for page table use only.
-
- To reduce the potential split operation on page table, the pages reserved for
- page table should be allocated in the times of PAGE_TABLE_POOL_UNIT_PAGES and
- at the boundary of PAGE_TABLE_POOL_ALIGNMENT. So the page pool is always
- initialized with number of pages greater than or equal to the given
- PoolPages.
-
- Once the pages in the pool are used up, this method should be called again to
- reserve at least another PAGE_TABLE_POOL_UNIT_PAGES. Usually this won't
- happen often in practice.
-
- @param[in] PoolPages The least page number of the pool to be created.
-
- @retval TRUE The pool is initialized successfully.
- @retval FALSE The memory is out of resource.
-**/
-STATIC
-BOOLEAN
-InitializePageTablePool (
- IN UINTN PoolPages
- )
-{
- VOID *Buffer;
-
- //
- // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for
- // header.
- //
- PoolPages += 1; // Add one page for header.
- PoolPages = ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) *
- PAGE_TABLE_POOL_UNIT_PAGES;
- Buffer = AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
- if (Buffer == NULL) {
- DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n"));
- return FALSE;
- }
-
- //
- // Link all pools into a list for easier track later.
- //
- if (mPageTablePool == NULL) {
- mPageTablePool = Buffer;
- mPageTablePool->NextPool = mPageTablePool;
- } else {
- ((PAGE_TABLE_POOL *)Buffer)->NextPool = mPageTablePool->NextPool;
- mPageTablePool->NextPool = Buffer;
- mPageTablePool = Buffer;
- }
-
- //
- // Reserve one page for pool header.
- //
- mPageTablePool->FreePages = PoolPages - 1;
- mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
-
- return TRUE;
-}
-
-/**
- This API provides a way to allocate memory for page table.
-
- This API can be called more than once to allocate memory for page tables.
-
- Allocates the number of 4KB pages 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 remaining 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.
-
-**/
-STATIC
-VOID *
-EFIAPI
-AllocatePageTableMemory (
- IN UINTN Pages
- )
-{
- VOID *Buffer;
-
- if (Pages == 0) {
- return NULL;
- }
-
- //
- // Renew the pool if necessary.
- //
- if (mPageTablePool == NULL ||
- Pages > mPageTablePool->FreePages) {
- if (!InitializePageTablePool (Pages)) {
- return NULL;
- }
- }
-
- Buffer = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
-
- mPageTablePool->Offset += EFI_PAGES_TO_SIZE (Pages);
- mPageTablePool->FreePages -= Pages;
-
- DEBUG ((
- DEBUG_VERBOSE,
- "%a:%a: Buffer=0x%Lx Pages=%ld\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- Buffer,
- Pages
- ));
-
- return Buffer;
-}
-
-
/**
- Split 2M page to 4K.
-
- @param[in] PhysicalAddress Start physical address the 2M page
- covered.
- @param[in, out] PageEntry2M Pointer to 2M page entry.
- @param[in] StackBase Stack base address.
- @param[in] StackSize Stack size.
-
+ Returns the (updated) address range state based upon the page table
+ entry.
+
+ @param[in] CurrentState The current address range state
+ @param[in] PageDirectoryEntry The page table entry to check
+ @param[in] AddressEncMask The encryption mask
+
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
+ unencrypted
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
+ encrypted
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
**/
STATIC
-VOID
-Split2MPageTo4K (
- IN PHYSICAL_ADDRESS PhysicalAddress,
- IN OUT UINT64 *PageEntry2M,
- IN PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
+UpdateAddressState (
+ IN MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE CurrentState,
+ IN UINT64 PageDirectoryEntry,
+ IN UINT64 AddressEncMask
)
{
- PHYSICAL_ADDRESS PhysicalAddress4K;
- UINTN IndexOfPageTableEntries;
- PAGE_TABLE_4K_ENTRY *PageTableEntry, *PageTableEntry1;
- UINT64 AddressEncMask;
-
- PageTableEntry = AllocatePageTableMemory(1);
-
- PageTableEntry1 = PageTableEntry;
-
- AddressEncMask = GetMemEncryptionAddressMask ();
-
- ASSERT (PageTableEntry != NULL);
- ASSERT (*PageEntry2M & AddressEncMask);
-
- PhysicalAddress4K = PhysicalAddress;
- for (IndexOfPageTableEntries = 0;
- IndexOfPageTableEntries < 512;
- (IndexOfPageTableEntries++,
- PageTableEntry++,
- PhysicalAddress4K += SIZE_4KB)) {
- //
- // Fill in the Page Table entries
- //
- PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;
- PageTableEntry->Bits.ReadWrite = 1;
- PageTableEntry->Bits.Present = 1;
- if ((PhysicalAddress4K >= StackBase) &&
- (PhysicalAddress4K < StackBase + StackSize)) {
- //
- // Set Nx bit for stack.
- //
- PageTableEntry->Bits.Nx = 1;
- }
- }
-
- //
- // Fill in 2M page entry.
- //
- *PageEntry2M = ((UINT64)(UINTN)PageTableEntry1 |
- IA32_PG_P | IA32_PG_RW | AddressEncMask);
-}
-
-/**
- Set one page of page table pool memory to be read-only.
-
- @param[in] PageTableBase Base address of page table (CR3).
- @param[in] Address Start address of a page to be set as read-only.
- @param[in] Level4Paging Level 4 paging flag.
-
-**/
-STATIC
-VOID
-SetPageTablePoolReadOnly (
- IN UINTN PageTableBase,
- IN EFI_PHYSICAL_ADDRESS Address,
- IN BOOLEAN Level4Paging
- )
-{
- UINTN Index;
- UINTN EntryIndex;
- UINT64 AddressEncMask;
- EFI_PHYSICAL_ADDRESS PhysicalAddress;
- UINT64 *PageTable;
- UINT64 *NewPageTable;
- UINT64 PageAttr;
- UINT64 LevelSize[5];
- UINT64 LevelMask[5];
- UINTN LevelShift[5];
- UINTN Level;
- UINT64 PoolUnitSize;
-
- ASSERT (PageTableBase != 0);
-
- //
- // Since the page table is always from page table pool, which is always
- // located at the boundary of PcdPageTablePoolAlignment, we just need to
- // set the whole pool unit to be read-only.
- //
- Address = Address & PAGE_TABLE_POOL_ALIGN_MASK;
-
- LevelShift[1] = PAGING_L1_ADDRESS_SHIFT;
- LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
- LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
- LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
-
- LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
- LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
- LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
- LevelMask[4] = PAGING_1G_ADDRESS_MASK_64;
-
- LevelSize[1] = SIZE_4KB;
- LevelSize[2] = SIZE_2MB;
- LevelSize[3] = SIZE_1GB;
- LevelSize[4] = SIZE_512GB;
-
- AddressEncMask = GetMemEncryptionAddressMask() &
- PAGING_1G_ADDRESS_MASK_64;
- PageTable = (UINT64 *)(UINTN)PageTableBase;
- PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
-
- for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) {
- Index = ((UINTN)RShiftU64 (Address, LevelShift[Level]));
- Index &= PAGING_PAE_INDEX_MASK;
-
- PageAttr = PageTable[Index];
- if ((PageAttr & IA32_PG_PS) == 0) {
- //
- // Go to next level of table.
- //
- PageTable = (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask &
- PAGING_4K_ADDRESS_MASK_64);
- continue;
+ if (CurrentState == MemEncryptSevAddressRangeEncrypted) {
+ if ((PageDirectoryEntry & AddressEncMask) == 0) {
+ CurrentState = MemEncryptSevAddressRangeMixed;
}
-
- if (PoolUnitSize >= LevelSize[Level]) {
- //
- // Clear R/W bit if current page granularity is not larger than pool unit
- // size.
- //
- if ((PageAttr & IA32_PG_RW) != 0) {
- while (PoolUnitSize > 0) {
- //
- // PAGE_TABLE_POOL_UNIT_SIZE and PAGE_TABLE_POOL_ALIGNMENT are fit in
- // one page (2MB). Then we don't need to update attributes for pages
- // crossing page directory. ASSERT below is for that purpose.
- //
- ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64));
-
- PageTable[Index] &= ~(UINT64)IA32_PG_RW;
- PoolUnitSize -= LevelSize[Level];
-
- ++Index;
- }
- }
-
- break;
-
- } else {
- //
- // The smaller granularity of page must be needed.
- //
- ASSERT (Level > 1);
-
- NewPageTable = AllocatePageTableMemory (1);
- ASSERT (NewPageTable != NULL);
-
- PhysicalAddress = PageAttr & LevelMask[Level];
- for (EntryIndex = 0;
- EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64);
- ++EntryIndex) {
- NewPageTable[EntryIndex] = PhysicalAddress | AddressEncMask |
- IA32_PG_P | IA32_PG_RW;
- if (Level > 2) {
- NewPageTable[EntryIndex] |= IA32_PG_PS;
- }
- PhysicalAddress += LevelSize[Level - 1];
- }
-
- PageTable[Index] = (UINT64)(UINTN)NewPageTable | AddressEncMask |
- IA32_PG_P | IA32_PG_RW;
- PageTable = NewPageTable;
+ } else if (CurrentState == MemEncryptSevAddressRangeUnencrypted) {
+ if ((PageDirectoryEntry & AddressEncMask) != 0) {
+ CurrentState = MemEncryptSevAddressRangeMixed;
}
- }
-}
-
-/**
- Prevent the memory pages used for page table from been overwritten.
-
- @param[in] PageTableBase Base address of page table (CR3).
- @param[in] Level4Paging Level 4 paging flag.
-
-**/
-STATIC
-VOID
-EnablePageTableProtection (
- IN UINTN PageTableBase,
- IN BOOLEAN Level4Paging
- )
-{
- PAGE_TABLE_POOL *HeadPool;
- PAGE_TABLE_POOL *Pool;
- UINT64 PoolSize;
- EFI_PHYSICAL_ADDRESS Address;
-
- if (mPageTablePool == NULL) {
- return;
- }
-
- //
- // SetPageTablePoolReadOnly might update mPageTablePool. It's safer to
- // remember original one in advance.
- //
- HeadPool = mPageTablePool;
- Pool = HeadPool;
- do {
- Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Pool;
- PoolSize = Pool->Offset + EFI_PAGES_TO_SIZE (Pool->FreePages);
-
+ } else if (CurrentState == MemEncryptSevAddressRangeError) {
//
- // The size of one pool must be multiple of PAGE_TABLE_POOL_UNIT_SIZE,
- // which is one of page size of the processor (2MB by default). Let's apply
- // the protection to them one by one.
+ // First address check, set initial state
//
- while (PoolSize > 0) {
- SetPageTablePoolReadOnly(PageTableBase, Address, Level4Paging);
- Address += PAGE_TABLE_POOL_UNIT_SIZE;
- PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
- }
-
- Pool = Pool->NextPool;
- } while (Pool != HeadPool);
-
-}
-
-
-/**
- Split 1G page to 2M.
-
- @param[in] PhysicalAddress Start physical address the 1G page
- covered.
- @param[in, out] PageEntry1G Pointer to 1G page entry.
- @param[in] StackBase Stack base address.
- @param[in] StackSize Stack size.
-
-**/
-STATIC
-VOID
-Split1GPageTo2M (
- IN PHYSICAL_ADDRESS PhysicalAddress,
- IN OUT UINT64 *PageEntry1G,
- IN PHYSICAL_ADDRESS StackBase,
- IN UINTN StackSize
- )
-{
- PHYSICAL_ADDRESS PhysicalAddress2M;
- UINTN IndexOfPageDirectoryEntries;
- PAGE_TABLE_ENTRY *PageDirectoryEntry;
- UINT64 AddressEncMask;
-
- PageDirectoryEntry = AllocatePageTableMemory(1);
-
- AddressEncMask = GetMemEncryptionAddressMask ();
- ASSERT (PageDirectoryEntry != NULL);
- ASSERT (*PageEntry1G & GetMemEncryptionAddressMask ());
- //
- // Fill in 1G page entry.
- //
- *PageEntry1G = ((UINT64)(UINTN)PageDirectoryEntry |
- IA32_PG_P | IA32_PG_RW | AddressEncMask);
-
- PhysicalAddress2M = PhysicalAddress;
- for (IndexOfPageDirectoryEntries = 0;
- IndexOfPageDirectoryEntries < 512;
- (IndexOfPageDirectoryEntries++,
- PageDirectoryEntry++,
- PhysicalAddress2M += SIZE_2MB)) {
- if ((PhysicalAddress2M < StackBase + StackSize) &&
- ((PhysicalAddress2M + SIZE_2MB) > StackBase)) {
- //
- // Need to split this 2M page that covers stack range.
- //
- Split2MPageTo4K (
- PhysicalAddress2M,
- (UINT64 *)PageDirectoryEntry,
- StackBase,
- StackSize
- );
+ if ((PageDirectoryEntry & AddressEncMask) == 0) {
+ CurrentState = MemEncryptSevAddressRangeUnencrypted;
} else {
- //
- // Fill in the Page Directory entries
- //
- PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M | AddressEncMask;
- PageDirectoryEntry->Bits.ReadWrite = 1;
- PageDirectoryEntry->Bits.Present = 1;
- PageDirectoryEntry->Bits.MustBe1 = 1;
+ CurrentState = MemEncryptSevAddressRangeEncrypted;
}
}
-}
-
-
-/**
- Set or Clear the memory encryption bit
-
- @param[in] PagetablePoint Page table entry pointer (PTE).
- @param[in] Mode Set or Clear encryption bit
-
-**/
-STATIC VOID
-SetOrClearCBit(
- IN OUT UINT64* PageTablePointer,
- IN MAP_RANGE_MODE Mode
- )
-{
- UINT64 AddressEncMask;
-
- AddressEncMask = GetMemEncryptionAddressMask ();
-
- if (Mode == SetCBit) {
- *PageTablePointer |= AddressEncMask;
- } else {
- *PageTablePointer &= ~AddressEncMask;
- }
+ return CurrentState;
}
/**
- Check the WP status in CR0 register. This bit is used to lock or unlock write
- access to pages marked as read-only.
-
- @retval TRUE Write protection is enabled.
- @retval FALSE Write protection is disabled.
-**/
-STATIC
-BOOLEAN
-IsReadOnlyPageWriteProtected (
- VOID
- )
-{
- return ((AsmReadCr0 () & BIT16) != 0);
-}
-
-
-/**
- Disable Write Protect on pages marked as read-only.
-**/
-STATIC
-VOID
-DisableReadOnlyPageWriteProtect (
- VOID
- )
-{
- AsmWriteCr0 (AsmReadCr0() & ~BIT16);
-}
-
-/**
- Enable Write Protect on pages marked as read-only.
-**/
-VOID
-EnableReadOnlyPageWriteProtect (
- VOID
- )
-{
- AsmWriteCr0 (AsmReadCr0() | BIT16);
-}
-
-
-/**
- This function either sets or clears memory encryption bit for the memory
- region specified by PhysicalAddress and Length from the current page table
- context.
-
- The function iterates through the PhysicalAddress one page at a time, and set
- or clears the memory encryption mask in the page table. If it encounters
- that a given physical address range is part of large page then it attempts to
- change the attribute at one go (based on size), otherwise it splits the
- large pages into smaller (e.g 2M page into 4K pages) and then try to set or
- clear the encryption bit on the smallest page size.
+ Returns the encryption state of the specified virtual address range.
@param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
current CR3)
- @param[in] PhysicalAddress The physical address that is the start
- address of a memory region.
- @param[in] Length The length of memory region
- @param[in] Mode Set or Clear mode
- @param[in] CacheFlush Flush the caches before applying the
- encryption mask
-
- @retval RETURN_SUCCESS The attributes were cleared for the
- memory region.
- @retval RETURN_INVALID_PARAMETER Number of pages is zero.
- @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute
- is not supported
+ @param[in] BaseAddress Base address to check
+ @param[in] Length Length of virtual address range
+
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
+ unencrypted
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
+ encrypted
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
+ @retval MemEncryptSevAddressRangeError Address range is not mapped
**/
-
-STATIC
-RETURN_STATUS
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
EFIAPI
-SetMemoryEncDec (
- IN PHYSICAL_ADDRESS Cr3BaseAddress,
- IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN MAP_RANGE_MODE Mode,
- IN BOOLEAN CacheFlush
+InternalMemEncryptSevGetAddressRangeState (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
)
{
- PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
- PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry;
- PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
- PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
- PAGE_TABLE_ENTRY *PageDirectory2MEntry;
- PAGE_TABLE_4K_ENTRY *PageTableEntry;
- UINT64 PgTableMask;
- UINT64 AddressEncMask;
- BOOLEAN IsWpEnabled;
- RETURN_STATUS Status;
-
- //
- // Set PageMapLevel4Entry to suppress incorrect compiler/analyzer warnings.
- //
- PageMapLevel4Entry = NULL;
-
- DEBUG ((
- DEBUG_VERBOSE,
- "%a:%a: Cr3Base=0x%Lx Physical=0x%Lx Length=0x%Lx Mode=%a CacheFlush=%u\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- Cr3BaseAddress,
- PhysicalAddress,
- (UINT64)Length,
- (Mode == SetCBit) ? "Encrypt" : "Decrypt",
- (UINT32)CacheFlush
- ));
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+ PAGE_TABLE_ENTRY *PageDirectory2MEntry;
+ PAGE_TABLE_4K_ENTRY *PageTableEntry;
+ UINT64 AddressEncMask;
+ UINT64 PgTableMask;
+ PHYSICAL_ADDRESS Address;
+ PHYSICAL_ADDRESS AddressEnd;
+ MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;
//
- // Check if we have a valid memory encryption mask
+ // If Cr3BaseAddress is not specified then read the current CR3
//
- AddressEncMask = GetMemEncryptionAddressMask ();
- if (!AddressEncMask) {
- return RETURN_ACCESS_DENIED;
+ if (Cr3BaseAddress == 0) {
+ Cr3BaseAddress = AsmReadCr3();
}
+ AddressEncMask = MemEncryptSevGetEncryptionMask ();
+ AddressEncMask &= PAGING_1G_ADDRESS_MASK_64;
+
PgTableMask = AddressEncMask | EFI_PAGE_MASK;
- if (Length == 0) {
- return RETURN_INVALID_PARAMETER;
- }
+ State = MemEncryptSevAddressRangeError;
//
- // We are going to change the memory encryption attribute from C=0 -> C=1 or
- // vice versa Flush the caches to ensure that data is written into memory
- // with correct C-bit
+ // Encryption is on a page basis, so start at the beginning of the
+ // virtual address page boundary and walk page-by-page.
//
- if (CacheFlush) {
- WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Length);
- }
-
- //
- // Make sure that the page table is changeable.
- //
- IsWpEnabled = IsReadOnlyPageWriteProtected ();
- if (IsWpEnabled) {
- DisableReadOnlyPageWriteProtect ();
- }
-
- Status = EFI_SUCCESS;
-
- while (Length)
- {
- //
- // If Cr3BaseAddress is not specified then read the current CR3
- //
- if (Cr3BaseAddress == 0) {
- Cr3BaseAddress = AsmReadCr3();
- }
+ Address = (PHYSICAL_ADDRESS) (UINTN) BaseAddress & ~EFI_PAGE_MASK;
+ AddressEnd = (PHYSICAL_ADDRESS)
+ (UINTN) (BaseAddress + Length);
+ while (Address < AddressEnd) {
PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask);
- PageMapLevel4Entry += PML4_OFFSET(PhysicalAddress);
+ PageMapLevel4Entry += PML4_OFFSET (Address);
if (!PageMapLevel4Entry->Bits.Present) {
- DEBUG ((
- DEBUG_ERROR,
- "%a:%a: bad PML4 for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- Status = RETURN_NO_MAPPING;
- goto Done;
+ return MemEncryptSevAddressRangeError;
}
- PageDirectory1GEntry = (VOID *)(
+ PageDirectory1GEntry = (VOID *) (
(PageMapLevel4Entry->Bits.PageTableBaseAddress <<
12) & ~PgTableMask
);
- PageDirectory1GEntry += PDP_OFFSET(PhysicalAddress);
+ PageDirectory1GEntry += PDP_OFFSET (Address);
if (!PageDirectory1GEntry->Bits.Present) {
- DEBUG ((
- DEBUG_ERROR,
- "%a:%a: bad PDPE for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- Status = RETURN_NO_MAPPING;
- goto Done;
+ return MemEncryptSevAddressRangeError;
}
//
@@ -686,212 +136,72 @@ SetMemoryEncDec (
if (PageDirectory1GEntry->Bits.MustBe1) {
//
// Valid 1GB page
- // If we have at least 1GB to go, we can just update this entry
- //
- if (!(PhysicalAddress & (BIT30 - 1)) && Length >= BIT30) {
- SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode);
- DEBUG ((
- DEBUG_VERBOSE,
- "%a:%a: updated 1GB entry for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- PhysicalAddress += BIT30;
- Length -= BIT30;
- } else {
- //
- // We must split the page
- //
- DEBUG ((
- DEBUG_VERBOSE,
- "%a:%a: splitting 1GB page for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- Split1GPageTo2M (
- (UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress << 30,
- (UINT64 *)PageDirectory1GEntry,
- 0,
- 0
- );
- continue;
- }
- } else {
//
- // Actually a PDP
- //
- PageUpperDirectoryPointerEntry =
- (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory1GEntry;
- PageDirectory2MEntry =
- (VOID *)(
- (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress <<
- 12) & ~PgTableMask
- );
- PageDirectory2MEntry += PDE_OFFSET(PhysicalAddress);
- if (!PageDirectory2MEntry->Bits.Present) {
- DEBUG ((
- DEBUG_ERROR,
- "%a:%a: bad PDE for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- Status = RETURN_NO_MAPPING;
- goto Done;
- }
- //
- // If the MustBe1 bit is not a 1, it's not a 2MB entry
- //
- if (PageDirectory2MEntry->Bits.MustBe1) {
- //
- // Valid 2MB page
- // If we have at least 2MB left to go, we can just update this entry
- //
- if (!(PhysicalAddress & (BIT21-1)) && Length >= BIT21) {
- SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode);
- PhysicalAddress += BIT21;
- Length -= BIT21;
- } else {
- //
- // We must split up this page into 4K pages
- //
- DEBUG ((
- DEBUG_VERBOSE,
- "%a:%a: splitting 2MB page for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- Split2MPageTo4K (
- (UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress << 21,
- (UINT64 *)PageDirectory2MEntry,
- 0,
- 0
- );
- continue;
- }
- } else {
- PageDirectoryPointerEntry =
- (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory2MEntry;
- PageTableEntry =
- (VOID *)(
- (PageDirectoryPointerEntry->Bits.PageTableBaseAddress <<
- 12) & ~PgTableMask
- );
- PageTableEntry += PTE_OFFSET(PhysicalAddress);
- if (!PageTableEntry->Bits.Present) {
- DEBUG ((
- DEBUG_ERROR,
- "%a:%a: bad PTE for Physical=0x%Lx\n",
- gEfiCallerBaseName,
- __FUNCTION__,
- PhysicalAddress
- ));
- Status = RETURN_NO_MAPPING;
- goto Done;
- }
- SetOrClearCBit (&PageTableEntry->Uint64, Mode);
- PhysicalAddress += EFI_PAGE_SIZE;
- Length -= EFI_PAGE_SIZE;
- }
- }
- }
-
- //
- // Protect the page table by marking the memory used for page table to be
- // read-only.
- //
- if (IsWpEnabled) {
- EnablePageTableProtection ((UINTN)PageMapLevel4Entry, TRUE);
- }
-
- //
- // Flush TLB
- //
- CpuFlushTlb();
-
-Done:
- //
- // Restore page table write protection, if any.
- //
- if (IsWpEnabled) {
- EnableReadOnlyPageWriteProtect ();
- }
+ State = UpdateAddressState (
+ State,
+ PageDirectory1GEntry->Uint64,
+ AddressEncMask
+ );
- return Status;
-}
+ Address += BIT30;
+ continue;
+ }
-/**
- This function clears memory encryption bit for the memory region specified by
- PhysicalAddress and Length from the current page table context.
+ //
+ // Actually a PDP
+ //
+ PageUpperDirectoryPointerEntry =
+ (PAGE_MAP_AND_DIRECTORY_POINTER *) PageDirectory1GEntry;
+ PageDirectory2MEntry =
+ (VOID *) (
+ (PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress <<
+ 12) & ~PgTableMask
+ );
+ PageDirectory2MEntry += PDE_OFFSET (Address);
+ if (!PageDirectory2MEntry->Bits.Present) {
+ return MemEncryptSevAddressRangeError;
+ }
- @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
- current CR3)
- @param[in] PhysicalAddress The physical address that is the start
- address of a memory region.
- @param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask
+ //
+ // If the MustBe1 bit is not a 1, it's not a 2MB entry
+ //
+ if (PageDirectory2MEntry->Bits.MustBe1) {
+ //
+ // Valid 2MB page
+ //
+ State = UpdateAddressState (
+ State,
+ PageDirectory2MEntry->Uint64,
+ AddressEncMask
+ );
- @retval RETURN_SUCCESS The attributes were cleared for the
- memory region.
- @retval RETURN_INVALID_PARAMETER Number of pages is zero.
- @retval RETURN_UNSUPPORTED Clearing the memory encyrption attribute
- is not supported
-**/
-RETURN_STATUS
-EFIAPI
-InternalMemEncryptSevSetMemoryDecrypted (
- IN PHYSICAL_ADDRESS Cr3BaseAddress,
- IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
- )
-{
+ Address += BIT21;
+ continue;
+ }
- return SetMemoryEncDec (
- Cr3BaseAddress,
- PhysicalAddress,
- Length,
- ClearCBit,
- Flush
- );
-}
+ //
+ // Actually a PMD
+ //
+ PageDirectoryPointerEntry =
+ (PAGE_MAP_AND_DIRECTORY_POINTER *)PageDirectory2MEntry;
+ PageTableEntry =
+ (VOID *)(
+ (PageDirectoryPointerEntry->Bits.PageTableBaseAddress <<
+ 12) & ~PgTableMask
+ );
+ PageTableEntry += PTE_OFFSET (Address);
+ if (!PageTableEntry->Bits.Present) {
+ return MemEncryptSevAddressRangeError;
+ }
-/**
- This function sets memory encryption bit for the memory region specified by
- PhysicalAddress and Length from the current page table context.
+ State = UpdateAddressState (
+ State,
+ PageTableEntry->Uint64,
+ AddressEncMask
+ );
- @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
- current CR3)
- @param[in] PhysicalAddress The physical address that is the start
- address of a memory region.
- @param[in] Length The length of memory region
- @param[in] Flush Flush the caches before applying the
- encryption mask
+ Address += EFI_PAGE_SIZE;
+ }
- @retval RETURN_SUCCESS The attributes were set for the memory
- region.
- @retval RETURN_INVALID_PARAMETER Number of pages is zero.
- @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute
- is not supported
-**/
-RETURN_STATUS
-EFIAPI
-InternalMemEncryptSevSetMemoryEncrypted (
- IN PHYSICAL_ADDRESS Cr3BaseAddress,
- IN PHYSICAL_ADDRESS PhysicalAddress,
- IN UINTN Length,
- IN BOOLEAN Flush
- )
-{
- return SetMemoryEncDec (
- Cr3BaseAddress,
- PhysicalAddress,
- Length,
- SetCBit,
- Flush
- );
+ return State;
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
index 0c33658e1c9..56a4f2d52c5 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
@@ -3,7 +3,7 @@
Virtual Memory Management Services to set or clear the memory encryption bit
Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -14,6 +14,7 @@
#ifndef __VIRTUAL_MEMORY__
#define __VIRTUAL_MEMORY__
+#include <IndustryStandard/PageTable.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/CacheMaintenanceLib.h>
@@ -23,148 +24,6 @@
#define SYS_CODE64_SEL 0x38
-#pragma pack(1)
-
-//
-// Page-Map Level-4 Offset (PML4) and
-// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
-//
-
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory,
- // 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching,
- // 1 = Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed,
- // 1 = Accessed (set by CPU)
- UINT64 Reserved:1; // Reserved
- UINT64 MustBeZero:2; // Must Be Zero
- UINT64 Available:3; // Available for use by system software
- UINT64 PageTableBaseAddress:40; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // No Execute bit
- } Bits;
- UINT64 Uint64;
-} PAGE_MAP_AND_DIRECTORY_POINTER;
-
-//
-// Page Table Entry 4KB
-//
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory,
- // 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching,
- // 1 = Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed,
- // 1 = Accessed (set by CPU)
- UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
- // processor on access to page
- UINT64 PAT:1; //
- UINT64 Global:1; // 0 = Not global page, 1 = global page
- // TLB not cleared on CR3 write
- UINT64 Available:3; // Available for use by system software
- UINT64 PageTableBaseAddress:40; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // 0 = Execute Code,
- // 1 = No Code Execution
- } Bits;
- UINT64 Uint64;
-} PAGE_TABLE_4K_ENTRY;
-
-//
-// Page Table Entry 2MB
-//
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory,
- // 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching,
- // 1=Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed,
- // 1 = Accessed (set by CPU)
- UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
- // processor on access to page
- UINT64 MustBe1:1; // Must be 1
- UINT64 Global:1; // 0 = Not global page, 1 = global page
- // TLB not cleared on CR3 write
- UINT64 Available:3; // Available for use by system software
- UINT64 PAT:1; //
- UINT64 MustBeZero:8; // Must be zero;
- UINT64 PageTableBaseAddress:31; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // 0 = Execute Code,
- // 1 = No Code Execution
- } Bits;
- UINT64 Uint64;
-} PAGE_TABLE_ENTRY;
-
-//
-// Page Table Entry 1GB
-//
-typedef union {
- struct {
- UINT64 Present:1; // 0 = Not present in memory,
- // 1 = Present in memory
- UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
- UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
- UINT64 WriteThrough:1; // 0 = Write-Back caching,
- // 1 = Write-Through caching
- UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
- UINT64 Accessed:1; // 0 = Not accessed,
- // 1 = Accessed (set by CPU)
- UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by
- // processor on access to page
- UINT64 MustBe1:1; // Must be 1
- UINT64 Global:1; // 0 = Not global page, 1 = global page
- // TLB not cleared on CR3 write
- UINT64 Available:3; // Available for use by system software
- UINT64 PAT:1; //
- UINT64 MustBeZero:17; // Must be zero;
- UINT64 PageTableBaseAddress:22; // Page Table Base Address
- UINT64 AvabilableHigh:11; // Available for use by system software
- UINT64 Nx:1; // 0 = Execute Code,
- // 1 = No Code Execution
- } Bits;
- UINT64 Uint64;
-} PAGE_TABLE_1G_ENTRY;
-
-#pragma pack()
-
-#define IA32_PG_P BIT0
-#define IA32_PG_RW BIT1
-#define IA32_PG_PS BIT7
-
-#define PAGING_PAE_INDEX_MASK 0x1FF
-
-#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
-#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
-#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
-
-#define PAGING_L1_ADDRESS_SHIFT 12
-#define PAGING_L2_ADDRESS_SHIFT 21
-#define PAGING_L3_ADDRESS_SHIFT 30
-#define PAGING_L4_ADDRESS_SHIFT 39
-
-#define PAGING_PML4E_NUMBER 4
-
-#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1)
-#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK)
-#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK)
-#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK)
-#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK)
-#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
-
#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB
#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB
#define PAGE_TABLE_POOL_UNIT_PAGES \
@@ -178,7 +37,17 @@ typedef struct {
UINTN FreePages;
} PAGE_TABLE_POOL;
+/**
+ Return the pagetable memory encryption mask.
+ @return The pagetable memory encryption mask.
+
+**/
+UINT64
+EFIAPI
+InternalGetMemEncryptionAddressMask (
+ VOID
+ );
/**
This function clears memory encryption bit for the memory region specified by
@@ -234,4 +103,27 @@ InternalMemEncryptSevSetMemoryEncrypted (
IN BOOLEAN Flush
);
+/**
+ Returns the encryption state of the specified virtual address range.
+
+ @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use
+ current CR3)
+ @param[in] BaseAddress Base address to check
+ @param[in] Length Length of virtual address range
+
+ @retval MemEncryptSevAddressRangeUnencrypted Address range is mapped
+ unencrypted
+ @retval MemEncryptSevAddressRangeEncrypted Address range is mapped
+ encrypted
+ @retval MemEncryptSevAddressRangeMixed Address range is mapped mixed
+ @retval MemEncryptSevAddressRangeError Address range is not mapped
+**/
+MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE
+EFIAPI
+InternalMemEncryptSevGetAddressRangeState (
+ IN PHYSICAL_ADDRESS Cr3BaseAddress,
+ IN PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
new file mode 100644
index 00000000000..5c74a1ca19a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.c
@@ -0,0 +1,428 @@
+/** @file
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+ Copyright (C) 2013, Red Hat, Inc.
+ Copyright (c) 2015, Nahanni Systems.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Uefi.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BhyveFwCtlLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#define FW_PORT 0x510
+#define FW_IPORT 0x511
+
+/* Transport protocol basic operations */
+#define OP_NULL 1
+#define OP_ECHO 2
+#define OP_GET 3
+#define OP_GET_LEN 4
+#define OP_SET 5
+
+/* Transport protocol error returns */
+#define T_ESUCCESS 0
+#define T_ENOENT 2
+#define T_E2BIG 7
+#define T_EMSGSIZE 40
+
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+
+STATIC CONST CHAR8 mBhyveSig[4] = { 'B', 'H', 'Y', 'V' };
+
+STATIC BOOLEAN mBhyveFwCtlSupported = FALSE;
+
+STATIC INT32 mBhyveFwCtlTxid = 0xa5;
+
+/* XXX Maybe a better inbuilt version of this ? */
+typedef struct {
+ VOID *Base;
+ UINT32 Len;
+} BIO_VEC;
+
+typedef struct {
+ UINT32 Sz;
+ UINT32 Op;
+ UINT32 TxId;
+ UINT32 Err;
+} MSG_RX_HDR;
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtl_CvtErr (
+ IN UINT32 errno
+ )
+{
+ RETURN_STATUS Status;
+
+ switch (errno) {
+ case T_ESUCCESS:
+ Status = RETURN_SUCCESS;
+ break;
+ case T_ENOENT:
+ Status = RETURN_NOT_FOUND;
+ break;
+ case T_E2BIG:
+ Status = RETURN_INVALID_PARAMETER;
+ break;
+ case T_EMSGSIZE:
+ Status = RETURN_BUFFER_TOO_SMALL;
+ break;
+ default:
+ Status = RETURN_PROTOCOL_ERROR;
+ break;
+ }
+
+ return Status;
+}
+
+STATIC
+UINT32
+EFIAPI
+BIov_WLen (
+ IN BIO_VEC b[]
+ )
+{
+ UINT32 i;
+ UINT32 tLen;
+
+ tLen = 0;
+
+ if (b != NULL) {
+ for (i = 0; b[i].Base != NULL; i++)
+ tLen += ROUNDUP (b[i].Len, sizeof(UINT32));
+ }
+
+ return tLen;
+}
+
+/**
+ Utility to send 1-3 bytes of input as a 4-byte value
+ with trailing zeroes.
+ **/
+STATIC
+UINT32
+BIov_Send_Rem (
+ IN UINT32 *Data,
+ IN UINT32 Len
+ )
+{
+ union {
+ UINT8 c[4];
+ UINT32 w;
+ } u;
+ UINT8 *cdata;
+ UINT32 i;
+
+ cdata = (UINT8 *)Data;
+ u.w = 0;
+
+ for (i = 0; i < Len; i++)
+ u.c[i] = *cdata++;
+
+ return u.w;
+}
+
+/**
+ Send a block of data out the i/o port as 4-byte quantities,
+ appending trailing zeroes on the last if required.
+ **/
+STATIC
+VOID
+BIov_Send (
+ IN char *Data,
+ IN UINT32 Len
+ )
+{
+ UINT32 *LData;
+
+ LData = (UINT32 *)Data;
+
+ while (Len > sizeof(UINT32)) {
+ IoWrite32 (FW_PORT, *LData++);
+ Len -= sizeof(UINT32);
+ }
+
+ if (Len > 0) {
+ IoWrite32 (FW_PORT, BIov_Send_Rem (LData, Len));
+ }
+}
+
+/**
+ Send data described by an array of iovecs out the i/o port.
+ **/
+STATIC
+VOID
+BIov_SendAll (
+ IN BIO_VEC b[]
+ )
+{
+ INT32 i;
+
+ if (b != NULL) {
+ for (i = 0; b[i].Base; i++) {
+ BIov_Send (b[i].Base, b[i].Len);
+ }
+ }
+}
+
+/**
+ Prepend the transport header to a block of data and send.
+ **/
+STATIC
+VOID
+EFIAPI
+BhyveFwCtl_MsgSend(
+ IN UINT32 OpCode,
+ IN BIO_VEC Data[]
+ )
+{
+ BIO_VEC hIov[4];
+ UINT32 Hdr[3];
+ UINT32 i;
+
+ /* Set up header as an iovec */
+ for (i = 0; i < 3; i++) {
+ hIov[i].Base = &Hdr[i];
+ hIov[i].Len = sizeof(Hdr[0]);
+ }
+ hIov[i].Base = NULL;
+ hIov[i].Len = 0;
+
+ /* Initialize header */
+ Hdr[0] = BIov_WLen (hIov) + BIov_WLen (Data);
+ Hdr[1] = (UINT32)OpCode;
+ Hdr[2] = mBhyveFwCtlTxid;
+
+ /* Send header and data */
+ BIov_SendAll (hIov);
+ BIov_SendAll (Data);
+}
+
+/**
+ Read a transport response and optional data from the i/o port.
+ **/
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtl_MsgRecv(
+ OUT MSG_RX_HDR *Rhdr,
+ OUT BIO_VEC Data[]
+ )
+{
+ RETURN_STATUS Status;
+ UINT32 *Dp;
+ UINT32 Rd;
+ UINT32 remLen;
+ INT32 oLen;
+ INT32 xLen;
+
+ Rd = IoRead32 (FW_PORT);
+ if (Rd < sizeof (MSG_RX_HDR)) {
+ ;
+ }
+
+ /* Read in header and setup initial error */
+ Rhdr->Sz = Rd;
+ Rhdr->Op = IoRead32 (FW_PORT);
+ Rhdr->TxId = IoRead32 (FW_PORT);
+ Rhdr->Err = IoRead32 (FW_PORT);
+
+ /* Convert transport errno into UEFI error status */
+ Status = BhyveFwCtl_CvtErr (Rhdr->Err);
+
+ remLen = Rd - sizeof (MSG_RX_HDR);
+ xLen = 0;
+
+ /*
+ * A few cases to handle:
+ * - the user didn't supply a read buffer
+ * - the buffer is too small for the response
+ * - the response is zero-length
+ */
+ if (Data != NULL) {
+ Dp = (UINT32 *)Data[0].Base;
+ oLen = remLen;
+ if (remLen > Data[0].Len) {
+ Status = RETURN_BUFFER_TOO_SMALL;
+ xLen = remLen - Data[0].Len;
+ oLen = remLen = Data[0].Len;
+ }
+ while (remLen > 0) {
+ *Dp++ = IoRead32 (FW_PORT);
+ remLen -= sizeof (UINT32);
+ }
+ Data[0].Len = oLen;
+ } else {
+ /* No user data, but data returned - drop */
+ if (remLen > 0) {
+ Status = RETURN_BUFFER_TOO_SMALL;
+ xLen = remLen;
+ }
+ }
+
+ /* Drop additional data */
+ while (xLen > 0) {
+ (void) IoRead32 (FW_PORT);
+ xLen -= sizeof (UINT32);
+ }
+
+ return Status;
+}
+
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtl_Msg(
+ IN UINT32 OpCode,
+ IN BIO_VEC Sdata[],
+ OUT BIO_VEC Rdata[]
+ )
+{
+ MSG_RX_HDR Rh;
+ RETURN_STATUS Status;
+
+ Status = RETURN_SUCCESS;
+
+ BhyveFwCtl_MsgSend (OpCode, Sdata);
+ Status = BhyveFwCtl_MsgRecv (&Rh, Rdata);
+
+ mBhyveFwCtlTxid++;
+
+ return Status;
+}
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGetLen (
+ IN CONST CHAR8 *Name,
+ IN OUT UINT32 *Size
+ )
+{
+ BIO_VEC Req[2], Resp[2];
+ RETURN_STATUS Status;
+
+ Req[0].Base = (VOID *)Name;
+ Req[0].Len = (UINT32)AsciiStrLen (Name) + 1;
+ Req[1].Base = NULL;
+
+ Resp[0].Base = Size;
+ Resp[0].Len = sizeof (UINT32);
+ Resp[1].Base = NULL;
+
+ Status = BhyveFwCtl_Msg (OP_GET_LEN, Req, Resp);
+
+ return Status;
+}
+
+#define FMAXSZ 1024
+STATIC struct {
+ UINT64 fSize;
+ UINT32 fData[FMAXSZ];
+} FwGetvalBuf;
+
+STATIC
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGetVal (
+ IN CONST CHAR8 *Name,
+ OUT VOID *Item,
+ IN OUT UINT32 *Size
+ )
+{
+ BIO_VEC Req[2];
+ BIO_VEC Resp[2];
+ RETURN_STATUS Status;
+
+ /* Make sure temp buffer is larger than passed-in size */
+ if (*Size > sizeof (FwGetvalBuf.fData))
+ return RETURN_INVALID_PARAMETER;
+
+ Req[0].Base = (VOID *)Name;
+ Req[0].Len = (UINT32)AsciiStrLen (Name) + 1;
+ Req[1].Base = NULL;
+
+ Resp[0].Base = &FwGetvalBuf;
+ Resp[0].Len = sizeof (UINT64) + *Size;
+ Resp[1].Base = NULL;
+
+ Status = BhyveFwCtl_Msg (OP_GET, Req, Resp);
+
+ /*
+ * Copy out data on success (or on a truncated message).
+ * XXX This step can be eliminted with Msg() supporting
+ * multiple iovecs.
+ */
+ if ((Status == RETURN_SUCCESS) || (Status == RETURN_BUFFER_TOO_SMALL)) {
+ *Size = (UINT32)FwGetvalBuf.fSize;
+ CopyMem (Item, FwGetvalBuf.fData, *Size);
+ }
+
+ return Status;
+}
+
+/**
+ Front end to the internal GET_LEN and GET protocols
+ **/
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlGet (
+ IN CONST CHAR8 *Name,
+ OUT VOID *Item,
+ IN OUT UINTN *Size
+ )
+{
+ RETURN_STATUS Status;
+
+ if (mBhyveFwCtlSupported == FALSE)
+ return RETURN_UNSUPPORTED;
+
+ if (Item == NULL) {
+ Status = BhyveFwCtlGetLen (Name, (UINT32*)Size);
+ } else {
+ Status = BhyveFwCtlGetVal (Name, Item, (UINT32*)Size);
+ }
+
+ return Status;
+}
+
+
+/**
+ Library initialization. Probe the host to see if the f/w ctl
+ interface is supported.
+ **/
+RETURN_STATUS
+EFIAPI
+BhyveFwCtlInitialize (
+ VOID
+ )
+{
+ UINT32 i;
+ UINT8 ch;
+
+ DEBUG ((DEBUG_INFO, "FwCtlInitialize\n"));
+
+ IoWrite16 (FW_PORT, 0x0000);
+ for (i = 0; i < 4; i++) {
+ ch = IoRead8 (FW_IPORT);
+ if (ch != mBhyveSig[i]) {
+ DEBUG ((DEBUG_INFO, "Host f/w sig mismatch %c/%c\n", ch, mBhyveSig[i]));
+ return RETURN_SUCCESS;
+ }
+ }
+
+ mBhyveFwCtlSupported = TRUE;
+
+ return RETURN_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
new file mode 100644
index 00000000000..add967d5022
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/BhyveFwCtlLib/BhyveFwCtlLib.inf
@@ -0,0 +1,40 @@
+## @file
+#
+# Copyright (C) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (C) 2015 Nahanni Systems
+# Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = BhyveFwCtlLib
+ FILE_GUID = fd982666-67f9-11e5-a42a-0025908602f6
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = BhyveFwCtlLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER
+
+ CONSTRUCTOR = BhyveFwCtlInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ BhyveFwCtlLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ IntrinsicLib
+ IoLib
+ MemoryAllocationLib
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c
index 8c16f968484..9bc52017a04 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.c
@@ -106,7 +106,8 @@ QemuLoadKernelImage (
goto UnloadImage;
default:
- DEBUG ((DEBUG_ERROR, "%a: LoadImage(): %r\n", __FUNCTION__, Status));
+ DEBUG ((Status == EFI_NOT_FOUND ? DEBUG_INFO : DEBUG_ERROR,
+ "%a: LoadImage(): %r\n", __FUNCTION__, Status));
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridge.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridge.h
index 7b9133bb177..a065f58c03b 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridge.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridge.h
@@ -11,59 +11,3 @@ PCI_ROOT_BRIDGE *
ScanForRootBridges (
UINTN *NumberOfRootBridges
);
-
-/**
- Initialize a PCI_ROOT_BRIDGE structure.
-
- @param[in] Supports Supported attributes.
-
- @param[in] Attributes Initial attributes.
-
- @param[in] AllocAttributes Allocation attributes.
-
- @param[in] RootBusNumber The bus number to store in RootBus.
-
- @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
- assigned to any subordinate bus found behind any
- PCI bridge hanging off this root bus.
-
- The caller is repsonsible for ensuring that
- RootBusNumber <= MaxSubBusNumber. If
- RootBusNumber equals MaxSubBusNumber, then the
- root bus has no room for subordinate buses.
-
- @param[in] Io IO aperture.
-
- @param[in] Mem MMIO aperture.
-
- @param[in] MemAbove4G MMIO aperture above 4G.
-
- @param[in] PMem Prefetchable MMIO aperture.
-
- @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
-
- @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the
- caller) that should be filled in by this
- function.
-
- @retval EFI_SUCCESS Initialization successful. A device path
- consisting of an ACPI device path node, with
- UID = RootBusNumber, has been allocated and
- linked into RootBus.
-
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
-**/
-EFI_STATUS
-InitRootBridge (
- IN UINT64 Supports,
- IN UINT64 Attributes,
- IN UINT64 AllocAttributes,
- IN UINT8 RootBusNumber,
- IN UINT8 MaxSubBusNumber,
- IN PCI_ROOT_BRIDGE_APERTURE *Io,
- IN PCI_ROOT_BRIDGE_APERTURE *Mem,
- IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
- IN PCI_ROOT_BRIDGE_APERTURE *PMem,
- IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
- OUT PCI_ROOT_BRIDGE *RootBus
- );
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
index 1161ece9662..a212c13344b 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
@@ -17,170 +17,15 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
-#include <Library/DevicePathLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
#include <Library/PciHostBridgeLib.h>
-#include <Library/PciLib.h>
-#include <Library/QemuFwCfgLib.h>
+#include <Library/PciHostBridgeUtilityLib.h>
#include "PciHostBridge.h"
-#pragma pack(1)
-typedef struct {
- ACPI_HID_DEVICE_PATH AcpiDevicePath;
- EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
-} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
-#pragma pack ()
-
-
-GLOBAL_REMOVE_IF_UNREFERENCED
-CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
- L"Mem", L"I/O", L"Bus"
-};
-
-
-STATIC
-CONST
-OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
- {
- {
- ACPI_DEVICE_PATH,
- ACPI_DP,
- {
- (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
- (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
- }
- },
- EISA_PNP_ID(0x0A03), // HID
- 0 // UID
- },
-
- {
- END_DEVICE_PATH_TYPE,
- END_ENTIRE_DEVICE_PATH_SUBTYPE,
- {
- END_DEVICE_PATH_LENGTH,
- 0
- }
- }
-};
-
STATIC PCI_ROOT_BRIDGE_APERTURE mNonExistAperture = { MAX_UINT64, 0 };
-/**
- Initialize a PCI_ROOT_BRIDGE structure.
-
- @param[in] Supports Supported attributes.
-
- @param[in] Attributes Initial attributes.
-
- @param[in] AllocAttributes Allocation attributes.
-
- @param[in] RootBusNumber The bus number to store in RootBus.
-
- @param[in] MaxSubBusNumber The inclusive maximum bus number that can be
- assigned to any subordinate bus found behind any
- PCI bridge hanging off this root bus.
-
- The caller is repsonsible for ensuring that
- RootBusNumber <= MaxSubBusNumber. If
- RootBusNumber equals MaxSubBusNumber, then the
- root bus has no room for subordinate buses.
-
- @param[in] Io IO aperture.
-
- @param[in] Mem MMIO aperture.
-
- @param[in] MemAbove4G MMIO aperture above 4G.
-
- @param[in] PMem Prefetchable MMIO aperture.
-
- @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
-
- @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the
- caller) that should be filled in by this
- function.
-
- @retval EFI_SUCCESS Initialization successful. A device path
- consisting of an ACPI device path node, with
- UID = RootBusNumber, has been allocated and
- linked into RootBus.
-
- @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
-**/
-EFI_STATUS
-InitRootBridge (
- IN UINT64 Supports,
- IN UINT64 Attributes,
- IN UINT64 AllocAttributes,
- IN UINT8 RootBusNumber,
- IN UINT8 MaxSubBusNumber,
- IN PCI_ROOT_BRIDGE_APERTURE *Io,
- IN PCI_ROOT_BRIDGE_APERTURE *Mem,
- IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
- IN PCI_ROOT_BRIDGE_APERTURE *PMem,
- IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
- OUT PCI_ROOT_BRIDGE *RootBus
- )
-{
- OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
-
- //
- // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
- //
- ZeroMem (RootBus, sizeof *RootBus);
-
- RootBus->Segment = 0;
-
- RootBus->Supports = Supports;
- RootBus->Attributes = Attributes;
-
- RootBus->DmaAbove4G = FALSE;
-
- RootBus->AllocationAttributes = AllocAttributes;
- RootBus->Bus.Base = RootBusNumber;
- RootBus->Bus.Limit = MaxSubBusNumber;
- CopyMem (&RootBus->Io, Io, sizeof (*Io));
- CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
- CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
- CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
- CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
-
- RootBus->NoExtendedConfigSpace = (PcdGet16 (PcdOvmfHostBridgePciDevId) !=
- INTEL_Q35_MCH_DEVICE_ID);
-
- DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
- &mRootBridgeDevicePathTemplate);
- if (DevicePath == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
- return EFI_OUT_OF_RESOURCES;
- }
- DevicePath->AcpiDevicePath.UID = RootBusNumber;
- RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
-
- DEBUG ((DEBUG_INFO,
- "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
- __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
- return EFI_SUCCESS;
-}
-
-
-/**
- Uninitialize a PCI_ROOT_BRIDGE structure set up with InitRootBridge().
-
- param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
- initialized with InitRootBridge(), that should be
- uninitialized. This function doesn't free RootBus.
-**/
-STATIC
-VOID
-UninitRootBridge (
- IN PCI_ROOT_BRIDGE *RootBus
- )
-{
- FreePool (RootBus->DevicePath);
-}
-
/**
Return all the root bridge instances in an array.
@@ -197,14 +42,6 @@ PciHostBridgeGetRootBridges (
UINTN *Count
)
{
- EFI_STATUS Status;
- FIRMWARE_CONFIG_ITEM FwCfgItem;
- UINTN FwCfgSize;
- UINT64 ExtraRootBridges;
- PCI_ROOT_BRIDGE *Bridges;
- UINTN Initialized;
- UINTN LastRootBridgeNumber;
- UINTN RootBridgeNumber;
UINT64 Attributes;
UINT64 AllocationAttributes;
PCI_ROOT_BRIDGE_APERTURE Io;
@@ -242,119 +79,20 @@ PciHostBridgeGetRootBridges (
Mem.Base = PcdGet64 (PcdPciMmio32Base);
Mem.Limit = PcdGet64 (PcdPciMmio32Base) + (PcdGet64 (PcdPciMmio32Size) - 1);
- *Count = 0;
-
- //
- // QEMU provides the number of extra root buses, shortening the exhaustive
- // search below. If there is no hint, the feature is missing.
- //
- Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
- if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridges) {
- ExtraRootBridges = 0;
- } else {
- QemuFwCfgSelectItem (FwCfgItem);
- QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);
-
- if (ExtraRootBridges > PCI_MAX_BUS) {
- DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "
- "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));
- return NULL;
- }
- DEBUG ((DEBUG_INFO, "%a: %Lu extra root buses reported by QEMU\n",
- __FUNCTION__, ExtraRootBridges));
- }
-
- //
- // Allocate the "main" root bridge, and any extra root bridges.
- //
- Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
- if (Bridges == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
- return NULL;
- }
- Initialized = 0;
-
- //
- // The "main" root bus is always there.
- //
- LastRootBridgeNumber = 0;
-
- //
- // Scan all other root buses. If function 0 of any device on a bus returns a
- // VendorId register value different from all-bits-one, then that bus is
- // alive.
- //
- for (RootBridgeNumber = 1;
- RootBridgeNumber <= PCI_MAX_BUS && Initialized < ExtraRootBridges;
- ++RootBridgeNumber) {
- UINTN Device;
-
- for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
- if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
- PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
- break;
- }
- }
- if (Device <= PCI_MAX_DEVICE) {
- //
- // Found the next root bus. We can now install the *previous* one,
- // because now we know how big a bus number range *that* one has, for any
- // subordinate buses that might exist behind PCI bridges hanging off it.
- //
- Status = InitRootBridge (
- Attributes,
- Attributes,
- AllocationAttributes,
- (UINT8) LastRootBridgeNumber,
- (UINT8) (RootBridgeNumber - 1),
- &Io,
- &Mem,
- &MemAbove4G,
- &mNonExistAperture,
- &mNonExistAperture,
- &Bridges[Initialized]
- );
- if (EFI_ERROR (Status)) {
- goto FreeBridges;
- }
- ++Initialized;
- LastRootBridgeNumber = RootBridgeNumber;
- }
- }
-
- //
- // Install the last root bus (which might be the only, ie. main, root bus, if
- // we've found no extra root buses).
- //
- Status = InitRootBridge (
- Attributes,
+ return PciHostBridgeUtilityGetRootBridges (
+ Count,
Attributes,
AllocationAttributes,
- (UINT8) LastRootBridgeNumber,
+ FALSE,
+ PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,
+ 0,
PCI_MAX_BUS,
&Io,
&Mem,
&MemAbove4G,
&mNonExistAperture,
- &mNonExistAperture,
- &Bridges[Initialized]
+ &mNonExistAperture
);
- if (EFI_ERROR (Status)) {
- goto FreeBridges;
- }
- ++Initialized;
-
- *Count = Initialized;
- return Bridges;
-
-FreeBridges:
- while (Initialized > 0) {
- --Initialized;
- UninitRootBridge (&Bridges[Initialized]);
- }
-
- FreePool (Bridges);
- return NULL;
}
@@ -372,17 +110,7 @@ PciHostBridgeFreeRootBridges (
UINTN Count
)
{
- if (Bridges == NULL && Count == 0) {
- return;
- }
- ASSERT (Bridges != NULL && Count > 0);
-
- do {
- --Count;
- UninitRootBridge (&Bridges[Count]);
- } while (Count > 0);
-
- FreePool (Bridges);
+ PciHostBridgeUtilityFreeRootBridges (Bridges, Count);
}
@@ -407,37 +135,5 @@ PciHostBridgeResourceConflict (
VOID *Configuration
)
{
- EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
- UINTN RootBridgeIndex;
- DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
-
- RootBridgeIndex = 0;
- Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
- while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
- DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
- for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
- ASSERT (Descriptor->ResType <
- ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr)
- );
- DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
- mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
- Descriptor->AddrLen, Descriptor->AddrRangeMax
- ));
- if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
- DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
- Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
- ((Descriptor->SpecificFlag &
- EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
- ) != 0) ? L" (Prefetchable)" : L""
- ));
- }
- }
- //
- // Skip the END descriptor for root bridge
- //
- ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
- Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
- (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
- );
- }
+ PciHostBridgeUtilityResourceConflict (Configuration);
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
index 3a75b915060..beec6281c84 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -37,10 +37,10 @@
[LibraryClasses]
BaseMemoryLib
DebugLib
- DevicePathLib
MemoryAllocationLib
+ PcdLib
+ PciHostBridgeUtilityLib
PciLib
- QemuFwCfgLib
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdPciIoBase
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/XenSupport.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
index b87d7a21ca9..db16a67a20f 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeLib/XenSupport.c
@@ -17,7 +17,9 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
#include <Library/PciHostBridgeLib.h>
+#include <Library/PciHostBridgeUtilityLib.h>
#include <Library/PciLib.h>
#include "PciHostBridge.h"
@@ -452,8 +454,9 @@ ScanForRootBridges (
RootBridges
);
ASSERT (RootBridges != NULL);
- InitRootBridge (
+ PciHostBridgeUtilityInitRootBridge (
Attributes, Attributes, 0,
+ FALSE, PcdGet16 (PcdOvmfHostBridgePciDevId) != INTEL_Q35_MCH_DEVICE_ID,
(UINT8) PrimaryBus, (UINT8) SubBus,
&Io, &Mem, &MemAbove4G, &mNonExistAperture, &mNonExistAperture,
&RootBridges[*NumberOfRootBridges]
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c
new file mode 100644
index 00000000000..e195d989c6e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c
@@ -0,0 +1,460 @@
+/** @file
+ Provide common utility functions to PciHostBridgeLib instances in
+ ArmVirtPkg and OvmfPkg.
+
+ Copyright (C) 2016, Red Hat, Inc.
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, Huawei Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/Acpi10.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PciHostBridgeUtilityLib.h>
+#include <Library/PciLib.h>
+#include <Library/QemuFwCfgLib.h>
+
+
+#pragma pack(1)
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {
+ L"Mem", L"I/O", L"Bus"
+};
+
+
+STATIC
+CONST
+OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID(0x0A03), // HID
+ 0 // UID
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+
+/**
+ Utility function to initialize a PCI_ROOT_BRIDGE structure.
+
+ @param[in] Supports Supported attributes.
+
+ @param[in] Attributes Initial attributes.
+
+ @param[in] AllocAttributes Allocation attributes.
+
+ @param[in] DmaAbove4G DMA above 4GB memory.
+
+ @param[in] NoExtendedConfigSpace No Extended Config Space.
+
+ @param[in] RootBusNumber The bus number to store in RootBus.
+
+ @param[in] MaxSubBusNumber The inclusive maximum bus number that can
+ be assigned to any subordinate bus found
+ behind any PCI bridge hanging off this
+ root bus.
+
+ The caller is repsonsible for ensuring
+ that RootBusNumber <= MaxSubBusNumber. If
+ RootBusNumber equals MaxSubBusNumber, then
+ the root bus has no room for subordinate
+ buses.
+
+ @param[in] Io IO aperture.
+
+ @param[in] Mem MMIO aperture.
+
+ @param[in] MemAbove4G MMIO aperture above 4G.
+
+ @param[in] PMem Prefetchable MMIO aperture.
+
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
+
+ @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated
+ by the caller) that should be filled in by
+ this function.
+
+ @retval EFI_SUCCESS Initialization successful. A device path
+ consisting of an ACPI device path node,
+ with UID = RootBusNumber, has been
+ allocated and linked into RootBus.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+PciHostBridgeUtilityInitRootBridge (
+ IN UINT64 Supports,
+ IN UINT64 Attributes,
+ IN UINT64 AllocAttributes,
+ IN BOOLEAN DmaAbove4G,
+ IN BOOLEAN NoExtendedConfigSpace,
+ IN UINT8 RootBusNumber,
+ IN UINT8 MaxSubBusNumber,
+ IN PCI_ROOT_BRIDGE_APERTURE *Io,
+ IN PCI_ROOT_BRIDGE_APERTURE *Mem,
+ IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMem,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
+ OUT PCI_ROOT_BRIDGE *RootBus
+ )
+{
+ OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
+
+ //
+ // Be safe if other fields are added to PCI_ROOT_BRIDGE later.
+ //
+ ZeroMem (RootBus, sizeof *RootBus);
+
+ RootBus->Segment = 0;
+
+ RootBus->Supports = Supports;
+ RootBus->Attributes = Attributes;
+
+ RootBus->DmaAbove4G = DmaAbove4G;
+
+ RootBus->AllocationAttributes = AllocAttributes;
+ RootBus->Bus.Base = RootBusNumber;
+ RootBus->Bus.Limit = MaxSubBusNumber;
+ CopyMem (&RootBus->Io, Io, sizeof (*Io));
+ CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));
+ CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));
+ CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));
+ CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));
+
+ RootBus->NoExtendedConfigSpace = NoExtendedConfigSpace;
+
+ DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,
+ &mRootBridgeDevicePathTemplate);
+ if (DevicePath == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DevicePath->AcpiDevicePath.UID = RootBusNumber;
+ RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
+
+ DEBUG ((DEBUG_INFO,
+ "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
+ __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Utility function to uninitialize a PCI_ROOT_BRIDGE structure set up with
+ PciHostBridgeUtilityInitRootBridge().
+
+ @param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and
+ initialized with PciHostBridgeUtilityInitRootBridge(),
+ that should be uninitialized. This function doesn't free
+ RootBus.
+**/
+VOID
+EFIAPI
+PciHostBridgeUtilityUninitRootBridge (
+ IN PCI_ROOT_BRIDGE *RootBus
+ )
+{
+ FreePool (RootBus->DevicePath);
+}
+
+
+/**
+ Utility function to return all the root bridge instances in an array.
+
+ @param[out] Count The number of root bridge instances.
+
+ @param[in] Attributes Initial attributes.
+
+ @param[in] AllocAttributes Allocation attributes.
+
+ @param[in] DmaAbove4G DMA above 4GB memory.
+
+ @param[in] NoExtendedConfigSpace No Extended Config Space.
+
+ @param[in] BusMin Minimum Bus number, inclusive.
+
+ @param[in] BusMax Maximum Bus number, inclusive.
+
+ @param[in] Io IO aperture.
+
+ @param[in] Mem MMIO aperture.
+
+ @param[in] MemAbove4G MMIO aperture above 4G.
+
+ @param[in] PMem Prefetchable MMIO aperture.
+
+ @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.
+
+ @return All the root bridge instances in an array.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeUtilityGetRootBridges (
+ OUT UINTN *Count,
+ IN UINT64 Attributes,
+ IN UINT64 AllocationAttributes,
+ IN BOOLEAN DmaAbove4G,
+ IN BOOLEAN NoExtendedConfigSpace,
+ IN UINTN BusMin,
+ IN UINTN BusMax,
+ IN PCI_ROOT_BRIDGE_APERTURE *Io,
+ IN PCI_ROOT_BRIDGE_APERTURE *Mem,
+ IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMem,
+ IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G
+ )
+{
+ EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ UINT64 ExtraRootBridges;
+ PCI_ROOT_BRIDGE *Bridges;
+ UINTN Initialized;
+ UINTN LastRootBridgeNumber;
+ UINTN RootBridgeNumber;
+
+ *Count = 0;
+
+ if (BusMin > BusMax || BusMax > PCI_MAX_BUS) {
+ DEBUG ((DEBUG_ERROR, "%a: invalid bus range with BusMin %Lu and BusMax "
+ "%Lu\n", __FUNCTION__, (UINT64)BusMin, (UINT64)BusMax));
+ return NULL;
+ }
+
+ //
+ // QEMU provides the number of extra root buses, shortening the exhaustive
+ // search below. If there is no hint, the feature is missing.
+ //
+ Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridges) {
+ ExtraRootBridges = 0;
+ } else {
+ QemuFwCfgSelectItem (FwCfgItem);
+ QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridges);
+
+ //
+ // Validate the number of extra root bridges. As BusMax is inclusive, the
+ // max bus count is (BusMax - BusMin + 1). From that, the "main" root bus
+ // is always a given, so the max count for the "extra" root bridges is one
+ // less, i.e. (BusMax - BusMin). If the QEMU hint exceeds that, we have
+ // invalid behavior.
+ //
+ if (ExtraRootBridges > BusMax - BusMin) {
+ DEBUG ((DEBUG_ERROR, "%a: invalid count of extra root buses (%Lu) "
+ "reported by QEMU\n", __FUNCTION__, ExtraRootBridges));
+ return NULL;
+ }
+ DEBUG ((DEBUG_INFO, "%a: %Lu extra root buses reported by QEMU\n",
+ __FUNCTION__, ExtraRootBridges));
+ }
+
+ //
+ // Allocate the "main" root bridge, and any extra root bridges.
+ //
+ Bridges = AllocatePool ((1 + (UINTN)ExtraRootBridges) * sizeof *Bridges);
+ if (Bridges == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
+ return NULL;
+ }
+ Initialized = 0;
+
+ //
+ // The "main" root bus is always there.
+ //
+ LastRootBridgeNumber = BusMin;
+
+ //
+ // Scan all other root buses. If function 0 of any device on a bus returns a
+ // VendorId register value different from all-bits-one, then that bus is
+ // alive.
+ //
+ for (RootBridgeNumber = BusMin + 1;
+ RootBridgeNumber <= BusMax && Initialized < ExtraRootBridges;
+ ++RootBridgeNumber) {
+ UINTN Device;
+
+ for (Device = 0; Device <= PCI_MAX_DEVICE; ++Device) {
+ if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
+ PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
+ break;
+ }
+ }
+ if (Device <= PCI_MAX_DEVICE) {
+ //
+ // Found the next root bus. We can now install the *previous* one,
+ // because now we know how big a bus number range *that* one has, for any
+ // subordinate buses that might exist behind PCI bridges hanging off it.
+ //
+ Status = PciHostBridgeUtilityInitRootBridge (
+ Attributes,
+ Attributes,
+ AllocationAttributes,
+ DmaAbove4G,
+ NoExtendedConfigSpace,
+ (UINT8) LastRootBridgeNumber,
+ (UINT8) (RootBridgeNumber - 1),
+ Io,
+ Mem,
+ MemAbove4G,
+ PMem,
+ PMemAbove4G,
+ &Bridges[Initialized]
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeBridges;
+ }
+ ++Initialized;
+ LastRootBridgeNumber = RootBridgeNumber;
+ }
+ }
+
+ //
+ // Install the last root bus (which might be the only, ie. main, root bus, if
+ // we've found no extra root buses).
+ //
+ Status = PciHostBridgeUtilityInitRootBridge (
+ Attributes,
+ Attributes,
+ AllocationAttributes,
+ DmaAbove4G,
+ NoExtendedConfigSpace,
+ (UINT8) LastRootBridgeNumber,
+ (UINT8) BusMax,
+ Io,
+ Mem,
+ MemAbove4G,
+ PMem,
+ PMemAbove4G,
+ &Bridges[Initialized]
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeBridges;
+ }
+ ++Initialized;
+
+ *Count = Initialized;
+ return Bridges;
+
+FreeBridges:
+ while (Initialized > 0) {
+ --Initialized;
+ PciHostBridgeUtilityUninitRootBridge (&Bridges[Initialized]);
+ }
+
+ FreePool (Bridges);
+ return NULL;
+}
+
+
+/**
+ Utility function to free root bridge instances array from
+ PciHostBridgeUtilityGetRootBridges().
+
+ @param[in] Bridges The root bridge instances array.
+ @param[in] Count The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeUtilityFreeRootBridges (
+ IN PCI_ROOT_BRIDGE *Bridges,
+ IN UINTN Count
+ )
+{
+ if (Bridges == NULL && Count == 0) {
+ return;
+ }
+ ASSERT (Bridges != NULL && Count > 0);
+
+ do {
+ --Count;
+ PciHostBridgeUtilityUninitRootBridge (&Bridges[Count]);
+ } while (Count > 0);
+
+ FreePool (Bridges);
+}
+
+
+/**
+ Utility function to inform the platform that the resource conflict happens.
+
+ @param[in] Configuration Pointer to PCI I/O and PCI memory resource
+ descriptors. The Configuration contains the
+ resources for all the root bridges. The resource
+ for each root bridge is terminated with END
+ descriptor and an additional END is appended
+ indicating the end of the entire resources. The
+ resource descriptor field values follow the
+ description in
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ .SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeUtilityResourceConflict (
+ IN VOID *Configuration
+ )
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+ UINTN RootBridgeIndex;
+ DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
+
+ RootBridgeIndex = 0;
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+ while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
+ for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
+ ASSERT (Descriptor->ResType <
+ ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)
+ );
+ DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
+ mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
+ Descriptor->AddrLen, Descriptor->AddrRangeMax
+ ));
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
+ Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
+ ((Descriptor->SpecificFlag &
+ EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
+ ) != 0) ? L" (Prefetchable)" : L""
+ ));
+ }
+ }
+ //
+ // Skip the END descriptor for root bridge
+ //
+ ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
+ (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
+ );
+ }
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
new file mode 100644
index 00000000000..6da978ac806
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
@@ -0,0 +1,43 @@
+## @file
+# Provide common utility functions to PciHostBridgeLib instances in
+# ArmVirtPkg and OvmfPkg.
+#
+# Copyright (C) 2016, Red Hat, Inc.
+# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, Huawei Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = PciHostBridgeUtilityLib
+ FILE_GUID = e3aa5932-527a-42e7-86f5-81b144c7e5f1
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciHostBridgeUtilityLib
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64 ARM
+#
+
+[Sources]
+ PciHostBridgeUtilityLib.c
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ PciLib
+ QemuFwCfgLib
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
index 2fca67abf40..1ea54162151 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
@@ -29,7 +29,10 @@ UINT16 mHostBridgeDevId;
// (for configuring PCI Interrupt Line register)
//
CONST UINT8 PciHostIrqs[] = {
- 0x0a, 0x0a, 0x0b, 0x0b
+ 0x0a, // LNKA, LNKE
+ 0x0a, // LNKB, LNKF
+ 0x0b, // LNKC, LNKG
+ 0x0b // LNKD, LNKH
};
//
@@ -1211,24 +1214,24 @@ PciAcpiInitialization (
//
// 00:01.0 ISA Bridge (PIIX4) LNK routing targets
//
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
- PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), PciHostIrqs[0]); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), PciHostIrqs[1]); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), PciHostIrqs[2]); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), PciHostIrqs[3]); // D
break;
case INTEL_Q35_MCH_DEVICE_ID:
Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
//
// 00:1f.0 LPC Bridge (Q35) LNK routing targets
//
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
- PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), PciHostIrqs[0]); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), PciHostIrqs[1]); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), PciHostIrqs[2]); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), PciHostIrqs[3]); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), PciHostIrqs[0]); // E
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), PciHostIrqs[1]); // F
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), PciHostIrqs[2]); // G
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), PciHostIrqs[3]); // H
break;
default:
if (XenDetected ()) {
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.c
new file mode 100644
index 00000000000..f1f74e8dc0e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.c
@@ -0,0 +1,1662 @@
+/** @file
+ Platform BDS customizations.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/PlatformBmPrintScLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+#include <Protocol/BlockIo.h>
+
+//
+// Global data
+//
+
+VOID *mEfiDevPathNotifyReg;
+EFI_EVENT mEfiDevPathEvent;
+VOID *mEmuVariableEventReg;
+EFI_EVENT mEmuVariableEvent;
+UINT16 mHostBridgeDevId;
+
+//
+// Table of host IRQs matching PCI IRQs A-D
+// (for configuring PCI Interrupt Line register)
+//
+CONST UINT8 PciHostIrqs[] = {
+ 0x0a, 0x0a, 0x0b, 0x0b
+};
+
+//
+// Type definitions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+/**
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ );
+
+
+//
+// Function prototypes
+//
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+VisitAllPciInstancesOfProtocol (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ );
+
+VOID
+InstallDevicePathCallback (
+ VOID
+ );
+
+VOID
+PlatformRegisterFvBootOption (
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ UINT32 Attributes
+ )
+{
+ EFI_STATUS Status;
+ INTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+ ASSERT (DevicePath != NULL);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ ASSERT (DevicePath != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &NewOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ Attributes,
+ Description,
+ DevicePath,
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DevicePath);
+
+ BootOptions = EfiBootManagerGetLoadOptions (
+ &BootOptionCount, LoadOptionTypeBoot
+ );
+
+ OptionIndex = EfiBootManagerFindLoadOption (
+ &NewOption, BootOptions, BootOptionCount
+ );
+
+ if (OptionIndex == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
+ ASSERT_EFI_ERROR (Status);
+ }
+ EfiBootManagerFreeLoadOption (&NewOption);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+/**
+ Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
+ whose device paths do not resolve exactly to an FvFile in the system.
+
+ This removes any boot options that point to binaries built into the firmware
+ and have become stale due to any of the following:
+ - DXEFV's base address or size changed (historical),
+ - DXEFV's FvNameGuid changed,
+ - the FILE_GUID of the pointed-to binary changed,
+ - the referenced binary is no longer built into the firmware.
+
+ EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
+ avoids exact duplicates.
+**/
+VOID
+RemoveStaleFvFileOptions (
+ VOID
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
+ LoadOptionTypeBoot);
+
+ for (Index = 0; Index < BootOptionCount; ++Index) {
+ EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+ EFI_STATUS Status;
+ EFI_HANDLE FvHandle;
+
+ //
+ // If the device path starts with neither MemoryMapped(...) nor Fv(...),
+ // then keep the boot option.
+ //
+ Node1 = BootOptions[Index].FilePath;
+ if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
+ !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+ continue;
+ }
+
+ //
+ // If the second device path node is not FvFile(...), then keep the boot
+ // option.
+ //
+ Node2 = NextDevicePathNode (Node1);
+ if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+ continue;
+ }
+
+ //
+ // Locate the Firmware Volume2 protocol instance that is denoted by the
+ // boot option. If this lookup fails (i.e., the boot option references a
+ // firmware volume that doesn't exist), then we'll proceed to delete the
+ // boot option.
+ //
+ SearchNode = Node1;
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
+ &SearchNode, &FvHandle);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // The firmware volume was found; now let's see if it contains the FvFile
+ // identified by GUID.
+ //
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+ UINTN BufferSize;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINT32 AuthenticationStatus;
+
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **)&FvProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
+ //
+ // Buffer==NULL means we request metadata only: BufferSize, FoundType,
+ // FileAttributes.
+ //
+ Status = FvProtocol->ReadFile (
+ FvProtocol,
+ &FvFileNode->FvFileName, // NameGuid
+ NULL, // Buffer
+ &BufferSize,
+ &FoundType,
+ &FileAttributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The FvFile was found. Keep the boot option.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Delete the boot option.
+ //
+ Status = EfiBootManagerDeleteLoadOptionVariable (
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ DEBUG_CODE (
+ CHAR16 *DevicePathString;
+
+ DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
+ FALSE, FALSE);
+ DEBUG ((
+ EFI_ERROR (Status) ? EFI_D_WARN : DEBUG_VERBOSE,
+ "%a: removing stale Boot#%04x %s: %r\n",
+ __FUNCTION__,
+ (UINT32)BootOptions[Index].OptionNumber,
+ DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+ Status
+ ));
+ if (DevicePathString != NULL) {
+ FreePool (DevicePathString);
+ }
+ );
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+VOID
+PlatformRegisterOptionsAndKeys (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Enter;
+ EFI_INPUT_KEY F2;
+ EFI_INPUT_KEY Esc;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
+
+ //
+ // Register ENTER as CONTINUE key
+ //
+ Enter.ScanCode = SCAN_NULL;
+ Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;
+ Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Map F2 to Boot Manager Menu
+ //
+ F2.ScanCode = SCAN_F2;
+ F2.UnicodeChar = CHAR_NULL;
+ Esc.ScanCode = SCAN_ESC;
+ Esc.UnicodeChar = CHAR_NULL;
+ Status = EfiBootManagerGetBootManagerMenu (&BootOption);
+ ASSERT_EFI_ERROR (Status);
+ Status = EfiBootManagerAddKeyOptionVariable (
+ NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL
+ );
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+ Status = EfiBootManagerAddKeyOptionVariable (
+ NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL
+ );
+ ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+STATIC
+VOID
+SaveS3BootScript (
+ VOID
+ );
+
+//
+// BDS Platform Functions
+//
+/**
+ Do the platform init, can be customized by OEM/IBV
+
+ Possible things that can be done in PlatformBootManagerBeforeConsole:
+
+ > Update console variable: 1. include hot-plug devices;
+ > 2. Clear ConIn and add SOL for AMT
+ > Register new Driver#### or Boot####
+ > Register new Key####: e.g.: F12
+ > Signal ReadyToLock event
+ > Authentication action: 1. connect Auth devices;
+ > 2. Identify auto logon user.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));
+ InstallDevicePathCallback ();
+
+ VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
+ ConnectRootBridge, NULL);
+
+ //
+ // Signal the ACPI platform driver that it can download QEMU ACPI tables.
+ //
+ EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
+
+ //
+ // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
+ // the preparation of S3 system information. That logic has a hard dependency
+ // on the presence of the FACS ACPI table. Since our ACPI tables are only
+ // installed after PCI enumeration completes, we must not trigger the S3 save
+ // earlier, hence we can't signal End-of-Dxe earlier.
+ //
+ EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+
+ //
+ // Prevent further changes to LockBoxes or SMRAM.
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (&Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
+ NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Dispatch deferred images after EndOfDxe event and ReadyToLock
+ // installation.
+ //
+ EfiBootManagerDispatchDeferredImages ();
+
+ PlatformInitializeConsole (gPlatformConsole);
+
+ PlatformRegisterOptionsAndKeys ();
+
+ //
+ // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
+ // instances on Virtio PCI RNG devices.
+ //
+ VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid, ConnectVirtioPciRng,
+ NULL);
+}
+
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make the PCI bus driver connect the root bridge, non-recursively. This
+ // will produce a number of child handles with PciIo on them.
+ //
+ Status = gBS->ConnectController (
+ RootBridgeHandle, // ControllerHandle
+ NULL, // DriverImageHandle
+ NULL, // RemainingDevicePath -- produce all
+ // children
+ FALSE // Recursive
+ );
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT8 RevisionId;
+ BOOLEAN Virtio10;
+ UINT16 SubsystemId;
+
+ PciIo = Instance;
+
+ //
+ // Read and check VendorId.
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET,
+ 1, &VendorId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ if (VendorId != VIRTIO_VENDOR_ID) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Read DeviceId and RevisionId.
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET,
+ 1, &DeviceId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_REVISION_ID_OFFSET,
+ 1, &RevisionId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // From DeviceId and RevisionId, determine whether the device is a
+ // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
+ // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
+ // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
+ // only be sanity-checked, and SubsystemId will decide.
+ //
+ if (DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE &&
+ RevisionId >= 0x01) {
+ Virtio10 = TRUE;
+ } else if (DeviceId >= 0x1000 && DeviceId <= 0x103F && RevisionId == 0x00) {
+ Virtio10 = FALSE;
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Read and check SubsystemId as dictated by Virtio10.
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16,
+ PCI_SUBSYSTEM_ID_OFFSET, 1, &SubsystemId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ if ((Virtio10 && SubsystemId >= 0x40) ||
+ (!Virtio10 && SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {
+ Status = gBS->ConnectController (
+ Handle, // ControllerHandle
+ NULL, // DriverImageHandle -- connect all drivers
+ NULL, // RemainingDevicePath -- produce all child handles
+ FALSE // Recursive -- don't follow child handles
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ }
+ return EFI_SUCCESS;
+
+Error:
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));
+ return Status;
+}
+
+
+/**
+ Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the LPC Bridge device.
+
+ @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
+ ConOut, ConIn, and ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ CHAR16 *DevPathStr;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TempDevicePath = DevicePath;
+
+ //
+ // Register Keyboard
+ //
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+
+ //
+ // Register COM1
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 0;
+
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ DEBUG_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ // Don't register COM2 which can be used for DBG instead so keep it clean
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetGopDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE PciDeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
+ UINTN GopHandleCount;
+ EFI_HANDLE *GopHandleBuffer;
+
+ if (PciDevicePath == NULL || GopDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the GopDevicePath to be PciDevicePath
+ //
+ *GopDevicePath = PciDevicePath;
+ TempPciDevicePath = PciDevicePath;
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempPciDevicePath,
+ &PciDeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Try to connect this handle, so that GOP driver could start on this
+ // device and create child handles with GraphicsOutput Protocol installed
+ // on them, then we get device paths of these child handles and select
+ // them as possible console device.
+ //
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ &GopHandleCount,
+ &GopHandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add all the child handles as possible Console Device
+ //
+ for (Index = 0; Index < GopHandleCount; Index++) {
+ Status = gBS->HandleProtocol (GopHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (CompareMem (
+ PciDevicePath,
+ TempDevicePath,
+ GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+ ) == 0) {
+ //
+ // In current implementation, we only enable one of the child handles
+ // as console device, i.e. sotre one of the child handle's device
+ // path to variable "ConOut"
+ // In future, we could select all child handles to be console device
+ //
+
+ *GopDevicePath = TempDevicePath;
+
+ //
+ // Delete the PCI device's path that added by
+ // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
+ //
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
+ }
+ }
+ gBS->FreePool (GopHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add PCI display to ConOut.
+
+ @param[in] DeviceHandle Handle of the PCI display device.
+
+ @retval EFI_SUCCESS The PCI display device has been added to ConOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciDisplayDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ DevicePath = NULL;
+ GopDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GetGopDevicePath (DevicePath, &GopDevicePath);
+ DevicePath = GopDevicePath;
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add PCI Serial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the PCI serial device.
+
+ @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
+ ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ VOID *Instance;
+
+ //
+ // Start to check all the PciIo to find all possible device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Id,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = (*CallBackFunction) (
+ HandleBuffer[Index],
+ Instance,
+ Context
+ );
+ }
+
+ gBS->FreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingAPciInstance (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+
+ //
+ // Check for all PCI device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
+ Handle,
+ PciIo,
+ &Pci
+ );
+
+}
+
+
+
+EFI_STATUS
+VisitAllPciInstances (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ )
+{
+ return VisitAllInstancesOfProtocol (
+ &gEfiPciIoProtocolGuid,
+ VisitingAPciInstance,
+ (VOID*)(UINTN) CallBackFunction
+ );
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to
+ ConOut, ConIn, ErrOut.
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update
+ successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Here we decide whether it is LPC Bridge
+ //
+ if ((IS_PCI_LPC (Pci)) ||
+ ((IS_PCI_ISA_PDECODE (Pci)) &&
+ (Pci->Hdr.VendorId == 0x8086) &&
+ (Pci->Hdr.DeviceId == 0x7000)
+ )
+ ) {
+ //
+ // Add IsaKeyboard to ConIn,
+ // add IsaSerial to ConOut, ConIn, ErrOut
+ //
+ DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
+ PrepareLpcBridgeDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ //
+ // Here we decide which Serial device to enable in PCI bus
+ //
+ if (IS_PCI_16550SERIAL (Pci)) {
+ //
+ // Add them to ConOut, ConIn, ErrOut.
+ //
+ DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
+ PreparePciSerialDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Here we decide which display device to enable in PCI bus
+ //
+ if (IS_PCI_DISPLAY (Pci)) {
+ //
+ // Add them to ConOut.
+ //
+ DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
+ PreparePciDisplayDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Connect the predefined platform default console device.
+
+ Always try to find and enable PCI display devices.
+
+ @param[in] PlatformConsole Predefined platform default console device array.
+**/
+VOID
+PlatformInitializeConsole (
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+{
+ UINTN Index;
+
+ //
+ // Do platform specific PCI Device check and add them to ConOut, ConIn,
+ // ErrOut
+ //
+ VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimum device group
+ // the platform should support
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+ //
+ // Update the console variable with the connect type
+ //
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ EfiBootManagerUpdateConsoleVariable (ConIn,
+ PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ EfiBootManagerUpdateConsoleVariable (ConOut,
+ PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ EfiBootManagerUpdateConsoleVariable (ErrOut,
+ PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+}
+
+
+/**
+ Configure PCI Interrupt Line register for applicable devices
+ Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] PciHdr - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPciIntLine (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *PciHdr
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ UINTN RootSlot;
+ UINTN Idx;
+ UINT8 IrqLine;
+ EFI_STATUS Status;
+ UINT32 RootBusNumber;
+
+ Status = EFI_SUCCESS;
+
+ if (PciHdr->Device.InterruptPin != 0) {
+
+ DevPathNode = DevicePathFromHandle (Handle);
+ ASSERT (DevPathNode != NULL);
+ DevPath = DevPathNode;
+
+ RootBusNumber = 0;
+ if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == ACPI_DP &&
+ ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+ RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
+ }
+
+ //
+ // Compute index into PciHostIrqs[] table by walking
+ // the device path and adding up all device numbers
+ //
+ Status = EFI_NOT_FOUND;
+ RootSlot = 0;
+ Idx = PciHdr->Device.InterruptPin - 1;
+ while (!IsDevicePathEnd (DevPathNode)) {
+ if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == HW_PCI_DP) {
+
+ Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+
+ //
+ // Unlike SeaBIOS, which starts climbing from the leaf device
+ // up toward the root, we traverse the device path starting at
+ // the root moving toward the leaf node.
+ // The slot number of the top-level parent bridge is needed for
+ // Q35 cases with more than 24 slots on the root bus.
+ //
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+ }
+ }
+
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RootBusNumber == 0 && RootSlot == 0) {
+ DEBUG((
+ DEBUG_ERROR,
+ "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
+ __FUNCTION__
+ ));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Final PciHostIrqs[] index calculation depends on the platform
+ // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
+ //
+ switch (mHostBridgeDevId) {
+ case 0x7432: // BHYVE (AMD hostbridge)
+ case 0x1275: // BHYVE (Intel hostbridge)
+ case INTEL_82441_DEVICE_ID:
+ Idx -= 1;
+ break;
+ case INTEL_Q35_MCH_DEVICE_ID:
+ //
+ // SeaBIOS contains the following comment:
+ // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
+ // with a different starting index - see q35-acpi-dsdt.dsl.
+ //
+ // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
+ //
+ if (RootSlot > 24) {
+ //
+ // in this case, subtract back out RootSlot from Idx
+ // (SeaBIOS never adds it to begin with, but that would make our
+ // device path traversal loop above too awkward)
+ //
+ Idx -= RootSlot;
+ }
+ break;
+ default:
+ ASSERT (FALSE); // should never get here
+ }
+ Idx %= ARRAY_SIZE (PciHostIrqs);
+ IrqLine = PciHostIrqs[Idx];
+
+ DEBUG_CODE_BEGIN ();
+ {
+ CHAR16 *DevPathString;
+ STATIC CHAR16 Fallback[] = L"<failed to convert>";
+ UINTN Segment, Bus, Device, Function;
+
+ DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
+ if (DevPathString == NULL) {
+ DevPathString = Fallback;
+ }
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
+ (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
+ IrqLine));
+
+ if (DevPathString != Fallback) {
+ FreePool (DevPathString);
+ }
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
+ //
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_INT_LINE_OFFSET,
+ 1,
+ &IrqLine
+ );
+ }
+
+ return Status;
+}
+
+
+VOID
+PciAcpiInitialization (
+ )
+{
+ UINTN Pmba;
+
+ //
+ // Query Host Bridge DID to determine platform type
+ //
+ mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+ switch (mHostBridgeDevId) {
+ case 0x7432: // BHYVE (AMD hostbridge)
+ case 0x1275: // BHYVE (Intel hostbridge)
+ case INTEL_82441_DEVICE_ID:
+ Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+ //
+ // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+ break;
+ case INTEL_Q35_MCH_DEVICE_ID:
+ Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
+ //
+ // 00:1f.0 LPC Bridge (Q35) LNK routing targets
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__, mHostBridgeDevId));
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
+ //
+ VisitAllPciInstances (SetPciIntLine);
+
+ //
+ // Set ACPI SCI_EN bit in PMCNTRL
+ //
+ IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRecursivelyIfPciMassStorage (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *Instance,
+ IN PCI_TYPE00 *PciHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CHAR16 *DevPathStr;
+
+ //
+ // Recognize PCI Mass Storage, and Xen PCI devices
+ //
+ if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ DEBUG_INFO,
+ "Found %s device: %s\n",
+ (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE) ?
+ L"Mass Storage" :
+ L"Xen"
+ ),
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This notification function is invoked when the
+ EMU Variable FVB has been changed.
+
+ @param Event The event that occurred
+ @param Context For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+EmuVariablesUpdatedCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ DEBUG ((DEBUG_INFO, "EmuVariablesUpdatedCallback\n"));
+ UpdateNvVarsOnFileSystem ();
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingFileSystemInstance (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ STATIC BOOLEAN ConnectedToFileSystem = FALSE;
+ RETURN_STATUS PcdStatus;
+
+ if (ConnectedToFileSystem) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = ConnectNvVarsToFileSystem (Handle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ConnectedToFileSystem = TRUE;
+ mEmuVariableEvent =
+ EfiCreateProtocolNotifyEvent (
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ EmuVariablesUpdatedCallback,
+ NULL,
+ &mEmuVariableEventReg
+ );
+ PcdStatus = PcdSet64S (PcdEmuVariableEvent,
+ (UINT64)(UINTN) mEmuVariableEvent);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ return EFI_SUCCESS;
+}
+
+
+VOID
+PlatformBdsRestoreNvVarsFromHardDisk (
+ )
+{
+ VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
+ VisitAllInstancesOfProtocol (
+ &gEfiSimpleFileSystemProtocolGuid,
+ VisitingFileSystemInstance,
+ NULL
+ );
+
+}
+
+/**
+ Connect with predefined platform connect sequence.
+
+ The OEM/IBV can customize with their own connect sequence.
+**/
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+{
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));
+
+ Index = 0;
+
+ //
+ // Here we can get the customized platform connect sequence
+ // Notes: we can connect with new variable which record the
+ // last time boots connect device path sequence
+ //
+ while (gPlatformConnectSequence[Index] != NULL) {
+ //
+ // Build the platform boot option
+ //
+ EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
+ Index++;
+ }
+
+ //
+ // Just use the simple policy to connect all devices
+ //
+ DEBUG ((DEBUG_INFO, "EfiBootManagerConnectAll\n"));
+ EfiBootManagerConnectAll ();
+}
+
+/**
+ Save the S3 boot script.
+
+ Note that DxeSmmReadyToLock must be signaled after this function returns;
+ otherwise the script wouldn't be saved actually.
+**/
+#if defined(__GNUC__)
+__attribute__((unused))
+#endif
+STATIC
+VOID
+SaveS3BootScript (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
+ STATIC CONST UINT8 Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
+
+ Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
+ (VOID **) &BootScript);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Despite the opcode documentation in the PI spec, the protocol
+ // implementation embeds a deep copy of the info in the boot script, rather
+ // than storing just a pointer to runtime or NVS storage.
+ //
+ Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
+ (UINT32) sizeof Info,
+ (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
+ ASSERT_EFI_ERROR (Status);
+}
+
+
+/**
+ Do the platform specific action after the console is ready
+
+ Possible things that can be done in PlatformBootManagerAfterConsole:
+
+ > Console post action:
+ > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
+ > Signal console ready platform customized event
+ > Run diagnostics like memory testing
+ > Connect certain devices
+ > Dispatch aditional option roms
+ > Special boot: e.g.: USB boot, enter UI
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+ VOID
+ )
+{
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
+
+ if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
+ DEBUG ((DEBUG_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
+ "from disk since flash variables appear to be supported.\n"));
+ } else {
+ //
+ // Try to restore variables from the hard disk early so
+ // they can be used for the other BDS connect operations.
+ //
+ /* XXX Calling this causes Keyboard to be removed from ConIn which
+ results in unresponsive guest boot loaders in the GUI. Restore it
+ when we figure out what is needed to get NvVars storage done
+ properly.
+ */
+ /*PlatformBdsRestoreNvVarsFromHardDisk ();*/
+ }
+
+ //
+ // Get current Boot Mode
+ //
+ BootMode = GetBootModeHob ();
+ DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
+
+ //
+ // Logo show
+ //
+ BootLogoEnableLogo ();
+
+ //
+ // Set PCI Interrupt Line registers and ACPI SCI_EN
+ //
+ PciAcpiInitialization ();
+
+ //
+ // Process TPM PPI request
+ //
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+
+ EfiBootManagerRefreshAllBootOption ();
+
+ //
+ // Register UEFI Shell
+ //
+ PlatformRegisterFvBootOption (
+ &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
+ );
+
+ RemoveStaleFvFileOptions ();
+
+ PlatformBmPrintScRegisterHandler ();
+}
+
+/**
+ This notification function is invoked when an instance of the
+ EFI_DEVICE_PATH_PROTOCOL is produced.
+
+ @param Event The event that occurred
+ @param Context For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+NotifyDevPath (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ ATAPI_DEVICE_PATH *Atapi;
+
+ //
+ // Examine all new handles
+ //
+ for (;;) {
+ //
+ // Get the next handle
+ //
+ BufferSize = sizeof (Handle);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mEfiDevPathNotifyReg,
+ &BufferSize,
+ &Handle
+ );
+
+ //
+ // If not found, we're done
+ //
+ if (EFI_NOT_FOUND == Status) {
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get the DevicePath protocol on that handle
+ //
+ Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,
+ (VOID **)&DevPathNode);
+ ASSERT_EFI_ERROR (Status);
+
+ while (!IsDevicePathEnd (DevPathNode)) {
+ //
+ // Find the handler to dump this device path node
+ //
+ if (
+ (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
+ (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
+ ) {
+ Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
+ PciOr16 (
+ PCI_LIB_ADDRESS (
+ 0,
+ 1,
+ 1,
+ (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
+ ),
+ BIT15
+ );
+ }
+
+ //
+ // Next device path node
+ //
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+ }
+
+ return;
+}
+
+
+VOID
+InstallDevicePathCallback (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
+ mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ NotifyDevPath,
+ NULL,
+ &mEfiDevPathNotifyReg
+ );
+}
+
+/**
+ This function is called each second during the boot manager waits the
+ timeout.
+
+ @param TimeoutRemain The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ )
+{
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;
+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;
+ UINT16 Timeout;
+
+ Timeout = PcdGet16 (PcdPlatformBootTimeOut);
+
+ Black.Raw = 0x00000000;
+ White.Raw = 0x00FFFFFF;
+
+ BootLogoUpdateProgress (
+ White.Pixel,
+ Black.Pixel,
+ L"Start boot option",
+ White.Pixel,
+ (Timeout - TimeoutRemain) * 100 / Timeout,
+ 0
+ );
+}
+
+/**
+ The function is called when no boot option could be launched,
+ including platform recovery options and options pointing to applications
+ built into firmware volumes.
+
+ If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ EFI_BOOT_MANAGER_LOAD_OPTION BootManagerMenu;
+ UINTN Index;
+
+ //
+ // BootManagerMenu doesn't contain the correct information when return status
+ // is EFI_NOT_FOUND.
+ //
+ Status = EfiBootManagerGetBootManagerMenu (&BootManagerMenu);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ //
+ // Normally BdsDxe does not print anything to the system console, but this is
+ // a last resort -- the end-user will likely not see any DEBUG messages
+ // logged in this situation.
+ //
+ // AsciiPrint() will NULL-check gST->ConOut internally. We check gST->ConIn
+ // here to see if it makes sense to request and wait for a keypress.
+ //
+ if (gST->ConIn != NULL) {
+ AsciiPrint (
+ "%a: No bootable option or device was found.\n"
+ "%a: Press any key to enter the Boot Manager Menu.\n",
+ gEfiCallerBaseName,
+ gEfiCallerBaseName
+ );
+ Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Index);
+ ASSERT_EFI_ERROR (Status);
+ ASSERT (Index == 0);
+
+ //
+ // Drain any queued keys.
+ //
+ while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {
+ //
+ // just throw away Key
+ //
+ }
+ }
+
+ for (;;) {
+ EfiBootManagerBoot (&BootManagerMenu);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h
new file mode 100644
index 00000000000..f1946c9a729
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/BdsPlatform.h
@@ -0,0 +1,190 @@
+/** @file
+ Platform BDS customizations include file.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ BdsPlatform.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Virtio095.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+#include <Library/NvVarsFileLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Library/QemuFwCfgS3Lib.h>
+#include <Library/QemuBootOrderLib.h>
+
+#include <Protocol/Decompress.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/S3SaveState.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Guid/Acpi.h>
+#include <Guid/SmBios.h>
+#include <Guid/HobList.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+#include <Guid/DebugAgentGuid.h>
+
+#include <OvmfPlatforms.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH gUartDeviceNode;
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+ { \
+ { \
+ HARDWARE_DEVICE_PATH, \
+ HW_PCI_DP, \
+ { \
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ (Func), \
+ (Dev) \
+ }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+ { \
+ { \
+ ACPI_DEVICE_PATH, \
+ ACPI_DP, \
+ { \
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+ }, \
+ }, \
+ EISA_PNP_ID((PnpId)), \
+ 0 \
+ }
+
+#define gPciIsaBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+ PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+ PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_UART_DP, \
+ { \
+ (UINT8) (sizeof (UART_DEVICE_PATH)), \
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ 0, \
+ 115200, \
+ 8, \
+ 1, \
+ 1 \
+ }
+
+#define gPcAnsiTerminal \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_VENDOR_DP, \
+ { \
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ DEVICE_PATH_MESSAGING_PC_ANSI \
+ }
+
+#define gEndEntire \
+ { \
+ END_DEVICE_PATH_TYPE, \
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+ { \
+ END_DEVICE_PATH_LENGTH, \
+ 0 \
+ } \
+ }
+
+#define PCI_CLASS_SCC 0x07
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_16550 0x02
+#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN BIT1
+#define STD_ERROR BIT2
+extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformInitializeConsole (
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ );
+
+/**
+ Loads and boots UEFI Linux via the FwCfg interface.
+
+ @retval EFI_NOT_FOUND - The Linux kernel was not found
+
+**/
+EFI_STATUS
+TryRunningQemuKernel (
+ VOID
+ );
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformBootManagerLibBhyve.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformBootManagerLibBhyve.inf
new file mode 100644
index 00000000000..5f9c196bb43
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformBootManagerLibBhyve.inf
@@ -0,0 +1,75 @@
+## @file
+# Platform BDS customizations library.
+#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformBootManagerLibBhyve
+ FILE_GUID = b0de5f0d-f676-42da-8d00-86997ee0dbb4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+ OvmfPkg/OvmfPkg.dec
+ SecurityPkg/SecurityPkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ UefiBootManagerLib
+ BootLogoLib
+ DevicePathLib
+ PciLib
+ NvVarsFileLib
+ ReportStatusCodeLib
+ UefiLib
+ PlatformBmPrintScLib
+ Tcg2PhysicalPresenceLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+ gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut
+
+[Pcd.IA32, Pcd.X64]
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock
+
+[Protocols]
+ gEfiDecompressProtocolGuid
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiS3SaveStateProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+ gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid
+ gRootBridgesConnectedEventGroupGuid
+ gUefiShellFileGuid
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformData.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformData.c
new file mode 100644
index 00000000000..945330e0b2a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibBhyve/PlatformData.c
@@ -0,0 +1,171 @@
+/** @file
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+ Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/QemuRamfb.h>
+
+//
+// Debug Agent UART Device Path structure
+//
+#pragma pack(1)
+typedef struct {
+ VENDOR_DEVICE_PATH VendorHardware;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} VENDOR_UART_DEVICE_PATH;
+#pragma pack()
+
+//
+// USB Keyboard Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+ USB_CLASS_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_KEYBOARD_DEVICE_PATH;
+#pragma pack ()
+
+//
+// QemuRamfb Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ ACPI_ADR_DEVICE_PATH AcpiAdr;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} VENDOR_RAMFB_DEVICE_PATH;
+#pragma pack ()
+
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH gUartDeviceNode = gUart;
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
+
+//
+// Platform specific keyboard device path
+//
+
+
+//
+// Debug Agent UART Device Path
+//
+VENDOR_UART_DEVICE_PATH gDebugAgentUartDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ EFI_DEBUG_AGENT_GUID,
+ },
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ {
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0, // Reserved
+ 0, // BaudRate - Default
+ 0, // DataBits - Default
+ 0, // Parity - Default
+ 0, // StopBits - Default
+ },
+ gPcAnsiTerminal,
+ gEndEntire
+};
+
+STATIC USB_KEYBOARD_DEVICE_PATH gUsbKeyboardDevicePath = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ {
+ (UINT8)sizeof (USB_CLASS_DEVICE_PATH),
+ (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) >> 8)
+ }
+ },
+ 0xFFFF, // VendorId: any
+ 0xFFFF, // ProductId: any
+ 3, // DeviceClass: HID
+ 1, // DeviceSubClass: boot
+ 1 // DeviceProtocol: keyboard
+ },
+ gEndEntire
+};
+
+STATIC VENDOR_RAMFB_DEVICE_PATH gQemuRamfbDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ QEMU_RAMFB_GUID,
+ },
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_ADR_DP,
+ {
+ (UINT8) (sizeof (ACPI_ADR_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_ADR_DEVICE_PATH)) >> 8)
+ }
+ },
+ ACPI_DISPLAY_ADR (
+ 1, // DeviceIdScheme
+ 0, // HeadId
+ 0, // NonVgaOutput
+ 1, // BiosCanDetect
+ 0, // VendorInfo
+ ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type
+ 0, // Port
+ 0 // Index
+ ),
+ },
+ gEndEntire
+};
+
+//
+// Predefined platform default console device path
+//
+PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gDebugAgentUartDevicePath,
+ (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUsbKeyboardDevicePath,
+ CONSOLE_IN
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *)&gQemuRamfbDevicePath,
+ CONSOLE_OUT
+ },
+ {
+ NULL,
+ 0
+ }
+};
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c
new file mode 100644
index 00000000000..66eed8c2fef
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.c
@@ -0,0 +1,1484 @@
+/** @file
+ Platform BDS customizations.
+
+ Copyright (C) 2020 James Bottomley, IBM Corporation.
+ Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/RootBridgesConnectedEventGroup.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Library/PlatformBmPrintScLib.h>
+#include <Library/Tcg2PhysicalPresenceLib.h>
+
+
+//
+// Global data
+//
+
+VOID *mEfiDevPathNotifyReg;
+EFI_EVENT mEfiDevPathEvent;
+UINT16 mHostBridgeDevId;
+
+//
+// Table of host IRQs matching PCI IRQs A-D
+// (for configuring PCI Interrupt Line register)
+//
+CONST UINT8 PciHostIrqs[] = {
+ 0x0a, 0x0a, 0x0b, 0x0b
+};
+
+//
+// Type definitions
+//
+
+typedef
+EFI_STATUS
+(EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+/**
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+**/
+typedef
+EFI_STATUS
+(EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ );
+
+
+//
+// Function prototypes
+//
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ );
+
+EFI_STATUS
+VisitAllPciInstancesOfProtocol (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ );
+
+VOID
+InstallDevicePathCallback (
+ VOID
+ );
+
+VOID
+PlatformRegisterFvBootOption (
+ EFI_GUID *FileGuid,
+ CHAR16 *Description,
+ UINT32 Attributes
+ )
+{
+ EFI_STATUS Status;
+ INTN OptionIndex;
+ EFI_BOOT_MANAGER_LOAD_OPTION NewOption;
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ Status = gBS->HandleProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);
+ DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);
+ ASSERT (DevicePath != NULL);
+ DevicePath = AppendDevicePathNode (
+ DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *) &FileNode
+ );
+ ASSERT (DevicePath != NULL);
+
+ Status = EfiBootManagerInitializeLoadOption (
+ &NewOption,
+ LoadOptionNumberUnassigned,
+ LoadOptionTypeBoot,
+ Attributes,
+ Description,
+ DevicePath,
+ NULL,
+ 0
+ );
+ ASSERT_EFI_ERROR (Status);
+ FreePool (DevicePath);
+
+ BootOptions = EfiBootManagerGetLoadOptions (
+ &BootOptionCount, LoadOptionTypeBoot
+ );
+
+ OptionIndex = EfiBootManagerFindLoadOption (
+ &NewOption, BootOptions, BootOptionCount
+ );
+
+ if (OptionIndex == -1) {
+ Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);
+ ASSERT_EFI_ERROR (Status);
+ }
+ EfiBootManagerFreeLoadOption (&NewOption);
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+/**
+ Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
+ whose device paths do not resolve exactly to an FvFile in the system.
+
+ Also strip out every boot option that is not an FvFile, meaning the system
+ can only boot either the Grub or (if built) the shell.
+
+ This removes any boot options that point to binaries built into the firmware
+ and have become stale due to any of the following:
+ - DXEFV's base address or size changed (historical),
+ - DXEFV's FvNameGuid changed,
+ - the FILE_GUID of the pointed-to binary changed,
+ - the referenced binary is no longer built into the firmware.
+
+ EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
+ avoids exact duplicates.
+**/
+VOID
+RemoveStaleFvFileOptions (
+ VOID
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
+ LoadOptionTypeBoot);
+
+ for (Index = 0; Index < BootOptionCount; ++Index) {
+ EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+ EFI_STATUS Status;
+ EFI_HANDLE FvHandle;
+
+ //
+ // If the device path starts with neither MemoryMapped(...) nor Fv(...),
+ // then delete the boot option.
+ //
+ Node1 = BootOptions[Index].FilePath;
+ if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
+ !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+ EfiBootManagerDeleteLoadOptionVariable (
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ continue;
+ }
+
+ //
+ // If the second device path node is not FvFile(...), then delete the boot
+ // option.
+ //
+ Node2 = NextDevicePathNode (Node1);
+ if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+ EfiBootManagerDeleteLoadOptionVariable (
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ continue;
+ }
+
+ //
+ // Locate the Firmware Volume2 protocol instance that is denoted by the
+ // boot option. If this lookup fails (i.e., the boot option references a
+ // firmware volume that doesn't exist), then we'll proceed to delete the
+ // boot option.
+ //
+ SearchNode = Node1;
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
+ &SearchNode, &FvHandle);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // The firmware volume was found; now let's see if it contains the FvFile
+ // identified by GUID.
+ //
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+ UINTN BufferSize;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINT32 AuthenticationStatus;
+
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **)&FvProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
+ //
+ // Buffer==NULL means we request metadata only: BufferSize, FoundType,
+ // FileAttributes.
+ //
+ Status = FvProtocol->ReadFile (
+ FvProtocol,
+ &FvFileNode->FvFileName, // NameGuid
+ NULL, // Buffer
+ &BufferSize,
+ &FoundType,
+ &FileAttributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The FvFile was found. Keep the boot option.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Delete the boot option.
+ //
+ Status = EfiBootManagerDeleteLoadOptionVariable (
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ DEBUG_CODE (
+ CHAR16 *DevicePathString;
+
+ DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
+ FALSE, FALSE);
+ DEBUG ((
+ EFI_ERROR (Status) ? DEBUG_WARN : DEBUG_VERBOSE,
+ "%a: removing stale Boot#%04x %s: %r\n",
+ __FUNCTION__,
+ (UINT32)BootOptions[Index].OptionNumber,
+ DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+ Status
+ ));
+ if (DevicePathString != NULL) {
+ FreePool (DevicePathString);
+ }
+ );
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ );
+
+//
+// BDS Platform Functions
+//
+/**
+ Do the platform init, can be customized by OEM/IBV
+
+ Possible things that can be done in PlatformBootManagerBeforeConsole:
+
+ > Update console variable: 1. include hot-plug devices;
+ > 2. Clear ConIn and add SOL for AMT
+ > Register new Driver#### or Boot####
+ > Register new Key####: e.g.: F12
+ > Signal ReadyToLock event
+ > Authentication action: 1. connect Auth devices;
+ > 2. Identify auto logon user.
+**/
+VOID
+EFIAPI
+PlatformBootManagerBeforeConsole (
+ VOID
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINT16 FrontPageTimeout;
+
+ FrontPageTimeout = 0;
+
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerBeforeConsole\n"));
+ InstallDevicePathCallback ();
+
+ VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
+ ConnectRootBridge, NULL);
+
+ //
+ // Signal the ACPI platform driver that it can download QEMU ACPI tables.
+ //
+ EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);
+
+ //
+ // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
+ // the preparation of S3 system information. That logic has a hard dependency
+ // on the presence of the FACS ACPI table. Since our ACPI tables are only
+ // installed after PCI enumeration completes, we must not trigger the S3 save
+ // earlier, hence we can't signal End-of-Dxe earlier.
+ //
+ EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);
+
+ //
+ // Prevent further changes to LockBoxes or SMRAM.
+ //
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (&Handle,
+ &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
+ NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Dispatch deferred images after EndOfDxe event and ReadyToLock
+ // installation.
+ //
+ EfiBootManagerDispatchDeferredImages ();
+
+ PlatformInitializeConsole (gPlatformConsole);
+
+ Status = gRT->SetVariable (
+ EFI_TIME_OUT_VARIABLE_NAME,
+ &gEfiGlobalVariableGuid,
+ (EFI_VARIABLE_NON_VOLATILE |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS),
+ sizeof FrontPageTimeout,
+ &FrontPageTimeout
+ );
+ //
+ // Install both VIRTIO_DEVICE_PROTOCOL and (dependent) EFI_RNG_PROTOCOL
+ // instances on Virtio PCI RNG devices.
+ //
+ VisitAllInstancesOfProtocol (&gEfiPciIoProtocolGuid, ConnectVirtioPciRng,
+ NULL);
+}
+
+
+EFI_STATUS
+EFIAPI
+ConnectRootBridge (
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Make the PCI bus driver connect the root bridge, non-recursively. This
+ // will produce a number of child handles with PciIo on them.
+ //
+ Status = gBS->ConnectController (
+ RootBridgeHandle, // ControllerHandle
+ NULL, // DriverImageHandle
+ NULL, // RemainingDevicePath -- produce all
+ // children
+ FALSE // Recursive
+ );
+ return Status;
+}
+
+
+STATIC
+EFI_STATUS
+EFIAPI
+ConnectVirtioPciRng (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ EFI_STATUS Status;
+ UINT16 VendorId;
+ UINT16 DeviceId;
+ UINT8 RevisionId;
+ BOOLEAN Virtio10;
+ UINT16 SubsystemId;
+
+ PciIo = Instance;
+
+ //
+ // Read and check VendorId.
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_VENDOR_ID_OFFSET,
+ 1, &VendorId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ if (VendorId != VIRTIO_VENDOR_ID) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Read DeviceId and RevisionId.
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PCI_DEVICE_ID_OFFSET,
+ 1, &DeviceId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, PCI_REVISION_ID_OFFSET,
+ 1, &RevisionId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // From DeviceId and RevisionId, determine whether the device is a
+ // modern-only Virtio 1.0 device. In case of Virtio 1.0, DeviceId can
+ // immediately be restricted to VIRTIO_SUBSYSTEM_ENTROPY_SOURCE, and
+ // SubsystemId will only play a sanity-check role. Otherwise, DeviceId can
+ // only be sanity-checked, and SubsystemId will decide.
+ //
+ if (DeviceId == 0x1040 + VIRTIO_SUBSYSTEM_ENTROPY_SOURCE &&
+ RevisionId >= 0x01) {
+ Virtio10 = TRUE;
+ } else if (DeviceId >= 0x1000 && DeviceId <= 0x103F && RevisionId == 0x00) {
+ Virtio10 = FALSE;
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Read and check SubsystemId as dictated by Virtio10.
+ //
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16,
+ PCI_SUBSYSTEM_ID_OFFSET, 1, &SubsystemId);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ if ((Virtio10 && SubsystemId >= 0x40) ||
+ (!Virtio10 && SubsystemId == VIRTIO_SUBSYSTEM_ENTROPY_SOURCE)) {
+ Status = gBS->ConnectController (
+ Handle, // ControllerHandle
+ NULL, // DriverImageHandle -- connect all drivers
+ NULL, // RemainingDevicePath -- produce all child handles
+ FALSE // Recursive -- don't follow child handles
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ }
+ return EFI_SUCCESS;
+
+Error:
+ DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, Status));
+ return Status;
+}
+
+
+/**
+ Add IsaKeyboard to ConIn; add IsaSerial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the LPC Bridge device.
+
+ @retval EFI_SUCCESS Console devices on the LPC bridge have been added to
+ ConOut, ConIn, and ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PrepareLpcBridgeDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ CHAR16 *DevPathStr;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TempDevicePath = DevicePath;
+
+ //
+ // Register Keyboard
+ //
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
+
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+
+ //
+ // Register COM1
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 0;
+
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ DEBUG_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ //
+ // Register COM2
+ //
+ DevicePath = TempDevicePath;
+ gPnp16550ComPortDeviceNode.UID = 1;
+
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ DEBUG_INFO,
+ "BdsPlatform.c+%d: COM%d DevPath: %s\n",
+ __LINE__,
+ gPnp16550ComPortDeviceNode.UID + 1,
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+GetGopDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
+ OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_HANDLE PciDeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempPciDevicePath;
+ UINTN GopHandleCount;
+ EFI_HANDLE *GopHandleBuffer;
+
+ if (PciDevicePath == NULL || GopDevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the GopDevicePath to be PciDevicePath
+ //
+ *GopDevicePath = PciDevicePath;
+ TempPciDevicePath = PciDevicePath;
+
+ Status = gBS->LocateDevicePath (
+ &gEfiDevicePathProtocolGuid,
+ &TempPciDevicePath,
+ &PciDeviceHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Try to connect this handle, so that GOP driver could start on this
+ // device and create child handles with GraphicsOutput Protocol installed
+ // on them, then we get device paths of these child handles and select
+ // them as possible console device.
+ //
+ gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiGraphicsOutputProtocolGuid,
+ NULL,
+ &GopHandleCount,
+ &GopHandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Add all the child handles as possible Console Device
+ //
+ for (Index = 0; Index < GopHandleCount; Index++) {
+ Status = gBS->HandleProtocol (GopHandleBuffer[Index],
+ &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ if (CompareMem (
+ PciDevicePath,
+ TempDevicePath,
+ GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
+ ) == 0) {
+ //
+ // In current implementation, we only enable one of the child handles
+ // as console device, i.e. sotre one of the child handle's device
+ // path to variable "ConOut"
+ // In future, we could select all child handles to be console device
+ //
+
+ *GopDevicePath = TempDevicePath;
+
+ //
+ // Delete the PCI device's path that added by
+ // GetPlugInPciVgaDevicePath(). Add the integrity GOP device path.
+ //
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, NULL, PciDevicePath);
+ EfiBootManagerUpdateConsoleVariable (ConOutDev, TempDevicePath, NULL);
+ }
+ }
+ gBS->FreePool (GopHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add PCI display to ConOut.
+
+ @param[in] DeviceHandle Handle of the PCI display device.
+
+ @retval EFI_SUCCESS The PCI display device has been added to ConOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciDisplayDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *GopDevicePath;
+
+ DevicePath = NULL;
+ GopDevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ GetGopDevicePath (DevicePath, &GopDevicePath);
+ DevicePath = GopDevicePath;
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add PCI Serial to ConOut, ConIn, ErrOut.
+
+ @param[in] DeviceHandle Handle of the PCI serial device.
+
+ @retval EFI_SUCCESS The PCI serial device has been added to ConOut, ConIn,
+ ErrOut.
+
+ @return Error codes, due to EFI_DEVICE_PATH_PROTOCOL missing
+ from DeviceHandle.
+**/
+EFI_STATUS
+PreparePciSerialDevicePath (
+ IN EFI_HANDLE DeviceHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
+ DevicePath = AppendDevicePathNode (DevicePath,
+ (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
+
+ EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL);
+ EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+VisitAllInstancesOfProtocol (
+ IN EFI_GUID *Id,
+ IN PROTOCOL_INSTANCE_CALLBACK CallBackFunction,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+ VOID *Instance;
+
+ //
+ // Start to check all the PciIo to find all possible device
+ //
+ HandleCount = 0;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Id,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = (*CallBackFunction) (
+ HandleBuffer[Index],
+ Instance,
+ Context
+ );
+ }
+
+ gBS->FreePool (HandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+EFI_STATUS
+EFIAPI
+VisitingAPciInstance (
+ IN EFI_HANDLE Handle,
+ IN VOID *Instance,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
+
+ //
+ // Check for all PCI device
+ //
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
+ Handle,
+ PciIo,
+ &Pci
+ );
+
+}
+
+
+
+EFI_STATUS
+VisitAllPciInstances (
+ IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
+ )
+{
+ return VisitAllInstancesOfProtocol (
+ &gEfiPciIoProtocolGuid,
+ VisitingAPciInstance,
+ (VOID*)(UINTN) CallBackFunction
+ );
+}
+
+
+/**
+ Do platform specific PCI Device check and add them to
+ ConOut, ConIn, ErrOut.
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] Pci - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Device check and Console variable update
+ successfully.
+ @retval EFI_STATUS - PCI Device check or Console variable update fail.
+
+**/
+EFI_STATUS
+EFIAPI
+DetectAndPreparePlatformPciDevicePath (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *Pci
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PciIo->Attributes (
+ PciIo,
+ EfiPciIoAttributeOperationEnable,
+ EFI_PCI_DEVICE_ENABLE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Here we decide whether it is LPC Bridge
+ //
+ if ((IS_PCI_LPC (Pci)) ||
+ ((IS_PCI_ISA_PDECODE (Pci)) &&
+ (Pci->Hdr.VendorId == 0x8086) &&
+ (Pci->Hdr.DeviceId == 0x7000)
+ )
+ ) {
+ //
+ // Add IsaKeyboard to ConIn,
+ // add IsaSerial to ConOut, ConIn, ErrOut
+ //
+ DEBUG ((DEBUG_INFO, "Found LPC Bridge device\n"));
+ PrepareLpcBridgeDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+ //
+ // Here we decide which Serial device to enable in PCI bus
+ //
+ if (IS_PCI_16550SERIAL (Pci)) {
+ //
+ // Add them to ConOut, ConIn, ErrOut.
+ //
+ DEBUG ((DEBUG_INFO, "Found PCI 16550 SERIAL device\n"));
+ PreparePciSerialDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Here we decide which display device to enable in PCI bus
+ //
+ if (IS_PCI_DISPLAY (Pci)) {
+ //
+ // Add them to ConOut.
+ //
+ DEBUG ((DEBUG_INFO, "Found PCI display device\n"));
+ PreparePciDisplayDevicePath (Handle);
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+
+/**
+ Connect the predefined platform default console device.
+
+ Always try to find and enable PCI display devices.
+
+ @param[in] PlatformConsole Predefined platform default console device array.
+**/
+VOID
+PlatformInitializeConsole (
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ )
+{
+ UINTN Index;
+
+ //
+ // Do platform specific PCI Device check and add them to ConOut, ConIn,
+ // ErrOut
+ //
+ VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
+
+ //
+ // Have chance to connect the platform default console,
+ // the platform default console is the minimum device group
+ // the platform should support
+ //
+ for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
+ //
+ // Update the console variable with the connect type
+ //
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
+ EfiBootManagerUpdateConsoleVariable (ConIn,
+ PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
+ EfiBootManagerUpdateConsoleVariable (ConOut,
+ PlatformConsole[Index].DevicePath, NULL);
+ }
+ if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
+ EfiBootManagerUpdateConsoleVariable (ErrOut,
+ PlatformConsole[Index].DevicePath, NULL);
+ }
+ }
+}
+
+
+/**
+ Configure PCI Interrupt Line register for applicable devices
+ Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
+
+ @param[in] Handle - Handle of PCI device instance
+ @param[in] PciIo - PCI IO protocol instance
+ @param[in] PciHdr - PCI Header register block
+
+ @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPciIntLine (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *PciIo,
+ IN PCI_TYPE00 *PciHdr
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ UINTN RootSlot;
+ UINTN Idx;
+ UINT8 IrqLine;
+ EFI_STATUS Status;
+ UINT32 RootBusNumber;
+
+ Status = EFI_SUCCESS;
+
+ if (PciHdr->Device.InterruptPin != 0) {
+
+ DevPathNode = DevicePathFromHandle (Handle);
+ ASSERT (DevPathNode != NULL);
+ DevPath = DevPathNode;
+
+ RootBusNumber = 0;
+ if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == ACPI_DP &&
+ ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
+ RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
+ }
+
+ //
+ // Compute index into PciHostIrqs[] table by walking
+ // the device path and adding up all device numbers
+ //
+ Status = EFI_NOT_FOUND;
+ RootSlot = 0;
+ Idx = PciHdr->Device.InterruptPin - 1;
+ while (!IsDevicePathEnd (DevPathNode)) {
+ if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (DevPathNode) == HW_PCI_DP) {
+
+ Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+
+ //
+ // Unlike SeaBIOS, which starts climbing from the leaf device
+ // up toward the root, we traverse the device path starting at
+ // the root moving toward the leaf node.
+ // The slot number of the top-level parent bridge is needed for
+ // Q35 cases with more than 24 slots on the root bus.
+ //
+ if (Status != EFI_SUCCESS) {
+ Status = EFI_SUCCESS;
+ RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
+ }
+ }
+
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RootBusNumber == 0 && RootSlot == 0) {
+ DEBUG((
+ DEBUG_ERROR,
+ "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
+ __FUNCTION__
+ ));
+ ASSERT (FALSE);
+ }
+
+ //
+ // Final PciHostIrqs[] index calculation depends on the platform
+ // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
+ //
+ switch (mHostBridgeDevId) {
+ case INTEL_82441_DEVICE_ID:
+ Idx -= 1;
+ break;
+ case INTEL_Q35_MCH_DEVICE_ID:
+ //
+ // SeaBIOS contains the following comment:
+ // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
+ // with a different starting index - see q35-acpi-dsdt.dsl.
+ //
+ // Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
+ //
+ if (RootSlot > 24) {
+ //
+ // in this case, subtract back out RootSlot from Idx
+ // (SeaBIOS never adds it to begin with, but that would make our
+ // device path traversal loop above too awkward)
+ //
+ Idx -= RootSlot;
+ }
+ break;
+ default:
+ ASSERT (FALSE); // should never get here
+ }
+ Idx %= ARRAY_SIZE (PciHostIrqs);
+ IrqLine = PciHostIrqs[Idx];
+
+ DEBUG_CODE_BEGIN ();
+ {
+ CHAR16 *DevPathString;
+ STATIC CHAR16 Fallback[] = L"<failed to convert>";
+ UINTN Segment, Bus, Device, Function;
+
+ DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
+ if (DevPathString == NULL) {
+ DevPathString = Fallback;
+ }
+ Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
+ (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
+ IrqLine));
+
+ if (DevPathString != Fallback) {
+ FreePool (DevPathString);
+ }
+ }
+ DEBUG_CODE_END ();
+
+ //
+ // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
+ //
+ Status = PciIo->Pci.Write (
+ PciIo,
+ EfiPciIoWidthUint8,
+ PCI_INT_LINE_OFFSET,
+ 1,
+ &IrqLine
+ );
+ }
+
+ return Status;
+}
+
+
+VOID
+PciAcpiInitialization (
+ )
+{
+ UINTN Pmba;
+
+ //
+ // Query Host Bridge DID to determine platform type
+ //
+ mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
+ switch (mHostBridgeDevId) {
+ case INTEL_82441_DEVICE_ID:
+ Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
+ //
+ // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
+ break;
+ case INTEL_Q35_MCH_DEVICE_ID:
+ Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
+ //
+ // 00:1f.0 LPC Bridge (Q35) LNK routing targets
+ //
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
+ PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
+ break;
+ default:
+ DEBUG ((DEBUG_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
+ __FUNCTION__, mHostBridgeDevId));
+ ASSERT (FALSE);
+ return;
+ }
+
+ //
+ // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
+ //
+ VisitAllPciInstances (SetPciIntLine);
+
+ //
+ // Set ACPI SCI_EN bit in PMCNTRL
+ //
+ IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
+}
+
+EFI_STATUS
+EFIAPI
+ConnectRecursivelyIfPciMassStorage (
+ IN EFI_HANDLE Handle,
+ IN EFI_PCI_IO_PROTOCOL *Instance,
+ IN PCI_TYPE00 *PciHeader
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CHAR16 *DevPathStr;
+
+ //
+ // Recognize PCI Mass Storage
+ //
+ if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
+ DevicePath = NULL;
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID*)&DevicePath
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Print Device Path
+ //
+ DevPathStr = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
+ if (DevPathStr != NULL) {
+ DEBUG((
+ DEBUG_INFO,
+ "Found Mass Storage device: %s\n",
+ DevPathStr
+ ));
+ FreePool(DevPathStr);
+ }
+
+ Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Connect with predefined platform connect sequence.
+
+ The OEM/IBV can customize with their own connect sequence.
+**/
+VOID
+PlatformBdsConnectSequence (
+ VOID
+ )
+{
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "PlatformBdsConnectSequence\n"));
+
+ Index = 0;
+
+ //
+ // Here we can get the customized platform connect sequence
+ // Notes: we can connect with new variable which record the
+ // last time boots connect device path sequence
+ //
+ while (gPlatformConnectSequence[Index] != NULL) {
+ //
+ // Build the platform boot option
+ //
+ EfiBootManagerConnectDevicePath (gPlatformConnectSequence[Index], NULL);
+ Index++;
+ }
+ EfiBootManagerConnectAll ();
+}
+
+/**
+ Do the platform specific action after the console is ready
+
+ Possible things that can be done in PlatformBootManagerAfterConsole:
+
+ > Console post action:
+ > Dynamically switch output mode from 100x31 to 80x25 for certain senarino
+ > Signal console ready platform customized event
+ > Run diagnostics like memory testing
+ > Connect certain devices
+ > Dispatch aditional option roms
+ > Special boot: e.g.: USB boot, enter UI
+**/
+VOID
+EFIAPI
+PlatformBootManagerAfterConsole (
+ VOID
+ )
+{
+ EFI_BOOT_MODE BootMode;
+
+ DEBUG ((DEBUG_INFO, "PlatformBootManagerAfterConsole\n"));
+
+ //
+ // Get current Boot Mode
+ //
+ BootMode = GetBootModeHob ();
+ DEBUG ((DEBUG_INFO, "Boot Mode:%x\n", BootMode));
+
+ //
+ // Go the different platform policy with different boot mode
+ // Notes: this part code can be change with the table policy
+ //
+ ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
+
+ //
+ // Logo show
+ //
+ BootLogoEnableLogo ();
+
+ //
+ // Set PCI Interrupt Line registers and ACPI SCI_EN
+ //
+ PciAcpiInitialization ();
+
+ //
+ // Process TPM PPI request
+ //
+ Tcg2PhysicalPresenceLibProcessRequest (NULL);
+
+ //
+ // Perform some platform specific connect sequence
+ //
+ PlatformBdsConnectSequence ();
+
+ EfiBootManagerRefreshAllBootOption ();
+
+ //
+ // Register UEFI Shell (Will be removed if the Shell isn't built
+ // which is the default)
+ //
+ PlatformRegisterFvBootOption (
+ &gUefiShellFileGuid, L"EFI Internal Shell", LOAD_OPTION_ACTIVE
+ );
+
+ //
+ // Register Grub
+ //
+ PlatformRegisterFvBootOption (
+ &gGrubFileGuid, L"Grub Bootloader", LOAD_OPTION_ACTIVE
+ );
+
+ RemoveStaleFvFileOptions ();
+
+ PlatformBmPrintScRegisterHandler ();
+}
+
+/**
+ This notification function is invoked when an instance of the
+ EFI_DEVICE_PATH_PROTOCOL is produced.
+
+ @param Event The event that occurred
+ @param Context For EFI compatibility. Not used.
+
+**/
+VOID
+EFIAPI
+NotifyDevPath (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;
+ ATAPI_DEVICE_PATH *Atapi;
+
+ //
+ // Examine all new handles
+ //
+ for (;;) {
+ //
+ // Get the next handle
+ //
+ BufferSize = sizeof (Handle);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ mEfiDevPathNotifyReg,
+ &BufferSize,
+ &Handle
+ );
+
+ //
+ // If not found, we're done
+ //
+ if (EFI_NOT_FOUND == Status) {
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Get the DevicePath protocol on that handle
+ //
+ Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid,
+ (VOID **)&DevPathNode);
+ ASSERT_EFI_ERROR (Status);
+
+ while (!IsDevicePathEnd (DevPathNode)) {
+ //
+ // Find the handler to dump this device path node
+ //
+ if (
+ (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
+ (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
+ ) {
+ Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
+ PciOr16 (
+ PCI_LIB_ADDRESS (
+ 0,
+ 1,
+ 1,
+ (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
+ ),
+ BIT15
+ );
+ }
+
+ //
+ // Next device path node
+ //
+ DevPathNode = NextDevicePathNode (DevPathNode);
+ }
+ }
+
+ return;
+}
+
+
+VOID
+InstallDevicePathCallback (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "Registered NotifyDevPath Event\n"));
+ mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
+ &gEfiDevicePathProtocolGuid,
+ TPL_CALLBACK,
+ NotifyDevPath,
+ NULL,
+ &mEfiDevPathNotifyReg
+ );
+}
+
+/**
+ This function is called each second during the boot manager waits the
+ timeout.
+
+ @param TimeoutRemain The remaining timeout.
+**/
+VOID
+EFIAPI
+PlatformBootManagerWaitCallback (
+ UINT16 TimeoutRemain
+ )
+{
+ //
+ // Since the timeout should be forced to zero we should never
+ // Get here
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ The function is called when no boot option could be launched,
+ including platform recovery options and options pointing to applications
+ built into firmware volumes.
+
+ If this function returns, BDS attempts to enter an infinite loop.
+**/
+VOID
+EFIAPI
+PlatformBootManagerUnableToBoot (
+ VOID
+ )
+{
+ //
+ // If we get here something failed about the grub boot but since
+ // We're privy to the secret we must panic and not retry or loop
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.h
new file mode 100644
index 00000000000..708eadb67e7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/BdsPlatform.h
@@ -0,0 +1,175 @@
+/** @file
+ Platform BDS customizations include file.
+
+ Copyright (C) 2020 James Bottomley, IBM Corporation.
+ Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ BdsPlatform.h
+
+Abstract:
+
+ Head file for BDS Platform specific code
+
+**/
+
+#ifndef _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+#define _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
+
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/SmBios.h>
+#include <IndustryStandard/PeImage.h>
+#include <IndustryStandard/Virtio095.h>
+
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciLib.h>
+#include <Library/UefiBootManagerLib.h>
+#include <Library/BootLogoLib.h>
+#include <Library/HobLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/IoLib.h>
+
+#include <Protocol/Decompress.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DxeSmmReadyToLock.h>
+#include <Protocol/LoadedImage.h>
+
+#include <Guid/Acpi.h>
+#include <Guid/SmBios.h>
+#include <Guid/HobList.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/EventGroup.h>
+#include <Guid/DebugAgentGuid.h>
+
+#include <OvmfPlatforms.h>
+
+extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[];
+extern ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode;
+extern ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode;
+extern UART_DEVICE_PATH gUartDeviceNode;
+extern VENDOR_DEVICE_PATH gTerminalTypeDeviceNode;
+
+#define PCI_DEVICE_PATH_NODE(Func, Dev) \
+ { \
+ { \
+ HARDWARE_DEVICE_PATH, \
+ HW_PCI_DP, \
+ { \
+ (UINT8) (sizeof (PCI_DEVICE_PATH)), \
+ (UINT8) ((sizeof (PCI_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ (Func), \
+ (Dev) \
+ }
+
+#define PNPID_DEVICE_PATH_NODE(PnpId) \
+ { \
+ { \
+ ACPI_DEVICE_PATH, \
+ ACPI_DP, \
+ { \
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), \
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) \
+ }, \
+ }, \
+ EISA_PNP_ID((PnpId)), \
+ 0 \
+ }
+
+#define gPciIsaBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1f)
+
+#define gP2PBridge \
+ PCI_DEVICE_PATH_NODE(0, 0x1e)
+
+#define gPnpPs2Keyboard \
+ PNPID_DEVICE_PATH_NODE(0x0303)
+
+#define gPnp16550ComPort \
+ PNPID_DEVICE_PATH_NODE(0x0501)
+
+#define gUart \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_UART_DP, \
+ { \
+ (UINT8) (sizeof (UART_DEVICE_PATH)), \
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ 0, \
+ 115200, \
+ 8, \
+ 1, \
+ 1 \
+ }
+
+#define gPcAnsiTerminal \
+ { \
+ { \
+ MESSAGING_DEVICE_PATH, \
+ MSG_VENDOR_DP, \
+ { \
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)), \
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) \
+ } \
+ }, \
+ DEVICE_PATH_MESSAGING_PC_ANSI \
+ }
+
+#define gEndEntire \
+ { \
+ END_DEVICE_PATH_TYPE, \
+ END_ENTIRE_DEVICE_PATH_SUBTYPE, \
+ { \
+ END_DEVICE_PATH_LENGTH, \
+ 0 \
+ } \
+ }
+
+#define PCI_CLASS_SCC 0x07
+#define PCI_SUBCLASS_SERIAL 0x00
+#define PCI_IF_16550 0x02
+#define IS_PCI_16550SERIAL(_p) IS_CLASS3 (_p, PCI_CLASS_SCC, PCI_SUBCLASS_SERIAL, PCI_IF_16550)
+#define IS_PCI_ISA_PDECODE(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
+
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN ConnectType;
+} PLATFORM_CONSOLE_CONNECT_ENTRY;
+
+#define CONSOLE_OUT BIT0
+#define CONSOLE_IN BIT1
+#define STD_ERROR BIT2
+extern PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[];
+extern PLATFORM_CONSOLE_CONNECT_ENTRY gXenPlatformConsole[];
+
+//
+// Platform BDS Functions
+//
+
+VOID
+PlatformInitializeConsole (
+ IN PLATFORM_CONSOLE_CONNECT_ENTRY *PlatformConsole
+ );
+
+#endif // _PLATFORM_SPECIFIC_BDS_PLATFORM_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf
new file mode 100644
index 00000000000..ec0ff682734
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformBootManagerLibGrub.inf
@@ -0,0 +1,71 @@
+## @file
+# Platform BDS customizations library.
+#
+# Copyright (C) 2020 James Bottomley, IBM Corporation.
+# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformBootManagerLibGrub
+ FILE_GUID = 3a8f8431-f0c9-4c95-8a1d-04445c582d4e
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PlatformBootManagerLib|DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources]
+ BdsPlatform.c
+ PlatformData.c
+ BdsPlatform.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SourceLevelDebugPkg/SourceLevelDebugPkg.dec
+ OvmfPkg/OvmfPkg.dec
+ SecurityPkg/SecurityPkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ UefiBootManagerLib
+ BootLogoLib
+ DevicePathLib
+ PciLib
+ UefiLib
+ PlatformBmPrintScLib
+ Tcg2PhysicalPresenceLib
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits ## CONSUMES
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid
+ gEfiDxeSmmReadyToLockProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiLoadedImageProtocolGuid # PROTOCOL SOMETIMES_PRODUCED
+ gEfiFirmwareVolume2ProtocolGuid # PROTOCOL SOMETIMES_CONSUMED
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid
+ gEfiGlobalVariableGuid
+ gRootBridgesConnectedEventGroupGuid
+ gUefiShellFileGuid
+ gGrubFileGuid
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformData.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformData.c
new file mode 100644
index 00000000000..e549a707100
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/PlatformBootManagerLibGrub/PlatformData.c
@@ -0,0 +1,214 @@
+/** @file
+ Defined the platform specific device path which will be used by
+ platform Bbd to perform the platform policy connect.
+
+ Copyright (C) 2020 James Bottomley, IBM Corporation.
+ Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "BdsPlatform.h"
+#include <Guid/QemuRamfb.h>
+#include <Guid/SerialPortLibVendor.h>
+
+//
+// Vendor UART Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH VendorHardware;
+ UART_DEVICE_PATH Uart;
+ VENDOR_DEVICE_PATH TerminalType;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} VENDOR_UART_DEVICE_PATH;
+#pragma pack ()
+
+//
+// USB Keyboard Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+ USB_CLASS_DEVICE_PATH Keyboard;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} USB_KEYBOARD_DEVICE_PATH;
+#pragma pack ()
+
+//
+// QemuRamfb Device Path structure
+//
+#pragma pack (1)
+typedef struct {
+ VENDOR_DEVICE_PATH Vendor;
+ ACPI_ADR_DEVICE_PATH AcpiAdr;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} VENDOR_RAMFB_DEVICE_PATH;
+#pragma pack ()
+
+ACPI_HID_DEVICE_PATH gPnpPs2KeyboardDeviceNode = gPnpPs2Keyboard;
+ACPI_HID_DEVICE_PATH gPnp16550ComPortDeviceNode = gPnp16550ComPort;
+UART_DEVICE_PATH gUartDeviceNode = gUart;
+VENDOR_DEVICE_PATH gTerminalTypeDeviceNode = gPcAnsiTerminal;
+
+//
+// Platform specific keyboard device path
+//
+
+
+//
+// Debug Agent UART Device Path
+//
+VENDOR_UART_DEVICE_PATH gDebugAgentUartDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ EFI_DEBUG_AGENT_GUID,
+ },
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ {
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0, // Reserved
+ 0, // BaudRate - Default
+ 0, // DataBits - Default
+ 0, // Parity - Default
+ 0, // StopBits - Default
+ },
+ gPcAnsiTerminal,
+ gEndEntire
+};
+
+STATIC USB_KEYBOARD_DEVICE_PATH gUsbKeyboardDevicePath = {
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_CLASS_DP,
+ {
+ (UINT8)sizeof (USB_CLASS_DEVICE_PATH),
+ (UINT8)(sizeof (USB_CLASS_DEVICE_PATH) >> 8)
+ }
+ },
+ 0xFFFF, // VendorId: any
+ 0xFFFF, // ProductId: any
+ 3, // DeviceClass: HID
+ 1, // DeviceSubClass: boot
+ 1 // DeviceProtocol: keyboard
+ },
+ gEndEntire
+};
+
+STATIC VENDOR_RAMFB_DEVICE_PATH gQemuRamfbDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ QEMU_RAMFB_GUID,
+ },
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_ADR_DP,
+ {
+ (UINT8) (sizeof (ACPI_ADR_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_ADR_DEVICE_PATH)) >> 8)
+ }
+ },
+ ACPI_DISPLAY_ADR (
+ 1, // DeviceIdScheme
+ 0, // HeadId
+ 0, // NonVgaOutput
+ 1, // BiosCanDetect
+ 0, // VendorInfo
+ ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL, // Type
+ 0, // Port
+ 0 // Index
+ ),
+ },
+ gEndEntire
+};
+
+STATIC VENDOR_UART_DEVICE_PATH gXenConsoleDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ EDKII_SERIAL_PORT_LIB_VENDOR_GUID
+ },
+ {
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ {
+ (UINT8) (sizeof (UART_DEVICE_PATH)),
+ (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8)
+ }
+ },
+ 0,
+ FixedPcdGet64 (PcdUartDefaultBaudRate),
+ FixedPcdGet8 (PcdUartDefaultDataBits),
+ FixedPcdGet8 (PcdUartDefaultParity),
+ FixedPcdGet8 (PcdUartDefaultStopBits),
+ },
+ gPcAnsiTerminal,
+ gEndEntire
+};
+
+//
+// Predefined platform default console device path
+//
+PLATFORM_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = {
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *) &gDebugAgentUartDevicePath,
+ (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *)&gUsbKeyboardDevicePath,
+ CONSOLE_IN
+ },
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *)&gQemuRamfbDevicePath,
+ CONSOLE_OUT
+ },
+ {
+ NULL,
+ 0
+ }
+};
+
+PLATFORM_CONSOLE_CONNECT_ENTRY gXenPlatformConsole[] = {
+ {
+ (EFI_DEVICE_PATH_PROTOCOL *)&gXenConsoleDevicePath,
+ (CONSOLE_OUT | CONSOLE_IN | STD_ERROR)
+ },
+ {
+ NULL,
+ 0
+ }
+};
+
+//
+// Predefined platform connect sequence
+//
+EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL };
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
index 7138cbf5904..b029bbf77d3 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
@@ -11,10 +11,13 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemEncryptSevLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
+#include <Library/SafeIntLib.h>
#include <Library/SmmCpuFeaturesLib.h>
#include <Library/SmmServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Pcd/CpuHotEjectData.h>
#include <PiSmm.h>
#include <Register/Intel/SmramSaveStateMap.h>
#include <Register/QemuSmramSaveStateMap.h>
@@ -171,6 +174,77 @@ SmmCpuFeaturesHookReturnFromSmm (
return OriginalInstructionPointer;
}
+STATIC CPU_HOT_EJECT_DATA *mCpuHotEjectData = NULL;
+
+/**
+ Initialize mCpuHotEjectData if PcdCpuMaxLogicalProcessorNumber > 1.
+
+ Also setup the corresponding PcdCpuHotEjectDataAddress.
+**/
+STATIC
+VOID
+InitCpuHotEjectData (
+ VOID
+ )
+{
+ UINTN Size;
+ UINT32 Idx;
+ UINT32 MaxNumberOfCpus;
+ RETURN_STATUS PcdStatus;
+
+ MaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ if (MaxNumberOfCpus == 1) {
+ return;
+ }
+
+ //
+ // We allocate CPU_HOT_EJECT_DATA and CPU_HOT_EJECT_DATA->QemuSelectorMap[]
+ // in a single allocation, and explicitly align the QemuSelectorMap[] (which
+ // is a UINT64 array) at its natural boundary.
+ // Accordingly, allocate:
+ // sizeof(*mCpuHotEjectData) + (MaxNumberOfCpus * sizeof(UINT64))
+ // and, add sizeof(UINT64) - 1 to use as padding if needed.
+ //
+
+ if (RETURN_ERROR (SafeUintnMult (MaxNumberOfCpus, sizeof (UINT64), &Size)) ||
+ RETURN_ERROR (SafeUintnAdd (Size, sizeof (*mCpuHotEjectData), &Size)) ||
+ RETURN_ERROR (SafeUintnAdd (Size, sizeof (UINT64) - 1, &Size))) {
+ DEBUG ((DEBUG_ERROR, "%a: invalid CPU_HOT_EJECT_DATA\n", __FUNCTION__));
+ goto Fatal;
+ }
+
+ mCpuHotEjectData = AllocatePool (Size);
+ if (mCpuHotEjectData == NULL) {
+ ASSERT (mCpuHotEjectData != NULL);
+ goto Fatal;
+ }
+
+ mCpuHotEjectData->Handler = NULL;
+ mCpuHotEjectData->ArrayLength = MaxNumberOfCpus;
+
+ mCpuHotEjectData->QemuSelectorMap = ALIGN_POINTER (mCpuHotEjectData + 1,
+ sizeof (UINT64));
+ //
+ // We use mCpuHotEjectData->QemuSelectorMap to map
+ // ProcessorNum -> QemuSelector. Initialize to invalid values.
+ //
+ for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {
+ mCpuHotEjectData->QemuSelectorMap[Idx] = CPU_EJECT_QEMU_SELECTOR_INVALID;
+ }
+
+ //
+ // Expose address of CPU Hot eject Data structure
+ //
+ PcdStatus = PcdSet64S (PcdCpuHotEjectDataAddress,
+ (UINTN)(VOID *)mCpuHotEjectData);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ return;
+
+Fatal:
+ CpuDeadLoop ();
+}
+
/**
Hook point in normal execution mode that allows the one CPU that was elected
as monarch during System Management Mode initialization to perform additional
@@ -188,6 +262,9 @@ SmmCpuFeaturesSmmRelocationComplete (
UINTN MapPagesBase;
UINTN MapPagesCount;
+
+ InitCpuHotEjectData ();
+
if (!MemEncryptSevIsEnabled ()) {
return;
}
@@ -375,6 +452,40 @@ SmmCpuFeaturesRendezvousExit (
IN UINTN CpuIndex
)
{
+ //
+ // We only call the Handler if CPU hot-eject is enabled
+ // (PcdCpuMaxLogicalProcessorNumber > 1), and hot-eject is needed
+ // in this SMI exit (otherwise mCpuHotEjectData->Handler is not armed.)
+ //
+
+ if (mCpuHotEjectData != NULL) {
+ CPU_HOT_EJECT_HANDLER Handler;
+
+ //
+ // As the comment above mentions, mCpuHotEjectData->Handler might be
+ // written to on the BSP as part of handling of the CPU-ejection.
+ //
+ // We know that any initial assignment to mCpuHotEjectData->Handler
+ // (on the BSP, in the CpuHotplugMmi() context) is ordered-before the
+ // load below, since it is guaranteed to happen before the
+ // control-dependency of the BSP's SMI exit signal -- by way of a store
+ // to AllCpusInSync (on the BSP, in BspHandler()) and the corresponding
+ // AllCpusInSync loop (on the APs, in SmiRendezvous()) which depends on
+ // that store.
+ //
+ // This guarantees that these pieces of code can never execute
+ // simultaneously. In addition, we ensure that the following load is
+ // ordered-after the AllCpusInSync loop by using a MemoryFence() with
+ // acquire semantics.
+ //
+ MemoryFence();
+
+ Handler = mCpuHotEjectData->Handler;
+
+ if (Handler != NULL) {
+ Handler (CpuIndex);
+ }
+ }
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
index 12ca50fb646..dbfcea8168f 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
@@ -30,9 +30,13 @@
BaseMemoryLib
DebugLib
MemEncryptSevLib
+ MemoryAllocationLib
PcdLib
+ SafeIntLib
SmmServicesTableLib
UefiBootServicesTableLib
[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+ gUefiOvmfPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
index 0ae73e62694..2cb52d3f337 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDevice.c
@@ -58,7 +58,6 @@ VirtioMmioInit (
)
{
UINT32 MagicValue;
- UINT32 VendorId;
UINT32 Version;
//
@@ -84,20 +83,6 @@ VirtioMmioInit (
return EFI_UNSUPPORTED;
}
- //
- // Double-check MMIO-specific values
- //
- VendorId = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_VENDOR_ID);
- if (VendorId != VIRTIO_VENDOR_ID) {
- //
- // The ARM Base and Foundation Models do not report a valid VirtIo VendorId.
- // They return a value of 0x0 for the VendorId.
- //
- DEBUG((DEBUG_WARN, "VirtioMmioInit: Warning: The VendorId (0x%X) does not "
- "match the VirtIo VendorId (0x%X).\n",
- VendorId, VIRTIO_VENDOR_ID));
- }
-
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
new file mode 100644
index 00000000000..5fce7ef41ad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/PeiDxeVmgExitVcHandler.c
@@ -0,0 +1,103 @@
+/** @file
+ X64 #VC Exception Handler functon.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Msr.h>
+
+#include "VmgExitVcHandler.h"
+
+/**
+ Handle a #VC exception.
+
+ Performs the necessary processing to handle a #VC exception.
+
+ @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
+ as value to use on error.
+ @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS Exception handled
+ @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
+ propagate provided
+ @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
+ propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+VmgExitHandleVc (
+ IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ GHCB *Ghcb;
+ GHCB *GhcbBackup;
+ EFI_STATUS VcRet;
+ BOOLEAN InterruptState;
+ SEV_ES_PER_CPU_DATA *SevEsData;
+
+ InterruptState = GetInterruptState ();
+ if (InterruptState) {
+ DisableInterrupts ();
+ }
+
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+ ASSERT (Msr.GhcbInfo.Function == 0);
+ ASSERT (Msr.Ghcb != 0);
+
+ Ghcb = Msr.Ghcb;
+ GhcbBackup = NULL;
+
+ SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);
+ SevEsData->VcCount++;
+
+ //
+ // Check for maximum PEI/DXE #VC nesting.
+ //
+ if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
+ VmgExitIssueAssert (SevEsData);
+ } else if (SevEsData->VcCount > 1) {
+ //
+ // Nested #VC
+ //
+ if (SevEsData->GhcbBackupPages == NULL) {
+ VmgExitIssueAssert (SevEsData);
+ }
+
+ //
+ // Save the active GHCB to a backup page.
+ // To access the correct backup page, increment the backup page pointer
+ // based on the current VcCount.
+ //
+ GhcbBackup = (GHCB *) SevEsData->GhcbBackupPages;
+ GhcbBackup += (SevEsData->VcCount - 2);
+
+ CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
+ }
+
+ VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
+
+ if (GhcbBackup != NULL) {
+ //
+ // Restore the active GHCB from the backup page.
+ //
+ CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
+ }
+
+ SevEsData->VcCount--;
+
+ if (InterruptState) {
+ EnableInterrupts ();
+ }
+
+ return VcRet;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
new file mode 100644
index 00000000000..05d556b09bb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
@@ -0,0 +1,45 @@
+## @file
+# VMGEXIT Support Library.
+#
+# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecVmgExitLib
+ FILE_GUID = dafff819-f86c-4cff-a70e-83161e5bcf9a
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VmgExitLib|SEC
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources.common]
+ VmgExitLib.c
+ VmgExitVcHandler.c
+ VmgExitVcHandler.h
+ SecVmgExitVcHandler.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ LocalApicLib
+ MemEncryptSevLib
+ PcdLib
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
new file mode 100644
index 00000000000..f6023146230
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/SecVmgExitVcHandler.c
@@ -0,0 +1,109 @@
+/** @file
+ X64 #VC Exception Handler functon.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Msr.h>
+
+#include "VmgExitVcHandler.h"
+
+/**
+ Handle a #VC exception.
+
+ Performs the necessary processing to handle a #VC exception.
+
+ @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
+ as value to use on error.
+ @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS Exception handled
+ @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
+ propagate provided
+ @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
+ propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+VmgExitHandleVc (
+ IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ GHCB *Ghcb;
+ GHCB *GhcbBackup;
+ EFI_STATUS VcRet;
+ BOOLEAN InterruptState;
+ SEV_ES_PER_CPU_DATA *SevEsData;
+
+ InterruptState = GetInterruptState ();
+ if (InterruptState) {
+ DisableInterrupts ();
+ }
+
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+ ASSERT (Msr.GhcbInfo.Function == 0);
+ ASSERT (Msr.Ghcb != 0);
+
+ Ghcb = Msr.Ghcb;
+ GhcbBackup = NULL;
+
+ SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);
+ SevEsData->VcCount++;
+
+ //
+ // Check for maximum SEC #VC nesting.
+ //
+ if (SevEsData->VcCount > VMGEXIT_MAXIMUM_VC_COUNT) {
+ VmgExitIssueAssert (SevEsData);
+ } else if (SevEsData->VcCount > 1) {
+ UINTN GhcbBackupSize;
+
+ //
+ // Be sure that the proper amount of pages are allocated
+ //
+ GhcbBackupSize = (VMGEXIT_MAXIMUM_VC_COUNT - 1) * sizeof (*Ghcb);
+ if (GhcbBackupSize > FixedPcdGet32 (PcdOvmfSecGhcbBackupSize)) {
+ //
+ // Not enough SEC backup pages allocated.
+ //
+ VmgExitIssueAssert (SevEsData);
+ }
+
+ //
+ // Save the active GHCB to a backup page.
+ // To access the correct backup page, increment the backup page pointer
+ // based on the current VcCount.
+ //
+ GhcbBackup = (GHCB *) FixedPcdGet32 (PcdOvmfSecGhcbBackupBase);
+ GhcbBackup += (SevEsData->VcCount - 2);
+
+ CopyMem (GhcbBackup, Ghcb, sizeof (*Ghcb));
+ }
+
+ VcRet = InternalVmgExitHandleVc (Ghcb, ExceptionType, SystemContext);
+
+ if (GhcbBackup != NULL) {
+ //
+ // Restore the active GHCB from the backup page.
+ //
+ CopyMem (Ghcb, GhcbBackup, sizeof (*Ghcb));
+ }
+
+ SevEsData->VcCount--;
+
+ if (InterruptState) {
+ EnableInterrupts ();
+ }
+
+ return VcRet;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
new file mode 100644
index 00000000000..17a379e247c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.c
@@ -0,0 +1,235 @@
+/** @file
+ VMGEXIT Support Library.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Msr.h>
+
+/**
+ Check for VMGEXIT error
+
+ Check if the hypervisor has returned an error after completion of the VMGEXIT
+ by examining the SwExitInfo1 field of the GHCB.
+
+ @param[in] Ghcb A pointer to the GHCB
+
+ @retval 0 VMGEXIT succeeded.
+ @return Exception number to be propagated, VMGEXIT processing
+ did not succeed.
+
+**/
+STATIC
+UINT64
+VmgExitErrorCheck (
+ IN GHCB *Ghcb
+ )
+{
+ GHCB_EVENT_INJECTION Event;
+ GHCB_EXIT_INFO ExitInfo;
+ UINT64 Status;
+
+ ExitInfo.Uint64 = Ghcb->SaveArea.SwExitInfo1;
+ ASSERT ((ExitInfo.Elements.Lower32Bits == 0) ||
+ (ExitInfo.Elements.Lower32Bits == 1));
+
+ Status = 0;
+ if (ExitInfo.Elements.Lower32Bits == 0) {
+ return Status;
+ }
+
+ if (ExitInfo.Elements.Lower32Bits == 1) {
+ ASSERT (Ghcb->SaveArea.SwExitInfo2 != 0);
+
+ //
+ // Check that the return event is valid
+ //
+ Event.Uint64 = Ghcb->SaveArea.SwExitInfo2;
+ if (Event.Elements.Valid &&
+ Event.Elements.Type == GHCB_EVENT_INJECTION_TYPE_EXCEPTION) {
+ switch (Event.Elements.Vector) {
+ case GP_EXCEPTION:
+ case UD_EXCEPTION:
+ //
+ // Use returned event as return code
+ //
+ Status = Event.Uint64;
+ }
+ }
+ }
+
+ if (Status == 0) {
+ GHCB_EVENT_INJECTION GpEvent;
+
+ GpEvent.Uint64 = 0;
+ GpEvent.Elements.Vector = GP_EXCEPTION;
+ GpEvent.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+ GpEvent.Elements.Valid = 1;
+
+ Status = GpEvent.Uint64;
+ }
+
+ return Status;
+}
+
+/**
+ Perform VMGEXIT.
+
+ Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
+ then handles the return actions.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] ExitCode VMGEXIT code to be assigned to the SwExitCode
+ field of the GHCB.
+ @param[in] ExitInfo1 VMGEXIT information to be assigned to the
+ SwExitInfo1 field of the GHCB.
+ @param[in] ExitInfo2 VMGEXIT information to be assigned to the
+ SwExitInfo2 field of the GHCB.
+
+ @retval 0 VMGEXIT succeeded.
+ @return Exception number to be propagated, VMGEXIT
+ processing did not succeed.
+
+**/
+UINT64
+EFIAPI
+VmgExit (
+ IN OUT GHCB *Ghcb,
+ IN UINT64 ExitCode,
+ IN UINT64 ExitInfo1,
+ IN UINT64 ExitInfo2
+ )
+{
+ Ghcb->SaveArea.SwExitCode = ExitCode;
+ Ghcb->SaveArea.SwExitInfo1 = ExitInfo1;
+ Ghcb->SaveArea.SwExitInfo2 = ExitInfo2;
+
+ VmgSetOffsetValid (Ghcb, GhcbSwExitCode);
+ VmgSetOffsetValid (Ghcb, GhcbSwExitInfo1);
+ VmgSetOffsetValid (Ghcb, GhcbSwExitInfo2);
+
+ //
+ // Guest memory is used for the guest-hypervisor communication, so fence
+ // the invocation of the VMGEXIT instruction to ensure GHCB accesses are
+ // synchronized properly.
+ //
+ MemoryFence ();
+ AsmVmgExit ();
+ MemoryFence ();
+
+ return VmgExitErrorCheck (Ghcb);
+}
+
+/**
+ Perform pre-VMGEXIT initialization/preparation.
+
+ Performs the necessary steps in preparation for invoking VMGEXIT. Must be
+ called before setting any fields within the GHCB.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in, out] InterruptState A pointer to hold the current interrupt
+ state, used for restoring in VmgDone ()
+
+**/
+VOID
+EFIAPI
+VmgInit (
+ IN OUT GHCB *Ghcb,
+ IN OUT BOOLEAN *InterruptState
+ )
+{
+ //
+ // Be sure that an interrupt can't cause a #VC while the GHCB is
+ // being used.
+ //
+ *InterruptState = GetInterruptState ();
+ if (*InterruptState) {
+ DisableInterrupts ();
+ }
+
+ SetMem (&Ghcb->SaveArea, sizeof (Ghcb->SaveArea), 0);
+}
+
+/**
+ Perform post-VMGEXIT cleanup.
+
+ Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
+ called after obtaining needed fields within the GHCB.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] InterruptState An indicator to conditionally (re)enable
+ interrupts
+
+**/
+VOID
+EFIAPI
+VmgDone (
+ IN OUT GHCB *Ghcb,
+ IN BOOLEAN InterruptState
+ )
+{
+ if (InterruptState) {
+ EnableInterrupts ();
+ }
+}
+
+/**
+ Marks a field at the specified offset as valid in the GHCB.
+
+ The ValidBitmap area represents the areas of the GHCB that have been marked
+ valid. Set the bit in ValidBitmap for the input offset.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication Block
+ @param[in] Offset Qword offset in the GHCB to mark valid
+
+**/
+VOID
+EFIAPI
+VmgSetOffsetValid (
+ IN OUT GHCB *Ghcb,
+ IN GHCB_REGISTER Offset
+ )
+{
+ UINT32 OffsetIndex;
+ UINT32 OffsetBit;
+
+ OffsetIndex = Offset / 8;
+ OffsetBit = Offset % 8;
+
+ Ghcb->SaveArea.ValidBitmap[OffsetIndex] |= (1 << OffsetBit);
+}
+
+/**
+ Checks if a specified offset is valid in the GHCB.
+
+ The ValidBitmap area represents the areas of the GHCB that have been marked
+ valid. Return whether the bit in the ValidBitmap is set for the input offset.
+
+ @param[in] Ghcb A pointer to the GHCB
+ @param[in] Offset Qword offset in the GHCB to mark valid
+
+ @retval TRUE Offset is marked valid in the GHCB
+ @retval FALSE Offset is not marked valid in the GHCB
+
+**/
+BOOLEAN
+EFIAPI
+VmgIsOffsetValid (
+ IN GHCB *Ghcb,
+ IN GHCB_REGISTER Offset
+ )
+{
+ UINT32 OffsetIndex;
+ UINT32 OffsetBit;
+
+ OffsetIndex = Offset / 8;
+ OffsetBit = Offset % 8;
+
+ return ((Ghcb->SaveArea.ValidBitmap[OffsetIndex] & (1 << OffsetBit)) != 0);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
new file mode 100644
index 00000000000..e5a56c20014
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
@@ -0,0 +1,40 @@
+## @file
+# VMGEXIT Support Library.
+#
+# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VmgExitLib
+ FILE_GUID = 0e923c25-13cd-430b-8714-ffe85652a97b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VmgExitLib|PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources.common]
+ VmgExitLib.c
+ VmgExitVcHandler.c
+ VmgExitVcHandler.h
+ PeiDxeVmgExitVcHandler.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ LocalApicLib
+ MemEncryptSevLib
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
new file mode 100644
index 00000000000..7b09ef0c88a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
@@ -0,0 +1,1877 @@
+/** @file
+ X64 #VC Exception Handler functon.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Msr.h>
+#include <Register/Intel/Cpuid.h>
+#include <IndustryStandard/InstructionParsing.h>
+
+#include "VmgExitVcHandler.h"
+
+//
+// Instruction execution mode definition
+//
+typedef enum {
+ LongMode64Bit = 0,
+ LongModeCompat32Bit,
+ LongModeCompat16Bit,
+} SEV_ES_INSTRUCTION_MODE;
+
+//
+// Instruction size definition (for operand and address)
+//
+typedef enum {
+ Size8Bits = 0,
+ Size16Bits,
+ Size32Bits,
+ Size64Bits,
+} SEV_ES_INSTRUCTION_SIZE;
+
+//
+// Intruction segment definition
+//
+typedef enum {
+ SegmentEs = 0,
+ SegmentCs,
+ SegmentSs,
+ SegmentDs,
+ SegmentFs,
+ SegmentGs,
+} SEV_ES_INSTRUCTION_SEGMENT;
+
+//
+// Instruction rep function definition
+//
+typedef enum {
+ RepNone = 0,
+ RepZ,
+ RepNZ,
+} SEV_ES_INSTRUCTION_REP;
+
+typedef struct {
+ UINT8 Rm;
+ UINT8 Reg;
+ UINT8 Mod;
+} SEV_ES_INSTRUCTION_MODRM_EXT;
+
+typedef struct {
+ UINT8 Base;
+ UINT8 Index;
+ UINT8 Scale;
+} SEV_ES_INSTRUCTION_SIB_EXT;
+
+//
+// Instruction opcode definition
+//
+typedef struct {
+ SEV_ES_INSTRUCTION_MODRM_EXT ModRm;
+
+ SEV_ES_INSTRUCTION_SIB_EXT Sib;
+
+ UINTN RegData;
+ UINTN RmData;
+} SEV_ES_INSTRUCTION_OPCODE_EXT;
+
+//
+// Instruction parsing context definition
+//
+typedef struct {
+ GHCB *Ghcb;
+
+ SEV_ES_INSTRUCTION_MODE Mode;
+ SEV_ES_INSTRUCTION_SIZE DataSize;
+ SEV_ES_INSTRUCTION_SIZE AddrSize;
+ BOOLEAN SegmentSpecified;
+ SEV_ES_INSTRUCTION_SEGMENT Segment;
+ SEV_ES_INSTRUCTION_REP RepMode;
+
+ UINT8 *Begin;
+ UINT8 *End;
+
+ UINT8 *Prefixes;
+ UINT8 *OpCodes;
+ UINT8 *Displacement;
+ UINT8 *Immediate;
+
+ INSTRUCTION_REX_PREFIX RexPrefix;
+
+ BOOLEAN ModRmPresent;
+ INSTRUCTION_MODRM ModRm;
+
+ BOOLEAN SibPresent;
+ INSTRUCTION_SIB Sib;
+
+ UINTN PrefixSize;
+ UINTN OpCodeSize;
+ UINTN DisplacementSize;
+ UINTN ImmediateSize;
+
+ SEV_ES_INSTRUCTION_OPCODE_EXT Ext;
+} SEV_ES_INSTRUCTION_DATA;
+
+//
+// Non-automatic Exit function prototype
+//
+typedef
+UINT64
+(*NAE_EXIT) (
+ GHCB *Ghcb,
+ EFI_SYSTEM_CONTEXT_X64 *Regs,
+ SEV_ES_INSTRUCTION_DATA *InstructionData
+ );
+
+/**
+ Return a pointer to the contents of the specified register.
+
+ Based upon the input register, return a pointer to the registers contents
+ in the x86 processor context.
+
+ @param[in] Regs x64 processor context
+ @param[in] Register Register to obtain pointer for
+
+ @return Pointer to the contents of the requested register
+
+**/
+STATIC
+UINT64 *
+GetRegisterPointer (
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN UINT8 Register
+ )
+{
+ UINT64 *Reg;
+
+ switch (Register) {
+ case 0:
+ Reg = &Regs->Rax;
+ break;
+ case 1:
+ Reg = &Regs->Rcx;
+ break;
+ case 2:
+ Reg = &Regs->Rdx;
+ break;
+ case 3:
+ Reg = &Regs->Rbx;
+ break;
+ case 4:
+ Reg = &Regs->Rsp;
+ break;
+ case 5:
+ Reg = &Regs->Rbp;
+ break;
+ case 6:
+ Reg = &Regs->Rsi;
+ break;
+ case 7:
+ Reg = &Regs->Rdi;
+ break;
+ case 8:
+ Reg = &Regs->R8;
+ break;
+ case 9:
+ Reg = &Regs->R9;
+ break;
+ case 10:
+ Reg = &Regs->R10;
+ break;
+ case 11:
+ Reg = &Regs->R11;
+ break;
+ case 12:
+ Reg = &Regs->R12;
+ break;
+ case 13:
+ Reg = &Regs->R13;
+ break;
+ case 14:
+ Reg = &Regs->R14;
+ break;
+ case 15:
+ Reg = &Regs->R15;
+ break;
+ default:
+ Reg = NULL;
+ }
+ ASSERT (Reg != NULL);
+
+ return Reg;
+}
+
+/**
+ Update the instruction parsing context for displacement bytes.
+
+ @param[in, out] InstructionData Instruction parsing context
+ @param[in] Size The instruction displacement size
+
+**/
+STATIC
+VOID
+UpdateForDisplacement (
+ IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData,
+ IN UINTN Size
+ )
+{
+ InstructionData->DisplacementSize = Size;
+ InstructionData->Immediate += Size;
+ InstructionData->End += Size;
+}
+
+/**
+ Determine if an instruction address if RIP relative.
+
+ Examine the instruction parsing context to determine if the address offset
+ is relative to the instruction pointer.
+
+ @param[in] InstructionData Instruction parsing context
+
+ @retval TRUE Instruction addressing is RIP relative
+ @retval FALSE Instruction addressing is not RIP relative
+
+**/
+STATIC
+BOOLEAN
+IsRipRelative (
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;
+
+ Ext = &InstructionData->Ext;
+
+ return ((InstructionData->Mode == LongMode64Bit) &&
+ (Ext->ModRm.Mod == 0) &&
+ (Ext->ModRm.Rm == 5) &&
+ (InstructionData->SibPresent == FALSE));
+}
+
+/**
+ Return the effective address of a memory operand.
+
+ Examine the instruction parsing context to obtain the effective memory
+ address of a memory operand.
+
+ @param[in] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @return The memory operand effective address
+
+**/
+STATIC
+UINT64
+GetEffectiveMemoryAddress (
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;
+ UINT64 EffectiveAddress;
+
+ Ext = &InstructionData->Ext;
+ EffectiveAddress = 0;
+
+ if (IsRipRelative (InstructionData)) {
+ //
+ // RIP-relative displacement is a 32-bit signed value
+ //
+ INT32 RipRelative;
+
+ RipRelative = *(INT32 *) InstructionData->Displacement;
+
+ UpdateForDisplacement (InstructionData, 4);
+
+ //
+ // Negative displacement is handled by standard UINT64 wrap-around.
+ //
+ return Regs->Rip + (UINT64) RipRelative;
+ }
+
+ switch (Ext->ModRm.Mod) {
+ case 1:
+ UpdateForDisplacement (InstructionData, 1);
+ EffectiveAddress += (UINT64) (*(INT8 *) (InstructionData->Displacement));
+ break;
+ case 2:
+ switch (InstructionData->AddrSize) {
+ case Size16Bits:
+ UpdateForDisplacement (InstructionData, 2);
+ EffectiveAddress += (UINT64) (*(INT16 *) (InstructionData->Displacement));
+ break;
+ default:
+ UpdateForDisplacement (InstructionData, 4);
+ EffectiveAddress += (UINT64) (*(INT32 *) (InstructionData->Displacement));
+ break;
+ }
+ break;
+ }
+
+ if (InstructionData->SibPresent) {
+ INT64 Displacement;
+
+ if (Ext->Sib.Index != 4) {
+ CopyMem (
+ &Displacement,
+ GetRegisterPointer (Regs, Ext->Sib.Index),
+ sizeof (Displacement)
+ );
+ Displacement *= (INT64)(1 << Ext->Sib.Scale);
+
+ //
+ // Negative displacement is handled by standard UINT64 wrap-around.
+ //
+ EffectiveAddress += (UINT64) Displacement;
+ }
+
+ if ((Ext->Sib.Base != 5) || Ext->ModRm.Mod) {
+ EffectiveAddress += *GetRegisterPointer (Regs, Ext->Sib.Base);
+ } else {
+ UpdateForDisplacement (InstructionData, 4);
+ EffectiveAddress += (UINT64) (*(INT32 *) (InstructionData->Displacement));
+ }
+ } else {
+ EffectiveAddress += *GetRegisterPointer (Regs, Ext->ModRm.Rm);
+ }
+
+ return EffectiveAddress;
+}
+
+/**
+ Decode a ModRM byte.
+
+ Examine the instruction parsing context to decode a ModRM byte and the SIB
+ byte, if present.
+
+ @param[in] Regs x64 processor context
+ @param[in, out] InstructionData Instruction parsing context
+
+**/
+STATIC
+VOID
+DecodeModRm (
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;
+ INSTRUCTION_REX_PREFIX *RexPrefix;
+ INSTRUCTION_MODRM *ModRm;
+ INSTRUCTION_SIB *Sib;
+
+ RexPrefix = &InstructionData->RexPrefix;
+ Ext = &InstructionData->Ext;
+ ModRm = &InstructionData->ModRm;
+ Sib = &InstructionData->Sib;
+
+ InstructionData->ModRmPresent = TRUE;
+ ModRm->Uint8 = *(InstructionData->End);
+
+ InstructionData->Displacement++;
+ InstructionData->Immediate++;
+ InstructionData->End++;
+
+ Ext->ModRm.Mod = ModRm->Bits.Mod;
+ Ext->ModRm.Reg = (RexPrefix->Bits.BitR << 3) | ModRm->Bits.Reg;
+ Ext->ModRm.Rm = (RexPrefix->Bits.BitB << 3) | ModRm->Bits.Rm;
+
+ Ext->RegData = *GetRegisterPointer (Regs, Ext->ModRm.Reg);
+
+ if (Ext->ModRm.Mod == 3) {
+ Ext->RmData = *GetRegisterPointer (Regs, Ext->ModRm.Rm);
+ } else {
+ if (ModRm->Bits.Rm == 4) {
+ InstructionData->SibPresent = TRUE;
+ Sib->Uint8 = *(InstructionData->End);
+
+ InstructionData->Displacement++;
+ InstructionData->Immediate++;
+ InstructionData->End++;
+
+ Ext->Sib.Scale = Sib->Bits.Scale;
+ Ext->Sib.Index = (RexPrefix->Bits.BitX << 3) | Sib->Bits.Index;
+ Ext->Sib.Base = (RexPrefix->Bits.BitB << 3) | Sib->Bits.Base;
+ }
+
+ Ext->RmData = GetEffectiveMemoryAddress (Regs, InstructionData);
+ }
+}
+
+/**
+ Decode instruction prefixes.
+
+ Parse the instruction data to track the instruction prefixes that have
+ been used.
+
+ @param[in] Regs x64 processor context
+ @param[in, out] InstructionData Instruction parsing context
+
+**/
+STATIC
+VOID
+DecodePrefixes (
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ SEV_ES_INSTRUCTION_MODE Mode;
+ SEV_ES_INSTRUCTION_SIZE ModeDataSize;
+ SEV_ES_INSTRUCTION_SIZE ModeAddrSize;
+ UINT8 *Byte;
+
+ //
+ // Always in 64-bit mode
+ //
+ Mode = LongMode64Bit;
+ ModeDataSize = Size32Bits;
+ ModeAddrSize = Size64Bits;
+
+ InstructionData->Mode = Mode;
+ InstructionData->DataSize = ModeDataSize;
+ InstructionData->AddrSize = ModeAddrSize;
+
+ InstructionData->Prefixes = InstructionData->Begin;
+
+ Byte = InstructionData->Prefixes;
+ for ( ; ; Byte++, InstructionData->PrefixSize++) {
+ //
+ // Check the 0x40 to 0x4F range using an if statement here since some
+ // compilers don't like the "case 0x40 ... 0x4F:" syntax. This avoids
+ // 16 case statements below.
+ //
+ if ((*Byte >= REX_PREFIX_START) && (*Byte <= REX_PREFIX_STOP)) {
+ InstructionData->RexPrefix.Uint8 = *Byte;
+ if ((*Byte & REX_64BIT_OPERAND_SIZE_MASK) != 0) {
+ InstructionData->DataSize = Size64Bits;
+ }
+ continue;
+ }
+
+ switch (*Byte) {
+ case OVERRIDE_SEGMENT_CS:
+ case OVERRIDE_SEGMENT_DS:
+ case OVERRIDE_SEGMENT_ES:
+ case OVERRIDE_SEGMENT_SS:
+ if (Mode != LongMode64Bit) {
+ InstructionData->SegmentSpecified = TRUE;
+ InstructionData->Segment = (*Byte >> 3) & 3;
+ }
+ break;
+
+ case OVERRIDE_SEGMENT_FS:
+ case OVERRIDE_SEGMENT_GS:
+ InstructionData->SegmentSpecified = TRUE;
+ InstructionData->Segment = *Byte & 7;
+ break;
+
+ case OVERRIDE_OPERAND_SIZE:
+ if (InstructionData->RexPrefix.Uint8 == 0) {
+ InstructionData->DataSize =
+ (Mode == LongMode64Bit) ? Size16Bits :
+ (Mode == LongModeCompat32Bit) ? Size16Bits :
+ (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
+ }
+ break;
+
+ case OVERRIDE_ADDRESS_SIZE:
+ InstructionData->AddrSize =
+ (Mode == LongMode64Bit) ? Size32Bits :
+ (Mode == LongModeCompat32Bit) ? Size16Bits :
+ (Mode == LongModeCompat16Bit) ? Size32Bits : 0;
+ break;
+
+ case LOCK_PREFIX:
+ break;
+
+ case REPZ_PREFIX:
+ InstructionData->RepMode = RepZ;
+ break;
+
+ case REPNZ_PREFIX:
+ InstructionData->RepMode = RepNZ;
+ break;
+
+ default:
+ InstructionData->OpCodes = Byte;
+ InstructionData->OpCodeSize = (*Byte == TWO_BYTE_OPCODE_ESCAPE) ? 2 : 1;
+
+ InstructionData->End = Byte + InstructionData->OpCodeSize;
+ InstructionData->Displacement = InstructionData->End;
+ InstructionData->Immediate = InstructionData->End;
+ return;
+ }
+ }
+}
+
+/**
+ Determine instruction length
+
+ Return the total length of the parsed instruction.
+
+ @param[in] InstructionData Instruction parsing context
+
+ @return Length of parsed instruction
+
+**/
+STATIC
+UINT64
+InstructionLength (
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ return (UINT64) (InstructionData->End - InstructionData->Begin);
+}
+
+/**
+ Initialize the instruction parsing context.
+
+ Initialize the instruction parsing context, which includes decoding the
+ instruction prefixes.
+
+ @param[in, out] InstructionData Instruction parsing context
+ @param[in] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in] Regs x64 processor context
+
+**/
+STATIC
+VOID
+InitInstructionData (
+ IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData,
+ IN GHCB *Ghcb,
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs
+ )
+{
+ SetMem (InstructionData, sizeof (*InstructionData), 0);
+ InstructionData->Ghcb = Ghcb;
+ InstructionData->Begin = (UINT8 *) Regs->Rip;
+ InstructionData->End = (UINT8 *) Regs->Rip;
+
+ DecodePrefixes (Regs, InstructionData);
+}
+
+/**
+ Report an unsupported event to the hypervisor
+
+ Use the VMGEXIT support to report an unsupported event to the hypervisor.
+
+ @param[in] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+UnsupportedExit (
+ IN GHCB *Ghcb,
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 Status;
+
+ Status = VmgExit (Ghcb, SVM_EXIT_UNSUPPORTED, Regs->ExceptionData, 0);
+ if (Status == 0) {
+ GHCB_EVENT_INJECTION Event;
+
+ Event.Uint64 = 0;
+ Event.Elements.Vector = GP_EXCEPTION;
+ Event.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+ Event.Elements.Valid = 1;
+
+ Status = Event.Uint64;
+ }
+
+ return Status;
+}
+
+/**
+ Validate that the MMIO memory access is not to encrypted memory.
+
+ Examine the pagetable entry for the memory specified. MMIO should not be
+ performed against encrypted memory. MMIO to the APIC page is always allowed.
+
+ @param[in] Ghcb Pointer to the Guest-Hypervisor Communication Block
+ @param[in] MemoryAddress Memory address to validate
+ @param[in] MemoryLength Memory length to validate
+
+ @retval 0 Memory is not encrypted
+ @return New exception value to propogate
+
+**/
+STATIC
+UINT64
+ValidateMmioMemory (
+ IN GHCB *Ghcb,
+ IN UINTN MemoryAddress,
+ IN UINTN MemoryLength
+ )
+{
+ MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;
+ GHCB_EVENT_INJECTION GpEvent;
+ UINTN Address;
+
+ //
+ // Allow APIC accesses (which will have the encryption bit set during
+ // SEC and PEI phases).
+ //
+ Address = MemoryAddress & ~(SIZE_4KB - 1);
+ if (Address == GetLocalApicBaseAddress ()) {
+ return 0;
+ }
+
+ State = MemEncryptSevGetAddressRangeState (
+ 0,
+ MemoryAddress,
+ MemoryLength
+ );
+ if (State == MemEncryptSevAddressRangeUnencrypted) {
+ return 0;
+ }
+
+ //
+ // Any state other than unencrypted is an error, issue a #GP.
+ //
+ DEBUG ((DEBUG_ERROR,
+ "MMIO using encrypted memory: %lx\n",
+ (UINT64) MemoryAddress));
+ GpEvent.Uint64 = 0;
+ GpEvent.Elements.Vector = GP_EXCEPTION;
+ GpEvent.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+ GpEvent.Elements.Valid = 1;
+
+ return GpEvent.Uint64;
+}
+
+/**
+ Handle an MMIO event.
+
+ Use the VMGEXIT instruction to handle either an MMIO read or an MMIO write.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in, out] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+MmioExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 ExitInfo1, ExitInfo2, Status;
+ UINTN Bytes;
+ UINT64 *Register;
+ UINT8 OpCode, SignByte;
+ UINTN Address;
+
+ Bytes = 0;
+
+ OpCode = *(InstructionData->OpCodes);
+ if (OpCode == TWO_BYTE_OPCODE_ESCAPE) {
+ OpCode = *(InstructionData->OpCodes + 1);
+ }
+
+ switch (OpCode) {
+ //
+ // MMIO write (MOV reg/memX, regX)
+ //
+ case 0x88:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0x89:
+ DecodeModRm (Regs, InstructionData);
+ Bytes = ((Bytes != 0) ? Bytes :
+ (InstructionData->DataSize == Size16Bits) ? 2 :
+ (InstructionData->DataSize == Size32Bits) ? 4 :
+ (InstructionData->DataSize == Size64Bits) ? 8 :
+ 0);
+
+ if (InstructionData->Ext.ModRm.Mod == 3) {
+ //
+ // NPF on two register operands???
+ //
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = InstructionData->Ext.RmData;
+ ExitInfo2 = Bytes;
+ CopyMem (Ghcb->SharedBuffer, &InstructionData->Ext.RegData, Bytes);
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+ break;
+
+ //
+ // MMIO write (MOV moffsetX, aX)
+ //
+ case 0xA2:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0xA3:
+ Bytes = ((Bytes != 0) ? Bytes :
+ (InstructionData->DataSize == Size16Bits) ? 2 :
+ (InstructionData->DataSize == Size32Bits) ? 4 :
+ (InstructionData->DataSize == Size64Bits) ? 8 :
+ 0);
+
+ InstructionData->ImmediateSize = (UINTN) (1 << InstructionData->AddrSize);
+ InstructionData->End += InstructionData->ImmediateSize;
+
+ //
+ // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
+ // Use a STATIC_ASSERT to be certain the code is being built as X64.
+ //
+ STATIC_ASSERT (
+ sizeof (UINTN) == sizeof (UINT64),
+ "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
+ );
+
+ Address = 0;
+ CopyMem (
+ &Address,
+ InstructionData->Immediate,
+ InstructionData->ImmediateSize
+ );
+
+ Status = ValidateMmioMemory (Ghcb, Address, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = Address;
+ ExitInfo2 = Bytes;
+ CopyMem (Ghcb->SharedBuffer, &Regs->Rax, Bytes);
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+ break;
+
+ //
+ // MMIO write (MOV reg/memX, immX)
+ //
+ case 0xC6:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0xC7:
+ DecodeModRm (Regs, InstructionData);
+ Bytes = ((Bytes != 0) ? Bytes :
+ (InstructionData->DataSize == Size16Bits) ? 2 :
+ (InstructionData->DataSize == Size32Bits) ? 4 :
+ 0);
+
+ InstructionData->ImmediateSize = Bytes;
+ InstructionData->End += Bytes;
+
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = InstructionData->Ext.RmData;
+ ExitInfo2 = Bytes;
+ CopyMem (Ghcb->SharedBuffer, InstructionData->Immediate, Bytes);
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+ break;
+
+ //
+ // MMIO read (MOV regX, reg/memX)
+ //
+ case 0x8A:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0x8B:
+ DecodeModRm (Regs, InstructionData);
+ Bytes = ((Bytes != 0) ? Bytes :
+ (InstructionData->DataSize == Size16Bits) ? 2 :
+ (InstructionData->DataSize == Size32Bits) ? 4 :
+ (InstructionData->DataSize == Size64Bits) ? 8 :
+ 0);
+ if (InstructionData->Ext.ModRm.Mod == 3) {
+ //
+ // NPF on two register operands???
+ //
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = InstructionData->Ext.RmData;
+ ExitInfo2 = Bytes;
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+
+ Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
+ if (Bytes == 4) {
+ //
+ // Zero-extend for 32-bit operation
+ //
+ *Register = 0;
+ }
+ CopyMem (Register, Ghcb->SharedBuffer, Bytes);
+ break;
+
+ //
+ // MMIO read (MOV aX, moffsetX)
+ //
+ case 0xA0:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0xA1:
+ Bytes = ((Bytes != 0) ? Bytes :
+ (InstructionData->DataSize == Size16Bits) ? 2 :
+ (InstructionData->DataSize == Size32Bits) ? 4 :
+ (InstructionData->DataSize == Size64Bits) ? 8 :
+ 0);
+
+ InstructionData->ImmediateSize = (UINTN) (1 << InstructionData->AddrSize);
+ InstructionData->End += InstructionData->ImmediateSize;
+
+ //
+ // This code is X64 only, so a possible 8-byte copy to a UINTN is ok.
+ // Use a STATIC_ASSERT to be certain the code is being built as X64.
+ //
+ STATIC_ASSERT (
+ sizeof (UINTN) == sizeof (UINT64),
+ "sizeof (UINTN) != sizeof (UINT64), this file must be built as X64"
+ );
+
+ Address = 0;
+ CopyMem (
+ &Address,
+ InstructionData->Immediate,
+ InstructionData->ImmediateSize
+ );
+
+ Status = ValidateMmioMemory (Ghcb, Address, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = Address;
+ ExitInfo2 = Bytes;
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (Bytes == 4) {
+ //
+ // Zero-extend for 32-bit operation
+ //
+ Regs->Rax = 0;
+ }
+ CopyMem (&Regs->Rax, Ghcb->SharedBuffer, Bytes);
+ break;
+
+ //
+ // MMIO read w/ zero-extension ((MOVZX regX, reg/memX)
+ //
+ case 0xB6:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0xB7:
+ DecodeModRm (Regs, InstructionData);
+ Bytes = (Bytes != 0) ? Bytes : 2;
+
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = InstructionData->Ext.RmData;
+ ExitInfo2 = Bytes;
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+
+ Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
+ SetMem (Register, (UINTN) (1 << InstructionData->DataSize), 0);
+ CopyMem (Register, Ghcb->SharedBuffer, Bytes);
+ break;
+
+ //
+ // MMIO read w/ sign-extension (MOVSX regX, reg/memX)
+ //
+ case 0xBE:
+ Bytes = 1;
+ //
+ // fall through
+ //
+ case 0xBF:
+ DecodeModRm (Regs, InstructionData);
+ Bytes = (Bytes != 0) ? Bytes : 2;
+
+ Status = ValidateMmioMemory (Ghcb, InstructionData->Ext.RmData, Bytes);
+ if (Status != 0) {
+ return Status;
+ }
+
+ ExitInfo1 = InstructionData->Ext.RmData;
+ ExitInfo2 = Bytes;
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_MMIO_READ, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (Bytes == 1) {
+ UINT8 *Data;
+
+ Data = (UINT8 *) Ghcb->SharedBuffer;
+ SignByte = ((*Data & BIT7) != 0) ? 0xFF : 0x00;
+ } else {
+ UINT16 *Data;
+
+ Data = (UINT16 *) Ghcb->SharedBuffer;
+ SignByte = ((*Data & BIT15) != 0) ? 0xFF : 0x00;
+ }
+
+ Register = GetRegisterPointer (Regs, InstructionData->Ext.ModRm.Reg);
+ SetMem (Register, (UINTN) (1 << InstructionData->DataSize), SignByte);
+ CopyMem (Register, Ghcb->SharedBuffer, Bytes);
+ break;
+
+ default:
+ DEBUG ((DEBUG_ERROR, "Invalid MMIO opcode (%x)\n", OpCode));
+ Status = GP_EXCEPTION;
+ ASSERT (FALSE);
+ }
+
+ return Status;
+}
+
+/**
+ Handle a MWAIT event.
+
+ Use the VMGEXIT instruction to handle a MWAIT event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+MwaitExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ DecodeModRm (Regs, InstructionData);
+
+ Ghcb->SaveArea.Rax = Regs->Rax;
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+ Ghcb->SaveArea.Rcx = Regs->Rcx;
+ VmgSetOffsetValid (Ghcb, GhcbRcx);
+
+ return VmgExit (Ghcb, SVM_EXIT_MWAIT, 0, 0);
+}
+
+/**
+ Handle a MONITOR event.
+
+ Use the VMGEXIT instruction to handle a MONITOR event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+MonitorExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ DecodeModRm (Regs, InstructionData);
+
+ Ghcb->SaveArea.Rax = Regs->Rax; // Identity mapped, so VA = PA
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+ Ghcb->SaveArea.Rcx = Regs->Rcx;
+ VmgSetOffsetValid (Ghcb, GhcbRcx);
+ Ghcb->SaveArea.Rdx = Regs->Rdx;
+ VmgSetOffsetValid (Ghcb, GhcbRdx);
+
+ return VmgExit (Ghcb, SVM_EXIT_MONITOR, 0, 0);
+}
+
+/**
+ Handle a WBINVD event.
+
+ Use the VMGEXIT instruction to handle a WBINVD event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+WbinvdExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ return VmgExit (Ghcb, SVM_EXIT_WBINVD, 0, 0);
+}
+
+/**
+ Handle a RDTSCP event.
+
+ Use the VMGEXIT instruction to handle a RDTSCP event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+RdtscpExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 Status;
+
+ DecodeModRm (Regs, InstructionData);
+
+ Status = VmgExit (Ghcb, SVM_EXIT_RDTSCP, 0, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRcx) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRdx)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
+ Regs->Rcx = Ghcb->SaveArea.Rcx;
+ Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+ return 0;
+}
+
+/**
+ Handle a VMMCALL event.
+
+ Use the VMGEXIT instruction to handle a VMMCALL event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+VmmCallExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 Status;
+
+ DecodeModRm (Regs, InstructionData);
+
+ Ghcb->SaveArea.Rax = Regs->Rax;
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+ Ghcb->SaveArea.Cpl = (UINT8) (Regs->Cs & 0x3);
+ VmgSetOffsetValid (Ghcb, GhcbCpl);
+
+ Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
+
+ return 0;
+}
+
+/**
+ Handle an MSR event.
+
+ Use the VMGEXIT instruction to handle either a RDMSR or WRMSR event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+MsrExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 ExitInfo1, Status;
+
+ ExitInfo1 = 0;
+
+ switch (*(InstructionData->OpCodes + 1)) {
+ case 0x30: // WRMSR
+ ExitInfo1 = 1;
+ Ghcb->SaveArea.Rax = Regs->Rax;
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+ Ghcb->SaveArea.Rdx = Regs->Rdx;
+ VmgSetOffsetValid (Ghcb, GhcbRdx);
+ //
+ // fall through
+ //
+ case 0x32: // RDMSR
+ Ghcb->SaveArea.Rcx = Regs->Rcx;
+ VmgSetOffsetValid (Ghcb, GhcbRcx);
+ break;
+ default:
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+
+ Status = VmgExit (Ghcb, SVM_EXIT_MSR, ExitInfo1, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (ExitInfo1 == 0) {
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRdx)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
+ Regs->Rdx = Ghcb->SaveArea.Rdx;
+ }
+
+ return 0;
+}
+
+/**
+ Build the IOIO event information.
+
+ The IOIO event information identifies the type of IO operation to be performed
+ by the hypervisor. Build this information based on the instruction data.
+
+ @param[in] Regs x64 processor context
+ @param[in, out] InstructionData Instruction parsing context
+
+ @return IOIO event information value
+
+**/
+STATIC
+UINT64
+IoioExitInfo (
+ IN EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN OUT SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 ExitInfo;
+
+ ExitInfo = 0;
+
+ switch (*(InstructionData->OpCodes)) {
+ //
+ // INS opcodes
+ //
+ case 0x6C:
+ case 0x6D:
+ ExitInfo |= IOIO_TYPE_INS;
+ ExitInfo |= IOIO_SEG_ES;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+
+ //
+ // OUTS opcodes
+ //
+ case 0x6E:
+ case 0x6F:
+ ExitInfo |= IOIO_TYPE_OUTS;
+ ExitInfo |= IOIO_SEG_DS;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+
+ //
+ // IN immediate opcodes
+ //
+ case 0xE4:
+ case 0xE5:
+ InstructionData->ImmediateSize = 1;
+ InstructionData->End++;
+ ExitInfo |= IOIO_TYPE_IN;
+ ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16);
+ break;
+
+ //
+ // OUT immediate opcodes
+ //
+ case 0xE6:
+ case 0xE7:
+ InstructionData->ImmediateSize = 1;
+ InstructionData->End++;
+ ExitInfo |= IOIO_TYPE_OUT;
+ ExitInfo |= ((*(InstructionData->OpCodes + 1)) << 16) | IOIO_TYPE_OUT;
+ break;
+
+ //
+ // IN register opcodes
+ //
+ case 0xEC:
+ case 0xED:
+ ExitInfo |= IOIO_TYPE_IN;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+
+ //
+ // OUT register opcodes
+ //
+ case 0xEE:
+ case 0xEF:
+ ExitInfo |= IOIO_TYPE_OUT;
+ ExitInfo |= ((Regs->Rdx & 0xffff) << 16);
+ break;
+
+ default:
+ return 0;
+ }
+
+ switch (*(InstructionData->OpCodes)) {
+ //
+ // Single-byte opcodes
+ //
+ case 0x6C:
+ case 0x6E:
+ case 0xE4:
+ case 0xE6:
+ case 0xEC:
+ case 0xEE:
+ ExitInfo |= IOIO_DATA_8;
+ break;
+
+ //
+ // Length determined by instruction parsing
+ //
+ default:
+ ExitInfo |= (InstructionData->DataSize == Size16Bits) ? IOIO_DATA_16
+ : IOIO_DATA_32;
+ }
+
+ switch (InstructionData->AddrSize) {
+ case Size16Bits:
+ ExitInfo |= IOIO_ADDR_16;
+ break;
+
+ case Size32Bits:
+ ExitInfo |= IOIO_ADDR_32;
+ break;
+
+ case Size64Bits:
+ ExitInfo |= IOIO_ADDR_64;
+ break;
+
+ default:
+ break;
+ }
+
+ if (InstructionData->RepMode != 0) {
+ ExitInfo |= IOIO_REP;
+ }
+
+ return ExitInfo;
+}
+
+/**
+ Handle an IOIO event.
+
+ Use the VMGEXIT instruction to handle an IOIO event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+IoioExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 ExitInfo1, ExitInfo2, Status;
+ BOOLEAN IsString;
+
+ ExitInfo1 = IoioExitInfo (Regs, InstructionData);
+ if (ExitInfo1 == 0) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+
+ IsString = ((ExitInfo1 & IOIO_TYPE_STR) != 0) ? TRUE : FALSE;
+ if (IsString) {
+ UINTN IoBytes, VmgExitBytes;
+ UINTN GhcbCount, OpCount;
+
+ Status = 0;
+
+ IoBytes = IOIO_DATA_BYTES (ExitInfo1);
+ GhcbCount = sizeof (Ghcb->SharedBuffer) / IoBytes;
+
+ OpCount = ((ExitInfo1 & IOIO_REP) != 0) ? Regs->Rcx : 1;
+ while (OpCount != 0) {
+ ExitInfo2 = MIN (OpCount, GhcbCount);
+ VmgExitBytes = ExitInfo2 * IoBytes;
+
+ if ((ExitInfo1 & IOIO_TYPE_IN) == 0) {
+ CopyMem (Ghcb->SharedBuffer, (VOID *) Regs->Rsi, VmgExitBytes);
+ Regs->Rsi += VmgExitBytes;
+ }
+
+ Ghcb->SaveArea.SwScratch = (UINT64) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, ExitInfo2);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
+ CopyMem ((VOID *) Regs->Rdi, Ghcb->SharedBuffer, VmgExitBytes);
+ Regs->Rdi += VmgExitBytes;
+ }
+
+ if ((ExitInfo1 & IOIO_REP) != 0) {
+ Regs->Rcx -= ExitInfo2;
+ }
+
+ OpCount -= ExitInfo2;
+ }
+ } else {
+ if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
+ Ghcb->SaveArea.Rax = 0;
+ } else {
+ CopyMem (&Ghcb->SaveArea.Rax, &Regs->Rax, IOIO_DATA_BYTES (ExitInfo1));
+ }
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+
+ Status = VmgExit (Ghcb, SVM_EXIT_IOIO_PROT, ExitInfo1, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if ((ExitInfo1 & IOIO_TYPE_IN) != 0) {
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ CopyMem (&Regs->Rax, &Ghcb->SaveArea.Rax, IOIO_DATA_BYTES (ExitInfo1));
+ }
+ }
+
+ return 0;
+}
+
+/**
+ Handle a INVD event.
+
+ Use the VMGEXIT instruction to handle a INVD event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+InvdExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ return VmgExit (Ghcb, SVM_EXIT_INVD, 0, 0);
+}
+
+/**
+ Handle a CPUID event.
+
+ Use the VMGEXIT instruction to handle a CPUID event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+CpuidExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 Status;
+
+ Ghcb->SaveArea.Rax = Regs->Rax;
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+ Ghcb->SaveArea.Rcx = Regs->Rcx;
+ VmgSetOffsetValid (Ghcb, GhcbRcx);
+ if (Regs->Rax == CPUID_EXTENDED_STATE) {
+ IA32_CR4 Cr4;
+
+ Cr4.UintN = AsmReadCr4 ();
+ Ghcb->SaveArea.XCr0 = (Cr4.Bits.OSXSAVE == 1) ? AsmXGetBv (0) : 1;
+ VmgSetOffsetValid (Ghcb, GhcbXCr0);
+ }
+
+ Status = VmgExit (Ghcb, SVM_EXIT_CPUID, 0, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRbx) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRcx) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRdx)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
+ Regs->Rbx = Ghcb->SaveArea.Rbx;
+ Regs->Rcx = Ghcb->SaveArea.Rcx;
+ Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+ return 0;
+}
+
+/**
+ Handle a RDPMC event.
+
+ Use the VMGEXIT instruction to handle a RDPMC event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+RdpmcExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 Status;
+
+ Ghcb->SaveArea.Rcx = Regs->Rcx;
+ VmgSetOffsetValid (Ghcb, GhcbRcx);
+
+ Status = VmgExit (Ghcb, SVM_EXIT_RDPMC, 0, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRdx)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
+ Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+ return 0;
+}
+
+/**
+ Handle a RDTSC event.
+
+ Use the VMGEXIT instruction to handle a RDTSC event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+RdtscExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ UINT64 Status;
+
+ Status = VmgExit (Ghcb, SVM_EXIT_RDTSC, 0, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ if (!VmgIsOffsetValid (Ghcb, GhcbRax) ||
+ !VmgIsOffsetValid (Ghcb, GhcbRdx)) {
+ return UnsupportedExit (Ghcb, Regs, InstructionData);
+ }
+ Regs->Rax = Ghcb->SaveArea.Rax;
+ Regs->Rdx = Ghcb->SaveArea.Rdx;
+
+ return 0;
+}
+
+/**
+ Handle a DR7 register write event.
+
+ Use the VMGEXIT instruction to handle a DR7 write event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+ @return New exception value to propagate
+
+**/
+STATIC
+UINT64
+Dr7WriteExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;
+ SEV_ES_PER_CPU_DATA *SevEsData;
+ UINT64 *Register;
+ UINT64 Status;
+
+ Ext = &InstructionData->Ext;
+ SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);
+
+ DecodeModRm (Regs, InstructionData);
+
+ //
+ // MOV DRn always treats MOD == 3 no matter how encoded
+ //
+ Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
+
+ //
+ // Using a value of 0 for ExitInfo1 means RAX holds the value
+ //
+ Ghcb->SaveArea.Rax = *Register;
+ VmgSetOffsetValid (Ghcb, GhcbRax);
+
+ Status = VmgExit (Ghcb, SVM_EXIT_DR7_WRITE, 0, 0);
+ if (Status != 0) {
+ return Status;
+ }
+
+ SevEsData->Dr7 = *Register;
+ SevEsData->Dr7Cached = 1;
+
+ return 0;
+}
+
+/**
+ Handle a DR7 register read event.
+
+ Use the VMGEXIT instruction to handle a DR7 read event.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication
+ Block
+ @param[in, out] Regs x64 processor context
+ @param[in] InstructionData Instruction parsing context
+
+ @retval 0 Event handled successfully
+
+**/
+STATIC
+UINT64
+Dr7ReadExit (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_SYSTEM_CONTEXT_X64 *Regs,
+ IN SEV_ES_INSTRUCTION_DATA *InstructionData
+ )
+{
+ SEV_ES_INSTRUCTION_OPCODE_EXT *Ext;
+ SEV_ES_PER_CPU_DATA *SevEsData;
+ UINT64 *Register;
+
+ Ext = &InstructionData->Ext;
+ SevEsData = (SEV_ES_PER_CPU_DATA *) (Ghcb + 1);
+
+ DecodeModRm (Regs, InstructionData);
+
+ //
+ // MOV DRn always treats MOD == 3 no matter how encoded
+ //
+ Register = GetRegisterPointer (Regs, Ext->ModRm.Rm);
+
+ //
+ // If there is a cached valued for DR7, return that. Otherwise return the
+ // DR7 standard reset value of 0x400 (no debug breakpoints set).
+ //
+ *Register = (SevEsData->Dr7Cached == 1) ? SevEsData->Dr7 : 0x400;
+
+ return 0;
+}
+
+/**
+ Handle a #VC exception.
+
+ Performs the necessary processing to handle a #VC exception.
+
+ @param[in, out] Ghcb Pointer to the GHCB
+ @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
+ as value to use on error.
+ @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS Exception handled
+ @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
+ propagate provided
+ @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
+ propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+InternalVmgExitHandleVc (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ EFI_SYSTEM_CONTEXT_X64 *Regs;
+ NAE_EXIT NaeExit;
+ SEV_ES_INSTRUCTION_DATA InstructionData;
+ UINT64 ExitCode, Status;
+ EFI_STATUS VcRet;
+ BOOLEAN InterruptState;
+
+ VcRet = EFI_SUCCESS;
+
+ Regs = SystemContext.SystemContextX64;
+
+ VmgInit (Ghcb, &InterruptState);
+
+ ExitCode = Regs->ExceptionData;
+ switch (ExitCode) {
+ case SVM_EXIT_DR7_READ:
+ NaeExit = Dr7ReadExit;
+ break;
+
+ case SVM_EXIT_DR7_WRITE:
+ NaeExit = Dr7WriteExit;
+ break;
+
+ case SVM_EXIT_RDTSC:
+ NaeExit = RdtscExit;
+ break;
+
+ case SVM_EXIT_RDPMC:
+ NaeExit = RdpmcExit;
+ break;
+
+ case SVM_EXIT_CPUID:
+ NaeExit = CpuidExit;
+ break;
+
+ case SVM_EXIT_INVD:
+ NaeExit = InvdExit;
+ break;
+
+ case SVM_EXIT_IOIO_PROT:
+ NaeExit = IoioExit;
+ break;
+
+ case SVM_EXIT_MSR:
+ NaeExit = MsrExit;
+ break;
+
+ case SVM_EXIT_VMMCALL:
+ NaeExit = VmmCallExit;
+ break;
+
+ case SVM_EXIT_RDTSCP:
+ NaeExit = RdtscpExit;
+ break;
+
+ case SVM_EXIT_WBINVD:
+ NaeExit = WbinvdExit;
+ break;
+
+ case SVM_EXIT_MONITOR:
+ NaeExit = MonitorExit;
+ break;
+
+ case SVM_EXIT_MWAIT:
+ NaeExit = MwaitExit;
+ break;
+
+ case SVM_EXIT_NPF:
+ NaeExit = MmioExit;
+ break;
+
+ default:
+ NaeExit = UnsupportedExit;
+ }
+
+ InitInstructionData (&InstructionData, Ghcb, Regs);
+
+ Status = NaeExit (Ghcb, Regs, &InstructionData);
+ if (Status == 0) {
+ Regs->Rip += InstructionLength (&InstructionData);
+ } else {
+ GHCB_EVENT_INJECTION Event;
+
+ Event.Uint64 = Status;
+ if (Event.Elements.ErrorCodeValid != 0) {
+ Regs->ExceptionData = Event.Elements.ErrorCode;
+ } else {
+ Regs->ExceptionData = 0;
+ }
+
+ *ExceptionType = Event.Elements.Vector;
+
+ VcRet = EFI_PROTOCOL_ERROR;
+ }
+
+ VmgDone (Ghcb, InterruptState);
+
+ return VcRet;
+}
+
+/**
+ Routine to allow ASSERT from within #VC.
+
+ @param[in, out] SevEsData Pointer to the per-CPU data
+
+**/
+VOID
+EFIAPI
+VmgExitIssueAssert (
+ IN OUT SEV_ES_PER_CPU_DATA *SevEsData
+ )
+{
+ //
+ // Progress will be halted, so set VcCount to allow for ASSERT output
+ // to be seen.
+ //
+ SevEsData->VcCount = 0;
+
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
new file mode 100644
index 00000000000..2835541ae38
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.h
@@ -0,0 +1,53 @@
+/** @file
+ X64 #VC Exception Handler functon header file.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __VMG_EXIT_VC_HANDLER_H__
+#define __VMG_EXIT_VC_HANDLER_H__
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/VmgExitLib.h>
+
+/**
+ Handle a #VC exception.
+
+ Performs the necessary processing to handle a #VC exception.
+
+ @param[in, out] Ghcb Pointer to the GHCB
+ @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
+ as value to use on error.
+ @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS Exception handled
+ @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
+ propagate provided
+ @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
+ propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+InternalVmgExitHandleVc (
+ IN OUT GHCB *Ghcb,
+ IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+/**
+ Routine to allow ASSERT from within #VC.
+
+ @param[in, out] SevEsData Pointer to the per-CPU data
+
+**/
+VOID
+EFIAPI
+VmgExitIssueAssert (
+ IN OUT SEV_ES_PER_CPU_DATA *SevEsData
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
index f60854a68ab..2df5985166b 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.c
@@ -161,6 +161,11 @@ QemuLoadLegacyImage (
LoadedImage->CommandLine = LoadLinuxAllocateCommandLinePages (
EFI_SIZE_TO_PAGES (
LoadedImage->CommandLineSize));
+ if (LoadedImage->CommandLine == NULL) {
+ DEBUG ((DEBUG_ERROR, "Unable to allocate memory for kernel command line!\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeImage;
+ }
QemuFwCfgSelectItem (QemuFwCfgItemCommandLineData);
QemuFwCfgReadBytes (LoadedImage->CommandLineSize, LoadedImage->CommandLine);
}
@@ -178,6 +183,11 @@ QemuLoadLegacyImage (
LoadedImage->InitrdData = LoadLinuxAllocateInitrdPages (
LoadedImage->SetupBuf,
EFI_SIZE_TO_PAGES (LoadedImage->InitrdSize));
+ if (LoadedImage->InitrdData == NULL) {
+ DEBUG ((DEBUG_ERROR, "Unable to allocate memory for initrd!\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeImage;
+ }
DEBUG ((DEBUG_INFO, "Initrd size: 0x%x\n",
(UINT32)LoadedImage->InitrdSize));
DEBUG ((DEBUG_INFO, "Reading initrd image ..."));
@@ -320,15 +330,21 @@ QemuLoadKernelImage (
case EFI_SECURITY_VIOLATION:
//
- // We are running with UEFI secure boot enabled, and the image failed to
- // authenticate. For compatibility reasons, we fall back to the legacy
- // loader in this case. Since the image has been loaded, we need to unload
- // it before proceeding
+ // Since the image has been loaded, we need to unload it before proceeding
+ // to the EFI_ACCESS_DENIED case below.
//
gBS->UnloadImage (KernelImageHandle);
//
// Fall through
//
+ case EFI_ACCESS_DENIED:
+ //
+ // We are running with UEFI secure boot enabled, and the image failed to
+ // authenticate. For compatibility reasons, we fall back to the legacy
+ // loader in this case.
+ //
+ // Fall through
+ //
case EFI_UNSUPPORTED:
//
// The image is not natively supported or cross-type supported. Let's try
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.c
new file mode 100644
index 00000000000..5e37b62560e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.c
@@ -0,0 +1,1210 @@
+/** @file
+
+ This driver produces Extended SCSI Pass Thru Protocol instances for
+ LSI 53C895A SCSI devices.
+
+ Copyright (C) 2020, SUSE LLC.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <IndustryStandard/LsiScsi.h>
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/ScsiPassThruExt.h>
+#include <Uefi/UefiSpec.h>
+
+#include "LsiScsi.h"
+
+STATIC
+EFI_STATUS
+Out8 (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT32 Addr,
+ IN UINT8 Data
+ )
+{
+ return Dev->PciIo->Io.Write (
+ Dev->PciIo,
+ EfiPciIoWidthUint8,
+ PCI_BAR_IDX0,
+ Addr,
+ 1,
+ &Data
+ );
+}
+
+STATIC
+EFI_STATUS
+Out32 (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT32 Addr,
+ IN UINT32 Data
+ )
+{
+ return Dev->PciIo->Io.Write (
+ Dev->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Addr,
+ 1,
+ &Data
+ );
+}
+
+STATIC
+EFI_STATUS
+In8 (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT32 Addr,
+ OUT UINT8 *Data
+ )
+{
+ return Dev->PciIo->Io.Read (
+ Dev->PciIo,
+ EfiPciIoWidthUint8,
+ PCI_BAR_IDX0,
+ Addr,
+ 1,
+ Data
+ );
+}
+
+STATIC
+EFI_STATUS
+In32 (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT32 Addr,
+ OUT UINT32 *Data
+ )
+{
+ return Dev->PciIo->Io.Read (
+ Dev->PciIo,
+ EfiPciIoWidthUint32,
+ PCI_BAR_IDX0,
+ Addr,
+ 1,
+ Data
+ );
+}
+
+STATIC
+EFI_STATUS
+LsiScsiReset (
+ IN LSI_SCSI_DEV *Dev
+ )
+{
+ return Out8 (Dev, LSI_REG_ISTAT0, LSI_ISTAT0_SRST);
+}
+
+STATIC
+EFI_STATUS
+ReportHostAdapterOverrunError (
+ OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ Packet->SenseDataLength = 0;
+ Packet->HostAdapterStatus =
+ EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+ return EFI_BAD_BUFFER_SIZE;
+}
+
+/**
+
+ Check the request packet from the Extended SCSI Pass Thru Protocol. The
+ request packet is modified, to be forwarded outwards by LsiScsiPassThru(),
+ if invalid or unsupported parameters are detected.
+
+ @param[in] Dev The LSI 53C895A SCSI device the packet targets.
+
+ @param[in] Target The SCSI target controlled by the LSI 53C895A SCSI
+ device.
+
+ @param[in] Lun The Logical Unit Number under the SCSI target.
+
+ @param[in out] Packet The Extended SCSI Pass Thru Protocol packet.
+
+
+ @retval EFI_SUCCESS The Extended SCSI Pass Thru Protocol packet was valid.
+
+ @return Otherwise, invalid or unsupported parameters were
+ detected. Status codes are meant for direct forwarding
+ by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
+ implementation.
+
+ **/
+STATIC
+EFI_STATUS
+LsiScsiCheckRequest (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT8 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ if (Target > Dev->MaxTarget || Lun > Dev->MaxLun ||
+ Packet->DataDirection > EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+ //
+ // Trying to receive, but destination pointer is NULL, or contradicting
+ // transfer direction
+ //
+ (Packet->InTransferLength > 0 &&
+ (Packet->InDataBuffer == NULL ||
+ Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE
+ )
+ ) ||
+
+ //
+ // Trying to send, but source pointer is NULL, or contradicting transfer
+ // direction
+ //
+ (Packet->OutTransferLength > 0 &&
+ (Packet->OutDataBuffer == NULL ||
+ Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ
+ )
+ )
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL ||
+ (Packet->InTransferLength > 0 && Packet->OutTransferLength > 0) ||
+ Packet->CdbLength > sizeof Dev->Dma->Cdb) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Packet->InTransferLength > sizeof Dev->Dma->Data) {
+ Packet->InTransferLength = sizeof Dev->Dma->Data;
+ return ReportHostAdapterOverrunError (Packet);
+ }
+ if (Packet->OutTransferLength > sizeof Dev->Dma->Data) {
+ Packet->OutTransferLength = sizeof Dev->Dma->Data;
+ return ReportHostAdapterOverrunError (Packet);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ Interpret the request packet from the Extended SCSI Pass Thru Protocol and
+ compose the script to submit the command and data to the controller.
+
+ @param[in] Dev The LSI 53C895A SCSI device the packet targets.
+
+ @param[in] Target The SCSI target controlled by the LSI 53C895A SCSI
+ device.
+
+ @param[in] Lun The Logical Unit Number under the SCSI target.
+
+ @param[in out] Packet The Extended SCSI Pass Thru Protocol packet.
+
+
+ @retval EFI_SUCCESS The Extended SCSI Pass Thru Protocol packet was valid.
+
+ @return Otherwise, invalid or unsupported parameters were
+ detected. Status codes are meant for direct forwarding
+ by the EFI_EXT_SCSI_PASS_THRU_PROTOCOL.PassThru()
+ implementation.
+
+ **/
+STATIC
+EFI_STATUS
+LsiScsiProcessRequest (
+ IN LSI_SCSI_DEV *Dev,
+ IN UINT8 Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
+ )
+{
+ EFI_STATUS Status;
+ UINT32 *Script;
+ UINT8 *Cdb;
+ UINT8 *MsgOut;
+ UINT8 *MsgIn;
+ UINT8 *ScsiStatus;
+ UINT8 *Data;
+ UINT8 DStat;
+ UINT8 SIst0;
+ UINT8 SIst1;
+ UINT32 Csbc;
+ UINT32 CsbcBase;
+ UINT32 Transferred;
+
+ Script = Dev->Dma->Script;
+ Cdb = Dev->Dma->Cdb;
+ Data = Dev->Dma->Data;
+ MsgIn = Dev->Dma->MsgIn;
+ MsgOut = &Dev->Dma->MsgOut;
+ ScsiStatus = &Dev->Dma->Status;
+
+ *ScsiStatus = 0xFF;
+
+ DStat = 0;
+ SIst0 = 0;
+ SIst1 = 0;
+
+ SetMem (Cdb, sizeof Dev->Dma->Cdb, 0x00);
+ CopyMem (Cdb, Packet->Cdb, Packet->CdbLength);
+
+ //
+ // Fetch the first Cumulative SCSI Byte Count (CSBC).
+ //
+ // CSBC is a cumulative counter of the actual number of bytes that have been
+ // transferred across the SCSI bus during data phases, i.e. it will not
+ // count bytes sent in command, status, message in and out phases.
+ //
+ Status = In32 (Dev, LSI_REG_CSBC, &CsbcBase);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // Clean up the DMA buffer for the script.
+ //
+ SetMem (Script, sizeof Dev->Dma->Script, 0x00);
+
+ //
+ // Compose the script to transfer data between the host and the device.
+ //
+ // References:
+ // * LSI53C895A PCI to Ultra2 SCSI Controller Version 2.2
+ // - Chapter 5 SCSI SCRIPT Instruction Set
+ // * SEABIOS lsi-scsi driver
+ //
+ // All instructions used here consist of 2 32bit words. The first word
+ // contains the command to execute. The second word is loaded into the
+ // DMA SCRIPTS Pointer Save (DSPS) register as either the DMA address
+ // for data transmission or the address/offset for the jump command.
+ // Some commands, such as the selection of the target, don't need to
+ // transfer data through DMA or jump to another instruction, then DSPS
+ // has to be zero.
+ //
+ // There are 3 major parts in this script. The first part (1~3) contains
+ // the instructions to select target and LUN and send the SCSI command
+ // from the request packet. The second part (4~7) is to handle the
+ // potential disconnection and prepare for the data transmission. The
+ // instructions in the third part (8~10) transmit the given data and
+ // collect the result. Instruction 11 raises the interrupt and marks the
+ // end of the script.
+ //
+
+ //
+ // 1. Select target.
+ //
+ *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_SEL | (UINT32)Target << 16;
+ *Script++ = 0x00000000;
+
+ //
+ // 2. Select LUN.
+ //
+ *MsgOut = 0x80 | (UINT8) Lun; // 0x80: Identify bit
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_OUT |
+ (UINT32)sizeof Dev->Dma->MsgOut;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgOut);
+
+ //
+ // 3. Send the SCSI Command.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_CMD |
+ (UINT32)sizeof Dev->Dma->Cdb;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, Cdb);
+
+ //
+ // 4. Check whether the current SCSI phase is "Message In" or not
+ // and jump to 7 if it is.
+ // Note: LSI_INS_TC_RA stands for "Relative Address Mode", so the
+ // offset 0x18 in the second word means jumping forward
+ // 3 (0x18/8) instructions.
+ //
+ *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_JMP |
+ LSI_INS_TC_SCSIP_MSG_IN | LSI_INS_TC_RA |
+ LSI_INS_TC_CP;
+ *Script++ = 0x00000018;
+
+ //
+ // 5. Read "Message" from the initiator to trigger reselect.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN |
+ (UINT32)sizeof Dev->Dma->MsgIn;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgIn);
+
+ //
+ // 6. Wait reselect.
+ //
+ *Script++ = LSI_INS_TYPE_IO | LSI_INS_IO_OPC_WAIT_RESEL;
+ *Script++ = 0x00000000;
+
+ //
+ // 7. Read "Message" from the initiator again
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN |
+ (UINT32)sizeof Dev->Dma->MsgIn;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgIn);
+
+ //
+ // 8. Set the DMA command for the read/write operations.
+ // Note: Some requests, e.g. "TEST UNIT READY", do not come with
+ // allocated InDataBuffer or OutDataBuffer. We skip the DMA
+ // data command for those requests or this script would fail
+ // with LSI_SIST0_SGE due to the zero data length.
+ //
+ // LsiScsiCheckRequest() prevents both integer overflows in the command
+ // opcodes, and buffer overflows.
+ //
+ if (Packet->InTransferLength > 0) {
+ ASSERT (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ);
+ ASSERT (Packet->InTransferLength <= sizeof Dev->Dma->Data);
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_IN |
+ Packet->InTransferLength;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
+ } else if (Packet->OutTransferLength > 0) {
+ ASSERT (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_WRITE);
+ ASSERT (Packet->OutTransferLength <= sizeof Dev->Dma->Data);
+ CopyMem (Data, Packet->OutDataBuffer, Packet->OutTransferLength);
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_DAT_OUT |
+ Packet->OutTransferLength;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, Data);
+ }
+
+ //
+ // 9. Get the SCSI status.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_STAT |
+ (UINT32)sizeof Dev->Dma->Status;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, Status);
+
+ //
+ // 10. Get the SCSI message.
+ //
+ *Script++ = LSI_INS_TYPE_BLK | LSI_INS_BLK_SCSIP_MSG_IN |
+ (UINT32)sizeof Dev->Dma->MsgIn;
+ *Script++ = LSI_SCSI_DMA_ADDR (Dev, MsgIn);
+
+ //
+ // 11. Raise the interrupt to end the script.
+ //
+ *Script++ = LSI_INS_TYPE_TC | LSI_INS_TC_OPC_INT |
+ LSI_INS_TC_SCSIP_DAT_OUT | LSI_INS_TC_JMP;
+ *Script++ = 0x00000000;
+
+ //
+ // Make sure the size of the script doesn't exceed the buffer.
+ //
+ ASSERT (Script <= Dev->Dma->Script + ARRAY_SIZE (Dev->Dma->Script));
+
+ //
+ // The controller starts to execute the script once the DMA Script
+ // Pointer (DSP) register is set.
+ //
+ Status = Out32 (Dev, LSI_REG_DSP, LSI_SCSI_DMA_ADDR (Dev, Script));
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // Poll the device registers (DSTAT, SIST0, and SIST1) until the SIR
+ // bit sets.
+ //
+ for(;;) {
+ Status = In8 (Dev, LSI_REG_DSTAT, &DStat);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ Status = In8 (Dev, LSI_REG_SIST0, &SIst0);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ Status = In8 (Dev, LSI_REG_SIST1, &SIst1);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ if (SIst0 != 0 || SIst1 != 0) {
+ goto Error;
+ }
+
+ //
+ // Check the SIR (SCRIPTS Interrupt Instruction Received) bit.
+ //
+ if (DStat & LSI_DSTAT_SIR) {
+ break;
+ }
+
+ gBS->Stall (Dev->StallPerPollUsec);
+ }
+
+ //
+ // Check if everything is good.
+ // SCSI Message Code 0x00: COMMAND COMPLETE
+ // SCSI Status Code 0x00: Good
+ //
+ if (MsgIn[0] != 0 || *ScsiStatus != 0) {
+ goto Error;
+ }
+
+ //
+ // Fetch CSBC again to calculate the transferred bytes and update
+ // InTransferLength/OutTransferLength.
+ //
+ // Note: The number of transferred bytes is bounded by
+ // "sizeof Dev->Dma->Data", so it's safe to subtract CsbcBase
+ // from Csbc. If the CSBC register wraps around, the correct
+ // difference is ensured by the standard C modular arithmetic.
+ //
+ Status = In32 (Dev, LSI_REG_CSBC, &Csbc);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Transferred = Csbc - CsbcBase;
+ if (Packet->InTransferLength > 0) {
+ if (Transferred <= Packet->InTransferLength) {
+ Packet->InTransferLength = Transferred;
+ } else {
+ goto Error;
+ }
+ } else if (Packet->OutTransferLength > 0) {
+ if (Transferred <= Packet->OutTransferLength) {
+ Packet->OutTransferLength = Transferred;
+ } else {
+ goto Error;
+ }
+ }
+
+ //
+ // Copy Data to InDataBuffer if necessary.
+ //
+ if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
+ CopyMem (Packet->InDataBuffer, Data, Packet->InTransferLength);
+ }
+
+ //
+ // Always set SenseDataLength to 0.
+ // The instructions of LSI53C895A don't reply sense data. Instead, it
+ // relies on the SCSI command, "REQUEST SENSE", to get sense data. We set
+ // SenseDataLength to 0 to notify ScsiDiskDxe that there is no sense data
+ // written even if this request is processed successfully, so that It will
+ // issue "REQUEST SENSE" later to retrieve sense data.
+ //
+ Packet->SenseDataLength = 0;
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK;
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_GOOD;
+
+ return EFI_SUCCESS;
+
+Error:
+ DEBUG ((DEBUG_VERBOSE, "%a: dstat: %02X, sist0: %02X, sist1: %02X\n",
+ __FUNCTION__, DStat, SIst0, SIst1));
+ //
+ // Update the request packet to reflect the status.
+ //
+ if (*ScsiStatus != 0xFF) {
+ Packet->TargetStatus = *ScsiStatus;
+ } else {
+ Packet->TargetStatus = EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED;
+ }
+
+ if (SIst0 & LSI_SIST0_PAR) {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR;
+ } else if (SIst0 & LSI_SIST0_RST) {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET;
+ } else if (SIst0 & LSI_SIST0_UDC) {
+ //
+ // The target device is disconnected unexpectedly. According to UEFI spec,
+ // this is TIMEOUT_COMMAND.
+ //
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND;
+ } else if (SIst0 & LSI_SIST0_SGE) {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN;
+ } else if (SIst1 & LSI_SIST1_HTH) {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT;
+ } else if (SIst1 & LSI_SIST1_GEN) {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT;
+ } else if (SIst1 & LSI_SIST1_STO) {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT;
+ } else {
+ Packet->HostAdapterStatus = EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER;
+ }
+
+ //
+ // SenseData may be used to inspect the error. Since we don't set sense data,
+ // SenseDataLength has to be 0.
+ //
+ Packet->SenseDataLength = 0;
+
+ return EFI_DEVICE_ERROR;
+}
+
+//
+// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
+// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
+// sections
+// - 14.1 SCSI Driver Model Overview,
+// - 14.7 Extended SCSI Pass Thru Protocol.
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiPassThru (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LSI_SCSI_DEV *Dev;
+
+ Dev = LSI_SCSI_FROM_PASS_THRU (This);
+ Status = LsiScsiCheckRequest (Dev, *Target, Lun, Packet);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return LsiScsiProcessRequest (Dev, *Target, Lun, Packet);
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **TargetPointer,
+ IN OUT UINT64 *Lun
+ )
+{
+ LSI_SCSI_DEV *Dev;
+ UINTN Idx;
+ UINT8 *Target;
+ UINT16 LastTarget;
+
+ //
+ // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
+ //
+ Target = *TargetPointer;
+
+ //
+ // Search for first non-0xFF byte. If not found, return first target & LUN.
+ //
+ for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
+ ;
+ if (Idx == TARGET_MAX_BYTES) {
+ SetMem (Target, TARGET_MAX_BYTES, 0x00);
+ *Lun = 0;
+ return EFI_SUCCESS;
+ }
+
+ CopyMem (&LastTarget, Target, sizeof LastTarget);
+
+ //
+ // increment (target, LUN) pair if valid on input
+ //
+ Dev = LSI_SCSI_FROM_PASS_THRU (This);
+ if (LastTarget > Dev->MaxTarget || *Lun > Dev->MaxLun) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*Lun < Dev->MaxLun) {
+ ++*Lun;
+ return EFI_SUCCESS;
+ }
+
+ if (LastTarget < Dev->MaxTarget) {
+ *Lun = 0;
+ ++LastTarget;
+ CopyMem (Target, &LastTarget, sizeof LastTarget);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiBuildDevicePath (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ UINT16 TargetValue;
+ LSI_SCSI_DEV *Dev;
+ SCSI_DEVICE_PATH *ScsiDevicePath;
+
+ if (DevicePath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ CopyMem (&TargetValue, Target, sizeof TargetValue);
+ Dev = LSI_SCSI_FROM_PASS_THRU (This);
+ if (TargetValue > Dev->MaxTarget || Lun > Dev->MaxLun || Lun > 0xFFFF) {
+ return EFI_NOT_FOUND;
+ }
+
+ ScsiDevicePath = AllocatePool (sizeof *ScsiDevicePath);
+ if (ScsiDevicePath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ScsiDevicePath->Header.Type = MESSAGING_DEVICE_PATH;
+ ScsiDevicePath->Header.SubType = MSG_SCSI_DP;
+ ScsiDevicePath->Header.Length[0] = (UINT8) sizeof *ScsiDevicePath;
+ ScsiDevicePath->Header.Length[1] = (UINT8) (sizeof *ScsiDevicePath >> 8);
+ ScsiDevicePath->Pun = TargetValue;
+ ScsiDevicePath->Lun = (UINT16) Lun;
+
+ *DevicePath = &ScsiDevicePath->Header;
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT8 **TargetPointer,
+ OUT UINT64 *Lun
+ )
+{
+ SCSI_DEVICE_PATH *ScsiDevicePath;
+ LSI_SCSI_DEV *Dev;
+ UINT8 *Target;
+
+ if (DevicePath == NULL || TargetPointer == NULL || *TargetPointer == NULL ||
+ Lun == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DevicePath->Type != MESSAGING_DEVICE_PATH ||
+ DevicePath->SubType != MSG_SCSI_DP) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ScsiDevicePath = (SCSI_DEVICE_PATH *) DevicePath;
+ Dev = LSI_SCSI_FROM_PASS_THRU (This);
+ if (ScsiDevicePath->Pun > Dev->MaxTarget ||
+ ScsiDevicePath->Lun > Dev->MaxLun) {
+ return EFI_NOT_FOUND;
+ }
+
+ Target = *TargetPointer;
+ ZeroMem (Target, TARGET_MAX_BYTES);
+ CopyMem (Target, &ScsiDevicePath->Pun, sizeof ScsiDevicePath->Pun);
+ *Lun = ScsiDevicePath->Lun;
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetChannel (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTarget (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **TargetPointer
+ )
+{
+ LSI_SCSI_DEV *Dev;
+ UINTN Idx;
+ UINT8 *Target;
+ UINT16 LastTarget;
+
+ //
+ // the TargetPointer input parameter is unnecessarily a pointer-to-pointer
+ //
+ Target = *TargetPointer;
+
+ //
+ // Search for first non-0xFF byte. If not found, return first target.
+ //
+ for (Idx = 0; Idx < TARGET_MAX_BYTES && Target[Idx] == 0xFF; ++Idx)
+ ;
+ if (Idx == TARGET_MAX_BYTES) {
+ SetMem (Target, TARGET_MAX_BYTES, 0x00);
+ return EFI_SUCCESS;
+ }
+
+ CopyMem (&LastTarget, Target, sizeof LastTarget);
+
+ //
+ // increment target if valid on input
+ //
+ Dev = LSI_SCSI_FROM_PASS_THRU (This);
+ if (LastTarget > Dev->MaxTarget) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (LastTarget < Dev->MaxTarget) {
+ ++LastTarget;
+ CopyMem (Target, &LastTarget, sizeof LastTarget);
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+STATIC
+VOID
+EFIAPI
+LsiScsiExitBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ LSI_SCSI_DEV *Dev;
+
+ Dev = Context;
+ DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
+ LsiScsiReset (Dev);
+}
+
+//
+// Probe, start and stop functions of this driver, called by the DXE core for
+// specific devices.
+//
+// The following specifications document these interfaces:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ PCI_TYPE00 Pci;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = PciIo->Pci.Read (
+ PciIo,
+ EfiPciIoWidthUint32,
+ 0,
+ sizeof (Pci) / sizeof (UINT32),
+ &Pci
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ if (Pci.Hdr.VendorId == LSI_LOGIC_PCI_VENDOR_ID &&
+ Pci.Hdr.DeviceId == LSI_53C895A_PCI_DEVICE_ID) {
+ Status = EFI_SUCCESS;
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+
+Done:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ LSI_SCSI_DEV *Dev;
+ UINTN Pages;
+ UINTN BytesMapped;
+
+ Dev = AllocateZeroPool (sizeof (*Dev));
+ if (Dev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Dev->Signature = LSI_SCSI_DEV_SIGNATURE;
+
+ STATIC_ASSERT (
+ FixedPcdGet8 (PcdLsiScsiMaxTargetLimit) < 8,
+ "LSI 53C895A supports targets [0..7]"
+ );
+ STATIC_ASSERT (
+ FixedPcdGet8 (PcdLsiScsiMaxLunLimit) < 128,
+ "LSI 53C895A supports LUNs [0..127]"
+ );
+ Dev->MaxTarget = PcdGet8 (PcdLsiScsiMaxTargetLimit);
+ Dev->MaxLun = PcdGet8 (PcdLsiScsiMaxLunLimit);
+ Dev->StallPerPollUsec = PcdGet32 (PcdLsiScsiStallPerPollUsec);
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&Dev->PciIo,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreePool;
+ }
+
+ Status = Dev->PciIo->Attributes (
+ Dev->PciIo,
+ EfiPciIoAttributeOperationGet,
+ 0,
+ &Dev->OrigPciAttrs
+ );
+ if (EFI_ERROR (Status)) {
+ goto CloseProtocol;
+ }
+
+ //
+ // Enable I/O Space & Bus-Mastering
+ //
+ Status = Dev->PciIo->Attributes (
+ Dev->PciIo,
+ EfiPciIoAttributeOperationEnable,
+ (EFI_PCI_IO_ATTRIBUTE_IO |
+ EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto CloseProtocol;
+ }
+
+ //
+ // Create buffers for data transfer
+ //
+ Pages = EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma));
+ Status = Dev->PciIo->AllocateBuffer (
+ Dev->PciIo,
+ AllocateAnyPages,
+ EfiBootServicesData,
+ Pages,
+ (VOID **)&Dev->Dma,
+ EFI_PCI_ATTRIBUTE_MEMORY_CACHED
+ );
+ if (EFI_ERROR (Status)) {
+ goto RestoreAttributes;
+ }
+
+ BytesMapped = EFI_PAGES_TO_SIZE (Pages);
+ Status = Dev->PciIo->Map (
+ Dev->PciIo,
+ EfiPciIoOperationBusMasterCommonBuffer,
+ Dev->Dma,
+ &BytesMapped,
+ &Dev->DmaPhysical,
+ &Dev->DmaMapping
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeBuffer;
+ }
+
+ if (BytesMapped != EFI_PAGES_TO_SIZE (Pages)) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Unmap;
+ }
+
+ Status = LsiScsiReset (Dev);
+ if (EFI_ERROR (Status)) {
+ goto Unmap;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,
+ TPL_CALLBACK,
+ &LsiScsiExitBoot,
+ Dev,
+ &Dev->ExitBoot
+ );
+ if (EFI_ERROR (Status)) {
+ goto UninitDev;
+ }
+
+ //
+ // Host adapter channel, doesn't exist
+ //
+ Dev->PassThruMode.AdapterId = MAX_UINT32;
+ Dev->PassThruMode.Attributes =
+ EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL |
+ EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
+
+ Dev->PassThru.Mode = &Dev->PassThruMode;
+ Dev->PassThru.PassThru = &LsiScsiPassThru;
+ Dev->PassThru.GetNextTargetLun = &LsiScsiGetNextTargetLun;
+ Dev->PassThru.BuildDevicePath = &LsiScsiBuildDevicePath;
+ Dev->PassThru.GetTargetLun = &LsiScsiGetTargetLun;
+ Dev->PassThru.ResetChannel = &LsiScsiResetChannel;
+ Dev->PassThru.ResetTargetLun = &LsiScsiResetTargetLun;
+ Dev->PassThru.GetNextTarget = &LsiScsiGetNextTarget;
+
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ &gEfiExtScsiPassThruProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &Dev->PassThru
+ );
+ if (EFI_ERROR (Status)) {
+ goto CloseExitBoot;
+ }
+
+ return EFI_SUCCESS;
+
+CloseExitBoot:
+ gBS->CloseEvent (Dev->ExitBoot);
+
+UninitDev:
+ LsiScsiReset (Dev);
+
+Unmap:
+ Dev->PciIo->Unmap (
+ Dev->PciIo,
+ Dev->DmaMapping
+ );
+
+FreeBuffer:
+ Dev->PciIo->FreeBuffer (
+ Dev->PciIo,
+ Pages,
+ Dev->Dma
+ );
+
+RestoreAttributes:
+ Dev->PciIo->Attributes (
+ Dev->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Dev->OrigPciAttrs,
+ NULL
+ );
+
+CloseProtocol:
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+FreePool:
+ FreePool (Dev);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
+ LSI_SCSI_DEV *Dev;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiExtScsiPassThruProtocolGuid,
+ (VOID **)&PassThru,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL // Lookup only
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Dev = LSI_SCSI_FROM_PASS_THRU (PassThru);
+
+ Status = gBS->UninstallProtocolInterface (
+ ControllerHandle,
+ &gEfiExtScsiPassThruProtocolGuid,
+ &Dev->PassThru
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ gBS->CloseEvent (Dev->ExitBoot);
+
+ LsiScsiReset (Dev);
+
+ Dev->PciIo->Unmap (
+ Dev->PciIo,
+ Dev->DmaMapping
+ );
+
+ Dev->PciIo->FreeBuffer (
+ Dev->PciIo,
+ EFI_SIZE_TO_PAGES (sizeof (*Dev->Dma)),
+ Dev->Dma
+ );
+
+ Dev->PciIo->Attributes (
+ Dev->PciIo,
+ EfiPciIoAttributeOperationSet,
+ Dev->OrigPciAttrs,
+ NULL
+ );
+
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiPciIoProtocolGuid,
+ This->DriverBindingHandle,
+ ControllerHandle
+ );
+
+ FreePool (Dev);
+
+ return Status;
+}
+
+//
+// The static object that groups the Supported() (ie. probe), Start() and
+// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
+// C, 10.1 EFI Driver Binding Protocol.
+//
+STATIC
+EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
+ &LsiScsiControllerSupported,
+ &LsiScsiControllerStart,
+ &LsiScsiControllerStop,
+ 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
+ NULL, // ImageHandle, to be overwritten by
+ // EfiLibInstallDriverBindingComponentName2() in LsiScsiEntryPoint()
+ NULL // DriverBindingHandle, ditto
+};
+
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+// Device type names ("LSI 53C895A SCSI Controller") are not formatted because
+// the driver supports only that device type. Therefore the driver name
+// suffices for unambiguous identification.
+//
+
+STATIC
+EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
+ { "eng;en", L"LSI 53C895A SCSI Controller Driver" },
+ { NULL, NULL }
+};
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName;
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gComponentName) // Iso639Language
+ );
+}
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDeviceName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_HANDLE ChildHandle,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+STATIC
+EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
+ &LsiScsiGetDriverName,
+ &LsiScsiGetDeviceName,
+ "eng" // SupportedLanguages, ISO 639-2 language codes
+};
+
+STATIC
+EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) &LsiScsiGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) &LsiScsiGetDeviceName,
+ "en" // SupportedLanguages, RFC 4646 language codes
+};
+
+//
+// Entry point of this driver
+//
+EFI_STATUS
+EFIAPI
+LsiScsiEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gDriverBinding,
+ ImageHandle, // The handle to install onto
+ &gComponentName,
+ &gComponentName2
+ );
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.h
new file mode 100644
index 00000000000..f9016280b1f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsi.h
@@ -0,0 +1,202 @@
+/** @file
+
+ Internal definitions for the LSI 53C895A SCSI driver, which produces
+ Extended SCSI Pass Thru Protocol instances for LSI 53C895A SCSI devices.
+
+ Copyright (C) 2020, SUSE LLC.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _LSI_SCSI_DXE_H_
+#define _LSI_SCSI_DXE_H_
+
+typedef struct {
+ //
+ // Allocate 32 UINT32 entries for the script and it's sufficient for
+ // 16 instructions.
+ //
+ UINT32 Script[32];
+ //
+ // The max size of CDB is 32.
+ //
+ UINT8 Cdb[32];
+ //
+ // Allocate 64KB for read/write buffer. It seems sufficient for the common
+ // boot scenarios.
+ //
+ // NOTE: The number of bytes for data transmission is bounded by DMA Byte
+ // Count (DBC), a 24-bit register, so the maximum is 0xFFFFFF (16MB-1).
+ //
+ UINT8 Data[SIZE_64KB];
+ //
+ // For SCSI Message In phase
+ //
+ UINT8 MsgIn[2];
+ //
+ // For SCSI Message Out phase
+ //
+ UINT8 MsgOut;
+ //
+ // For SCSI Status phase
+ //
+ UINT8 Status;
+} LSI_SCSI_DMA_BUFFER;
+
+typedef struct {
+ UINT32 Signature;
+ UINT64 OrigPciAttrs;
+ EFI_EVENT ExitBoot;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 MaxTarget;
+ UINT8 MaxLun;
+ UINT32 StallPerPollUsec;
+ LSI_SCSI_DMA_BUFFER *Dma;
+ EFI_PHYSICAL_ADDRESS DmaPhysical;
+ VOID *DmaMapping;
+ EFI_EXT_SCSI_PASS_THRU_MODE PassThruMode;
+ EFI_EXT_SCSI_PASS_THRU_PROTOCOL PassThru;
+} LSI_SCSI_DEV;
+
+#define LSI_SCSI_DEV_SIGNATURE SIGNATURE_32 ('L','S','I','S')
+
+#define LSI_SCSI_FROM_PASS_THRU(PassThruPtr) \
+ CR (PassThruPtr, LSI_SCSI_DEV, PassThru, LSI_SCSI_DEV_SIGNATURE)
+
+#define LSI_SCSI_DMA_ADDR(Dev, MemberName) \
+ ((UINT32)(Dev->DmaPhysical + OFFSET_OF (LSI_SCSI_DMA_BUFFER, MemberName)))
+
+
+//
+// Probe, start and stop functions of this driver, called by the DXE core for
+// specific devices.
+//
+// The following specifications document these interfaces:
+// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
+// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiControllerStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+
+//
+// The next seven functions implement EFI_EXT_SCSI_PASS_THRU_PROTOCOL
+// for the LSI 53C895A SCSI Controller. Refer to UEFI Spec 2.3.1 + Errata C,
+// sections
+// - 14.1 SCSI Driver Model Overview,
+// - 14.7 Extended SCSI Pass Thru Protocol.
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiPassThru (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun,
+ IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
+ IN EFI_EVENT Event OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **TargetPointer,
+ IN OUT UINT64 *Lun
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiBuildDevicePath (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT UINT8 **TargetPointer,
+ OUT UINT64 *Lun
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetChannel (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiResetTargetLun (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN UINT8 *Target,
+ IN UINT64 Lun
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetNextTarget (
+ IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
+ IN OUT UINT8 **TargetPointer
+ );
+
+
+//
+// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
+// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
+// in English, for display on standard console devices. This is recommended for
+// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
+// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
+//
+// Device type names ("LSI 53C895A SCSI Controller") are not formatted because
+// the driver supports only that device type. Therefore the driver name
+// suffices for unambiguous identification.
+//
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+LsiScsiGetDeviceName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_HANDLE ChildHandle,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+#endif // _LSI_SCSI_DXE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
new file mode 100644
index 00000000000..4f2a2139f99
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
@@ -0,0 +1,46 @@
+## @file
+# This driver produces Extended SCSI Pass Thru Protocol instances for
+# LSI 53C895A SCSI devices.
+#
+# Copyright (C) 2020, SUSE LLC.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = LsiScsiDxe
+ FILE_GUID = EB4EB21F-5A3D-40BE-8BD2-F1B0E38E5744
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = LsiScsiEntryPoint
+
+[Sources]
+ LsiScsi.c
+ LsiScsi.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PcdLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiExtScsiPassThruProtocolGuid ## BY_START
+ gEfiPciIoProtocolGuid ## TO_START
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit ## CONSUMES
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit ## CONSUMES
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.ci.yaml
index 31532c139e6..983f27a19a1 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.ci.yaml
@@ -5,9 +5,26 @@
# used for code analysis.
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ ## options defined .pytool/Plugin/LicenseCheck
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ],
+ "skip": True
+ },
## options defined .pytool/Plugin/CompilerPlugin
"CompilerPlugin": {
"DscPath": "" # Don't support this test
@@ -62,7 +79,7 @@
"IgnoreGuidName": ["ResetVector", "XenResetVector"], # Expected duplication for gEfiFirmwareVolumeTopFileGuid
"IgnoreGuidValue": [],
"IgnoreFoldersAndFiles": [],
- "IgnoreDuplicates": [],
+ "IgnoreDuplicates": ["gGrubFileGuid=Grub"],
},
## options defined .pytool/Plugin/LibraryClassCheck
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.dec b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.dec
index 3f9fe2ee7c1..5579b4006c0 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkg.dec
@@ -1,7 +1,9 @@
## @file
# EFI/Framework Open Virtual Machine Firmware (OVMF) platform
#
+# Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014, Pluribus Networks, Inc.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -18,6 +20,9 @@
Csm/Include
[LibraryClasses]
+ ## @libraryclass Access bhyve's firmware control interface.
+ BhyveFwCtlLib|Include/Library/BhyveFwCtlLib.h
+
## @libraryclass Loads and boots a Linux kernel image
#
LoadLinuxLib|Include/Library/LoadLinuxLib.h
@@ -44,6 +49,10 @@
# access.
PciCapPciSegmentLib|Include/Library/PciCapPciSegmentLib.h
+ ## @libraryclass Provide common utility functions to PciHostBridgeLib
+ # instances in ArmVirtPkg and OvmfPkg.
+ PciHostBridgeUtilityLib|Include/Library/PciHostBridgeUtilityLib.h
+
## @libraryclass Register a status code handler for printing the Boot
# Manager's LoadImage() and StartImage() preparations, and
# return codes, to the UEFI console.
@@ -111,12 +120,18 @@
gEfiLegacyDevOrderVariableGuid = {0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52}}
gLinuxEfiInitrdMediaGuid = {0x5568e427, 0x68fc, 0x4f3d, {0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68}}
gQemuKernelLoaderFsMediaGuid = {0x1428f772, 0xb64a, 0x441e, {0xb8, 0xc3, 0x9e, 0xbd, 0xd7, 0xf8, 0x93, 0xc7}}
+ gGrubFileGuid = {0xb5ae312c, 0xbc8a, 0x43b1, {0x9c, 0x62, 0xeb, 0xb8, 0x26, 0xdd, 0x5d, 0x07}}
+ gConfidentialComputingSecretGuid = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}}
[Ppis]
# PPI whose presence in the PPI database signals that the TPM base address
# has been discovered and recorded
gOvmfTpmDiscoveredPpiGuid = {0xb9a61ad0, 0x2802, 0x41f3, {0xb5, 0x13, 0x96, 0x51, 0xce, 0x6b, 0xd5, 0x75}}
+ # This PPI signals that accessing the MMIO range of the TPM is possible in
+ # the PEI phase, regardless of memory encryption
+ gOvmfTpmMmioAccessiblePpiGuid = {0x35c84ff2, 0x7bfe, 0x453d, {0x84, 0x5f, 0x68, 0x3a, 0x49, 0x2c, 0xf7, 0xb7}}
+
[Protocols]
gVirtioDeviceProtocolGuid = {0xfa920010, 0x6785, 0x4941, {0xb6, 0xec, 0x49, 0x8c, 0x57, 0x9f, 0x16, 0x0a}}
gXenBusProtocolGuid = {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}}
@@ -172,7 +187,15 @@
gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiMaxTargetLimit|7|UINT8|0x39
## Microseconds to stall between polling for MptScsi request result
- gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x40
+ gUefiOvmfPkgTokenSpaceGuid.PcdMptScsiStallPerPollUsec|5|UINT32|0x3a
+
+ ## Set the *inclusive* number of targets and LUNs that LsiScsi exposes for
+ # scan by ScsiBusDxe.
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxTargetLimit|7|UINT8|0x3b
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiMaxLunLimit|0|UINT8|0x3c
+
+ ## Microseconds to stall between polling for LsiScsi request result
+ gUefiOvmfPkgTokenSpaceGuid.PcdLsiScsiStallPerPollUsec|5|UINT32|0x3d
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogBase|0x0|UINT32|0x8
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashNvStorageEventLogSize|0x0|UINT32|0x9
@@ -281,6 +304,23 @@
## Number of page frames to use for storing grant table entries.
gUefiOvmfPkgTokenSpaceGuid.PcdXenGrantFrames|4|UINT32|0x33
+ ## Specify the extra page table needed to mark the GHCB as unencrypted.
+ # The value should be a multiple of 4KB for each.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|0x0|UINT32|0x3e
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize|0x0|UINT32|0x3f
+
+ ## The base address of the SEC GHCB page used by SEV-ES.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|0|UINT32|0x40
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize|0|UINT32|0x41
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45
+
+ ## The base address and size of the SEV Launch Secret Area provisioned
+ # after remote attestation. If this is set in the .fdf, the platform
+ # is responsible for protecting the area from DXE phase overwrites.
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|0x0|UINT32|0x42
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize|0x0|UINT32|0x43
+
[PcdsDynamic, PcdsDynamicEx]
gUefiOvmfPkgTokenSpaceGuid.PcdEmuVariableEvent|0|UINT64|2
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFlashVariablesEnable|FALSE|BOOLEAN|0x10
@@ -316,6 +356,10 @@
# This PCD is only accessed if PcdSmmSmramRequire is TRUE (see below).
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase|FALSE|BOOLEAN|0x34
+ ## This PCD adds a communication channel between OVMF's SmmCpuFeaturesLib
+ # instance in PiSmmCpuDxeSmm, and CpuHotplugSmm.
+ gUefiOvmfPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress|0|UINT64|0x46
+
[PcdsFeatureFlag]
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderPciTranslation|TRUE|BOOLEAN|0x1c
gUefiOvmfPkgTokenSpaceGuid.PcdQemuBootOrderMmioTranslation|FALSE|BOOLEAN|0x1d
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc
index e28216ff6de..fd12467ea60 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.dsc
@@ -1,8 +1,9 @@
## @file
# EFI/Framework Open Virtual Machine Firmware (OVMF) platform
#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -46,6 +47,7 @@
DEFINE NETWORK_IP6_ENABLE = FALSE
DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = TRUE
!include NetworkPkg/NetworkDefines.dsc.inc
@@ -54,6 +56,7 @@
#
DEFINE PVSCSI_ENABLE = TRUE
DEFINE MPT_SCSI_ENABLE = TRUE
+ DEFINE LSI_SCSI_ENABLE = FALSE
#
# Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -81,11 +84,15 @@
!if $(TOOL_CHAIN_TAG) != "XCODE5" && $(TOOL_CHAIN_TAG) != "CLANGPDB"
GCC:*_*_*_CC_FLAGS = -mno-mmx -mno-sse
!endif
+ RELEASE_*_*_GENFW_FLAGS = --zero
+
+!ifdef $(VBOX)
!ifdef $(SOURCE_DEBUG_ENABLE)
MSFT:*_*_IA32_GENFW_FLAGS = --keepexceptiontable
GCC:*_*_IA32_GENFW_FLAGS = --keepexceptiontable
INTEL:*_*_IA32_GENFW_FLAGS = --keepexceptiontable
!endif
+!endif
#
# Disable deprecated APIs.
@@ -94,6 +101,8 @@
INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+!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
@@ -140,6 +149,9 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
@@ -148,6 +160,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
@@ -180,6 +193,7 @@
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
@@ -196,7 +210,7 @@
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
- MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
!if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
!endif
@@ -225,6 +239,7 @@
!else
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
!endif
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -233,6 +248,8 @@
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
#
@@ -265,6 +282,7 @@
[LibraryClasses.common]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
[LibraryClasses.common.SEC]
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
@@ -351,6 +369,8 @@
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
!endif
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
@@ -393,6 +413,10 @@
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+!if $(SMM_REQUIRE) == TRUE
+ MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
+!endif
[LibraryClasses.common.UEFI_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -446,11 +470,7 @@
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE
- QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
-!else
QemuLoadImageLib|OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
-!endif
!if $(TPM_ENABLE) == TRUE
Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
@@ -528,8 +548,6 @@
################################################################################
[PcdsFeatureFlag]
gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
@@ -550,6 +568,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
!endif
gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
@@ -572,6 +591,8 @@
!endif
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
@@ -634,6 +655,8 @@
#
!include NetworkPkg/NetworkPcds.dsc.inc
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000
+
!if $(SMM_REQUIRE) == TRUE
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x4000
!endif
@@ -699,6 +722,11 @@
# Set memory encryption mask
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+ # Set SEV-ES defaults
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0
+
!if $(SMM_REQUIRE) == TRUE
gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes|8
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase|FALSE
@@ -783,6 +811,7 @@
UefiCpuPkg/CpuMpPei/CpuMpPei.inf
!if $(TPM_ENABLE) == TRUE
+ OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
SecurityPkg/Tcg/TcgPei/TcgPei.inf
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
@@ -835,6 +864,7 @@
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
<LibraryClasses>
PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
}
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
@@ -886,6 +916,9 @@
!if $(MPT_SCSI_ENABLE) == TRUE
OvmfPkg/MptScsiDxe/MptScsiDxe.inf
!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+ OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -908,6 +941,7 @@
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
FatPkg/EnhancedFatDxe/Fat.inf
MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+ OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
OvmfPkg/SataControllerDxe/SataControllerDxe.inf
@@ -1018,6 +1052,10 @@
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
@@ -1092,6 +1130,7 @@
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf
index 218eb1a41ad..e04d333cc74 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32.fdf
@@ -162,6 +162,7 @@ INF OvmfPkg/SmmAccess/SmmAccessPei.inf
INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf
!if $(TPM_ENABLE) == TRUE
+INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -240,6 +241,9 @@ INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf
!if $(MPT_SCSI_ENABLE) == TRUE
INF OvmfPkg/MptScsiDxe/MptScsiDxe.inf
!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
!if $(SECURE_BOOT_ENABLE) == TRUE
INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -307,9 +311,11 @@ INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
INF FatPkg/EnhancedFatDxe/Fat.inf
INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
!if $(TOOL_CHAIN_TAG) != "XCODE5"
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
!endif
INF ShellPkg/Application/Shell/Shell.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.dsc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.dsc
index 08306f072df..3d7387947d6 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -1,8 +1,9 @@
## @file
# EFI/Framework Open Virtual Machine Firmware (OVMF) platform
#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -41,6 +42,7 @@
DEFINE NETWORK_IP6_ENABLE = FALSE
DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = TRUE
!include NetworkPkg/NetworkDefines.dsc.inc
@@ -49,6 +51,7 @@
#
DEFINE PVSCSI_ENABLE = TRUE
DEFINE MPT_SCSI_ENABLE = TRUE
+ DEFINE LSI_SCSI_ENABLE = FALSE
#
# Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -81,6 +84,7 @@
GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable
INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
!endif
+ RELEASE_*_*_GENFW_FLAGS = --zero
#
# Disable deprecated APIs.
@@ -89,6 +93,8 @@
INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+!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
@@ -116,6 +122,9 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
@@ -124,6 +133,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
@@ -152,6 +162,7 @@
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
@@ -168,7 +179,7 @@
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
- MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
!if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
!endif
@@ -192,6 +203,7 @@
!else
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
!endif
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -200,6 +212,8 @@
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
#
@@ -232,6 +246,7 @@
[LibraryClasses.common]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
[LibraryClasses.common.SEC]
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
@@ -304,6 +319,8 @@
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
!endif
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
@@ -338,6 +355,10 @@
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+!if $(SMM_REQUIRE) == TRUE
+ MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
+!endif
[LibraryClasses.common.UEFI_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -383,11 +404,7 @@
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE
- QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
-!else
QemuLoadImageLib|OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
-!endif
!if $(TPM_ENABLE) == TRUE
Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
@@ -453,8 +470,6 @@
################################################################################
[PcdsFeatureFlag]
gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
@@ -475,6 +490,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
!endif
gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
@@ -497,6 +513,8 @@
!endif
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
@@ -559,6 +577,8 @@
#
!include NetworkPkg/NetworkPcds.dsc.inc
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000
+
!if $(SMM_REQUIRE) == TRUE
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x4000
!endif
@@ -621,6 +641,11 @@
# Set memory encryption mask
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+ # Set SEV-ES defaults
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0
+
!if $(SMM_REQUIRE) == TRUE
gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes|8
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase|FALSE
@@ -694,6 +719,7 @@
UefiCpuPkg/CpuMpPei/CpuMpPei.inf
!if $(TPM_ENABLE) == TRUE
+ OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
SecurityPkg/Tcg/TcgPei/TcgPei.inf
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
@@ -747,6 +773,7 @@
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
<LibraryClasses>
PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
}
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
@@ -790,6 +817,9 @@
!if $(MPT_SCSI_ENABLE) == TRUE
OvmfPkg/MptScsiDxe/MptScsiDxe.inf
!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+ OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -812,6 +842,7 @@
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
FatPkg/EnhancedFatDxe/Fat.inf
MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+ OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
OvmfPkg/SataControllerDxe/SataControllerDxe.inf
@@ -897,6 +928,10 @@
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
@@ -972,6 +1007,7 @@
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.fdf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.fdf
index d3eea5004c4..a243d0c7b8d 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -162,6 +162,7 @@ INF OvmfPkg/SmmAccess/SmmAccessPei.inf
INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf
!if $(TPM_ENABLE) == TRUE
+INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -237,6 +238,9 @@ INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf
!if $(MPT_SCSI_ENABLE) == TRUE
INF OvmfPkg/MptScsiDxe/MptScsiDxe.inf
!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
!if $(SECURE_BOOT_ENABLE) == TRUE
INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -288,9 +292,11 @@ INF MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResour
INF FatPkg/EnhancedFatDxe/Fat.inf
INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
!if $(TOOL_CHAIN_TAG) != "XCODE5"
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
!endif
INF ShellPkg/Application/Shell/Shell.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc
index 63c464e6a70..ab3b256c8c1 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.dsc
@@ -1,8 +1,9 @@
## @file
# EFI/Framework Open Virtual Machine Firmware (OVMF) platform
#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -47,6 +48,7 @@
DEFINE NETWORK_IP6_ENABLE = FALSE
DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = TRUE
!include NetworkPkg/NetworkDefines.dsc.inc
@@ -55,6 +57,7 @@
#
DEFINE PVSCSI_ENABLE = TRUE
DEFINE MPT_SCSI_ENABLE = TRUE
+ DEFINE LSI_SCSI_ENABLE = FALSE
#
# Flash size selection. Setting FD_SIZE_IN_KB on the command line directly to
@@ -87,6 +90,7 @@
GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable
INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
!endif
+ RELEASE_*_*_GENFW_FLAGS = --zero
#
# Disable deprecated APIs.
@@ -95,6 +99,8 @@
INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+!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
@@ -142,6 +148,9 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
@@ -150,6 +159,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
+ TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
BmpSupportLib|MdeModulePkg/Library/BaseBmpSupportLib/BaseBmpSupportLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
@@ -182,6 +192,7 @@
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
@@ -198,7 +209,7 @@
QemuFwCfgSimpleParserLib|OvmfPkg/Library/QemuFwCfgSimpleParserLib/QemuFwCfgSimpleParserLib.inf
VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
- MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
!if $(SMM_REQUIRE) == FALSE
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
!endif
@@ -227,6 +238,7 @@
!else
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
!endif
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf
@@ -235,6 +247,8 @@
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
!endif
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
#
@@ -267,6 +281,7 @@
[LibraryClasses.common]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ VmgExitLib|OvmfPkg/Library/VmgExitLib/VmgExitLib.inf
[LibraryClasses.common.SEC]
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseRomAcpiTimerLib.inf
@@ -294,6 +309,8 @@
!else
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
!endif
+ VmgExitLib|OvmfPkg/Library/VmgExitLib/SecVmgExitLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLib.inf
[LibraryClasses.common.PEI_CORE]
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
@@ -353,6 +370,8 @@
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
!endif
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
@@ -395,6 +414,10 @@
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
+!if $(SMM_REQUIRE) == TRUE
+ MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
+!endif
[LibraryClasses.common.UEFI_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -448,11 +471,7 @@
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE
- QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
-!else
QemuLoadImageLib|OvmfPkg/Library/X86QemuLoadImageLib/X86QemuLoadImageLib.inf
-!endif
!if $(TPM_ENABLE) == TRUE
Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibTcg/Tpm12DeviceLibTcg.inf
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
@@ -530,8 +549,6 @@
################################################################################
[PcdsFeatureFlag]
gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
@@ -552,6 +569,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
!endif
gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
@@ -574,6 +592,8 @@
!endif
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
@@ -636,6 +656,8 @@
#
!include NetworkPkg/NetworkPcds.dsc.inc
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000
+
!if $(SMM_REQUIRE) == TRUE
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize|0x4000
!endif
@@ -707,6 +729,11 @@
# Set memory encryption mask
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+ # Set SEV-ES defaults
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase|0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize|0
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|0
+
!if $(SMM_REQUIRE) == TRUE
gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes|8
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase|FALSE
@@ -788,6 +815,7 @@
UefiCpuPkg/CpuMpPei/CpuMpPei.inf
!if $(TPM_ENABLE) == TRUE
+ OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
SecurityPkg/Tcg/TcgPei/TcgPei.inf
SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf {
@@ -840,6 +868,7 @@
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
<LibraryClasses>
PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
}
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
@@ -891,6 +920,9 @@
!if $(MPT_SCSI_ENABLE) == TRUE
OvmfPkg/MptScsiDxe/MptScsiDxe.inf
!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+ OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
@@ -913,6 +945,7 @@
MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
FatPkg/EnhancedFatDxe/Fat.inf
MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+ OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
OvmfPkg/SataControllerDxe/SataControllerDxe.inf
@@ -1021,6 +1054,10 @@
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
@@ -1055,7 +1092,9 @@
!endif
OvmfPkg/PlatformDxe/Platform.inf
+!ifndef $(VBOX)
OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+!endif
OvmfPkg/IoMmuDxe/IoMmuDxe.inf
!if $(SMM_REQUIRE) == TRUE
@@ -1096,6 +1135,7 @@
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmm.inf {
<LibraryClasses>
NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf
+ NULL|MdeModulePkg/Library/VarCheckPolicyLib/VarCheckPolicyLib.inf
}
MdeModulePkg/Universal/Variable/RuntimeDxe/VariableSmmRuntimeDxe.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf
index e4cb2baa5dd..93c39e596d8 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfPkgX64.fdf
@@ -76,6 +76,18 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase|gUefiOvmfPkgTokenSpaceGuid.
0x007000|0x001000
gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+0x008000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize
+
+0x009000|0x002000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
+
+0x00B000|0x001000
+gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize
+
+0x00C000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
@@ -162,6 +174,7 @@ INF OvmfPkg/SmmAccess/SmmAccessPei.inf
INF UefiCpuPkg/CpuMpPei/CpuMpPei.inf
!if $(TPM_ENABLE) == TRUE
+INF OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
INF SecurityPkg/Tcg/TcgPei/TcgPei.inf
INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -193,7 +206,9 @@ READ_LOCK_STATUS = TRUE
APRIORI DXE {
INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+!ifndef $(VBOX)
INF OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+!endif
!if $(SMM_REQUIRE) == FALSE
INF OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
!endif
@@ -241,6 +256,9 @@ INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf
!if $(MPT_SCSI_ENABLE) == TRUE
INF OvmfPkg/MptScsiDxe/MptScsiDxe.inf
!endif
+!if $(LSI_SCSI_ENABLE) == TRUE
+INF OvmfPkg/LsiScsiDxe/LsiScsiDxe.inf
+!endif
!if $(SECURE_BOOT_ENABLE) == TRUE
INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -308,9 +326,11 @@ INF MdeModulePkg/Universal/Acpi/AcpiPlatformDxe/AcpiPlatformDxe.inf
INF FatPkg/EnhancedFatDxe/Fat.inf
INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
+INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
!if $(TOOL_CHAIN_TAG) != "XCODE5"
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
!endif
INF ShellPkg/Application/Shell/Shell.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.dsc b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.dsc
index 00e5f6527b8..8a0c3e67404 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.dsc
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.dsc
@@ -1,9 +1,10 @@
## @file
# EFI/Framework Open Virtual Machine Firmware (OVMF) platform
#
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
# Copyright (c) 2019, Citrix Systems, Inc.
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -38,6 +39,7 @@
DEFINE NETWORK_IP6_ENABLE = FALSE
DEFINE NETWORK_HTTP_BOOT_ENABLE = FALSE
DEFINE NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ DEFINE NETWORK_ISCSI_ENABLE = TRUE
!include NetworkPkg/NetworkDefines.dsc.inc
@@ -72,6 +74,7 @@
GCC:*_*_X64_GENFW_FLAGS = --keepexceptiontable
INTEL:*_*_X64_GENFW_FLAGS = --keepexceptiontable
!endif
+ RELEASE_*_*_GENFW_FLAGS = --zero
#
# Disable deprecated APIs.
@@ -80,6 +83,8 @@
INTEL:*_*_*_CC_FLAGS = /D DISABLE_NEW_DEPRECATED_INTERFACES
GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+!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
@@ -107,6 +112,9 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf
@@ -143,6 +151,7 @@
OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
@@ -157,7 +166,7 @@
SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
- MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
@@ -179,9 +188,12 @@
!else
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
!endif
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
#
@@ -205,6 +217,7 @@
Tcg2PhysicalPresenceLib|OvmfPkg/Library/Tcg2PhysicalPresenceLibNull/DxeTcg2PhysicalPresenceLib.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
RealTimeClockLib|OvmfPkg/Library/XenRealTimeClockLib/XenRealTimeClockLib.inf
+ TimeBaseLib|EmbeddedPkg/Library/TimeBaseLib/TimeBaseLib.inf
!ifdef $(DEBUG_ON_HYPERVISOR_CONSOLE)
DebugLib|OvmfPkg/Library/PlatformDebugLibIoPort/PlatformRomDebugLibIoPortNocheck.inf
!else
@@ -213,6 +226,7 @@
[LibraryClasses.common]
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
[LibraryClasses.common.SEC]
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSecLib.inf
@@ -265,6 +279,7 @@
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
+ MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
[LibraryClasses.common.DXE_CORE]
HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
@@ -289,6 +304,7 @@
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
PciLib|OvmfPkg/Library/DxePciLibI440FxQ35/DxePciLibI440FxQ35.inf
QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/DxeQemuFwCfgS3LibFwCfg.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
[LibraryClasses.common.UEFI_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -334,8 +350,6 @@
################################################################################
[PcdsFeatureFlag]
gEfiMdeModulePkgTokenSpaceGuid.PcdHiiOsRuntimeSupport|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSupportUefiDecompress|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
@@ -349,6 +363,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeMemorySize|1
gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
gEfiMdePkgTokenSpaceGuid.PcdMaximumGuidedExtractHandler|0x10
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength|0
!if ($(FD_SIZE_IN_KB) == 1024) || ($(FD_SIZE_IN_KB) == 2048)
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
@@ -371,6 +386,8 @@
!endif
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|TRUE
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x07
@@ -430,8 +447,8 @@
# Point to the MdeModulePkg/Application/UiApp/UiApp.inf
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
- ## Xen vlapic's frequence is 100 MHz
- gEfiMdePkgTokenSpaceGuid.PcdFSBClock|100000000
+ # We populate DXE IPL tables with 1G pages preferably on Xen
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
################################################################################
#
@@ -456,6 +473,7 @@
gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Base|0x0
gUefiOvmfPkgTokenSpaceGuid.PcdPciMmio64Size|0x800000000
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock|100000000
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|0
# Set video resolution for text setup.
@@ -541,6 +559,7 @@
MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
<LibraryClasses>
PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+ PciHostBridgeUtilityLib|OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.inf
NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
}
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
@@ -675,6 +694,10 @@
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf {
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.fdf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.fdf
index ea700962264..46a39bcc984 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.fdf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/OvmfXen.fdf
@@ -363,6 +363,7 @@ INF MdeModulePkg/Universal/Disk/UdfDxe/UdfDxe.inf
!if $(TOOL_CHAIN_TAG) != "XCODE5"
INF ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf
+INF ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
INF OvmfPkg/LinuxInitrdDynamicShellCommand/LinuxInitrdDynamicShellCommand.inf
!endif
INF ShellPkg/Application/Shell/Shell.inf
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
index be799b6ff9b..7eb5702cc22 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Ubuntu-GCC5.yml
@@ -10,14 +10,16 @@
##
trigger:
- master
+ - stable/*
pr:
- master
+ - stable/*
jobs:
- job: Platform_CI
variables:
package: 'OvmfPkg'
- vm_image: 'ubuntu-latest'
+ vm_image: 'ubuntu-18.04'
should_run: true
run_flags: "MAKE_STARTUP_NSH=TRUE QEMU_HEADLESS=TRUE"
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
index 565af4348a5..1a99a2d3e49 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformCI/.azurepipelines/Windows-VS2019.yml
@@ -10,8 +10,10 @@
##
trigger:
- master
+ - stable/*
pr:
- master
+ - stable/*
jobs:
- job: Platform_CI
variables:
@@ -132,7 +134,7 @@ jobs:
build_flags: $(Build.Flags)
run_flags: $(Run.Flags)
extra_install_step:
- - powershell: choco install qemu; Write-Host "##vso[task.prependpath]c:\Program Files\qemu"
+ - powershell: choco install qemu --version=2020.08.14; Write-Host "##vso[task.prependpath]c:\Program Files\qemu"
displayName: Install QEMU and Set QEMU on path # friendly name displayed in the UI
condition: and(gt(variables.pkg_count, 0), succeeded())
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/AmdSev.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/AmdSev.c
index 0734e166da5..38ca819d4c4 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/AmdSev.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/AmdSev.c
@@ -1,7 +1,7 @@
/**@file
Initialize Secure Encrypted Virtualization (SEV) support
- Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,19 +10,127 @@
// The package level header files this module uses
//
#include <IndustryStandard/Q35MchIch9.h>
+#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/MemEncryptSevLib.h>
+#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <PiPei.h>
-#include <Register/Amd/Cpuid.h>
-#include <Register/Cpuid.h>
+#include <Register/Amd/Msr.h>
#include <Register/Intel/SmramSaveStateMap.h>
#include "Platform.h"
/**
+ Initialize SEV-ES support if running as an SEV-ES guest.
+
+ **/
+STATIC
+VOID
+AmdSevEsInitialize (
+ VOID
+ )
+{
+ UINT8 *GhcbBase;
+ PHYSICAL_ADDRESS GhcbBasePa;
+ UINTN GhcbPageCount;
+ UINT8 *GhcbBackupBase;
+ UINT8 *GhcbBackupPages;
+ UINTN GhcbBackupPageCount;
+ SEV_ES_PER_CPU_DATA *SevEsData;
+ UINTN PageCount;
+ RETURN_STATUS PcdStatus, DecryptStatus;
+ IA32_DESCRIPTOR Gdtr;
+ VOID *Gdt;
+
+ if (!MemEncryptSevEsIsEnabled ()) {
+ return;
+ }
+
+ PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ //
+ // Allocate GHCB and per-CPU variable pages.
+ // Since the pages must survive across the UEFI to OS transition
+ // make them reserved.
+ //
+ GhcbPageCount = mMaxCpuCount * 2;
+ GhcbBase = AllocateReservedPages (GhcbPageCount);
+ ASSERT (GhcbBase != NULL);
+
+ GhcbBasePa = (PHYSICAL_ADDRESS)(UINTN) GhcbBase;
+
+ //
+ // Each vCPU gets two consecutive pages, the first is the GHCB and the
+ // second is the per-CPU variable page. Loop through the allocation and
+ // only clear the encryption mask for the GHCB pages.
+ //
+ for (PageCount = 0; PageCount < GhcbPageCount; PageCount += 2) {
+ DecryptStatus = MemEncryptSevClearPageEncMask (
+ 0,
+ GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),
+ 1,
+ TRUE
+ );
+ ASSERT_RETURN_ERROR (DecryptStatus);
+ }
+
+ ZeroMem (GhcbBase, EFI_PAGES_TO_SIZE (GhcbPageCount));
+
+ PcdStatus = PcdSet64S (PcdGhcbBase, GhcbBasePa);
+ ASSERT_RETURN_ERROR (PcdStatus);
+ PcdStatus = PcdSet64S (PcdGhcbSize, EFI_PAGES_TO_SIZE (GhcbPageCount));
+ ASSERT_RETURN_ERROR (PcdStatus);
+
+ DEBUG ((DEBUG_INFO,
+ "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",
+ (UINT64)GhcbPageCount, GhcbBase));
+
+ //
+ // Allocate #VC recursion backup pages. The number of backup pages needed is
+ // one less than the maximum VC count.
+ //
+ GhcbBackupPageCount = mMaxCpuCount * (VMGEXIT_MAXIMUM_VC_COUNT - 1);
+ GhcbBackupBase = AllocatePages (GhcbBackupPageCount);
+ ASSERT (GhcbBackupBase != NULL);
+
+ GhcbBackupPages = GhcbBackupBase;
+ for (PageCount = 1; PageCount < GhcbPageCount; PageCount += 2) {
+ SevEsData =
+ (SEV_ES_PER_CPU_DATA *)(GhcbBase + EFI_PAGES_TO_SIZE (PageCount));
+ SevEsData->GhcbBackupPages = GhcbBackupPages;
+
+ GhcbBackupPages += EFI_PAGE_SIZE * (VMGEXIT_MAXIMUM_VC_COUNT - 1);
+ }
+
+ DEBUG ((DEBUG_INFO,
+ "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",
+ (UINT64)GhcbBackupPageCount, GhcbBackupBase));
+
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);
+
+ //
+ // The SEV support will clear the C-bit from non-RAM areas. The early GDT
+ // lives in a non-RAM area, so when an exception occurs (like a #VC) the GDT
+ // will be read as un-encrypted even though it was created before the C-bit
+ // was cleared (encrypted). This will result in a failure to be able to
+ // handle the exception.
+ //
+ AsmReadGdtr (&Gdtr);
+
+ Gdt = AllocatePages (EFI_SIZE_TO_PAGES ((UINTN) Gdtr.Limit + 1));
+ ASSERT (Gdt != NULL);
+
+ CopyMem (Gdt, (VOID *) Gdtr.Base, Gdtr.Limit + 1);
+ Gdtr.Base = (UINTN) Gdt;
+ AsmWriteGdtr (&Gdtr);
+}
+
+/**
+
Function checks if SEV support is available, if present then it sets
the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
@@ -32,7 +140,6 @@ AmdSevInitialize (
VOID
)
{
- CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
UINT64 EncryptionMask;
RETURN_STATUS PcdStatus;
@@ -44,14 +151,9 @@ AmdSevInitialize (
}
//
- // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
- //
- AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
- EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
-
- //
// Set Memory Encryption Mask PCD
//
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();
PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
ASSERT_RETURN_ERROR (PcdStatus);
@@ -103,4 +205,9 @@ AmdSevInitialize (
);
}
}
+
+ //
+ // Check and perform SEV-ES initialization if required.
+ //
+ AmdSevEsInitialize ();
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/MemDetect.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/MemDetect.c
index d6695182a1a..2bc8b0fa2fd 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/MemDetect.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/MemDetect.c
@@ -27,6 +27,7 @@ Module Name:
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
#include <Library/IoLib.h>
+#include <Library/MemEncryptSevLib.h>
#include <Library/PcdLib.h>
#include <Library/PciLib.h>
#include <Library/PeimEntryPoint.h>
@@ -938,6 +939,33 @@ InitializeRamRegions (
(UINT64)(UINTN) PcdGet32 (PcdOvmfSecPageTablesSize),
EfiACPIMemoryNVS
);
+
+ if (MemEncryptSevEsIsEnabled ()) {
+ //
+ // If SEV-ES is enabled, reserve the GHCB-related memory area. This
+ // includes the extra page table used to break down the 2MB page
+ // mapping into 4KB page entries where the GHCB resides and the
+ // GHCB area itself.
+ //
+ // Since this memory range will be used by the Reset Vector on S3
+ // resume, it must be reserved as ACPI NVS.
+ //
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecGhcbPageTableBase),
+ (UINT64)(UINTN) PcdGet32 (PcdOvmfSecGhcbPageTableSize),
+ EfiACPIMemoryNVS
+ );
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecGhcbBase),
+ (UINT64)(UINTN) PcdGet32 (PcdOvmfSecGhcbSize),
+ EfiACPIMemoryNVS
+ );
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) PcdGet32 (PcdOvmfSecGhcbBackupBase),
+ (UINT64)(UINTN) PcdGet32 (PcdOvmfSecGhcbBackupSize),
+ EfiACPIMemoryNVS
+ );
+ }
#endif
}
@@ -995,5 +1023,25 @@ InitializeRamRegions (
);
}
}
+
+#ifdef MDE_CPU_X64
+ if (MemEncryptSevEsIsEnabled ()) {
+ //
+ // If SEV-ES is enabled, reserve the SEV-ES work area.
+ //
+ // Since this memory range will be used by the Reset Vector on S3
+ // resume, it must be reserved as ACPI NVS.
+ //
+ // If S3 is unsupported, then various drivers might still write to the
+ // work area. We ought to prevent DXE from serving allocation requests
+ // such that they would overlap the work area.
+ //
+ BuildMemoryAllocationHob (
+ (EFI_PHYSICAL_ADDRESS)(UINTN) FixedPcdGet32 (PcdSevEsWorkAreaBase),
+ (UINT64)(UINTN) FixedPcdGet32 (PcdSevEsWorkAreaSize),
+ mS3Supported ? EfiACPIMemoryNVS : EfiBootServicesData
+ );
+ }
+#endif
}
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf
index 7ca27a5cf66..c534b119918 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -76,6 +76,10 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
gUefiOvmfPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
@@ -100,11 +104,14 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy
gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
gUefiCpuPkgTokenSpaceGuid.PcdCpuBootLogicalProcessorNumber
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled
#[FixedPcd]
# gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
@@ -113,6 +120,10 @@
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
gEmbeddedTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdCsmEnable
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
index fc899895a9a..610932ace65 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
@@ -38,6 +38,7 @@
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
OvmfPkg/OvmfPkg.dec
[LibraryClasses]
@@ -52,6 +53,7 @@
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeLib
+ VmgExitLib
[Guids]
gEfiEventVirtualAddressChangeGuid # ALWAYS_CONSUMED
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
index aa59562ee80..c718e0bc7e7 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c
@@ -9,6 +9,7 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
#include <Library/PcdLib.h>
#include "QemuFlash.h"
@@ -80,6 +81,21 @@ QemuFlashDetected (
DEBUG ((DEBUG_INFO, "QEMU Flash: Attempting flash detection at %p\n", Ptr));
+ if (MemEncryptSevEsIsEnabled ()) {
+ //
+ // When SEV-ES is enabled, the check below can result in an infinite
+ // loop with respect to a nested page fault. When the memslot is mapped
+ // read-only, the nested page table entry is read-only. The check below
+ // will cause a nested page fault that cannot be emulated, causing
+ // the instruction to retried over and over. For SEV-ES, acknowledge that
+ // the FD appears as ROM and not as FLASH, but report FLASH anyway because
+ // FLASH behavior can be simulated using VMGEXIT.
+ //
+ DEBUG ((DEBUG_INFO,
+ "QEMU Flash: SEV-ES enabled, assuming FD behaves as FLASH\n"));
+ return TRUE;
+ }
+
OriginalUint8 = *Ptr;
*Ptr = CLEAR_STATUS_CMD;
ProbeUint8 = *Ptr;
@@ -181,8 +197,9 @@ QemuFlashWrite (
//
Ptr = QemuFlashPtr (Lba, Offset);
for (Loop = 0; Loop < *NumBytes; Loop++) {
- *Ptr = WRITE_BYTE_CMD;
- *Ptr = Buffer[Loop];
+ QemuFlashPtrWrite (Ptr, WRITE_BYTE_CMD);
+ QemuFlashPtrWrite (Ptr, Buffer[Loop]);
+
Ptr++;
}
@@ -190,7 +207,7 @@ QemuFlashWrite (
// Restore flash to read mode
//
if (*NumBytes > 0) {
- *(Ptr - 1) = READ_ARRAY_CMD;
+ QemuFlashPtrWrite (Ptr - 1, READ_ARRAY_CMD);
}
return EFI_SUCCESS;
@@ -215,8 +232,8 @@ QemuFlashEraseBlock (
}
Ptr = QemuFlashPtr (Lba, 0);
- *Ptr = BLOCK_ERASE_CMD;
- *Ptr = BLOCK_ERASE_CONFIRM_CMD;
+ QemuFlashPtrWrite (Ptr, BLOCK_ERASE_CMD);
+ QemuFlashPtrWrite (Ptr, BLOCK_ERASE_CONFIRM_CMD);
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h
index de12f03bb57..5d61ded106c 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.h
@@ -89,5 +89,18 @@ QemuFlashBeforeProbe (
IN UINTN FdBlockCount
);
+/**
+ Write to QEMU Flash
+
+ @param[in] Ptr Pointer to the location to write.
+ @param[in] Value The value to write.
+
+**/
+VOID
+QemuFlashPtrWrite (
+ IN volatile UINT8 *Ptr,
+ IN UINT8 Value
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
index 854a471add8..6b0286a0350 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashDxe.c
@@ -10,14 +10,23 @@
**/
#include <Library/UefiRuntimeLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Msr.h>
#include "QemuFlash.h"
+STATIC EFI_PHYSICAL_ADDRESS mSevEsFlashPhysBase;
+
VOID
QemuFlashConvertPointers (
VOID
)
{
+ if (MemEncryptSevEsIsEnabled ()) {
+ mSevEsFlashPhysBase = (UINTN) mFlashBase;
+ }
+
EfiConvertPointer (0x0, (VOID **) &mFlashBase);
}
@@ -32,3 +41,54 @@ QemuFlashBeforeProbe (
// Do nothing
//
}
+
+/**
+ Write to QEMU Flash
+
+ @param[in] Ptr Pointer to the location to write.
+ @param[in] Value The value to write.
+
+**/
+VOID
+QemuFlashPtrWrite (
+ IN volatile UINT8 *Ptr,
+ IN UINT8 Value
+ )
+{
+ if (MemEncryptSevEsIsEnabled ()) {
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ GHCB *Ghcb;
+ EFI_PHYSICAL_ADDRESS PhysAddr;
+ BOOLEAN InterruptState;
+
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+ Ghcb = Msr.Ghcb;
+
+ //
+ // The MMIO write needs to be to the physical address of the flash pointer.
+ // Since this service is available as part of the EFI runtime services,
+ // account for a non-identity mapped VA after SetVirtualAddressMap().
+ //
+ if (mSevEsFlashPhysBase == 0) {
+ PhysAddr = (UINTN) Ptr;
+ } else {
+ PhysAddr = mSevEsFlashPhysBase + (Ptr - mFlashBase);
+ }
+
+ //
+ // Writing to flash is emulated by the hypervisor through the use of write
+ // protection. This won't work for an SEV-ES guest because the write won't
+ // be recognized as a true MMIO write, which would result in the required
+ // #VC exception. Instead, use the the VMGEXIT MMIO write support directly
+ // to perform the update.
+ //
+ VmgInit (Ghcb, &InterruptState);
+ Ghcb->SharedBuffer[0] = Value;
+ Ghcb->SaveArea.SwScratch = (UINT64) (UINTN) Ghcb->SharedBuffer;
+ VmgSetOffsetValid (Ghcb, GhcbSwScratch);
+ VmgExit (Ghcb, SVM_EXIT_MMIO_WRITE, PhysAddr, 1);
+ VmgDone (Ghcb, InterruptState);
+ } else {
+ *Ptr = Value;
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
index e02b66142ea..61523294bd7 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlashSmm.c
@@ -46,3 +46,19 @@ QemuFlashBeforeProbe (
);
ASSERT_EFI_ERROR (Status);
}
+
+/**
+ Write to QEMU Flash
+
+ @param[in] Ptr Pointer to the location to write.
+ @param[in] Value The value to write.
+
+**/
+VOID
+QemuFlashPtrWrite (
+ IN volatile UINT8 *Ptr,
+ IN UINT8 Value
+ )
+{
+ *Ptr = Value;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/README b/src/VBox/Devices/EFI/Firmware/OvmfPkg/README
index bc227557fcb..cd50a6c8b57 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/README
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/README
@@ -303,16 +303,27 @@ and encrypted connection.
* Besides the trusted certificates, it's also possible to configure the trusted
cipher suites for HTTPS through another fw_cfg entry: etc/edk2/https/ciphers.
- -fw_cfg name=etc/edk2/https/ciphers,file=<cipher suites>
-
OVMF expects a binary UINT16 array which comprises the cipher suites HEX
IDs(*4). If the cipher suite list is given, OVMF will choose the cipher
suite from the intersection of the given list and the built-in cipher
suites. Otherwise, OVMF just chooses whatever proper cipher suites from the
built-in ones.
- While the tool(*5) to create the cipher suite array is still under
- development, the array can be generated with the following script:
+ - Using QEMU 5.2 or later, QEMU can expose the ordered list of permitted TLS
+ cipher suites from the host side to OVMF:
+
+ -object tls-cipher-suites,id=mysuite0,priority=@SYSTEM \
+ -fw_cfg name=etc/edk2/https/ciphers,gen_id=mysuite0
+
+ (Refer to the QEMU manual and to
+ <https://gnutls.org/manual/html_node/Priority-Strings.html> for more
+ information on the "priority" property.)
+
+ - Using QEMU 5.1 or earlier, the array has to be passed from a file:
+
+ -fw_cfg name=etc/edk2/https/ciphers,file=<cipher suites>
+
+ whose contents can be generated with the following script, for example:
export LC_ALL=C
openssl ciphers -V \
@@ -337,15 +348,10 @@ and encrypted connection.
-e 's/^ *0x([0-9A-F]{2}),0x([0-9A-F]{2}) - .*$/\\\\x\1 \\\\x\2/p' \
| xargs -r -- printf -- '%b' > ciphers.bin
-* In the future (after release 2.12), QEMU should populate both above fw_cfg
- files automatically from the local host configuration, and enable the user
- to override either with dedicated options or properties.
-
(*1) See "31.4.1 Signature Database" in UEFI specification 2.7 errata A.
(*2) p11-kit: https://github.com/p11-glue/p11-kit/
(*3) efisiglist: https://github.com/rhboot/pesign/blob/master/src/efisiglist.c
(*4) https://wiki.mozilla.org/Security/Server_Side_TLS#Cipher_names_correspondence_table
-(*5) update-crypto-policies: https://gitlab.com/redhat-crypto/fedora-crypto-policies
=== OVMF Flash Layout ===
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
new file mode 100644
index 00000000000..2f4a0a95a82
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia16/ResetVectorVtf0.asm
@@ -0,0 +1,148 @@
+;------------------------------------------------------------------------------
+; @file
+; First code executed by processor after resetting.
+; Derived from UefiCpuPkg/ResetVector/Vtf0/Ia16/ResetVectorVtf0.asm
+;
+; Copyright (c) 2008 - 2014, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS 16
+
+ALIGN 16
+
+;
+; Pad the image size to 4k when page tables are in VTF0
+;
+; If the VTF0 image has page tables built in, then we need to make
+; sure the end of VTF0 is 4k above where the page tables end.
+;
+; This is required so the page tables will be 4k aligned when VTF0 is
+; located just below 0x100000000 (4GB) in the firmware device.
+;
+%ifdef ALIGN_TOP_TO_4K_FOR_PAGING
+ TIMES (0x1000 - ($ - EndOfPageTables) - 0x20) DB 0
+%endif
+
+;
+; Padding to ensure first guid starts at 0xffffffd0
+;
+TIMES (15 - ((guidedStructureEnd - guidedStructureStart + 15) % 16)) DB 0
+
+; GUIDed structure. To traverse this you should first verify the
+; presence of the table footer guid
+; (96b582de-1fb2-45f7-baea-a366c55a082d) at 0xffffffd0. If that
+; is found, the two bytes at 0xffffffce are the entire table length.
+;
+; The table is composed of structures with the form:
+;
+; Data (arbitrary bytes identified by guid)
+; length from start of data to end of guid (2 bytes)
+; guid (16 bytes)
+;
+; so work back from the footer using the length to traverse until you
+; either find the guid you're looking for or run off the beginning of
+; the table.
+;
+guidedStructureStart:
+
+;
+; SEV Secret block
+;
+; This describes the guest ram area where the hypervisor should
+; inject the secret. The data format is:
+;
+; base physical address (32 bit word)
+; table length (32 bit word)
+;
+; GUID (SEV secret block): 4c2eb361-7d9b-4cc3-8081-127c90d3d294
+;
+sevSecretBlockStart:
+ DD SEV_LAUNCH_SECRET_BASE
+ DD SEV_LAUNCH_SECRET_SIZE
+ DW sevSecretBlockEnd - sevSecretBlockStart
+ DB 0x61, 0xB3, 0x2E, 0x4C, 0x9B, 0x7D, 0xC3, 0x4C
+ DB 0x80, 0x81, 0x12, 0x7C, 0x90, 0xD3, 0xD2, 0x94
+sevSecretBlockEnd:
+
+;
+; SEV-ES Processor Reset support
+;
+; sevEsResetBlock:
+; For the initial boot of an AP under SEV-ES, the "reset" RIP must be
+; programmed to the RAM area defined by SEV_ES_AP_RESET_IP. The data
+; format is:
+;
+; IP value [0:15]
+; CS segment base [31:16]
+;
+; GUID (SEV-ES reset block): 00f771de-1a7e-4fcb-890e-68c77e2fb44e
+;
+; A hypervisor reads the CS segement base and IP value. The CS segment base
+; value represents the high order 16-bits of the CS segment base, so the
+; hypervisor must left shift the value of the CS segement base by 16 bits to
+; form the full CS segment base for the CS segment register. It would then
+; program the EIP register with the IP value as read.
+;
+
+sevEsResetBlockStart:
+ DD SEV_ES_AP_RESET_IP
+ DW sevEsResetBlockEnd - sevEsResetBlockStart
+ DB 0xDE, 0x71, 0xF7, 0x00, 0x7E, 0x1A, 0xCB, 0x4F
+ DB 0x89, 0x0E, 0x68, 0xC7, 0x7E, 0x2F, 0xB4, 0x4E
+sevEsResetBlockEnd:
+
+;
+; Table footer:
+;
+; length of whole table (16 bit word)
+; GUID (table footer): 96b582de-1fb2-45f7-baea-a366c55a082d
+;
+ DW guidedStructureEnd - guidedStructureStart
+ DB 0xDE, 0x82, 0xB5, 0x96, 0xB2, 0x1F, 0xF7, 0x45
+ DB 0xBA, 0xEA, 0xA3, 0x66, 0xC5, 0x5A, 0x08, 0x2D
+
+guidedStructureEnd:
+
+ALIGN 16
+
+applicationProcessorEntryPoint:
+;
+; Application Processors entry point
+;
+; GenFv generates code aligned on a 4k boundary which will jump to this
+; location. (0xffffffe0) This allows the Local APIC Startup IPI to be
+; used to wake up the application processors.
+;
+ jmp EarlyApInitReal16
+
+ALIGN 8
+
+ DD 0
+
+;
+; The VTF signature
+;
+; VTF-0 means that the VTF (Volume Top File) code does not require
+; any fixups.
+;
+vtfSignature:
+ DB 'V', 'T', 'F', 0
+
+ALIGN 16
+
+resetVector:
+;
+; Reset Vector
+;
+; This is where the processor will begin execution
+;
+ nop
+ nop
+ jmp EarlyBspInitReal16
+
+ALIGN 16
+
+fourGigabytes:
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
new file mode 100644
index 00000000000..656d335e574
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/Flat32ToFlat64.asm
@@ -0,0 +1,118 @@
+;------------------------------------------------------------------------------
+; @file
+; Transition from 32 bit flat protected mode into 64 bit flat protected mode
+;
+; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;------------------------------------------------------------------------------
+
+BITS 32
+
+;
+; Modified: EAX, ECX, EDX
+;
+Transition32FlatTo64Flat:
+
+ OneTimeCall SetCr3ForPageTables64
+
+ mov eax, cr4
+ bts eax, 5 ; enable PAE
+ mov cr4, eax
+
+ mov ecx, 0xc0000080
+ rdmsr
+ bts eax, 8 ; set LME
+ wrmsr
+
+ ;
+ ; SEV-ES mitigation check support
+ ;
+ xor ebx, ebx
+
+ cmp byte[SEV_ES_WORK_AREA], 0
+ jz EnablePaging
+
+ ;
+ ; SEV-ES is active, perform a quick sanity check against the reported
+ ; encryption bit position. This is to help mitigate against attacks where
+ ; the hypervisor reports an incorrect encryption bit position.
+ ;
+ ; This is the first step in a two step process. Before paging is enabled
+ ; writes to memory are encrypted. Using the RDRAND instruction (available
+ ; on all SEV capable processors), write 64-bits of random data to the
+ ; SEV_ES_WORK_AREA and maintain the random data in registers (register
+ ; state is protected under SEV-ES). This will be used in the second step.
+ ;
+RdRand1:
+ rdrand ecx
+ jnc RdRand1
+ mov dword[SEV_ES_WORK_AREA_RDRAND], ecx
+RdRand2:
+ rdrand edx
+ jnc RdRand2
+ mov dword[SEV_ES_WORK_AREA_RDRAND + 4], edx
+
+ ;
+ ; Use EBX instead of the SEV_ES_WORK_AREA memory to determine whether to
+ ; perform the second step.
+ ;
+ mov ebx, 1
+
+EnablePaging:
+ mov eax, cr0
+ bts eax, 31 ; set PG
+ mov cr0, eax ; enable paging
+
+ jmp LINEAR_CODE64_SEL:ADDR_OF(jumpTo64BitAndLandHere)
+BITS 64
+jumpTo64BitAndLandHere:
+
+ ;
+ ; Check if the second step of the SEV-ES mitigation is to be performed.
+ ;
+ test ebx, ebx
+ jz InsnCompare
+
+ ;
+ ; SEV-ES is active, perform the second step of the encryption bit postion
+ ; mitigation check. The ECX and EDX register contain data from RDRAND that
+ ; was stored to memory in encrypted form. If the encryption bit position is
+ ; valid, the contents of ECX and EDX will match the memory location.
+ ;
+ cmp dword[SEV_ES_WORK_AREA_RDRAND], ecx
+ jne SevEncBitHlt
+ cmp dword[SEV_ES_WORK_AREA_RDRAND + 4], edx
+ jne SevEncBitHlt
+
+ ;
+ ; If SEV or SEV-ES is active, perform a quick sanity check against
+ ; the reported encryption bit position. This is to help mitigate
+ ; against attacks where the hypervisor reports an incorrect encryption
+ ; bit position. If SEV is not active, this check will always succeed.
+ ;
+ ; The cmp instruction compares the first four bytes of the cmp instruction
+ ; itself (which will be read decrypted if SEV or SEV-ES is active and the
+ ; encryption bit position is valid) against the immediate within the
+ ; instruction (an instruction fetch is always decrypted correctly by
+ ; hardware) based on RIP relative addressing.
+ ;
+InsnCompare:
+ cmp dword[rel InsnCompare], 0xFFF63D81
+ je GoodCompare
+
+ ;
+ ; The hypervisor provided an incorrect encryption bit position, do not
+ ; proceed.
+ ;
+SevEncBitHlt:
+ cli
+ hlt
+ jmp SevEncBitHlt
+
+GoodCompare:
+ debugShowPostCode POSTCODE_64BIT_MODE
+
+ OneTimeCallRet Transition32FlatTo64Flat
+
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 67c4404ed75..00a4403a17d 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -3,6 +3,7 @@
; Sets the CR3 register for 64-bit paging
;
; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2017 - 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
;------------------------------------------------------------------------------
@@ -21,6 +22,11 @@ BITS 32
%define PAGE_2M_MBO 0x080
%define PAGE_2M_PAT 0x01000
+%define PAGE_4K_PDE_ATTR (PAGE_ACCESSED + \
+ PAGE_DIRTY + \
+ PAGE_READ_WRITE + \
+ PAGE_PRESENT)
+
%define PAGE_2M_PDE_ATTR (PAGE_2M_MBO + \
PAGE_ACCESSED + \
PAGE_DIRTY + \
@@ -31,13 +37,62 @@ BITS 32
PAGE_READ_WRITE + \
PAGE_PRESENT)
-; Check if Secure Encrypted Virtualization (SEV) feature is enabled
;
-; If SEV is enabled then EAX will be at least 32
+; SEV-ES #VC exception handler support
+;
+; #VC handler local variable locations
+;
+%define VC_CPUID_RESULT_EAX 0
+%define VC_CPUID_RESULT_EBX 4
+%define VC_CPUID_RESULT_ECX 8
+%define VC_CPUID_RESULT_EDX 12
+%define VC_GHCB_MSR_EDX 16
+%define VC_GHCB_MSR_EAX 20
+%define VC_CPUID_REQUEST_REGISTER 24
+%define VC_CPUID_FUNCTION 28
+
+; #VC handler total local variable size
+;
+%define VC_VARIABLE_SIZE 32
+
+; #VC handler GHCB CPUID request/response protocol values
+;
+%define GHCB_CPUID_REQUEST 4
+%define GHCB_CPUID_RESPONSE 5
+%define GHCB_CPUID_REGISTER_SHIFT 30
+%define CPUID_INSN_LEN 2
+
+
+; Check if Secure Encrypted Virtualization (SEV) features are enabled.
+;
+; Register usage is tight in this routine, so multiple calls for the
+; same CPUID and MSR data are performed to keep things simple.
+;
+; Modified: EAX, EBX, ECX, EDX, ESP
+;
+; If SEV is enabled then EAX will be at least 32.
; If SEV is disabled then EAX will be zero.
;
-CheckSevFeature:
+CheckSevFeatures:
+ ; Set the first byte of the workarea to zero to communicate to the SEC
+ ; phase that SEV-ES is not enabled. If SEV-ES is enabled, the CPUID
+ ; instruction will trigger a #VC exception where the first byte of the
+ ; workarea will be set to one or, if CPUID is not being intercepted,
+ ; the MSR check below will set the first byte of the workarea to one.
+ mov byte[SEV_ES_WORK_AREA], 0
+
+ ;
+ ; Set up exception handlers to check for SEV-ES
+ ; Load temporary RAM stack based on PCDs (see SevEsIdtVmmComm for
+ ; stack usage)
+ ; Establish exception handlers
+ ;
+ mov esp, SEV_ES_VC_TOP_OF_STACK
+ mov eax, ADDR_OF(Idtr)
+ lidt [cs:eax]
+
; Check if we have a valid (0x8000_001F) CPUID leaf
+ ; CPUID raises a #VC exception if running as an SEV-ES guest
mov eax, 0x80000000
cpuid
@@ -47,40 +102,123 @@ CheckSevFeature:
cmp eax, 0x8000001f
jl NoSev
- ; Check for memory encryption feature:
- ; CPUID Fn8000_001F[EAX] - Bit 1
- ;
- mov eax, 0x8000001f
+ ; Check for SEV memory encryption feature:
+ ; CPUID Fn8000_001F[EAX] - Bit 1
+ ; CPUID raises a #VC exception if running as an SEV-ES guest
+ mov eax, 0x8000001f
cpuid
bt eax, 1
jnc NoSev
- ; Check if memory encryption is enabled
+ ; Check if SEV memory encryption is enabled
; MSR_0xC0010131 - Bit 0 (SEV enabled)
mov ecx, 0xc0010131
rdmsr
bt eax, 0
jnc NoSev
+ ; Check for SEV-ES memory encryption feature:
+ ; CPUID Fn8000_001F[EAX] - Bit 3
+ ; CPUID raises a #VC exception if running as an SEV-ES guest
+ mov eax, 0x8000001f
+ cpuid
+ bt eax, 3
+ jnc GetSevEncBit
+
+ ; Check if SEV-ES is enabled
+ ; MSR_0xC0010131 - Bit 1 (SEV-ES enabled)
+ mov ecx, 0xc0010131
+ rdmsr
+ bt eax, 1
+ jnc GetSevEncBit
+
+ ; Set the first byte of the workarea to one to communicate to the SEC
+ ; phase that SEV-ES is enabled.
+ mov byte[SEV_ES_WORK_AREA], 1
+
+GetSevEncBit:
; Get pte bit position to enable memory encryption
; CPUID Fn8000_001F[EBX] - Bits 5:0
;
+ and ebx, 0x3f
mov eax, ebx
- and eax, 0x3f
+
+ ; The encryption bit position is always above 31
+ sub ebx, 32
+ jns SevSaveMask
+
+ ; Encryption bit was reported as 31 or below, enter a HLT loop
+SevEncBitLowHlt:
+ cli
+ hlt
+ jmp SevEncBitLowHlt
+
+SevSaveMask:
+ xor edx, edx
+ bts edx, ebx
+
+ mov dword[SEV_ES_WORK_AREA_ENC_MASK], 0
+ mov dword[SEV_ES_WORK_AREA_ENC_MASK + 4], edx
jmp SevExit
NoSev:
+ ;
+ ; Perform an SEV-ES sanity check by seeing if a #VC exception occurred.
+ ;
+ cmp byte[SEV_ES_WORK_AREA], 0
+ jz NoSevPass
+
+ ;
+ ; A #VC was received, yet CPUID indicates no SEV-ES support, something
+ ; isn't right.
+ ;
+NoSevEsVcHlt:
+ cli
+ hlt
+ jmp NoSevEsVcHlt
+
+NoSevPass:
xor eax, eax
SevExit:
- OneTimeCallRet CheckSevFeature
+ ;
+ ; Clear exception handlers and stack
+ ;
+ push eax
+ mov eax, ADDR_OF(IdtrClear)
+ lidt [cs:eax]
+ pop eax
+ mov esp, 0
+
+ OneTimeCallRet CheckSevFeatures
+
+; Check if Secure Encrypted Virtualization - Encrypted State (SEV-ES) feature
+; is enabled.
+;
+; Modified: EAX
+;
+; If SEV-ES is enabled then EAX will be non-zero.
+; If SEV-ES is disabled then EAX will be zero.
+;
+IsSevEsEnabled:
+ xor eax, eax
+
+ ; During CheckSevFeatures, the SEV_ES_WORK_AREA was set to 1 if
+ ; SEV-ES is enabled.
+ cmp byte[SEV_ES_WORK_AREA], 1
+ jne SevEsDisabled
+
+ mov eax, 1
+
+SevEsDisabled:
+ OneTimeCallRet IsSevEsEnabled
;
; Modified: EAX, EBX, ECX, EDX
;
SetCr3ForPageTables64:
- OneTimeCall CheckSevFeature
+ OneTimeCall CheckSevFeatures
xor edx, edx
test eax, eax
jz SevNotActive
@@ -139,6 +277,46 @@ pageTableEntriesLoop:
mov [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
loop pageTableEntriesLoop
+ OneTimeCall IsSevEsEnabled
+ test eax, eax
+ jz SetCr3
+
+ ;
+ ; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted.
+ ; This requires the 2MB page for this range be broken down into 512 4KB
+ ; pages. All will be marked encrypted, except for the GHCB.
+ ;
+ mov ecx, (GHCB_BASE >> 21)
+ mov eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
+ mov [ecx * 8 + PT_ADDR (0x2000)], eax
+
+ ;
+ ; Page Table Entries (512 * 4KB entries => 2MB)
+ ;
+ mov ecx, 512
+pageTableEntries4kLoop:
+ mov eax, ecx
+ dec eax
+ shl eax, 12
+ add eax, GHCB_BASE & 0xFFE0_0000
+ add eax, PAGE_4K_PDE_ATTR
+ mov [ecx * 8 + GHCB_PT_ADDR - 8], eax
+ mov [(ecx * 8 + GHCB_PT_ADDR - 8) + 4], edx
+ loop pageTableEntries4kLoop
+
+ ;
+ ; Clear the encryption bit from the GHCB entry
+ ;
+ mov ecx, (GHCB_BASE & 0x1F_FFFF) >> 12
+ mov [ecx * 8 + GHCB_PT_ADDR + 4], strict dword 0
+
+ mov ecx, GHCB_SIZE / 4
+ xor eax, eax
+clearGhcbMemoryLoop:
+ mov dword[ecx * 4 + GHCB_BASE - 4], eax
+ loop clearGhcbMemoryLoop
+
+SetCr3:
;
; Set CR3 now that the paging structures are available
;
@@ -146,3 +324,218 @@ pageTableEntriesLoop:
mov cr3, eax
OneTimeCallRet SetCr3ForPageTables64
+
+;
+; Start of #VC exception handling routines
+;
+
+SevEsIdtNotCpuid:
+ ;
+ ; Use VMGEXIT to request termination.
+ ; 1 - #VC was not for CPUID
+ ;
+ mov eax, 1
+ jmp SevEsIdtTerminate
+
+SevEsIdtNoCpuidResponse:
+ ;
+ ; Use VMGEXIT to request termination.
+ ; 2 - GHCB_CPUID_RESPONSE not received
+ ;
+ mov eax, 2
+
+SevEsIdtTerminate:
+ ;
+ ; Use VMGEXIT to request termination. At this point the reason code is
+ ; located in EAX, so shift it left 16 bits to the proper location.
+ ;
+ ; EAX[11:0] => 0x100 - request termination
+ ; EAX[15:12] => 0x1 - OVMF
+ ; EAX[23:16] => 0xXX - REASON CODE
+ ;
+ shl eax, 16
+ or eax, 0x1100
+ xor edx, edx
+ mov ecx, 0xc0010130
+ wrmsr
+ ;
+ ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+ ; mode, so work around this by temporarily switching to 64-bit mode.
+ ;
+BITS 64
+ rep vmmcall
+BITS 32
+
+ ;
+ ; We shouldn't come back from the VMGEXIT, but if we do, just loop.
+ ;
+SevEsIdtHlt:
+ hlt
+ jmp SevEsIdtHlt
+ iret
+
+ ;
+ ; Total stack usage for the #VC handler is 44 bytes:
+ ; - 12 bytes for the exception IRET (after popping error code)
+ ; - 32 bytes for the local variables.
+ ;
+SevEsIdtVmmComm:
+ ;
+ ; If we're here, then we are an SEV-ES guest and this
+ ; was triggered by a CPUID instruction
+ ;
+ ; Set the first byte of the workarea to one to communicate that
+ ; a #VC was taken.
+ mov byte[SEV_ES_WORK_AREA], 1
+
+ pop ecx ; Error code
+ cmp ecx, 0x72 ; Be sure it was CPUID
+ jne SevEsIdtNotCpuid
+
+ ; Set up local variable room on the stack
+ ; CPUID function : + 28
+ ; CPUID request register : + 24
+ ; GHCB MSR (EAX) : + 20
+ ; GHCB MSR (EDX) : + 16
+ ; CPUID result (EDX) : + 12
+ ; CPUID result (ECX) : + 8
+ ; CPUID result (EBX) : + 4
+ ; CPUID result (EAX) : + 0
+ sub esp, VC_VARIABLE_SIZE
+
+ ; Save the CPUID function being requested
+ mov [esp + VC_CPUID_FUNCTION], eax
+
+ ; The GHCB CPUID protocol uses the following mapping to request
+ ; a specific register:
+ ; 0 => EAX, 1 => EBX, 2 => ECX, 3 => EDX
+ ;
+ ; Set EAX as the first register to request. This will also be used as a
+ ; loop variable to request all register values (EAX to EDX).
+ xor eax, eax
+ mov [esp + VC_CPUID_REQUEST_REGISTER], eax
+
+ ; Save current GHCB MSR value
+ mov ecx, 0xc0010130
+ rdmsr
+ mov [esp + VC_GHCB_MSR_EAX], eax
+ mov [esp + VC_GHCB_MSR_EDX], edx
+
+NextReg:
+ ;
+ ; Setup GHCB MSR
+ ; GHCB_MSR[63:32] = CPUID function
+ ; GHCB_MSR[31:30] = CPUID register
+ ; GHCB_MSR[11:0] = CPUID request protocol
+ ;
+ mov eax, [esp + VC_CPUID_REQUEST_REGISTER]
+ cmp eax, 4
+ jge VmmDone
+
+ shl eax, GHCB_CPUID_REGISTER_SHIFT
+ or eax, GHCB_CPUID_REQUEST
+ mov edx, [esp + VC_CPUID_FUNCTION]
+ mov ecx, 0xc0010130
+ wrmsr
+
+ ;
+ ; Issue VMGEXIT - NASM doesn't support the vmmcall instruction in 32-bit
+ ; mode, so work around this by temporarily switching to 64-bit mode.
+ ;
+BITS 64
+ rep vmmcall
+BITS 32
+
+ ;
+ ; Read GHCB MSR
+ ; GHCB_MSR[63:32] = CPUID register value
+ ; GHCB_MSR[31:30] = CPUID register
+ ; GHCB_MSR[11:0] = CPUID response protocol
+ ;
+ mov ecx, 0xc0010130
+ rdmsr
+ mov ecx, eax
+ and ecx, 0xfff
+ cmp ecx, GHCB_CPUID_RESPONSE
+ jne SevEsIdtNoCpuidResponse
+
+ ; Save returned value
+ shr eax, GHCB_CPUID_REGISTER_SHIFT
+ mov [esp + eax * 4], edx
+
+ ; Next register
+ inc word [esp + VC_CPUID_REQUEST_REGISTER]
+
+ jmp NextReg
+
+VmmDone:
+ ;
+ ; At this point we have all CPUID register values. Restore the GHCB MSR,
+ ; set the return register values and return.
+ ;
+ mov eax, [esp + VC_GHCB_MSR_EAX]
+ mov edx, [esp + VC_GHCB_MSR_EDX]
+ mov ecx, 0xc0010130
+ wrmsr
+
+ mov eax, [esp + VC_CPUID_RESULT_EAX]
+ mov ebx, [esp + VC_CPUID_RESULT_EBX]
+ mov ecx, [esp + VC_CPUID_RESULT_ECX]
+ mov edx, [esp + VC_CPUID_RESULT_EDX]
+
+ add esp, VC_VARIABLE_SIZE
+
+ ; Update the EIP value to skip over the now handled CPUID instruction
+ ; (the CPUID instruction has a length of 2)
+ add word [esp], CPUID_INSN_LEN
+ iret
+
+ALIGN 2
+
+Idtr:
+ dw IDT_END - IDT_BASE - 1 ; Limit
+ dd ADDR_OF(IDT_BASE) ; Base
+
+IdtrClear:
+ dw 0 ; Limit
+ dd 0 ; Base
+
+ALIGN 16
+
+;
+; The Interrupt Descriptor Table (IDT)
+; This will be used to determine if SEV-ES is enabled. Upon execution
+; of the CPUID instruction, a VMM Communication Exception will occur.
+; This will tell us if SEV-ES is enabled. We can use the current value
+; of the GHCB MSR to determine the SEV attributes.
+;
+IDT_BASE:
+;
+; Vectors 0 - 28 (No handlers)
+;
+%rep 29
+ dw 0 ; Offset low bits 15..0
+ dw 0x10 ; Selector
+ db 0 ; Reserved
+ db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+ dw 0 ; Offset high bits 31..16
+%endrep
+;
+; Vector 29 (VMM Communication Exception)
+;
+ dw (ADDR_OF(SevEsIdtVmmComm) & 0xffff) ; Offset low bits 15..0
+ dw 0x10 ; Selector
+ db 0 ; Reserved
+ db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+ dw (ADDR_OF(SevEsIdtVmmComm) >> 16) ; Offset high bits 31..16
+;
+; Vectors 30 - 31 (No handlers)
+;
+%rep 2
+ dw 0 ; Offset low bits 15..0
+ dw 0x10 ; Selector
+ db 0 ; Reserved
+ db 0x8E ; Gate Type (IA32_IDT_GATE_TYPE_INTERRUPT_32)
+ dw 0 ; Offset high bits 31..16
+%endrep
+IDT_END:
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.inf
index 7f8562b5ed6..249550ce44a 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.inf
@@ -26,6 +26,7 @@
[Packages]
OvmfPkg/OvmfPkg.dec
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
[BuildOptions]
@@ -33,5 +34,16 @@
*_*_X64_NASMB_FLAGS = -I$(WORKSPACE)/UefiCpuPkg/ResetVector/Vtf0/
[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbPageTableSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+
+[FixedPcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretSize
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.nasmb b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.nasmb
index f652226dbfa..bd19e5980a8 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.nasmb
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/ResetVector/ResetVector.nasmb
@@ -3,6 +3,7 @@
; This file includes all other code files to assemble the reset vector code
;
; Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
;------------------------------------------------------------------------------
@@ -53,7 +54,28 @@
%error "This implementation inherently depends on PcdOvmfSecPageTablesSize"
%endif
+ %if (FixedPcdGet32 (PcdOvmfSecGhcbPageTableSize) != 0x1000)
+ %error "This implementation inherently depends on PcdOvmfSecGhcbPageTableSize"
+ %endif
+
+ %if (FixedPcdGet32 (PcdOvmfSecGhcbSize) != 0x2000)
+ %error "This implementation inherently depends on PcdOvmfSecGhcbSize"
+ %endif
+
+ %if ((FixedPcdGet32 (PcdOvmfSecGhcbBase) >> 21) != \
+ ((FixedPcdGet32 (PcdOvmfSecGhcbBase) + FixedPcdGet32 (PcdOvmfSecGhcbSize) - 1) >> 21))
+ %error "This implementation inherently depends on PcdOvmfSecGhcbBase not straddling a 2MB boundary"
+ %endif
+
%define PT_ADDR(Offset) (FixedPcdGet32 (PcdOvmfSecPageTablesBase) + (Offset))
+
+ %define GHCB_PT_ADDR (FixedPcdGet32 (PcdOvmfSecGhcbPageTableBase))
+ %define GHCB_BASE (FixedPcdGet32 (PcdOvmfSecGhcbBase))
+ %define GHCB_SIZE (FixedPcdGet32 (PcdOvmfSecGhcbSize))
+ %define SEV_ES_WORK_AREA (FixedPcdGet32 (PcdSevEsWorkAreaBase))
+ %define SEV_ES_WORK_AREA_RDRAND (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 8)
+ %define SEV_ES_WORK_AREA_ENC_MASK (FixedPcdGet32 (PcdSevEsWorkAreaBase) + 16)
+ %define SEV_ES_VC_TOP_OF_STACK (FixedPcdGet32 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
%include "Ia32/Flat32ToFlat64.asm"
%include "Ia32/PageTables64.asm"
%endif
@@ -63,5 +85,8 @@
%include "Main.asm"
+ %define SEV_ES_AP_RESET_IP FixedPcdGet32 (PcdSevEsWorkAreaBase)
+ %define SEV_LAUNCH_SECRET_BASE FixedPcdGet32 (PcdSevLaunchSecretBase)
+ %define SEV_LAUNCH_SECRET_SIZE FixedPcdGet32 (PcdSevLaunchSecretSize)
%include "Ia16/ResetVectorVtf0.asm"
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.c
index bc88132a56a..21b8227fef0 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.c
@@ -3,6 +3,7 @@
Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -24,6 +25,10 @@
#include <Library/PeCoffExtraActionLib.h>
#include <Library/ExtractGuidedSectionLib.h>
#include <Library/LocalApicLib.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Register/Amd/Ghcb.h>
+#include <Register/Amd/Msr.h>
#include <Ppi/TemporaryRamSupport.h>
@@ -712,6 +717,120 @@ FindAndReportEntryPoints (
return;
}
+/**
+ Handle an SEV-ES/GHCB protocol check failure.
+
+ Notify the hypervisor using the VMGEXIT instruction that the SEV-ES guest
+ wishes to be terminated.
+
+ @param[in] ReasonCode Reason code to provide to the hypervisor for the
+ termination request.
+
+**/
+STATIC
+VOID
+SevEsProtocolFailure (
+ IN UINT8 ReasonCode
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+
+ //
+ // Use the GHCB MSR Protocol to request termination by the hypervisor
+ //
+ Msr.GhcbPhysicalAddress = 0;
+ Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST;
+ Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB;
+ Msr.GhcbTerminate.ReasonCode = ReasonCode;
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+ AsmVmgExit ();
+
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+/**
+ Validate the SEV-ES/GHCB protocol level.
+
+ Verify that the level of SEV-ES/GHCB protocol supported by the hypervisor
+ and the guest intersect. If they don't intersect, request termination.
+
+**/
+STATIC
+VOID
+SevEsProtocolCheck (
+ VOID
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ GHCB *Ghcb;
+
+ //
+ // Use the GHCB MSR Protocol to obtain the GHCB SEV-ES Information for
+ // protocol checking
+ //
+ Msr.GhcbPhysicalAddress = 0;
+ Msr.GhcbInfo.Function = GHCB_INFO_SEV_INFO_GET;
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+ AsmVmgExit ();
+
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+ if (Msr.GhcbInfo.Function != GHCB_INFO_SEV_INFO) {
+ SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);
+ }
+
+ if (Msr.GhcbProtocol.SevEsProtocolMin > Msr.GhcbProtocol.SevEsProtocolMax) {
+ SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);
+ }
+
+ if ((Msr.GhcbProtocol.SevEsProtocolMin > GHCB_VERSION_MAX) ||
+ (Msr.GhcbProtocol.SevEsProtocolMax < GHCB_VERSION_MIN)) {
+ SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);
+ }
+
+ //
+ // SEV-ES protocol checking succeeded, set the initial GHCB address
+ //
+ Msr.GhcbPhysicalAddress = FixedPcdGet32 (PcdOvmfSecGhcbBase);
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+ Ghcb = Msr.Ghcb;
+ SetMem (Ghcb, sizeof (*Ghcb), 0);
+
+ //
+ // Set the version to the maximum that can be supported
+ //
+ Ghcb->ProtocolVersion = MIN (Msr.GhcbProtocol.SevEsProtocolMax, GHCB_VERSION_MAX);
+ Ghcb->GhcbUsage = GHCB_STANDARD_USAGE;
+}
+
+/**
+ Determine if SEV-ES is active.
+
+ During early booting, SEV-ES support code will set a flag to indicate that
+ SEV-ES is enabled. Return the value of this flag as an indicator that SEV-ES
+ is enabled.
+
+ @retval TRUE SEV-ES is enabled
+ @retval FALSE SEV-ES is not enabled
+
+**/
+STATIC
+BOOLEAN
+SevEsIsEnabled (
+ VOID
+ )
+{
+ SEC_SEV_ES_WORK_AREA *SevEsWorkArea;
+
+ SevEsWorkArea = (SEC_SEV_ES_WORK_AREA *) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+
+ return ((SevEsWorkArea != NULL) && (SevEsWorkArea->SevEsEnabled != 0));
+}
+
VOID
EFIAPI
SecCoreStartupWithStack (
@@ -737,8 +856,63 @@ SecCoreStartupWithStack (
Table[Index] = 0;
}
+ //
+ // Initialize IDT - Since this is before library constructors are called,
+ // we use a loop rather than CopyMem.
+ //
+ IdtTableInStack.PeiService = NULL;
+ for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
+ UINT8 *Src;
+ UINT8 *Dst;
+ UINTN Byte;
+
+ Src = (UINT8 *) &mIdtEntryTemplate;
+ Dst = (UINT8 *) &IdtTableInStack.IdtTable[Index];
+ for (Byte = 0; Byte < sizeof (mIdtEntryTemplate); Byte++) {
+ Dst[Byte] = Src[Byte];
+ }
+ }
+
+ IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
+ IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
+
+ if (SevEsIsEnabled ()) {
+ SevEsProtocolCheck ();
+
+ //
+ // For SEV-ES guests, the exception handler is needed before calling
+ // ProcessLibraryConstructorList() because some of the library constructors
+ // perform some functions that result in #VC exceptions being generated.
+ //
+ // Due to this code executing before library constructors, *all* library
+ // API calls are theoretically interface contract violations. However,
+ // because this is SEC (executing in flash), those constructors cannot
+ // write variables with static storage duration anyway. Furthermore, only
+ // a small, restricted set of APIs, such as AsmWriteIdtr() and
+ // InitializeCpuExceptionHandlers(), are called, where we require that the
+ // underlying library not require constructors to have been invoked and
+ // that the library instance not trigger any #VC exceptions.
+ //
+ AsmWriteIdtr (&IdtDescriptor);
+ InitializeCpuExceptionHandlers (NULL);
+ }
+
ProcessLibraryConstructorList (NULL, NULL);
+ if (!SevEsIsEnabled ()) {
+ //
+ // For non SEV-ES guests, just load the IDTR.
+ //
+ AsmWriteIdtr (&IdtDescriptor);
+ } else {
+ //
+ // Under SEV-ES, the hypervisor can't modify CR0 and so can't enable
+ // caching in order to speed up the boot. Enable caching early for
+ // an SEV-ES guest.
+ //
+ AsmEnableCache ();
+ }
+
DEBUG ((DEBUG_INFO,
"SecCoreStartupWithStack(0x%x, 0x%x)\n",
(UINT32)(UINTN)BootFv,
@@ -751,19 +925,6 @@ SecCoreStartupWithStack (
//
InitializeFloatingPointUnits ();
- //
- // Initialize IDT
- //
- IdtTableInStack.PeiService = NULL;
- for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
- CopyMem (&IdtTableInStack.IdtTable[Index], &mIdtEntryTemplate, sizeof (mIdtEntryTemplate));
- }
-
- IdtDescriptor.Base = (UINTN)&IdtTableInStack.IdtTable;
- IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
-
- AsmWriteIdtr (&IdtDescriptor);
-
#if defined (MDE_CPU_X64)
//
// ASSERT that the Page Tables were set by the reset vector code to
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.inf
index 7c30059029b..7664e21f508 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Sec/SecMain.inf
@@ -50,15 +50,19 @@
PeCoffExtraActionLib
ExtractGuidedSectionLib
LocalApicLib
+ CpuExceptionHandlerLib
[Ppis]
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/SioBusDxe/SioService.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/SioBusDxe/SioService.c
index 261ffc34af4..62df9252e08 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/SioBusDxe/SioService.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/SioBusDxe/SioService.c
@@ -265,7 +265,7 @@ SioModify (
@param[in] DeviceIndex Index of the device supported by this driver.
@retval EFI_SUCCESS The child device has been created successfully.
- @retval Others Error occured during the child device creation.
+ @retval Others Error occurred during the child device creation.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmiFeatures.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmiFeatures.c
index e58e790436e..1ac8dea91e1 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmiFeatures.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmiFeatures.c
@@ -9,6 +9,7 @@
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/QemuFwCfgLib.h>
@@ -21,6 +22,18 @@
// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.
//
#define ICH9_LPC_SMI_F_BROADCAST BIT0
+//
+// The following bit value stands for "enable CPU hotplug, and inject an SMI
+// with control value ICH9_APM_CNT_CPU_HOTPLUG upon hotplug", in the
+// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.
+//
+#define ICH9_LPC_SMI_F_CPU_HOTPLUG BIT1
+//
+// The following bit value stands for "enable CPU hot-unplug, and inject an SMI
+// with control value ICH9_APM_CNT_CPU_HOTPLUG upon hot-unplug", in the
+// "etc/smi/supported-features" and "etc/smi/requested-features" fw_cfg files.
+//
+#define ICH9_LPC_SMI_F_CPU_HOT_UNPLUG BIT2
//
// Provides a scratch buffer (allocated in EfiReservedMemoryType type memory)
@@ -67,6 +80,7 @@ NegotiateSmiFeatures (
UINTN SupportedFeaturesSize;
UINTN RequestedFeaturesSize;
UINTN FeaturesOkSize;
+ UINT64 RequestedFeaturesMask;
//
// Look up the fw_cfg files used for feature negotiation. The selector keys
@@ -104,9 +118,18 @@ NegotiateSmiFeatures (
QemuFwCfgReadBytes (sizeof mSmiFeatures, &mSmiFeatures);
//
- // We want broadcast SMI and nothing else.
+ // We want broadcast SMI, SMI on CPU hotplug, SMI on CPU hot-unplug
+ // and nothing else.
//
- mSmiFeatures &= ICH9_LPC_SMI_F_BROADCAST;
+ RequestedFeaturesMask = ICH9_LPC_SMI_F_BROADCAST;
+ if (!MemEncryptSevIsEnabled ()) {
+ //
+ // For now, we only support hotplug with SEV disabled.
+ //
+ RequestedFeaturesMask |= ICH9_LPC_SMI_F_CPU_HOTPLUG;
+ RequestedFeaturesMask |= ICH9_LPC_SMI_F_CPU_HOT_UNPLUG;
+ }
+ mSmiFeatures &= RequestedFeaturesMask;
QemuFwCfgSelectItem (mRequestedFeaturesItem);
QemuFwCfgWriteBytes (sizeof mSmiFeatures, &mSmiFeatures);
@@ -144,6 +167,20 @@ NegotiateSmiFeatures (
DEBUG ((DEBUG_INFO, "%a: using SMI broadcast\n", __FUNCTION__));
}
+ if ((mSmiFeatures & ICH9_LPC_SMI_F_CPU_HOTPLUG) == 0) {
+ DEBUG ((DEBUG_INFO, "%a: CPU hotplug not negotiated\n", __FUNCTION__));
+ } else {
+ DEBUG ((DEBUG_INFO, "%a: CPU hotplug with SMI negotiated\n",
+ __FUNCTION__));
+ }
+
+ if ((mSmiFeatures & ICH9_LPC_SMI_F_CPU_HOT_UNPLUG) == 0) {
+ DEBUG ((DEBUG_INFO, "%a: CPU hot-unplug not negotiated\n", __FUNCTION__));
+ } else {
+ DEBUG ((DEBUG_INFO, "%a: CPU hot-unplug with SMI negotiated\n",
+ __FUNCTION__));
+ }
+
//
// Negotiation successful (although we may not have gotten the optimal
// feature set).
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
index 4fd4cded676..dc92b88bad2 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/SmmControl2Dxe/SmmControl2Dxe.inf
@@ -46,6 +46,7 @@
BaseLib
DebugLib
IoLib
+ MemEncryptSevLib
MemoryAllocationLib
PcdLib
PciLib
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
index 3dcf127ad71..e3491551579 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
@@ -2,7 +2,7 @@
# Set TPM device type
#
# In SecurityPkg, this module initializes the TPM device type based on a UEFI
-# variable and/or hardware detection. In OvmfPkg, the module only performs TPM2
+# variable and/or hardware detection. In OvmfPkg, the module only performs TPM
# hardware detection.
#
# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
@@ -37,12 +37,12 @@
[LibraryClasses]
PeimEntryPoint
- BaseLib
DebugLib
PeiServicesLib
Tpm2DeviceLib
[LibraryClasses.IA32, LibraryClasses.X64]
+ BaseLib
Tpm12DeviceLib
[Guids]
@@ -57,7 +57,7 @@
gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## PRODUCES
[Depex.IA32, Depex.X64]
- TRUE
+ gOvmfTpmMmioAccessiblePpiGuid
[Depex.ARM, Depex.AARCH64]
gOvmfTpmDiscoveredPpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
index 068c1a8ca6b..cf4b3f1d737 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPeim.c
@@ -2,7 +2,7 @@
Set TPM device type
In SecurityPkg, this module initializes the TPM device type based on a UEFI
- variable and/or hardware detection. In OvmfPkg, the module only performs TPM2
+ variable and/or hardware detection. In OvmfPkg, the module only performs TPM
hardware detection.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
new file mode 100644
index 00000000000..15fa8e32419
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPei.inf
@@ -0,0 +1,40 @@
+## @file
+# Map TPM MMIO range unencrypted when SEV-ES is active.
+# Install gOvmfTpmMmioAccessiblePpiGuid unconditionally.
+#
+# Copyright (C) 2021, Advanced Micro Devices, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = TpmMmioSevDecryptPei
+ FILE_GUID = F12F698A-E506-4A1B-B32E-6920E55DA1C4
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = TpmMmioSevDecryptPeimEntryPoint
+
+[Sources]
+ TpmMmioSevDecryptPeim.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ MemEncryptSevLib
+ PcdLib
+ PeimEntryPoint
+ PeiServicesLib
+
+[Ppis]
+ gOvmfTpmMmioAccessiblePpiGuid ## PRODUCES
+
+[FixedPcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
+
+[Depex]
+ gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c
new file mode 100644
index 00000000000..9315ffedbdc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/Tcg/TpmMmioSevDecryptPei/TpmMmioSevDecryptPeim.c
@@ -0,0 +1,87 @@
+/** @file
+ Map TPM MMIO range unencrypted when SEV-ES is active.
+ Install gOvmfTpmMmioAccessiblePpiGuid unconditionally.
+
+ Copyright (C) 2021, Advanced Micro Devices, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/MemEncryptSevLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeiServicesLib.h>
+
+STATIC CONST EFI_PEI_PPI_DESCRIPTOR mTpmMmioRangeAccessible = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gOvmfTpmMmioAccessiblePpiGuid,
+ NULL
+};
+
+/**
+ The entry point for TPM MMIO range mapping driver.
+
+ @param[in] FileHandle Handle of the file being invoked.
+ @param[in] PeiServices Describes the list of possible PEI Services.
+
+ @retval EFI_ABORTED No need to keep this PEIM resident
+**/
+EFI_STATUS
+EFIAPI
+TpmMmioSevDecryptPeimEntryPoint (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ RETURN_STATUS DecryptStatus;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a\n", __FUNCTION__));
+
+ //
+ // If SEV is active, MMIO succeeds against an encrypted physical address
+ // because the nested page fault (NPF) that occurs on access does not
+ // include the encryption bit in the guest physical address provided to the
+ // hypervisor.
+ //
+ // If SEV-ES is active, MMIO would succeed against an encrypted physical
+ // address because the #VC handler uses the virtual address (which is an
+ // identity mapped physical address without the encryption bit) as the guest
+ // physical address of the MMIO target in the VMGEXIT.
+ //
+ // However, if SEV-ES is active, before performing the actual MMIO, an
+ // additional MMIO mitigation check is performed in the #VC handler to ensure
+ // that MMIO is being done to/from an unencrypted address. To prevent guest
+ // termination in this scenario, mark the range unencrypted ahead of access.
+ //
+ if (MemEncryptSevEsIsEnabled ()) {
+ DEBUG ((DEBUG_INFO,
+ "%a: mapping TPM MMIO address range unencrypted\n",
+ __FUNCTION__));
+
+ DecryptStatus = MemEncryptSevClearPageEncMask (
+ 0,
+ FixedPcdGet64 (PcdTpmBaseAddress),
+ EFI_SIZE_TO_PAGES ((UINTN) 0x5000),
+ FALSE
+ );
+
+ if (RETURN_ERROR (DecryptStatus)) {
+ DEBUG ((DEBUG_ERROR,
+ "%a: failed to map TPM MMIO address range unencrypted\n",
+ __FUNCTION__));
+ ASSERT_RETURN_ERROR (DecryptStatus);
+ }
+ }
+
+ //
+ // MMIO range available
+ //
+ Status = PeiServicesInstallPpi (&mTpmMmioRangeAccessible);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_ABORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/DriverBinding.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/DriverBinding.c
new file mode 100644
index 00000000000..0b7a8222cd1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/DriverBinding.c
@@ -0,0 +1,232 @@
+/** @file
+ Provide EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instances on virtio-fs devices.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrCmp()
+#include <Library/MemoryAllocationLib.h> // AllocatePool()
+#include <Library/UefiBootServicesTableLib.h> // gBS
+#include <Protocol/ComponentName2.h> // EFI_COMPONENT_NAME2_PROTOCOL
+#include <Protocol/DriverBinding.h> // EFI_DRIVER_BINDING_PROTOCOL
+
+#include "VirtioFsDxe.h"
+
+//
+// UEFI Driver Model protocol instances.
+//
+STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding;
+STATIC EFI_COMPONENT_NAME2_PROTOCOL mComponentName2;
+
+//
+// UEFI Driver Model protocol member functions.
+//
+EFI_STATUS
+EFIAPI
+VirtioFsBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ VIRTIO_DEVICE_PROTOCOL *Virtio;
+ EFI_STATUS CloseStatus;
+
+ Status = gBS->OpenProtocol (ControllerHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&Virtio, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Virtio->SubSystemDeviceId != VIRTIO_SUBSYSTEM_FILESYSTEM) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+ CloseStatus = gBS->CloseProtocol (ControllerHandle,
+ &gVirtioDeviceProtocolGuid, This->DriverBindingHandle,
+ ControllerHandle);
+ ASSERT_EFI_ERROR (CloseStatus);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ EFI_STATUS CloseStatus;
+
+ VirtioFs = AllocatePool (sizeof *VirtioFs);
+ if (VirtioFs == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ VirtioFs->Signature = VIRTIO_FS_SIG;
+
+ Status = gBS->OpenProtocol (ControllerHandle, &gVirtioDeviceProtocolGuid,
+ (VOID **)&VirtioFs->Virtio, This->DriverBindingHandle,
+ ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER);
+ if (EFI_ERROR (Status)) {
+ goto FreeVirtioFs;
+ }
+
+ Status = VirtioFsInit (VirtioFs);
+ if (EFI_ERROR (Status)) {
+ goto CloseVirtio;
+ }
+
+ Status = VirtioFsFuseInitSession (VirtioFs);
+ if (EFI_ERROR (Status)) {
+ goto UninitVirtioFs;
+ }
+
+ Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_CALLBACK,
+ VirtioFsExitBoot, VirtioFs, &VirtioFs->ExitBoot);
+ if (EFI_ERROR (Status)) {
+ goto UninitVirtioFs;
+ }
+
+ InitializeListHead (&VirtioFs->OpenFiles);
+ VirtioFs->SimpleFs.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
+ VirtioFs->SimpleFs.OpenVolume = VirtioFsOpenVolume;
+
+ Status = gBS->InstallProtocolInterface (&ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid, EFI_NATIVE_INTERFACE,
+ &VirtioFs->SimpleFs);
+ if (EFI_ERROR (Status)) {
+ goto CloseExitBoot;
+ }
+
+ return EFI_SUCCESS;
+
+CloseExitBoot:
+ CloseStatus = gBS->CloseEvent (VirtioFs->ExitBoot);
+ ASSERT_EFI_ERROR (CloseStatus);
+
+UninitVirtioFs:
+ VirtioFsUninit (VirtioFs);
+
+CloseVirtio:
+ CloseStatus = gBS->CloseProtocol (ControllerHandle,
+ &gVirtioDeviceProtocolGuid, This->DriverBindingHandle,
+ ControllerHandle);
+ ASSERT_EFI_ERROR (CloseStatus);
+
+FreeVirtioFs:
+ FreePool (VirtioFs);
+
+ return Status;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs;
+ VIRTIO_FS *VirtioFs;
+
+ Status = gBS->OpenProtocol (ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid, (VOID **)&SimpleFs,
+ This->DriverBindingHandle, ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ VirtioFs = VIRTIO_FS_FROM_SIMPLE_FS (SimpleFs);
+
+ if (!IsListEmpty (&VirtioFs->OpenFiles)) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = gBS->UninstallProtocolInterface (ControllerHandle,
+ &gEfiSimpleFileSystemProtocolGuid, SimpleFs);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->CloseEvent (VirtioFs->ExitBoot);
+ ASSERT_EFI_ERROR (Status);
+
+ VirtioFsUninit (VirtioFs);
+
+ Status = gBS->CloseProtocol (ControllerHandle, &gVirtioDeviceProtocolGuid,
+ This->DriverBindingHandle, ControllerHandle);
+ ASSERT_EFI_ERROR (Status);
+
+ FreePool (VirtioFs);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsGetDriverName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ if (AsciiStrCmp (Language, "en") != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ *DriverName = L"Virtio Filesystem Driver";
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsGetControllerName (
+ IN EFI_COMPONENT_NAME2_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+//
+// Entry point of this driver.
+//
+EFI_STATUS
+EFIAPI
+VirtioFsEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mDriverBinding.Supported = VirtioFsBindingSupported;
+ mDriverBinding.Start = VirtioFsBindingStart;
+ mDriverBinding.Stop = VirtioFsBindingStop;
+ mDriverBinding.Version = 0x10;
+ mDriverBinding.ImageHandle = ImageHandle;
+ mDriverBinding.DriverBindingHandle = ImageHandle;
+
+ mComponentName2.GetDriverName = VirtioFsGetDriverName;
+ mComponentName2.GetControllerName = VirtioFsGetControllerName;
+ mComponentName2.SupportedLanguages = "en";
+
+ Status = gBS->InstallMultipleProtocolInterfaces (&ImageHandle,
+ &gEfiDriverBindingProtocolGuid, &mDriverBinding,
+ &gEfiComponentName2ProtocolGuid, &mComponentName2, NULL);
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFlush.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFlush.c
new file mode 100644
index 00000000000..c13a7921559
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFlush.c
@@ -0,0 +1,111 @@
+/** @file
+ FUSE_FLUSH wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Flush changes queued on the local virtualization host to the remote storage
+ server's memory (not storage device), over the network, by sending the
+ FUSE_FLUSH request to the Virtio Filesystem device.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_FLUSH
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] NodeId The inode number of the regular file to flush.
+
+ @param[in] FuseHandle The open handle to the regular file to flush.
+
+ @retval EFI_SUCCESS The regular file has been flushed.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseFlush (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_FLUSH_REQUEST FlushReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[1];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &FlushReq;
+ ReqIoVec[1].Size = sizeof FlushReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpFlush, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_FLUSH-specific fields.
+ //
+ FlushReq.FileHandle = FuseHandle;
+ FlushReq.Unused = 0;
+ FlushReq.Padding = 0;
+ FlushReq.LockOwner = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
+ "Errno=%d\n", __FUNCTION__, VirtioFs->Label, NodeId, FuseHandle,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseForget.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseForget.c
new file mode 100644
index 00000000000..7549baee683
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseForget.c
@@ -0,0 +1,85 @@
+/** @file
+ FUSE_FORGET wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Make the Virtio Filesysem device drop one reference count from a NodeId that
+ the driver looked up by filename.
+
+ Send the FUSE_FORGET request to the Virtio Filesysem device for this. Unlike
+ most other FUSE requests, FUSE_FORGET doesn't elicit a response, not even the
+ common VIRTIO_FS_FUSE_RESPONSE header.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_FORGET
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] NodeId The inode number that the client learned by way of
+ lookup, and that the server should now un-reference
+ exactly once.
+
+ @retval EFI_SUCCESS The FUSE_FORGET request has been submitted.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit().
+**/
+EFI_STATUS
+VirtioFsFuseForget (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_FORGET_REQUEST ForgetReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather list (note: only request).
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &ForgetReq;
+ ReqIoVec[1].Size = sizeof ForgetReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ //
+ // Validate the scatter-gather list (request only); calculate the total
+ // transfer size.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpForget, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_FORGET-specific fields.
+ //
+ ForgetReq.NumberOfLookups = 1;
+
+ //
+ // Submit the request. There's not going to be a response.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, NULL);
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFsync.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFsync.c
new file mode 100644
index 00000000000..9235cf91277
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseFsync.c
@@ -0,0 +1,121 @@
+/** @file
+ FUSE_FSYNC / FUSE_FSYNCDIR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Synchronize the in-core state of a regular file or a directory with the
+ storage device on the host, by sending the FUSE_FSYNC or FUSE_FSYNCDIR
+ request to the Virtio Filesystem device.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_FSYNC
+ / FUSE_FSYNCDIR request to. On output, the FUSE
+ request counter "VirtioFs->RequestId" will have been
+ incremented.
+
+ @param[in] NodeId The inode number of the file or directory to sync.
+
+ @param[in] FuseHandle The open handle to the file or directory to sync.
+
+ @param[in] IsDir TRUE if NodeId and FuseHandle refer to a directory,
+ FALSE if NodeId and FuseHandle refer to a regular
+ file.
+
+ @retval EFI_SUCCESS The file or directory has been synchronized.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseFsyncFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN BOOLEAN IsDir
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_FSYNC_REQUEST FsyncReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[1];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &FsyncReq;
+ ReqIoVec[1].Size = sizeof FsyncReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (
+ VirtioFs,
+ &CommonReq,
+ ReqSgList.TotalSize,
+ IsDir ? VirtioFsFuseOpFsyncDir : VirtioFsFuseOpFsync,
+ NodeId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_FSYNC- / FUSE_FSYNCDIR-specific fields.
+ //
+ FsyncReq.FileHandle = FuseHandle;
+ FsyncReq.FsyncFlags = 0;
+ FsyncReq.Padding = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
+ "IsDir=%d Errno=%d\n", __FUNCTION__, VirtioFs->Label, NodeId, FuseHandle,
+ IsDir, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseGetAttr.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseGetAttr.c
new file mode 100644
index 00000000000..f07a4786f4a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseGetAttr.c
@@ -0,0 +1,116 @@
+/** @file
+ FUSE_GETATTR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_GETATTR request to the Virtio Filesystem device, for fetching the
+ attributes of an inode.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the
+ FUSE_GETATTR request to. On output, the FUSE request
+ counter "VirtioFs->RequestId" will have been
+ incremented.
+
+ @param[in] NodeId The inode number for which the attributes should be
+ retrieved.
+
+ @param[out] FuseAttr The VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object
+ describing the properties of the inode.
+
+ @retval EFI_SUCCESS FuseAttr has been filled in.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseGetAttr (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ OUT VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_GETATTR_REQUEST GetAttrReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_GETATTR_RESPONSE GetAttrResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &GetAttrReq;
+ ReqIoVec[1].Size = sizeof GetAttrReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &GetAttrResp;
+ RespIoVec[1].Size = sizeof GetAttrResp;
+ RespIoVec[2].Buffer = FuseAttr;
+ RespIoVec[2].Size = sizeof *FuseAttr;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpGetAttr, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_GETATTR-specific fields.
+ //
+ GetAttrReq.GetAttrFlags = 0;
+ GetAttrReq.Dummy = 0;
+ GetAttrReq.FileHandle = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu Errno=%d\n",
+ __FUNCTION__, VirtioFs->Label, NodeId, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseInit.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseInit.c
new file mode 100644
index 00000000000..80450219122
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseInit.c
@@ -0,0 +1,142 @@
+/** @file
+ FUSE_INIT wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_INIT request to the Virtio Filesystem device, for starting the
+ FUSE session.
+
+ From virtio-v1.1-cs01-87fa6b5d8155, 5.11.5 Device Initialization: "On
+ initialization the driver first discovers the device's virtqueues. The FUSE
+ session is started by sending a FUSE_INIT request as defined by the FUSE
+ protocol on one request virtqueue."
+
+ The function may only be called after VirtioFsInit() returns successfully and
+ before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_INIT
+ request to. The FUSE request counter
+ "VirtioFs->RequestId" is set to 1 on output. The
+ maximum write buffer size exposed in the FUSE_INIT
+ response is saved in "VirtioFs->MaxWrite", on
+ output.
+
+ @retval EFI_SUCCESS The FUSE session has been started.
+
+ @retval EFI_UNSUPPORTED FUSE interface version or feature negotiation
+ failed.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if
+ the Virtio Filesystem device explicitly reported an
+ error.
+
+ @return Error codes propagated from
+ VirtioFsSgListsValidate(), VirtioFsFuseNewRequest(),
+ VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseInitSession (
+ IN OUT VIRTIO_FS *VirtioFs
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_INIT_REQUEST InitReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_INIT_RESPONSE InitResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Initialize the FUSE request counter.
+ //
+ VirtioFs->RequestId = 1;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &InitReq;
+ ReqIoVec[1].Size = sizeof InitReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &InitResp;
+ RespIoVec[1].Size = sizeof InitResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpInit, 0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_INIT-specific fields.
+ //
+ InitReq.Major = VIRTIO_FS_FUSE_MAJOR;
+ InitReq.Minor = VIRTIO_FS_FUSE_MINOR;
+ InitReq.MaxReadahead = 0;
+ InitReq.Flags = VIRTIO_FS_FUSE_INIT_REQ_F_DO_READDIRPLUS;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" Errno=%d\n", __FUNCTION__,
+ VirtioFs->Label, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Check FUSE interface version / feature compatibility.
+ //
+ if (InitResp.Major < InitReq.Major ||
+ (InitResp.Major == InitReq.Major && InitResp.Minor < InitReq.Minor) ||
+ (InitResp.Flags & VIRTIO_FS_FUSE_INIT_REQ_F_DO_READDIRPLUS) == 0 ||
+ InitResp.MaxWrite < SIZE_4KB) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Save the maximum write buffer size for FUSE_WRITE requests.
+ //
+ VirtioFs->MaxWrite = InitResp.MaxWrite;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseLookup.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseLookup.c
new file mode 100644
index 00000000000..72b5cbaa3c5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseLookup.c
@@ -0,0 +1,148 @@
+/** @file
+ FUSE_LOOKUP wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrSize()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_LOOKUP request to the Virtio Filesystem device, for resolving a
+ filename to an inode.
+
+ The function returns EFI_NOT_FOUND exclusively if the Virtio Filesystem
+ device explicitly responds with ENOENT -- "No such file or directory".
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_LOOKUP
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] DirNodeId The inode number of the directory in which Name
+ should be resolved to an inode.
+
+ @param[in] Name The single-component filename to resolve in the
+ directory identified by DirNodeId.
+
+ @param[out] NodeId The inode number which Name has been resolved to.
+
+ @param[out] FuseAttr The VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object
+ describing the properties of the resolved inode.
+
+ @retval EFI_SUCCESS Filename to inode resolution successful.
+
+ @retval EFI_NOT_FOUND The Virtio Filesystem device explicitly reported
+ ENOENT -- "No such file or directory".
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error
+ different from ENOENT. If said mapping resulted in
+ EFI_NOT_FOUND, it is remapped to EFI_DEVICE_ERROR.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse(). EFI_NOT_FOUND is remapped
+ to EFI_DEVICE_ERROR.
+**/
+EFI_STATUS
+VirtioFsFuseLookup (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 DirNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId,
+ OUT VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = Name;
+ ReqIoVec[1].Size = AsciiStrSize (Name);
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &NodeResp;
+ RespIoVec[1].Size = sizeof NodeResp;
+ RespIoVec[2].Buffer = FuseAttr;
+ RespIoVec[2].Size = sizeof *FuseAttr;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ goto Fail;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpLookup, DirNodeId);
+ if (EFI_ERROR (Status)) {
+ goto Fail;
+ }
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ goto Fail;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((
+ ((CommonResp.Error == VIRTIO_FS_FUSE_ERRNO_ENOENT) ?
+ DEBUG_VERBOSE :
+ DEBUG_ERROR),
+ "%a: Label=\"%s\" DirNodeId=%Lu Name=\"%a\" Errno=%d\n",
+ __FUNCTION__,
+ VirtioFs->Label,
+ DirNodeId,
+ Name,
+ CommonResp.Error
+ ));
+ if (CommonResp.Error == VIRTIO_FS_FUSE_ERRNO_ENOENT) {
+ return EFI_NOT_FOUND;
+ }
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ goto Fail;
+ }
+
+ //
+ // Output the NodeId to which Name has been resolved to.
+ //
+ *NodeId = NodeResp.NodeId;
+ return EFI_SUCCESS;
+
+Fail:
+ return (Status == EFI_NOT_FOUND) ? EFI_DEVICE_ERROR : Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseMkDir.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseMkDir.c
new file mode 100644
index 00000000000..5d88af0b488
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseMkDir.c
@@ -0,0 +1,134 @@
+/** @file
+ FUSE_MKDIR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrSize()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_MKDIR request to the Virtio Filesystem device, for creating a
+ directory.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_MKDIR
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] ParentNodeId The inode number of the direct parent directory of
+ the directory to create.
+
+ @param[in] Name The single-component filename of the directory to
+ create, under the parent directory identified by
+ ParentNodeId.
+
+ @param[out] NodeId The inode number of the new directory.
+
+ @retval EFI_SUCCESS The directory has been created.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseMkDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 ParentNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_MKDIR_REQUEST MkDirReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &MkDirReq;
+ ReqIoVec[1].Size = sizeof MkDirReq;
+ ReqIoVec[2].Buffer = Name;
+ ReqIoVec[2].Size = AsciiStrSize (Name);
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &NodeResp;
+ RespIoVec[1].Size = sizeof NodeResp;
+ RespIoVec[2].Buffer = &AttrResp;
+ RespIoVec[2].Size = sizeof AttrResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpMkDir, ParentNodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_MKDIR-specific fields.
+ //
+ MkDirReq.Mode = (VIRTIO_FS_FUSE_MODE_PERM_RWXU |
+ VIRTIO_FS_FUSE_MODE_PERM_RWXG |
+ VIRTIO_FS_FUSE_MODE_PERM_RWXO);
+ MkDirReq.Umask = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" ParentNodeId=%Lu Name=\"%a\" "
+ "Errno=%d\n", __FUNCTION__, VirtioFs->Label, ParentNodeId, Name,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Output the NodeId of the new directory.
+ //
+ *NodeId = NodeResp.NodeId;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpen.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpen.c
new file mode 100644
index 00000000000..04c369a574e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpen.c
@@ -0,0 +1,126 @@
+/** @file
+ FUSE_OPEN wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_OPEN request to the Virtio Filesystem device, for opening a
+ regular file.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_OPEN
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] NodeId The inode number of the regular file to open.
+
+ @param[in] ReadWrite If TRUE, open the regular file in read-write mode.
+ If FALSE, open the regular file in read-only mode.
+
+ @param[out] FuseHandle The open handle to the regular file, returned by the
+ Virtio Filesystem device.
+
+ @retval EFI_SUCCESS The regular file has been opened.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseOpen (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN BOOLEAN ReadWrite,
+ OUT UINT64 *FuseHandle
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_OPEN_REQUEST OpenReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_OPEN_RESPONSE OpenResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &OpenReq;
+ ReqIoVec[1].Size = sizeof OpenReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &OpenResp;
+ RespIoVec[1].Size = sizeof OpenResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpOpen, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_OPEN-specific fields.
+ //
+ OpenReq.Flags = (ReadWrite ?
+ VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR :
+ VIRTIO_FS_FUSE_OPEN_REQ_F_RDONLY);
+ OpenReq.Unused = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu ReadWrite=%d "
+ "Errno=%d\n", __FUNCTION__, VirtioFs->Label, NodeId, ReadWrite,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Output the open handle.
+ //
+ *FuseHandle = OpenResp.FileHandle;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenDir.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenDir.c
new file mode 100644
index 00000000000..9e4f1453c09
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenDir.c
@@ -0,0 +1,120 @@
+/** @file
+ FUSE_OPENDIR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_OPENDIR request to the Virtio Filesystem device, for opening a
+ directory.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the
+ FUSE_OPENDIR request to. On output, the FUSE request
+ counter "VirtioFs->RequestId" will have been
+ incremented.
+
+ @param[in] NodeId The inode number of the directory to open.
+
+ @param[out] FuseHandle The open file handle returned by the Virtio
+ Filesystem device.
+
+ @retval EFI_SUCCESS The directory has been opened.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseOpenDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ OUT UINT64 *FuseHandle
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_OPEN_REQUEST OpenReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_OPEN_RESPONSE OpenResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &OpenReq;
+ ReqIoVec[1].Size = sizeof OpenReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &OpenResp;
+ RespIoVec[1].Size = sizeof OpenResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpOpenDir, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_OPENDIR-specific fields.
+ //
+ OpenReq.Flags = 0;
+ OpenReq.Unused = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu Errno=%d\n",
+ __FUNCTION__, VirtioFs->Label, NodeId, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Output the open file handle.
+ //
+ *FuseHandle = OpenResp.FileHandle;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenOrCreate.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenOrCreate.c
new file mode 100644
index 00000000000..a4527ecf25c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseOpenOrCreate.c
@@ -0,0 +1,155 @@
+/** @file
+ FUSE_CREATE wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrSize()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send a FUSE_CREATE request to the Virtio Filesystem device, for opening a
+ regular file with (O_RDWR | O_CREAT) semantics.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_CREATE
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] ParentNodeId The inode number of the direct parent directory of
+ the regular file to open or create.
+
+ @param[in] Name The single-component filename of the regular file to
+ open or create, under the parent directory
+ identified by ParentNodeId.
+
+ @param[out] NodeId The inode number of the regular file, returned by
+ the Virtio Filesystem device.
+
+ @param[out] FuseHandle The open file handle returned by the Virtio
+ Filesystem device.
+
+ @retval EFI_SUCCESS The regular file has been opened, and (if necessary)
+ created.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseOpenOrCreate (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 ParentNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId,
+ OUT UINT64 *FuseHandle
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_CREATE_REQUEST CreateReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_NODE_RESPONSE NodeResp;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
+ VIRTIO_FS_FUSE_OPEN_RESPONSE OpenResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[4];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &CreateReq;
+ ReqIoVec[1].Size = sizeof CreateReq;
+ ReqIoVec[2].Buffer = Name;
+ ReqIoVec[2].Size = AsciiStrSize (Name);
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &NodeResp;
+ RespIoVec[1].Size = sizeof NodeResp;
+ RespIoVec[2].Buffer = &AttrResp;
+ RespIoVec[2].Size = sizeof AttrResp;
+ RespIoVec[3].Buffer = &OpenResp;
+ RespIoVec[3].Size = sizeof OpenResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpCreate, ParentNodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_CREATE-specific fields.
+ //
+ // VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR is why this request can never open a
+ // directory (EISDIR). And VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR is consistent with
+ // the only OpenMode of EFI_FILE_PROTOCOL.Open() that enables filesystem
+ // object creation -- that is, Create/Read/Write.
+ //
+ CreateReq.Flags = VIRTIO_FS_FUSE_OPEN_REQ_F_RDWR;
+ CreateReq.Mode = (VIRTIO_FS_FUSE_MODE_PERM_RUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_WUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_RGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_WGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_ROTH |
+ VIRTIO_FS_FUSE_MODE_PERM_WOTH);
+ CreateReq.Umask = 0;
+ CreateReq.Padding = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" ParentNodeId=%Lu Name=\"%a\" "
+ "Errno=%d\n", __FUNCTION__, VirtioFs->Label, ParentNodeId, Name,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Output the NodeId of the (possibly new) regular file. Also output the open
+ // file handle.
+ //
+ *NodeId = NodeResp.NodeId;
+ *FuseHandle = OpenResp.FileHandle;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRead.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRead.c
new file mode 100644
index 00000000000..3e68a2840e7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRead.c
@@ -0,0 +1,191 @@
+/** @file
+ FUSE_READ / FUSE_READDIRPLUS wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Read a chunk from a regular file or a directory stream, by sending the
+ FUSE_READ / FUSE_READDIRPLUS request to the Virtio Filesystem device.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_READ
+ or FUSE_READDIRPLUS request to. On output, the FUSE
+ request counter "VirtioFs->RequestId" will have been
+ incremented.
+
+ @param[in] NodeId The inode number of the regular file or directory
+ stream to read from.
+
+ @param[in] FuseHandle The open handle to the regular file or directory
+ stream to read from.
+
+ @param[in] IsDir TRUE if NodeId and FuseHandle refer to a directory,
+ FALSE if NodeId and FuseHandle refer to a regular
+ file.
+
+ @param[in] Offset If IsDir is FALSE: the absolute file position at
+ which to start reading.
+
+ If IsDir is TRUE: the directory stream cookie at
+ which to start or continue reading. The zero-valued
+ cookie identifies the start of the directory stream.
+ Further positions in the directory stream can be
+ passed in from the CookieForNextEntry field of
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE.
+
+ @param[in,out] Size On input, the number of bytes to read. On successful
+ return, the number of bytes actually read, which may
+ be smaller than the value on input.
+
+ When reading a regular file (i.e., when IsDir is
+ FALSE), EOF can be detected by passing in a nonzero
+ Size, and finding a zero Size on output.
+
+ When reading a directory stream (i.e., when IsDir is
+ TRUE), Data consists of a sequence of variably-sized
+ records (directory entries). A read operation
+ returns the maximal sequence of records that fits in
+ Size, without having to truncate a record. In order
+ to guarantee progress, call
+
+ VirtioFsFuseStatFs (VirtioFs, NodeId,
+ &FilesysAttr)
+
+ first, to learn the maximum Namelen for the
+ directory stream. Then assign Size at least
+
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE (
+ FilesysAttr.Namelen)
+
+ on input. (Remember that
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE() may return
+ 0 if its Namelen argument is invalid.) EOF can be
+ detected if Size is set on input like described
+ above, and Size is zero on output.
+
+ @param[out] Data Buffer to read the bytes from the regular file or
+ the directory stream into. The caller is responsible
+ for providing room for (at least) as many bytes in
+ Data as Size is on input.
+
+ @retval EFI_SUCCESS Read successful. The caller is responsible for checking
+ Size to learn the actual byte count transferred.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseReadFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN BOOLEAN IsDir,
+ IN UINT64 Offset,
+ IN OUT UINT32 *Size,
+ OUT VOID *Data
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_READ_REQUEST ReadReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+ UINTN TailBufferFill;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &ReadReq;
+ ReqIoVec[1].Size = sizeof ReadReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = Data;
+ RespIoVec[1].Size = *Size;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (
+ VirtioFs,
+ &CommonReq,
+ ReqSgList.TotalSize,
+ IsDir ? VirtioFsFuseOpReadDirPlus : VirtioFsFuseOpRead,
+ NodeId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_READ- / FUSE_READDIRPLUS-specific fields.
+ //
+ ReadReq.FileHandle = FuseHandle;
+ ReadReq.Offset = Offset;
+ ReadReq.Size = *Size;
+ ReadReq.ReadFlags = 0;
+ ReadReq.LockOwner = 0;
+ ReadReq.Flags = 0;
+ ReadReq.Padding = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response. Note that TailBufferFill is variable.
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique,
+ &TailBufferFill);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
+ "IsDir=%d Offset=0x%Lx Size=0x%x Data@%p Errno=%d\n", __FUNCTION__,
+ VirtioFs->Label, NodeId, FuseHandle, IsDir, Offset, *Size, Data,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Report the actual transfer size.
+ //
+ // Integer overflow in the (UINT32) cast below is not possible; the
+ // VIRTIO_FS_SCATTER_GATHER_LIST functions would have caught that.
+ //
+ *Size = (UINT32)TailBufferFill;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRelease.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRelease.c
new file mode 100644
index 00000000000..6685a6d1805
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRelease.c
@@ -0,0 +1,121 @@
+/** @file
+ FUSE_RELEASE / FUSE_RELEASEDIR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Close a regular file or a directory that is open, by sending the FUSE_RELEASE
+ or FUSE_RELEASEDIR request to the Virtio Filesystem device.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the
+ FUSE_RELEASE / FUSE_RELEASEDIR request to. On
+ output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] NodeId The inode number of the file or directory to close.
+
+ @param[in] FuseHandle The open handle to the file or directory to close.
+
+ @param[in] IsDir TRUE if NodeId and FuseHandle refer to a directory,
+ FALSE if NodeId and FuseHandle refer to a regular
+ file.
+
+ @retval EFI_SUCCESS The file or directory has been closed.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseReleaseFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN BOOLEAN IsDir
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_RELEASE_REQUEST ReleaseReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[1];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &ReleaseReq;
+ ReqIoVec[1].Size = sizeof ReleaseReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (
+ VirtioFs,
+ &CommonReq,
+ ReqSgList.TotalSize,
+ IsDir ? VirtioFsFuseOpReleaseDir : VirtioFsFuseOpRelease,
+ NodeId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_RELEASE- / FUSE_RELEASEDIR-specific fields.
+ //
+ ReleaseReq.FileHandle = FuseHandle;
+ ReleaseReq.Flags = 0;
+ ReleaseReq.ReleaseFlags = 0;
+ ReleaseReq.LockOwner = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
+ "IsDir=%d Errno=%d\n", __FUNCTION__, VirtioFs->Label, NodeId, FuseHandle,
+ IsDir, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRename.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRename.c
new file mode 100644
index 00000000000..cb648ac953b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseRename.c
@@ -0,0 +1,131 @@
+/** @file
+ FUSE_RENAME2 wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrSize()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Rename a regular file or a directory, by sending the FUSE_RENAME2 request to
+ the Virtio Filesystem device. If the new filename exists, the request will
+ fail.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the
+ FUSE_RENAME2 request to. On output, the FUSE
+ request counter "VirtioFs->RequestId" will have
+ been incremented.
+
+ @param[in] OldParentNodeId The inode number of the directory in which
+ OldName should be removed.
+
+ @param[in] OldName The single-component filename to remove in the
+ directory identified by OldParentNodeId.
+
+ @param[in] NewParentNodeId The inode number of the directory in which
+ NewName should be created, such that on
+ successful return, (NewParentNodeId, NewName)
+ refer to the same inode as (OldParentNodeId,
+ OldName) did on entry.
+
+ @param[in] NewName The single-component filename to create in the
+ directory identified by NewParentNodeId.
+
+ @retval EFI_SUCCESS The file or directory has been renamed.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseRename (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 OldParentNodeId,
+ IN CHAR8 *OldName,
+ IN UINT64 NewParentNodeId,
+ IN CHAR8 *NewName
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_RENAME2_REQUEST Rename2Req;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[4];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[1];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &Rename2Req;
+ ReqIoVec[1].Size = sizeof Rename2Req;
+ ReqIoVec[2].Buffer = OldName;
+ ReqIoVec[2].Size = AsciiStrSize (OldName);
+ ReqIoVec[3].Buffer = NewName;
+ ReqIoVec[3].Size = AsciiStrSize (NewName);
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpRename2, OldParentNodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_RENAME2-specific fields.
+ //
+ Rename2Req.NewDir = NewParentNodeId;
+ Rename2Req.Flags = VIRTIO_FS_FUSE_RENAME2_REQ_F_NOREPLACE;
+ Rename2Req.Padding = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" OldParentNodeId=%Lu OldName=\"%a\" "
+ "NewParentNodeId=%Lu NewName=\"%a\" Errno=%d\n", __FUNCTION__,
+ VirtioFs->Label, OldParentNodeId, OldName, NewParentNodeId, NewName,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseSetAttr.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseSetAttr.c
new file mode 100644
index 00000000000..99647de0782
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseSetAttr.c
@@ -0,0 +1,174 @@
+/** @file
+ FUSE_SETATTR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send the FUSE_SETATTR request to the Virtio Filesystem device, for changing
+ the attributes of an inode.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the
+ FUSE_SETATTR request to. On output, the FUSE request
+ counter "VirtioFs->RequestId" will have been
+ incremented.
+
+ @param[in] NodeId The inode number representing the regular file or
+ directory whose attributes should be changed.
+
+ @param[in] Size The new size to set for the regular file. If NULL,
+ then the file size will not be changed. If NodeId
+ refers to a directory, then the caller is
+ responsible for passing NULL as Size.
+
+ @param[in] Atime The new last access time to set for the regular file
+ or directory (seconds since the Epoch). If NULL,
+ then the last access time is not changed.
+
+ @param[in] Mtime The new last modification time to set for the
+ regular file or directory (seconds since the Epoch).
+ If NULL, then the last modification time is not
+ changed.
+
+ @param[in] Mode The new file mode bits to set for the regular file
+ or directory. If NULL, then the file mode bits are
+ not changed.
+
+ @retval EFI_SUCCESS The attributes have been updated.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseSetAttr (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 *Size OPTIONAL,
+ IN UINT64 *Atime OPTIONAL,
+ IN UINT64 *Mtime OPTIONAL,
+ IN UINT32 *Mode OPTIONAL
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_SETATTR_REQUEST AttrReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_GETATTR_RESPONSE GetAttrResp;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE AttrResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &AttrReq;
+ ReqIoVec[1].Size = sizeof AttrReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &GetAttrResp;
+ RespIoVec[1].Size = sizeof GetAttrResp;
+ RespIoVec[2].Buffer = &AttrResp;
+ RespIoVec[2].Size = sizeof AttrResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpSetAttr, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_SETATTR-specific fields.
+ //
+ AttrReq.Valid = 0;
+ AttrReq.Padding = 0;
+ AttrReq.FileHandle = 0;
+ AttrReq.Size = (Size == NULL) ? 0 : *Size;
+ AttrReq.LockOwner = 0;
+ AttrReq.Atime = (Atime == NULL) ? 0 : *Atime;
+ AttrReq.Mtime = (Mtime == NULL) ? 0 : *Mtime;
+ AttrReq.Ctime = 0;
+ AttrReq.AtimeNsec = 0;
+ AttrReq.MtimeNsec = 0;
+ AttrReq.CtimeNsec = 0;
+ AttrReq.Mode = (Mode == NULL) ? 0 : *Mode;
+ AttrReq.Unused4 = 0;
+ AttrReq.Uid = 0;
+ AttrReq.Gid = 0;
+ AttrReq.Unused5 = 0;
+
+ if (Size != NULL) {
+ AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_SIZE;
+ }
+ if (Atime != NULL) {
+ AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_ATIME;
+ }
+ if (Mtime != NULL) {
+ AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_MTIME;
+ }
+ if (Mode != NULL) {
+ AttrReq.Valid |= VIRTIO_FS_FUSE_SETATTR_REQ_F_MODE;
+ }
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu", __FUNCTION__,
+ VirtioFs->Label, NodeId));
+ if (Size != NULL) {
+ DEBUG ((DEBUG_ERROR, " Size=0x%Lx", *Size));
+ }
+ if (Atime != NULL) {
+ DEBUG ((DEBUG_ERROR, " Atime=%Lu", *Atime));
+ }
+ if (Mtime != NULL) {
+ DEBUG ((DEBUG_ERROR, " Mtime=%Lu", *Mtime));
+ }
+ if (Mode != NULL) {
+ DEBUG ((DEBUG_ERROR, " Mode=0x%x", *Mode)); // no support for octal :/
+ }
+ DEBUG ((DEBUG_ERROR, " Errno=%d\n", CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseStatFs.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseStatFs.c
new file mode 100644
index 00000000000..9377ca8a047
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseStatFs.c
@@ -0,0 +1,102 @@
+/** @file
+ FUSE_STATFS wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Send the FUSE_STATFS request to the Virtio Filesysem device, for retrieving
+ the attributes of the host-side filesystem that contains NodeId.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_STATFS
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] NodeId The inode whose containing filesystem is to be
+ queried for its attributes.
+
+ @param[out] FilesysAttr The VIRTIO_FS_FUSE_STATFS_RESPONSE object describing
+ the filesystem that underlies NodeId.
+
+ @retval EFI_SUCCESS FilesysAttr has been filled in.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseStatFs (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ OUT VIRTIO_FS_FUSE_STATFS_RESPONSE *FilesysAttr
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[1];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = FilesysAttr;
+ RespIoVec[1].Size = sizeof *FilesysAttr;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpStatFs, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu Errno=%d\n",
+ __FUNCTION__, VirtioFs->Label, NodeId, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseUnlink.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseUnlink.c
new file mode 100644
index 00000000000..b51349e7faa
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseUnlink.c
@@ -0,0 +1,114 @@
+/** @file
+ FUSE_UNLINK / FUSE_RMDIR wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrSize()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Remove a regular file or a directory, by sending the FUSE_UNLINK or
+ FUSE_RMDIR request to the Virtio Filesystem device.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_UNLINK
+ / FUSE_RMDIR request to. On output, the FUSE request
+ counter "VirtioFs->RequestId" will have been
+ incremented.
+
+ @param[in] ParentNodeId The inode number of the directory in which Name
+ should be removed.
+
+ @param[in] Name The single-component filename to remove in the
+ directory identified by ParentNodeId.
+
+ @param[in] IsDir TRUE if Name refers to a directory, FALSE otherwise.
+
+ @retval EFI_SUCCESS The file or directory has been removed.
+
+ @return The "errno" value mapped to an EFI_STATUS code, if the
+ Virtio Filesystem device explicitly reported an error.
+
+ @return Error codes propagated from VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseRemoveFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 ParentNodeId,
+ IN CHAR8 *Name,
+ IN BOOLEAN IsDir
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[1];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = Name;
+ ReqIoVec[1].Size = AsciiStrSize (Name);
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (
+ VirtioFs,
+ &CommonReq,
+ ReqSgList.TotalSize,
+ IsDir ? VirtioFsFuseOpRmDir : VirtioFsFuseOpUnlink,
+ ParentNodeId
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" ParentNodeId=%Lu Name=\"%a\" "
+ "IsDir=%d Errno=%d\n", __FUNCTION__, VirtioFs->Label, ParentNodeId, Name,
+ IsDir, CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseWrite.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseWrite.c
new file mode 100644
index 00000000000..cb6db575282
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/FuseWrite.c
@@ -0,0 +1,155 @@
+/** @file
+ FUSE_WRITE wrapper for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+/**
+ Write a chunk to a regular file, by sending the FUSE_WRITE request to the
+ Virtio Filesystem device.
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send the FUSE_WRITE
+ request to. On output, the FUSE request counter
+ "VirtioFs->RequestId" will have been incremented.
+
+ @param[in] NodeId The inode number of the regular file to write to.
+
+ @param[in] FuseHandle The open handle to the regular file to write to.
+
+ @param[in] Offset The absolute file position at which to start
+ writing.
+
+ @param[in,out] Size On input, the number of bytes to write. On
+ successful return, the number of bytes actually
+ written, which may be smaller than the value on
+ input.
+
+ @param[in] Data The buffer to write to the regular file.
+
+ @retval EFI_SUCCESS Write successful. The caller is responsible for
+ checking Size to learn the actual byte count
+ transferred.
+
+ @retval EFI_BAD_BUFFER_SIZE On input, Size is larger than
+ "VirtioFs->MaxWrite".
+
+ @return The "errno" value mapped to an EFI_STATUS code,
+ if the Virtio Filesystem device explicitly
+ reported an error.
+
+ @return Error codes propagated from
+ VirtioFsSgListsValidate(),
+ VirtioFsFuseNewRequest(),
+ VirtioFsSgListsSubmit(),
+ VirtioFsFuseCheckResponse().
+**/
+EFI_STATUS
+VirtioFsFuseWrite (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN UINT64 Offset,
+ IN OUT UINT32 *Size,
+ IN VOID *Data
+ )
+{
+ VIRTIO_FS_FUSE_REQUEST CommonReq;
+ VIRTIO_FS_FUSE_WRITE_REQUEST WriteReq;
+ VIRTIO_FS_IO_VECTOR ReqIoVec[3];
+ VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
+ VIRTIO_FS_FUSE_RESPONSE CommonResp;
+ VIRTIO_FS_FUSE_WRITE_RESPONSE WriteResp;
+ VIRTIO_FS_IO_VECTOR RespIoVec[2];
+ VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
+ EFI_STATUS Status;
+
+ //
+ // Honor the write buffer size limit of the Virtio Filesystem device.
+ //
+ if (*Size > VirtioFs->MaxWrite) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //
+ // Set up the scatter-gather lists.
+ //
+ ReqIoVec[0].Buffer = &CommonReq;
+ ReqIoVec[0].Size = sizeof CommonReq;
+ ReqIoVec[1].Buffer = &WriteReq;
+ ReqIoVec[1].Size = sizeof WriteReq;
+ ReqIoVec[2].Buffer = Data;
+ ReqIoVec[2].Size = *Size;
+ ReqSgList.IoVec = ReqIoVec;
+ ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
+
+ RespIoVec[0].Buffer = &CommonResp;
+ RespIoVec[0].Size = sizeof CommonResp;
+ RespIoVec[1].Buffer = &WriteResp;
+ RespIoVec[1].Size = sizeof WriteResp;
+ RespSgList.IoVec = RespIoVec;
+ RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
+
+ //
+ // Validate the scatter-gather lists; calculate the total transfer sizes.
+ //
+ Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the common request header.
+ //
+ Status = VirtioFsFuseNewRequest (VirtioFs, &CommonReq, ReqSgList.TotalSize,
+ VirtioFsFuseOpWrite, NodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Populate the FUSE_WRITE-specific fields.
+ //
+ WriteReq.FileHandle = FuseHandle;
+ WriteReq.Offset = Offset;
+ WriteReq.Size = *Size;
+ WriteReq.WriteFlags = 0;
+ WriteReq.LockOwner = 0;
+ WriteReq.Flags = 0;
+ WriteReq.Padding = 0;
+
+ //
+ // Submit the request.
+ //
+ Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Verify the response (all response buffers are fixed size).
+ //
+ Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_DEVICE_ERROR) {
+ DEBUG ((DEBUG_ERROR, "%a: Label=\"%s\" NodeId=%Lu FuseHandle=%Lu "
+ "Offset=0x%Lx Size=0x%x Data@%p Errno=%d\n", __FUNCTION__,
+ VirtioFs->Label, NodeId, FuseHandle, Offset, *Size, Data,
+ CommonResp.Error));
+ Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
+ }
+ return Status;
+ }
+
+ //
+ // Report the actual transfer size.
+ //
+ *Size = WriteResp.Size;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/Helpers.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/Helpers.c
new file mode 100644
index 00000000000..dbd9136d68a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/Helpers.c
@@ -0,0 +1,2426 @@
+/** @file
+ Initialization and helper routines for the Virtio Filesystem device.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // StrLen()
+#include <Library/BaseMemoryLib.h> // CopyMem()
+#include <Library/MemoryAllocationLib.h> // AllocatePool()
+#include <Library/TimeBaseLib.h> // EpochToEfiTime()
+#include <Library/VirtioLib.h> // Virtio10WriteFeatures()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Read the Virtio Filesystem device configuration structure in full.
+
+ @param[in] Virtio The Virtio protocol underlying the VIRTIO_FS object.
+
+ @param[out] Config The fully populated VIRTIO_FS_CONFIG structure.
+
+ @retval EFI_SUCCESS Config has been filled in.
+
+ @return Error codes propagated from Virtio->ReadDevice(). The
+ contents of Config are indeterminate.
+**/
+STATIC
+EFI_STATUS
+VirtioFsReadConfig (
+ IN VIRTIO_DEVICE_PROTOCOL *Virtio,
+ OUT VIRTIO_FS_CONFIG *Config
+ )
+{
+ UINTN Idx;
+ EFI_STATUS Status;
+
+ for (Idx = 0; Idx < VIRTIO_FS_TAG_BYTES; Idx++) {
+ Status = Virtio->ReadDevice (
+ Virtio, // This
+ OFFSET_OF (VIRTIO_FS_CONFIG, Tag[Idx]), // FieldOffset
+ sizeof Config->Tag[Idx], // FieldSize
+ sizeof Config->Tag[Idx], // BufferSize
+ &Config->Tag[Idx] // Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = Virtio->ReadDevice (
+ Virtio, // This
+ OFFSET_OF (VIRTIO_FS_CONFIG, NumReqQueues), // FieldOffset
+ sizeof Config->NumReqQueues, // FieldSize
+ sizeof Config->NumReqQueues, // BufferSize
+ &Config->NumReqQueues // Buffer
+ );
+ return Status;
+}
+
+/**
+ Configure the Virtio Filesystem device underlying VirtioFs.
+
+ @param[in,out] VirtioFs The VIRTIO_FS object for which Virtio communication
+ should be set up. On input, the caller is
+ responsible for VirtioFs->Virtio having been
+ initialized. On output, synchronous Virtio
+ Filesystem commands (primitives) may be submitted to
+ the device.
+
+ @retval EFI_SUCCESS Virtio machinery has been set up.
+
+ @retval EFI_UNSUPPORTED The host-side configuration of the Virtio Filesystem
+ is not supported by this driver.
+
+ @return Error codes from underlying functions.
+**/
+EFI_STATUS
+VirtioFsInit (
+ IN OUT VIRTIO_FS *VirtioFs
+ )
+{
+ UINT8 NextDevStat;
+ EFI_STATUS Status;
+ UINT64 Features;
+ VIRTIO_FS_CONFIG Config;
+ UINTN Idx;
+ UINT64 RingBaseShift;
+
+ //
+ // Execute virtio-v1.1-cs01-87fa6b5d8155, 3.1.1 Driver Requirements: Device
+ // Initialization.
+ //
+ // 1. Reset the device.
+ //
+ NextDevStat = 0;
+ Status = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 2. Set the ACKNOWLEDGE status bit [...]
+ //
+ NextDevStat |= VSTAT_ACK;
+ Status = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 3. Set the DRIVER status bit [...]
+ //
+ NextDevStat |= VSTAT_DRIVER;
+ Status = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 4. Read device feature bits...
+ //
+ Status = VirtioFs->Virtio->GetDeviceFeatures (VirtioFs->Virtio, &Features);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if ((Features & VIRTIO_F_VERSION_1) == 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+ //
+ // No device-specific feature bits have been defined in file "virtio-fs.tex"
+ // of the virtio spec at <https://github.com/oasis-tcs/virtio-spec.git>, as
+ // of commit 87fa6b5d8155.
+ //
+ Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
+
+ //
+ // ... and write the subset of feature bits understood by the [...] driver to
+ // the device. [...]
+ // 5. Set the FEATURES_OK status bit.
+ // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]
+ //
+ Status = Virtio10WriteFeatures (VirtioFs->Virtio, Features, &NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 7. Perform device-specific setup, including discovery of virtqueues for
+ // the device, [...] reading [...] the device's virtio configuration space
+ //
+ Status = VirtioFsReadConfig (VirtioFs->Virtio, &Config);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 7.a. Convert the filesystem label from UTF-8 to UCS-2. Only labels with
+ // printable ASCII code points (U+0020 through U+007E) are supported.
+ // NUL-terminate at either the terminator we find, or right after the
+ // original label.
+ //
+ for (Idx = 0; Idx < VIRTIO_FS_TAG_BYTES && Config.Tag[Idx] != '\0'; Idx++) {
+ if (Config.Tag[Idx] < 0x20 || Config.Tag[Idx] > 0x7E) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+ VirtioFs->Label[Idx] = Config.Tag[Idx];
+ }
+ VirtioFs->Label[Idx] = L'\0';
+
+ //
+ // 7.b. We need one queue for sending normal priority requests.
+ //
+ if (Config.NumReqQueues < 1) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+
+ //
+ // 7.c. Fetch and remember the number of descriptors we can place on the
+ // queue at once. We'll need two descriptors per request, as a minimum --
+ // request header, response header.
+ //
+ Status = VirtioFs->Virtio->SetQueueSel (VirtioFs->Virtio,
+ VIRTIO_FS_REQUEST_QUEUE);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ Status = VirtioFs->Virtio->GetQueueNumMax (VirtioFs->Virtio,
+ &VirtioFs->QueueSize);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if (VirtioFs->QueueSize < 2) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+
+ //
+ // 7.d. [...] population of virtqueues [...]
+ //
+ Status = VirtioRingInit (VirtioFs->Virtio, VirtioFs->QueueSize,
+ &VirtioFs->Ring);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ Status = VirtioRingMap (VirtioFs->Virtio, &VirtioFs->Ring, &RingBaseShift,
+ &VirtioFs->RingMap);
+ if (EFI_ERROR (Status)) {
+ goto ReleaseQueue;
+ }
+
+ Status = VirtioFs->Virtio->SetQueueAddress (VirtioFs->Virtio,
+ &VirtioFs->Ring, RingBaseShift);
+ if (EFI_ERROR (Status)) {
+ goto UnmapQueue;
+ }
+
+ //
+ // 8. Set the DRIVER_OK status bit.
+ //
+ NextDevStat |= VSTAT_DRIVER_OK;
+ Status = VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto UnmapQueue;
+ }
+
+ return EFI_SUCCESS;
+
+UnmapQueue:
+ VirtioFs->Virtio->UnmapSharedBuffer (VirtioFs->Virtio, VirtioFs->RingMap);
+
+ReleaseQueue:
+ VirtioRingUninit (VirtioFs->Virtio, &VirtioFs->Ring);
+
+Failed:
+ //
+ // If any of these steps go irrecoverably wrong, the driver SHOULD set the
+ // FAILED status bit to indicate that it has given up on the device (it can
+ // reset the device later to restart if desired). [...]
+ //
+ // Virtio access failure here should not mask the original error.
+ //
+ NextDevStat |= VSTAT_FAILED;
+ VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, NextDevStat);
+
+ return Status;
+}
+
+/**
+ De-configure the Virtio Filesystem device underlying VirtioFs.
+
+ @param[in] VirtioFs The VIRTIO_FS object for which Virtio communication
+ should be torn down. On input, the caller is responsible
+ for having called VirtioFsInit(). On output, Virtio
+ Filesystem commands (primitives) must no longer be
+ submitted to the device.
+**/
+VOID
+VirtioFsUninit (
+ IN OUT VIRTIO_FS *VirtioFs
+ )
+{
+ //
+ // Resetting the Virtio device makes it release its resources and forget its
+ // configuration.
+ //
+ VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, 0);
+ VirtioFs->Virtio->UnmapSharedBuffer (VirtioFs->Virtio, VirtioFs->RingMap);
+ VirtioRingUninit (VirtioFs->Virtio, &VirtioFs->Ring);
+}
+
+/**
+ ExitBootServices event notification function for a Virtio Filesystem object.
+
+ This function resets the VIRTIO_FS.Virtio device, causing it to release all
+ references to guest-side resources. The function may only be called after
+ VirtioFsInit() returns successfully and before VirtioFsUninit() is called.
+
+ @param[in] ExitBootEvent The VIRTIO_FS.ExitBoot event that has been
+ signaled.
+
+ @param[in] VirtioFsAsVoid Pointer to the VIRTIO_FS object, passed in as
+ (VOID*).
+**/
+VOID
+EFIAPI
+VirtioFsExitBoot (
+ IN EFI_EVENT ExitBootEvent,
+ IN VOID *VirtioFsAsVoid
+ )
+{
+ VIRTIO_FS *VirtioFs;
+
+ VirtioFs = VirtioFsAsVoid;
+ DEBUG ((DEBUG_VERBOSE, "%a: VirtioFs=0x%p Label=\"%s\"\n", __FUNCTION__,
+ VirtioFsAsVoid, VirtioFs->Label));
+ VirtioFs->Virtio->SetDeviceStatus (VirtioFs->Virtio, 0);
+}
+
+/**
+ Validate two VIRTIO_FS_SCATTER_GATHER_LIST objects -- list of request
+ buffers, list of response buffers -- together.
+
+ On input, the caller is required to populate the following fields:
+ - VIRTIO_FS_IO_VECTOR.Buffer,
+ - VIRTIO_FS_IO_VECTOR.Size,
+ - VIRTIO_FS_SCATTER_GATHER_LIST.IoVec,
+ - VIRTIO_FS_SCATTER_GATHER_LIST.NumVec.
+
+ On output (on successful return), the following fields will be
+ zero-initialized:
+ - VIRTIO_FS_IO_VECTOR.Mapped,
+ - VIRTIO_FS_IO_VECTOR.MappedAddress,
+ - VIRTIO_FS_IO_VECTOR.Mapping,
+ - VIRTIO_FS_IO_VECTOR.Transferred.
+
+ On output (on successful return), the following fields will be calculated:
+ - VIRTIO_FS_SCATTER_GATHER_LIST.TotalSize.
+
+ The function may only be called after VirtioFsInit() returns successfully and
+ before VirtioFsUninit() is called.
+
+ @param[in] VirtioFs The Virtio Filesystem device that the
+ request-response exchange, expressed via
+ RequestSgList and ResponseSgList, will be
+ submitted to.
+
+ @param[in,out] RequestSgList The scatter-gather list that describes the
+ request part of the exchange -- the buffers
+ that should be sent to the Virtio Filesystem
+ device in the virtio transfer.
+
+ @param[in,out] ResponseSgList The scatter-gather list that describes the
+ response part of the exchange -- the buffers
+ that the Virtio Filesystem device should
+ populate in the virtio transfer. May be NULL
+ if the exchange with the Virtio Filesystem
+ device consists of a request only, with the
+ response part omitted altogether.
+
+ @retval EFI_SUCCESS RequestSgList and ResponseSgList have been
+ validated, output fields have been set.
+
+ @retval EFI_INVALID_PARAMETER RequestSgList is NULL.
+
+ @retval EFI_INVALID_PARAMETER On input, a
+ VIRTIO_FS_SCATTER_GATHER_LIST.IoVec field is
+ NULL, or a
+ VIRTIO_FS_SCATTER_GATHER_LIST.NumVec field is
+ zero.
+
+ @retval EFI_INVALID_PARAMETER On input, a VIRTIO_FS_IO_VECTOR.Buffer field
+ is NULL, or a VIRTIO_FS_IO_VECTOR.Size field
+ is zero.
+
+ @retval EFI_UNSUPPORTED (RequestSgList->NumVec +
+ ResponseSgList->NumVec) exceeds
+ VirtioFs->QueueSize, meaning that the total
+ list of buffers cannot be placed on the virtio
+ queue in a single descriptor chain (with one
+ descriptor per buffer).
+
+ @retval EFI_UNSUPPORTED One of the
+ VIRTIO_FS_SCATTER_GATHER_LIST.TotalSize fields
+ would exceed MAX_UINT32.
+**/
+EFI_STATUS
+VirtioFsSgListsValidate (
+ IN VIRTIO_FS *VirtioFs,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *RequestSgList,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *ResponseSgList OPTIONAL
+ )
+{
+ VIRTIO_FS_SCATTER_GATHER_LIST *SgListParam[2];
+ UINT16 DescriptorsNeeded;
+ UINTN ListId;
+
+ if (RequestSgList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SgListParam[0] = RequestSgList;
+ SgListParam[1] = ResponseSgList;
+
+ DescriptorsNeeded = 0;
+ for (ListId = 0; ListId < ARRAY_SIZE (SgListParam); ListId++) {
+ VIRTIO_FS_SCATTER_GATHER_LIST *SgList;
+ UINT32 SgListTotalSize;
+ UINTN IoVecIdx;
+
+ SgList = SgListParam[ListId];
+ if (SgList == NULL) {
+ continue;
+ }
+ //
+ // Sanity-check SgList -- it must provide at least one IO Vector.
+ //
+ if (SgList->IoVec == NULL || SgList->NumVec == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure that, for each IO Vector in this SgList, a virtio descriptor
+ // can be added to the virtio queue, after the other descriptors added
+ // previously.
+ //
+ if (SgList->NumVec > (UINTN)(MAX_UINT16 - DescriptorsNeeded) ||
+ DescriptorsNeeded + SgList->NumVec > VirtioFs->QueueSize) {
+ return EFI_UNSUPPORTED;
+ }
+ DescriptorsNeeded += (UINT16)SgList->NumVec;
+
+ SgListTotalSize = 0;
+ for (IoVecIdx = 0; IoVecIdx < SgList->NumVec; IoVecIdx++) {
+ VIRTIO_FS_IO_VECTOR *IoVec;
+
+ IoVec = &SgList->IoVec[IoVecIdx];
+ //
+ // Sanity-check this IoVec -- it must describe a non-empty buffer.
+ //
+ if (IoVec->Buffer == NULL || IoVec->Size == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Make sure the cumulative size of all IO Vectors in this SgList remains
+ // expressible as a UINT32.
+ //
+ if (IoVec->Size > MAX_UINT32 - SgListTotalSize) {
+ return EFI_UNSUPPORTED;
+ }
+ SgListTotalSize += (UINT32)IoVec->Size;
+
+ //
+ // Initialize those fields in this IO Vector that will be updated in
+ // relation to mapping / transfer.
+ //
+ IoVec->Mapped = FALSE;
+ IoVec->MappedAddress = 0;
+ IoVec->Mapping = NULL;
+ IoVec->Transferred = 0;
+ }
+
+ //
+ // Store the cumulative size of all IO Vectors that we have calculated in
+ // this SgList.
+ //
+ SgList->TotalSize = SgListTotalSize;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Submit a validated pair of (request buffer list, response buffer list) to the
+ Virtio Filesystem device.
+
+ On input, the pair of VIRTIO_FS_SCATTER_GATHER_LIST objects must have been
+ validated together, using the VirtioFsSgListsValidate() function.
+
+ On output (on successful return), the following fields will be re-initialized
+ to zero (after temporarily setting them to different values):
+ - VIRTIO_FS_IO_VECTOR.Mapped,
+ - VIRTIO_FS_IO_VECTOR.MappedAddress,
+ - VIRTIO_FS_IO_VECTOR.Mapping.
+
+ On output (on successful return), the following fields will be calculated:
+ - VIRTIO_FS_IO_VECTOR.Transferred.
+
+ The function may only be called after VirtioFsInit() returns successfully and
+ before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device that the
+ request-response exchange, expressed via
+ RequestSgList and ResponseSgList, should now
+ be submitted to.
+
+ @param[in,out] RequestSgList The scatter-gather list that describes the
+ request part of the exchange -- the buffers
+ that should be sent to the Virtio Filesystem
+ device in the virtio transfer.
+
+ @param[in,out] ResponseSgList The scatter-gather list that describes the
+ response part of the exchange -- the buffers
+ that the Virtio Filesystem device should
+ populate in the virtio transfer. May be NULL
+ if and only if NULL was passed to
+ VirtioFsSgListsValidate() as ResponseSgList.
+
+ @retval EFI_SUCCESS Transfer complete. The caller should investigate
+ the VIRTIO_FS_IO_VECTOR.Transferred fields in
+ ResponseSgList, to ensure coverage of the relevant
+ response buffers. Subsequently, the caller should
+ investigate the contents of those buffers.
+
+ @retval EFI_DEVICE_ERROR The Virtio Filesystem device reported populating
+ more response bytes than ResponseSgList->TotalSize.
+
+ @return Error codes propagated from
+ VirtioMapAllBytesInSharedBuffer(), VirtioFlush(),
+ or VirtioFs->Virtio->UnmapSharedBuffer().
+**/
+EFI_STATUS
+VirtioFsSgListsSubmit (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *RequestSgList,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *ResponseSgList OPTIONAL
+ )
+{
+ VIRTIO_FS_SCATTER_GATHER_LIST *SgListParam[2];
+ VIRTIO_MAP_OPERATION SgListVirtioMapOp[ARRAY_SIZE (SgListParam)];
+ UINT16 SgListDescriptorFlag[ARRAY_SIZE (SgListParam)];
+ UINTN ListId;
+ VIRTIO_FS_SCATTER_GATHER_LIST *SgList;
+ UINTN IoVecIdx;
+ VIRTIO_FS_IO_VECTOR *IoVec;
+ EFI_STATUS Status;
+ DESC_INDICES Indices;
+ UINT32 TotalBytesWrittenByDevice;
+ UINT32 BytesPermittedForWrite;
+
+ SgListParam[0] = RequestSgList;
+ SgListVirtioMapOp[0] = VirtioOperationBusMasterRead;
+ SgListDescriptorFlag[0] = 0;
+
+ SgListParam[1] = ResponseSgList;
+ SgListVirtioMapOp[1] = VirtioOperationBusMasterWrite;
+ SgListDescriptorFlag[1] = VRING_DESC_F_WRITE;
+
+ //
+ // Map all IO Vectors.
+ //
+ for (ListId = 0; ListId < ARRAY_SIZE (SgListParam); ListId++) {
+ SgList = SgListParam[ListId];
+ if (SgList == NULL) {
+ continue;
+ }
+ for (IoVecIdx = 0; IoVecIdx < SgList->NumVec; IoVecIdx++) {
+ IoVec = &SgList->IoVec[IoVecIdx];
+ //
+ // Map this IO Vector.
+ //
+ Status = VirtioMapAllBytesInSharedBuffer (
+ VirtioFs->Virtio,
+ SgListVirtioMapOp[ListId],
+ IoVec->Buffer,
+ IoVec->Size,
+ &IoVec->MappedAddress,
+ &IoVec->Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ goto Unmap;
+ }
+ IoVec->Mapped = TRUE;
+ }
+ }
+
+ //
+ // Compose the descriptor chain.
+ //
+ VirtioPrepare (&VirtioFs->Ring, &Indices);
+ for (ListId = 0; ListId < ARRAY_SIZE (SgListParam); ListId++) {
+ SgList = SgListParam[ListId];
+ if (SgList == NULL) {
+ continue;
+ }
+ for (IoVecIdx = 0; IoVecIdx < SgList->NumVec; IoVecIdx++) {
+ UINT16 NextFlag;
+
+ IoVec = &SgList->IoVec[IoVecIdx];
+ //
+ // Set VRING_DESC_F_NEXT on all except the very last descriptor.
+ //
+ NextFlag = VRING_DESC_F_NEXT;
+ if (ListId == ARRAY_SIZE (SgListParam) - 1 &&
+ IoVecIdx == SgList->NumVec - 1) {
+ NextFlag = 0;
+ }
+ VirtioAppendDesc (
+ &VirtioFs->Ring,
+ IoVec->MappedAddress,
+ (UINT32)IoVec->Size,
+ SgListDescriptorFlag[ListId] | NextFlag,
+ &Indices
+ );
+ }
+ }
+
+ //
+ // Submit the descriptor chain.
+ //
+ Status = VirtioFlush (VirtioFs->Virtio, VIRTIO_FS_REQUEST_QUEUE,
+ &VirtioFs->Ring, &Indices, &TotalBytesWrittenByDevice);
+ if (EFI_ERROR (Status)) {
+ goto Unmap;
+ }
+
+ //
+ // Sanity-check: the Virtio Filesystem device should not have written more
+ // bytes than what we offered buffers for.
+ //
+ if (ResponseSgList == NULL) {
+ BytesPermittedForWrite = 0;
+ } else {
+ BytesPermittedForWrite = ResponseSgList->TotalSize;
+ }
+ if (TotalBytesWrittenByDevice > BytesPermittedForWrite) {
+ Status = EFI_DEVICE_ERROR;
+ goto Unmap;
+ }
+
+ //
+ // Update the transfer sizes in the IO Vectors.
+ //
+ for (ListId = 0; ListId < ARRAY_SIZE (SgListParam); ListId++) {
+ SgList = SgListParam[ListId];
+ if (SgList == NULL) {
+ continue;
+ }
+ for (IoVecIdx = 0; IoVecIdx < SgList->NumVec; IoVecIdx++) {
+ IoVec = &SgList->IoVec[IoVecIdx];
+ if (SgListVirtioMapOp[ListId] == VirtioOperationBusMasterRead) {
+ //
+ // We report that the Virtio Filesystem device has read all buffers in
+ // the request.
+ //
+ IoVec->Transferred = IoVec->Size;
+ } else {
+ //
+ // Regarding the response, calculate how much of the current IO Vector
+ // has been populated by the Virtio Filesystem device. In
+ // "TotalBytesWrittenByDevice", VirtioFlush() reported the total count
+ // across all device-writeable descriptors, in the order they were
+ // chained on the ring.
+ //
+ IoVec->Transferred = MIN ((UINTN)TotalBytesWrittenByDevice,
+ IoVec->Size);
+ TotalBytesWrittenByDevice -= (UINT32)IoVec->Transferred;
+ }
+ }
+ }
+
+ //
+ // By now, "TotalBytesWrittenByDevice" has been exhausted.
+ //
+ ASSERT (TotalBytesWrittenByDevice == 0);
+
+ //
+ // We've succeeded; fall through.
+ //
+Unmap:
+ //
+ // Unmap all mapped IO Vectors on both the success and the error paths. The
+ // unmapping occurs in reverse order of mapping, in an attempt to avoid
+ // memory fragmentation.
+ //
+ ListId = ARRAY_SIZE (SgListParam);
+ while (ListId > 0) {
+ --ListId;
+ SgList = SgListParam[ListId];
+ if (SgList == NULL) {
+ continue;
+ }
+ IoVecIdx = SgList->NumVec;
+ while (IoVecIdx > 0) {
+ EFI_STATUS UnmapStatus;
+
+ --IoVecIdx;
+ IoVec = &SgList->IoVec[IoVecIdx];
+ //
+ // Unmap this IO Vector, if it has been mapped.
+ //
+ if (!IoVec->Mapped) {
+ continue;
+ }
+ UnmapStatus = VirtioFs->Virtio->UnmapSharedBuffer (VirtioFs->Virtio,
+ IoVec->Mapping);
+ //
+ // Re-set the following fields to the values they initially got from
+ // VirtioFsSgListsValidate() -- the above unmapping attempt is considered
+ // final, even if it fails.
+ //
+ IoVec->Mapped = FALSE;
+ IoVec->MappedAddress = 0;
+ IoVec->Mapping = NULL;
+
+ //
+ // If we are on the success path, but the unmapping failed, we need to
+ // transparently flip to the failure path -- the caller must learn they
+ // should not consult the response buffers.
+ //
+ // The branch below can be taken at most once.
+ //
+ if (!EFI_ERROR (Status) && EFI_ERROR (UnmapStatus)) {
+ Status = UnmapStatus;
+ }
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Set up the fields of a new VIRTIO_FS_FUSE_REQUEST object.
+
+ The function may only be called after VirtioFsInit() returns successfully and
+ before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device that the request is
+ being prepared for. The "VirtioFs->RequestId" field
+ will be copied into "Request->Unique". On output (on
+ successful return), "VirtioFs->RequestId" will be
+ incremented.
+
+ @param[out] Request The VIRTIO_FS_FUSE_REQUEST object whose fields are to
+ be set.
+
+ @param[in] RequestSize The total size of the request, including
+ sizeof(VIRTIO_FS_FUSE_REQUEST).
+
+ @param[in] Opcode The VIRTIO_FS_FUSE_OPCODE that identifies the command
+ to send.
+
+ @param[in] NodeId The inode number of the file that the request refers
+ to. When Opcode is VirtioFsFuseOpInit, NodeId is
+ ignored by the Virtio Filesystem device.
+
+ @retval EFI_INVALID_PARAMETER RequestSize is smaller than
+ sizeof(VIRTIO_FS_FUSE_REQUEST).
+
+ @retval EFI_OUT_OF_RESOURCES "VirtioFs->RequestId" is MAX_UINT64, and can
+ be incremented no more.
+
+ @retval EFI_SUCCESS Request has been populated,
+ "VirtioFs->RequestId" has been incremented.
+**/
+EFI_STATUS
+VirtioFsFuseNewRequest (
+ IN OUT VIRTIO_FS *VirtioFs,
+ OUT VIRTIO_FS_FUSE_REQUEST *Request,
+ IN UINT32 RequestSize,
+ IN VIRTIO_FS_FUSE_OPCODE Opcode,
+ IN UINT64 NodeId
+ )
+{
+ if (RequestSize < sizeof *Request) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (VirtioFs->RequestId == MAX_UINT64) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Request->Len = RequestSize;
+ Request->Opcode = Opcode;
+ Request->Unique = VirtioFs->RequestId++;
+ Request->NodeId = NodeId;
+ Request->Uid = 0;
+ Request->Gid = 0;
+ Request->Pid = 1;
+ Request->Padding = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Check the common FUSE response format.
+
+ The first buffer in the response scatter-gather list is assumed a
+ VIRTIO_FS_FUSE_RESPONSE structure. Subsequent response buffers, if any, up to
+ and excluding the last one, are assumed fixed size. The last response buffer
+ may or may not be fixed size, as specified by the caller.
+
+ This function may only be called after VirtioFsSgListsSubmit() returns
+ successfully.
+
+ @param[in] ResponseSgList The scatter-gather list that describes the
+ response part of the exchange -- the buffers that
+ the Virtio Filesystem device filled in during the
+ virtio transfer.
+
+ @param[in] RequestId The request identifier to which the response is
+ expected to belong.
+
+ @param[out] TailBufferFill If NULL, then the last buffer in ResponseSgList
+ is considered fixed size. Otherwise, the last
+ buffer is considered variable size, and on
+ successful return, TailBufferFill reports the
+ number of bytes in the last buffer.
+
+ @retval EFI_INVALID_PARAMETER TailBufferFill is not NULL (i.e., the last
+ buffer is considered variable size), and
+ ResponseSgList->NumVec is 1.
+
+ @retval EFI_INVALID_PARAMETER The allocated size of the first buffer does
+ not match sizeof(VIRTIO_FS_FUSE_RESPONSE).
+
+ @retval EFI_PROTOCOL_ERROR The VIRTIO_FS_FUSE_RESPONSE structure in the
+ first buffer has not been fully populated.
+
+ @retval EFI_PROTOCOL_ERROR "VIRTIO_FS_FUSE_RESPONSE.Len" in the first
+ buffer does not equal the sum of the
+ individual buffer sizes (as populated).
+
+ @retval EFI_PROTOCOL_ERROR "VIRTIO_FS_FUSE_RESPONSE.Unique" in the first
+ buffer does not equal RequestId.
+
+ @retval EFI_PROTOCOL_ERROR "VIRTIO_FS_FUSE_RESPONSE.Error" in the first
+ buffer is zero, but a subsequent fixed size
+ buffer has not been fully populated.
+
+ @retval EFI_DEVICE_ERROR "VIRTIO_FS_FUSE_RESPONSE.Error" in the first
+ buffer is nonzero. The caller may investigate
+ "VIRTIO_FS_FUSE_RESPONSE.Error". Note that the
+ completeness of the subsequent fixed size
+ buffers is not verified in this case.
+
+ @retval EFI_SUCCESS Verification successful.
+**/
+EFI_STATUS
+VirtioFsFuseCheckResponse (
+ IN VIRTIO_FS_SCATTER_GATHER_LIST *ResponseSgList,
+ IN UINT64 RequestId,
+ OUT UINTN *TailBufferFill
+ )
+{
+ UINTN NumFixedSizeVec;
+ VIRTIO_FS_FUSE_RESPONSE *CommonResp;
+ UINT32 TotalTransferred;
+ UINTN Idx;
+
+ //
+ // Ensured by VirtioFsSgListsValidate().
+ //
+ ASSERT (ResponseSgList->NumVec > 0);
+
+ if (TailBufferFill == NULL) {
+ //
+ // All buffers are considered fixed size.
+ //
+ NumFixedSizeVec = ResponseSgList->NumVec;
+ } else {
+ //
+ // If the last buffer is variable size, then we need that buffer to be
+ // different from the first buffer, which is considered a
+ // VIRTIO_FS_FUSE_RESPONSE (fixed size) structure.
+ //
+ if (ResponseSgList->NumVec == 1) {
+ return EFI_INVALID_PARAMETER;
+ }
+ NumFixedSizeVec = ResponseSgList->NumVec - 1;
+ }
+
+ //
+ // The first buffer is supposed to carry a (fully populated)
+ // VIRTIO_FS_FUSE_RESPONSE structure.
+ //
+ if (ResponseSgList->IoVec[0].Size != sizeof *CommonResp) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (ResponseSgList->IoVec[0].Transferred != ResponseSgList->IoVec[0].Size) {
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // FUSE must report the same number of bytes, written by the Virtio
+ // Filesystem device, as the virtio transport does.
+ //
+ CommonResp = ResponseSgList->IoVec[0].Buffer;
+ TotalTransferred = 0;
+ for (Idx = 0; Idx < ResponseSgList->NumVec; Idx++) {
+ //
+ // Integer overflow and truncation are not possible, based on
+ // VirtioFsSgListsValidate() and VirtioFsSgListsSubmit().
+ //
+ TotalTransferred += (UINT32)ResponseSgList->IoVec[Idx].Transferred;
+ }
+ if (CommonResp->Len != TotalTransferred) {
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Enforce that FUSE match our request ID in the response.
+ //
+ if (CommonResp->Unique != RequestId) {
+ return EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // If there is an explicit error report, skip checking the transfer
+ // counts for the rest of the fixed size buffers.
+ //
+ if (CommonResp->Error != 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // There was no error reported, so we require that the Virtio Filesystem
+ // device populate all fixed size buffers. We checked this for the very first
+ // buffer above; let's check the rest (if any).
+ //
+ ASSERT (NumFixedSizeVec >= 1);
+ for (Idx = 1; Idx < NumFixedSizeVec; Idx++) {
+ if (ResponseSgList->IoVec[Idx].Transferred !=
+ ResponseSgList->IoVec[Idx].Size) {
+ return EFI_PROTOCOL_ERROR;
+ }
+ }
+
+ //
+ // If the last buffer is considered variable size, report its filled size.
+ //
+ if (TailBufferFill != NULL) {
+ *TailBufferFill = ResponseSgList->IoVec[NumFixedSizeVec].Transferred;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ An ad-hoc function for mapping FUSE (well, Linux) "errno" values to
+ EFI_STATUS.
+
+ @param[in] Errno The "VIRTIO_FS_FUSE_RESPONSE.Error" value, returned by the
+ Virtio Filesystem device. The value is expected to be
+ negative.
+
+ @return An EFI_STATUS error code that's deemed a passable
+ mapping for the Errno value.
+
+ @retval EFI_DEVICE_ERROR Fallback EFI_STATUS code for unrecognized Errno
+ values.
+**/
+EFI_STATUS
+VirtioFsErrnoToEfiStatus (
+ IN INT32 Errno
+ )
+{
+ switch (Errno) {
+ case -1: // EPERM Operation not permitted
+ return EFI_SECURITY_VIOLATION;
+
+ case -2: // ENOENT No such file or directory
+ case -3: // ESRCH No such process
+ case -6: // ENXIO No such device or address
+ case -10: // ECHILD No child processes
+ case -19: // ENODEV No such device
+ case -49: // EUNATCH Protocol driver not attached
+ case -65: // ENOPKG Package not installed
+ case -79: // ELIBACC Can not access a needed shared library
+ case -126: // ENOKEY Required key not available
+ return EFI_NOT_FOUND;
+
+ case -4: // EINTR Interrupted system call
+ case -11: // EAGAIN, EWOULDBLOCK Resource temporarily unavailable
+ case -16: // EBUSY Device or resource busy
+ case -26: // ETXTBSY Text file busy
+ case -35: // EDEADLK, EDEADLOCK Resource deadlock avoided
+ case -39: // ENOTEMPTY Directory not empty
+ case -42: // ENOMSG No message of desired type
+ case -61: // ENODATA No data available
+ case -85: // ERESTART Interrupted system call should be restarted
+ return EFI_NOT_READY;
+
+ case -5: // EIO Input/output error
+ case -45: // EL2NSYNC Level 2 not synchronized
+ case -46: // EL3HLT Level 3 halted
+ case -47: // EL3RST Level 3 reset
+ case -51: // EL2HLT Level 2 halted
+ case -121: // EREMOTEIO Remote I/O error
+ case -133: // EHWPOISON Memory page has hardware error
+ return EFI_DEVICE_ERROR;
+
+ case -7: // E2BIG Argument list too long
+ case -36: // ENAMETOOLONG File name too long
+ case -90: // EMSGSIZE Message too long
+ return EFI_BAD_BUFFER_SIZE;
+
+ case -8: // ENOEXEC Exec format error
+ case -15: // ENOTBLK Block device required
+ case -18: // EXDEV Invalid cross-device link
+ case -20: // ENOTDIR Not a directory
+ case -21: // EISDIR Is a directory
+ case -25: // ENOTTY Inappropriate ioctl for device
+ case -27: // EFBIG File too large
+ case -29: // ESPIPE Illegal seek
+ case -38: // ENOSYS Function not implemented
+ case -59: // EBFONT Bad font file format
+ case -60: // ENOSTR Device not a stream
+ case -83: // ELIBEXEC Cannot exec a shared library directly
+ case -88: // ENOTSOCK Socket operation on non-socket
+ case -91: // EPROTOTYPE Protocol wrong type for socket
+ case -92: // ENOPROTOOPT Protocol not available
+ case -93: // EPROTONOSUPPORT Protocol not supported
+ case -94: // ESOCKTNOSUPPORT Socket type not supported
+ case -95: // ENOTSUP, EOPNOTSUPP Operation not supported
+ case -96: // EPFNOSUPPORT Protocol family not supported
+ case -97: // EAFNOSUPPORT Address family not supported by protocol
+ case -99: // EADDRNOTAVAIL Cannot assign requested address
+ case -118: // ENOTNAM Not a XENIX named type file
+ case -120: // EISNAM Is a named type file
+ case -124: // EMEDIUMTYPE Wrong medium type
+ return EFI_UNSUPPORTED;
+
+ case -9: // EBADF Bad file descriptor
+ case -14: // EFAULT Bad address
+ case -44: // ECHRNG Channel number out of range
+ case -48: // ELNRNG Link number out of range
+ case -53: // EBADR Invalid request descriptor
+ case -56: // EBADRQC Invalid request code
+ case -57: // EBADSLT Invalid slot
+ case -76: // ENOTUNIQ Name not unique on network
+ case -84: // EILSEQ Invalid or incomplete multibyte or wide character
+ return EFI_NO_MAPPING;
+
+ case -12: // ENOMEM Cannot allocate memory
+ case -23: // ENFILE Too many open files in system
+ case -24: // EMFILE Too many open files
+ case -31: // EMLINK Too many links
+ case -37: // ENOLCK No locks available
+ case -40: // ELOOP Too many levels of symbolic links
+ case -50: // ENOCSI No CSI structure available
+ case -55: // ENOANO No anode
+ case -63: // ENOSR Out of streams resources
+ case -82: // ELIBMAX Attempting to link in too many shared libraries
+ case -87: // EUSERS Too many users
+ case -105: // ENOBUFS No buffer space available
+ case -109: // ETOOMANYREFS Too many references: cannot splice
+ case -119: // ENAVAIL No XENIX semaphores available
+ case -122: // EDQUOT Disk quota exceeded
+ return EFI_OUT_OF_RESOURCES;
+
+ case -13: // EACCES Permission denied
+ return EFI_ACCESS_DENIED;
+
+ case -17: // EEXIST File exists
+ case -98: // EADDRINUSE Address already in use
+ case -106: // EISCONN Transport endpoint is already connected
+ case -114: // EALREADY Operation already in progress
+ case -115: // EINPROGRESS Operation now in progress
+ return EFI_ALREADY_STARTED;
+
+ case -22: // EINVAL Invalid argument
+ case -33: // EDOM Numerical argument out of domain
+ return EFI_INVALID_PARAMETER;
+
+ case -28: // ENOSPC No space left on device
+ case -54: // EXFULL Exchange full
+ return EFI_VOLUME_FULL;
+
+ case -30: // EROFS Read-only file system
+ return EFI_WRITE_PROTECTED;
+
+ case -32: // EPIPE Broken pipe
+ case -43: // EIDRM Identifier removed
+ case -67: // ENOLINK Link has been severed
+ case -68: // EADV Advertise error
+ case -69: // ESRMNT Srmount error
+ case -70: // ECOMM Communication error on send
+ case -73: // EDOTDOT RFS specific error
+ case -78: // EREMCHG Remote address changed
+ case -86: // ESTRPIPE Streams pipe error
+ case -102: // ENETRESET Network dropped connection on reset
+ case -103: // ECONNABORTED Software caused connection abort
+ case -104: // ECONNRESET Connection reset by peer
+ case -116: // ESTALE Stale file handle
+ case -125: // ECANCELED Operation canceled
+ case -128: // EKEYREVOKED Key has been revoked
+ case -129: // EKEYREJECTED Key was rejected by service
+ case -130: // EOWNERDEAD Owner died
+ case -131: // ENOTRECOVERABLE State not recoverable
+ return EFI_ABORTED;
+
+ case -34: // ERANGE Numerical result out of range
+ case -75: // EOVERFLOW Value too large for defined data type
+ return EFI_BUFFER_TOO_SMALL;
+
+ case -52: // EBADE Invalid exchange
+ case -108: // ESHUTDOWN Cannot send after transport endpoint shutdown
+ case -111: // ECONNREFUSED Connection refused
+ return EFI_END_OF_FILE;
+
+ case -62: // ETIME Timer expired
+ case -110: // ETIMEDOUT Connection timed out
+ case -127: // EKEYEXPIRED Key has expired
+ return EFI_TIMEOUT;
+
+ case -64: // ENONET Machine is not on the network
+ case -66: // EREMOTE Object is remote
+ case -72: // EMULTIHOP Multihop attempted
+ case -100: // ENETDOWN Network is down
+ case -101: // ENETUNREACH Network is unreachable
+ case -112: // EHOSTDOWN Host is down
+ case -113: // EHOSTUNREACH No route to host
+ case -123: // ENOMEDIUM No medium found
+ case -132: // ERFKILL Operation not possible due to RF-kill
+ return EFI_NO_MEDIA;
+
+ case -71: // EPROTO Protocol error
+ return EFI_PROTOCOL_ERROR;
+
+ case -74: // EBADMSG Bad message
+ case -77: // EBADFD File descriptor in bad state
+ case -80: // ELIBBAD Accessing a corrupted shared library
+ case -81: // ELIBSCN .lib section in a.out corrupted
+ case -117: // EUCLEAN Structure needs cleaning
+ return EFI_VOLUME_CORRUPTED;
+
+ case -89: // EDESTADDRREQ Destination address required
+ case -107: // ENOTCONN Transport endpoint is not connected
+ return EFI_NOT_STARTED;
+
+ default:
+ break;
+ }
+
+ return EFI_DEVICE_ERROR;
+}
+
+//
+// Parser states for canonicalizing a POSIX pathname.
+//
+typedef enum {
+ ParserInit, // just starting
+ ParserEnd, // finished
+ ParserSlash, // slash(es) seen
+ ParserDot, // one dot seen since last slash
+ ParserDotDot, // two dots seen since last slash
+ ParserNormal, // a different sequence seen
+} PARSER_STATE;
+
+/**
+ Strip the trailing slash from the parser's output buffer, unless the trailing
+ slash stands for the root directory.
+
+ @param[in] Buffer The parser's output buffer. Only used for
+ sanity-checking.
+
+ @param[in,out] Position On entry, points at the next character to produce
+ (i.e., right past the end of the output written by
+ the parser thus far). The last character in the
+ parser's output buffer is a slash. On return, the
+ slash is stripped, by decrementing Position by one.
+ If this action would remove the slash character
+ standing for the root directory, then the function
+ has no effect.
+**/
+STATIC
+VOID
+ParserStripSlash (
+ IN CHAR8 *Buffer,
+ IN OUT UINTN *Position
+ )
+{
+ ASSERT (*Position >= 1);
+ ASSERT (Buffer[*Position - 1] == '/');
+ if (*Position == 1) {
+ return;
+ }
+ (*Position)--;
+}
+
+/**
+ Produce one character in the parser's output buffer.
+
+ @param[out] Buffer The parser's output buffer. On return, Char8 will
+ have been written.
+
+ @param[in,out] Position On entry, points at the next character to produce
+ (i.e., right past the end of the output written by
+ the parser thus far). On return, Position is
+ incremented by one.
+
+ @param[in] Size Total allocated size of the parser's output buffer.
+ Used for sanity-checking.
+
+ @param[in] Char8 The character to place in the output buffer.
+**/
+STATIC
+VOID
+ParserCopy (
+ OUT CHAR8 *Buffer,
+ IN OUT UINTN *Position,
+ IN UINTN Size,
+ IN CHAR8 Char8
+ )
+{
+ ASSERT (*Position < Size);
+ Buffer[(*Position)++] = Char8;
+}
+
+/**
+ Rewind the last single-dot in the parser's output buffer.
+
+ @param[in] Buffer The parser's output buffer. Only used for
+ sanity-checking.
+
+ @param[in,out] Position On entry, points at the next character to produce
+ (i.e., right past the end of the output written by
+ the parser thus far); the parser's output buffer
+ ends with the characters ('/', '.'). On return, the
+ dot is rewound by decrementing Position by one; a
+ slash character will reside at the new end of the
+ parser's output buffer.
+**/
+STATIC
+VOID
+ParserRewindDot (
+ IN CHAR8 *Buffer,
+ IN OUT UINTN *Position
+ )
+{
+ ASSERT (*Position >= 2);
+ ASSERT (Buffer[*Position - 1] == '.');
+ ASSERT (Buffer[*Position - 2] == '/');
+ (*Position)--;
+}
+
+/**
+ Rewind the last dot-dot in the parser's output buffer.
+
+ @param[in] Buffer The parser's output buffer. Only used for
+ sanity-checking.
+
+ @param[in,out] Position On entry, points at the next character to produce
+ (i.e., right past the end of the output written by
+ the parser thus far); the parser's output buffer
+ ends with the characters ('/', '.', '.'). On return,
+ the ('.', '.') pair is rewound unconditionally, by
+ decrementing Position by two; a slash character
+ resides at the new end of the parser's output
+ buffer.
+
+ If this slash character stands for the root
+ directory, then RootEscape is set to TRUE.
+
+ Otherwise (i.e., if this slash character is not the
+ one standing for the root directory), then the slash
+ character, and the pathname component preceding it,
+ are removed by decrementing Position further. In
+ this case, the slash character preceding the removed
+ pathname component will reside at the new end of the
+ parser's output buffer.
+
+ @param[out] RootEscape Set to TRUE on output if the dot-dot component tries
+ to escape the root directory, as described above.
+ Otherwise, RootEscape is not modified.
+**/
+STATIC
+VOID
+ParserRewindDotDot (
+ IN CHAR8 *Buffer,
+ IN OUT UINTN *Position,
+ OUT BOOLEAN *RootEscape
+
+ )
+{
+ ASSERT (*Position >= 3);
+ ASSERT (Buffer[*Position - 1] == '.');
+ ASSERT (Buffer[*Position - 2] == '.');
+ ASSERT (Buffer[*Position - 3] == '/');
+ (*Position) -= 2;
+
+ if (*Position == 1) {
+ //
+ // Root directory slash reached; don't try to climb higher.
+ //
+ *RootEscape = TRUE;
+ return;
+ }
+
+ //
+ // Skip slash.
+ //
+ (*Position)--;
+ //
+ // Scan until next slash to the left.
+ //
+ do {
+ ASSERT (*Position > 0);
+ (*Position)--;
+ } while (Buffer[*Position] != '/');
+ (*Position)++;
+}
+
+/**
+ Append the UEFI-style RhsPath16 to the POSIX-style, canonical format
+ LhsPath8. Output the POSIX-style, canonical format result in ResultPath, as a
+ dynamically allocated string.
+
+ Canonicalization (aka sanitization) establishes the following properties:
+ - ResultPath is absolute (starts with "/"),
+ - dot (.) and dot-dot (..) components are resolved/eliminated in ResultPath,
+ with the usual semantics,
+ - ResultPath uses forward slashes,
+ - sequences of slashes are squashed in ResultPath,
+ - the printable ASCII character set covers ResultPath,
+ - CHAR8 encoding is used in ResultPath,
+ - no trailing slash present in ResultPath except for the standalone root
+ directory,
+ - the length of ResultPath is at most VIRTIO_FS_MAX_PATHNAME_LENGTH.
+
+ Any dot-dot in RhsPath16 that would remove the root directory is dropped, and
+ reported through RootEscape, without failing the function call.
+
+ @param[in] LhsPath8 Identifies the base directory. The caller is
+ responsible for ensuring that LhsPath8 conform to
+ the above canonical pathname format on entry.
+
+ @param[in] RhsPath16 Identifies the desired file with a UEFI-style CHAR16
+ pathname. If RhsPath16 starts with a backslash, then
+ RhsPath16 is considered absolute, and LhsPath8 is
+ ignored; RhsPath16 is sanitized in isolation, for
+ producing ResultPath8. Otherwise (i.e., if RhsPath16
+ is relative), RhsPath16 is transliterated to CHAR8,
+ and naively appended to LhsPath8. The resultant
+ fused pathname is then sanitized, to produce
+ ResultPath8.
+
+ @param[out] ResultPath8 The POSIX-style, canonical format pathname that
+ leads to the file desired by the caller. After use,
+ the caller is responsible for freeing ResultPath8.
+
+ @param[out] RootEscape Set to TRUE if at least one dot-dot component in
+ RhsPath16 attempted to escape the root directory;
+ set to FALSE otherwise.
+
+ @retval EFI_SUCCESS ResultPath8 has been produced. RootEscape has
+ been output.
+
+ @retval EFI_INVALID_PARAMETER RhsPath16 is zero-length.
+
+ @retval EFI_INVALID_PARAMETER RhsPath16 failed the
+ VIRTIO_FS_MAX_PATHNAME_LENGTH check.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+
+ @retval EFI_OUT_OF_RESOURCES ResultPath8 would have failed the
+ VIRTIO_FS_MAX_PATHNAME_LENGTH check.
+
+ @retval EFI_UNSUPPORTED RhsPath16 contains a character that either
+ falls outside of the printable ASCII set, or
+ is a forward slash.
+**/
+EFI_STATUS
+VirtioFsAppendPath (
+ IN CHAR8 *LhsPath8,
+ IN CHAR16 *RhsPath16,
+ OUT CHAR8 **ResultPath8,
+ OUT BOOLEAN *RootEscape
+ )
+{
+ UINTN RhsLen;
+ CHAR8 *RhsPath8;
+ UINTN Idx;
+ EFI_STATUS Status;
+ UINTN SizeToSanitize;
+ CHAR8 *BufferToSanitize;
+ CHAR8 *SanitizedBuffer;
+ PARSER_STATE State;
+ UINTN SanitizedPosition;
+
+ //
+ // Appending an empty pathname is not allowed.
+ //
+ RhsLen = StrLen (RhsPath16);
+ if (RhsLen == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Enforce length restriction on RhsPath16.
+ //
+ if (RhsLen > VIRTIO_FS_MAX_PATHNAME_LENGTH) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Transliterate RhsPath16 to RhsPath8 by:
+ // - rejecting RhsPath16 if a character outside of printable ASCII is seen,
+ // - rejecting RhsPath16 if a forward slash is seen,
+ // - replacing backslashes with forward slashes,
+ // - casting the characters from CHAR16 to CHAR8.
+ //
+ RhsPath8 = AllocatePool (RhsLen + 1);
+ if (RhsPath8 == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ for (Idx = 0; RhsPath16[Idx] != L'\0'; Idx++) {
+ if (RhsPath16[Idx] < 0x20 || RhsPath16[Idx] > 0x7E ||
+ RhsPath16[Idx] == L'/') {
+ Status = EFI_UNSUPPORTED;
+ goto FreeRhsPath8;
+ }
+ RhsPath8[Idx] = (CHAR8)((RhsPath16[Idx] == L'\\') ? L'/' : RhsPath16[Idx]);
+ }
+ RhsPath8[Idx++] = '\0';
+
+ //
+ // Now prepare the input for the canonicalization (squashing of sequences of
+ // forward slashes, and eliminating . (dot) and .. (dot-dot) pathname
+ // components).
+ //
+ // The sanitized path can never be longer than the naive concatenation of the
+ // left hand side and right hand side paths, so we'll use the catenated size
+ // for allocating the sanitized output too.
+ //
+ if (RhsPath8[0] == '/') {
+ //
+ // If the right hand side path is absolute, then it is not appended to the
+ // left hand side path -- it *replaces* the left hand side path.
+ //
+ SizeToSanitize = RhsLen + 1;
+ BufferToSanitize = RhsPath8;
+ } else {
+ //
+ // If the right hand side path is relative, then it is appended (naively)
+ // to the left hand side.
+ //
+ UINTN LhsLen;
+
+ LhsLen = AsciiStrLen (LhsPath8);
+ SizeToSanitize = LhsLen + 1 + RhsLen + 1;
+ BufferToSanitize = AllocatePool (SizeToSanitize);
+ if (BufferToSanitize == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeRhsPath8;
+ }
+ CopyMem (BufferToSanitize, LhsPath8, LhsLen);
+ BufferToSanitize[LhsLen] = '/';
+ CopyMem (BufferToSanitize + LhsLen + 1, RhsPath8, RhsLen + 1);
+ }
+
+ //
+ // Allocate the output buffer.
+ //
+ SanitizedBuffer = AllocatePool (SizeToSanitize);
+ if (SanitizedBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeBufferToSanitize;
+ }
+
+ //
+ // State machine for parsing the input and producing the canonical output
+ // follows.
+ //
+ *RootEscape = FALSE;
+ Idx = 0;
+ State = ParserInit;
+ SanitizedPosition = 0;
+ do {
+ CHAR8 Chr8;
+
+ ASSERT (Idx < SizeToSanitize);
+ Chr8 = BufferToSanitize[Idx++];
+
+ switch (State) {
+ case ParserInit: // just starting
+ ASSERT (Chr8 == '/');
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserSlash;
+ break;
+
+ case ParserSlash: // slash(es) seen
+ switch (Chr8) {
+ case '\0':
+ ParserStripSlash (SanitizedBuffer, &SanitizedPosition);
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserEnd;
+ break;
+ case '/':
+ //
+ // skip & stay in same state
+ //
+ break;
+ case '.':
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserDot;
+ break;
+ default:
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserNormal;
+ break;
+ }
+ break;
+
+ case ParserDot: // one dot seen since last slash
+ switch (Chr8) {
+ case '\0':
+ ParserRewindDot (SanitizedBuffer, &SanitizedPosition);
+ ParserStripSlash (SanitizedBuffer, &SanitizedPosition);
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserEnd;
+ break;
+ case '/':
+ ParserRewindDot (SanitizedBuffer, &SanitizedPosition);
+ State = ParserSlash;
+ break;
+ case '.':
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserDotDot;
+ break;
+ default:
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserNormal;
+ break;
+ }
+ break;
+
+ case ParserDotDot: // two dots seen since last slash
+ switch (Chr8) {
+ case '\0':
+ ParserRewindDotDot (SanitizedBuffer, &SanitizedPosition, RootEscape);
+ ParserStripSlash (SanitizedBuffer, &SanitizedPosition);
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserEnd;
+ break;
+ case '/':
+ ParserRewindDotDot (SanitizedBuffer, &SanitizedPosition, RootEscape);
+ State = ParserSlash;
+ break;
+ case '.':
+ //
+ // fall through
+ //
+ default:
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserNormal;
+ break;
+ }
+ break;
+
+ case ParserNormal: // a different sequence seen
+ switch (Chr8) {
+ case '\0':
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserEnd;
+ break;
+ case '/':
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ State = ParserSlash;
+ break;
+ case '.':
+ //
+ // fall through
+ //
+ default:
+ //
+ // copy and stay in same state
+ //
+ ParserCopy (SanitizedBuffer, &SanitizedPosition, SizeToSanitize, Chr8);
+ break;
+ }
+ break;
+
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ } while (State != ParserEnd);
+
+ //
+ // Ensure length invariant on ResultPath8.
+ //
+ ASSERT (SanitizedPosition >= 2);
+ if (SanitizedPosition - 1 > VIRTIO_FS_MAX_PATHNAME_LENGTH) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeSanitizedBuffer;
+ }
+
+ *ResultPath8 = SanitizedBuffer;
+ SanitizedBuffer = NULL;
+ Status = EFI_SUCCESS;
+ //
+ // Fall through.
+ //
+FreeSanitizedBuffer:
+ if (SanitizedBuffer != NULL) {
+ FreePool (SanitizedBuffer);
+ }
+
+FreeBufferToSanitize:
+ if (RhsPath8[0] != '/') {
+ FreePool (BufferToSanitize);
+ }
+
+FreeRhsPath8:
+ FreePool (RhsPath8);
+ return Status;
+}
+
+/**
+ For a given canonical pathname (as defined at VirtioFsAppendPath()), look up
+ the NodeId of the most specific parent directory, plus output a pointer to
+ the last pathname component (which is therefore a direct child of said parent
+ directory).
+
+ The function may only be called after VirtioFsFuseInitSession() returns
+ successfully and before VirtioFsUninit() is called.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device to send FUSE_LOOKUP
+ and FUSE_FORGET requests to. On output, the FUSE
+ request counter "VirtioFs->RequestId" will have
+ been incremented several times.
+
+ @param[in,out] Path The canonical pathname (as defined in the
+ description of VirtioFsAppendPath()) to split.
+ Path is modified in-place temporarily; however, on
+ return (successful or otherwise), Path reassumes
+ its original contents.
+
+ @param[out] DirNodeId The NodeId of the most specific parent directory
+ identified by Path. The caller is responsible for
+ sending a FUSE_FORGET request to the Virtio
+ Filesystem device for DirNodeId -- unless
+ DirNodeId equals VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID
+ --, when DirNodeId's use ends.
+
+ @param[out] LastComponent A pointer into Path, pointing at the start of the
+ last pathname component.
+
+ @retval EFI_SUCCESS Splitting successful.
+
+ @retval EFI_INVALID_PARAMETER Path is "/".
+
+ @retval EFI_ACCESS_DENIED One of the components on Path before the last
+ is not a directory.
+
+ @return Error codes propagated from
+ VirtioFsFuseLookup() and
+ VirtioFsFuseAttrToEfiFileInfo().
+**/
+EFI_STATUS
+VirtioFsLookupMostSpecificParentDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN OUT CHAR8 *Path,
+ OUT UINT64 *DirNodeId,
+ OUT CHAR8 **LastComponent
+ )
+{
+ UINT64 ParentDirNodeId;
+ CHAR8 *Slash;
+ EFI_STATUS Status;
+ UINT64 NextDirNodeId;
+
+ if (AsciiStrCmp (Path, "/") == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ParentDirNodeId = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID;
+ Slash = Path;
+ for (;;) {
+ CHAR8 *NextSlash;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+ EFI_FILE_INFO FileInfo;
+
+ //
+ // Find the slash (if any) that terminates the next pathname component.
+ //
+ NextSlash = AsciiStrStr (Slash + 1, "/");
+ if (NextSlash == NULL) {
+ break;
+ }
+
+ //
+ // Temporarily replace the found slash character with a NUL in-place, for
+ // easy construction of the single-component filename that we need to look
+ // up.
+ //
+ *NextSlash = '\0';
+ Status = VirtioFsFuseLookup (VirtioFs, ParentDirNodeId, Slash + 1,
+ &NextDirNodeId, &FuseAttr);
+ *NextSlash = '/';
+
+ //
+ // We're done with the directory inode that was the basis for the lookup.
+ //
+ if (ParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, ParentDirNodeId);
+ }
+
+ //
+ // If we couldn't look up the next *non-final* pathname component, bail.
+ //
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Lookup successful; now check if the next (non-final) component is a
+ // directory. If not, bail.
+ //
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ goto ForgetNextDirNodeId;
+ }
+ if ((FileInfo.Attribute & EFI_FILE_DIRECTORY) == 0) {
+ Status = EFI_ACCESS_DENIED;
+ goto ForgetNextDirNodeId;
+ }
+
+ //
+ // Advance.
+ //
+ ParentDirNodeId = NextDirNodeId;
+ Slash = NextSlash;
+ }
+
+ //
+ // ParentDirNodeId corresponds to the last containing directory. The
+ // remaining single-component filename represents a direct child under that
+ // directory. Said filename starts at (Slash + 1).
+ //
+ *DirNodeId = ParentDirNodeId;
+ *LastComponent = Slash + 1;
+ return EFI_SUCCESS;
+
+ForgetNextDirNodeId:
+ VirtioFsFuseForget (VirtioFs, NextDirNodeId);
+ return Status;
+}
+
+/**
+ Format the last component of a canonical pathname into a caller-provided
+ CHAR16 array.
+
+ @param[in] Path The canonical pathname (as defined in the
+ description of VirtioFsAppendPath()) to format
+ the last component of.
+
+ @param[out] Basename If BasenameSize is zero on input, Basename may
+ be NULL. Otherwise, Basename is allocated by the
+ caller. On successful return, Basename contains
+ the last component of Path, formatted as a
+ NUL-terminated CHAR16 string. When Path is "/"
+ on input, Basename is L"" on output.
+
+ @param[in,out] BasenameSize On input, the number of bytes the caller
+ provides in Basename. On output, regardless of
+ return value, the number of bytes required for
+ formatting Basename, including the terminating
+ L'\0'.
+
+ @retval EFI_SUCCESS Basename has been filled in.
+
+ @retval EFI_BUFFER_TOO_SMALL BasenameSize was too small on input; Basename
+ has not been modified.
+**/
+EFI_STATUS
+VirtioFsGetBasename (
+ IN CHAR8 *Path,
+ OUT CHAR16 *Basename OPTIONAL,
+ IN OUT UINTN *BasenameSize
+ )
+{
+ UINTN AllocSize;
+ UINTN LastComponent;
+ UINTN Idx;
+ UINTN PathSize;
+
+ AllocSize = *BasenameSize;
+
+ LastComponent = MAX_UINTN;
+ for (Idx = 0; Path[Idx] != '\0'; Idx++) {
+ if (Path[Idx] == '/') {
+ LastComponent = Idx;
+ }
+ }
+ PathSize = Idx + 1;
+ ASSERT (LastComponent < MAX_UINTN);
+ LastComponent++;
+ *BasenameSize = (PathSize - LastComponent) * sizeof Basename[0];
+
+ if (*BasenameSize > AllocSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ for (Idx = LastComponent; Idx < PathSize; Idx++) {
+ Basename[Idx - LastComponent] = Path[Idx];
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Format the destination of a rename/move operation as a dynamically allocated
+ canonical pathname.
+
+ Any dot-dot in RhsPath16 that would remove the root directory is dropped, and
+ reported through RootEscape, without failing the function call.
+
+ @param[in] LhsPath8 The source pathname operand of the rename/move
+ operation, expressed as a canonical pathname (as
+ defined in the description of VirtioFsAppendPath()).
+ The root directory "/" cannot be renamed/moved, and
+ will be rejected.
+
+ @param[in] RhsPath16 The destination pathname operand expressed as a
+ UEFI-style CHAR16 pathname.
+
+ If RhsPath16 starts with a backslash, then RhsPath16
+ is considered absolute. Otherwise, RhsPath16 is
+ interpreted relative to the most specific parent
+ directory found in LhsPath8.
+
+ Independently, if RhsPath16 ends with a backslash
+ (i.e., RhsPath16 is given in the "move into
+ directory" convenience form), then RhsPath16 is
+ interpreted with the basename of LhsPath8 appended.
+ Otherwise, the last pathname component of RhsPath16
+ is taken as the last pathname component of the
+ rename/move destination.
+
+ An empty RhsPath16 is rejected.
+
+ @param[out] ResultPath8 The POSIX-style, canonical format pathname that
+ leads to the renamed/moved file. After use, the
+ caller is responsible for freeing ResultPath8.
+
+ @param[out] RootEscape Set to TRUE if at least one dot-dot component in
+ RhsPath16 attempted to escape the root directory;
+ set to FALSE otherwise.
+
+ @retval EFI_SUCCESS ResultPath8 has been produced. RootEscape has
+ been output.
+
+ @retval EFI_INVALID_PARAMETER LhsPath8 is "/".
+
+ @retval EFI_INVALID_PARAMETER RhsPath16 is zero-length.
+
+ @retval EFI_INVALID_PARAMETER RhsPath16 failed the
+ VIRTIO_FS_MAX_PATHNAME_LENGTH check.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+
+ @retval EFI_OUT_OF_RESOURCES ResultPath8 would have failed the
+ VIRTIO_FS_MAX_PATHNAME_LENGTH check.
+
+ @retval EFI_UNSUPPORTED RhsPath16 contains a character that either
+ falls outside of the printable ASCII set, or
+ is a forward slash.
+**/
+EFI_STATUS
+VirtioFsComposeRenameDestination (
+ IN CHAR8 *LhsPath8,
+ IN CHAR16 *RhsPath16,
+ OUT CHAR8 **ResultPath8,
+ OUT BOOLEAN *RootEscape
+ )
+{
+ //
+ // Lengths are expressed as numbers of characters (CHAR8 or CHAR16),
+ // excluding terminating NULs. Sizes are expressed as byte counts, including
+ // the bytes taken up by terminating NULs.
+ //
+ UINTN RhsLen;
+ UINTN LhsBasename16Size;
+ EFI_STATUS Status;
+ UINTN LhsBasenameLen;
+ UINTN DestSuffix16Size;
+ CHAR16 *DestSuffix16;
+ CHAR8 *DestPrefix8;
+
+ //
+ // An empty destination operand for the rename/move operation is not allowed.
+ //
+ RhsLen = StrLen (RhsPath16);
+ if (RhsLen == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Enforce length restriction on RhsPath16.
+ //
+ if (RhsLen > VIRTIO_FS_MAX_PATHNAME_LENGTH) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Determine the length of the basename of LhsPath8.
+ //
+ LhsBasename16Size = 0;
+ Status = VirtioFsGetBasename (LhsPath8, NULL, &LhsBasename16Size);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ ASSERT (LhsBasename16Size >= sizeof (CHAR16));
+ ASSERT (LhsBasename16Size % sizeof (CHAR16) == 0);
+ LhsBasenameLen = LhsBasename16Size / sizeof (CHAR16) - 1;
+ if (LhsBasenameLen == 0) {
+ //
+ // The root directory cannot be renamed/moved.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Resolve the "move into directory" convenience form in RhsPath16.
+ //
+ if (RhsPath16[RhsLen - 1] == L'\\') {
+ //
+ // Append the basename of LhsPath8 as a CHAR16 string to RhsPath16.
+ //
+ DestSuffix16Size = RhsLen * sizeof (CHAR16) + LhsBasename16Size;
+ DestSuffix16 = AllocatePool (DestSuffix16Size);
+ if (DestSuffix16 == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (DestSuffix16, RhsPath16, RhsLen * sizeof (CHAR16));
+ Status = VirtioFsGetBasename (LhsPath8, DestSuffix16 + RhsLen,
+ &LhsBasename16Size);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ //
+ // Just create a copy of RhsPath16.
+ //
+ DestSuffix16Size = (RhsLen + 1) * sizeof (CHAR16);
+ DestSuffix16 = AllocateCopyPool (DestSuffix16Size, RhsPath16);
+ if (DestSuffix16 == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // If the destination operand is absolute, it will be interpreted relative to
+ // the root directory.
+ //
+ // Otherwise (i.e., if the destination operand is relative), then create the
+ // canonical pathname that the destination operand is interpreted relatively
+ // to; that is, the canonical pathname of the most specific parent directory
+ // found in LhsPath8.
+ //
+ if (DestSuffix16[0] == L'\\') {
+ DestPrefix8 = AllocateCopyPool (sizeof "/", "/");
+ if (DestPrefix8 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeDestSuffix16;
+ }
+ } else {
+ UINTN LhsLen;
+ UINTN DestPrefixLen;
+
+ //
+ // Strip the basename of LhsPath8.
+ //
+ LhsLen = AsciiStrLen (LhsPath8);
+ ASSERT (LhsBasenameLen < LhsLen);
+ DestPrefixLen = LhsLen - LhsBasenameLen;
+ ASSERT (LhsPath8[DestPrefixLen - 1] == '/');
+ //
+ // If we're not at the root directory, strip the slash too.
+ //
+ if (DestPrefixLen > 1) {
+ DestPrefixLen--;
+ }
+ DestPrefix8 = AllocatePool (DestPrefixLen + 1);
+ if (DestPrefix8 == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeDestSuffix16;
+ }
+ CopyMem (DestPrefix8, LhsPath8, DestPrefixLen);
+ DestPrefix8[DestPrefixLen] = '\0';
+ }
+
+ //
+ // Now combine DestPrefix8 and DestSuffix16 into the final canonical
+ // pathname.
+ //
+ Status = VirtioFsAppendPath (DestPrefix8, DestSuffix16, ResultPath8,
+ RootEscape);
+
+ FreePool (DestPrefix8);
+ //
+ // Fall through.
+ //
+FreeDestSuffix16:
+ FreePool (DestSuffix16);
+
+ return Status;
+}
+
+/**
+ Convert select fields of a VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to
+ corresponding fields in EFI_FILE_INFO.
+
+ @param[in] FuseAttr The VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE object to
+ convert the relevant fields from.
+
+ @param[out] FileInfo The EFI_FILE_INFO structure to modify. Importantly, the
+ FileInfo->Size and FileInfo->FileName fields are not
+ overwritten.
+
+ @retval EFI_SUCCESS Conversion successful.
+
+ @retval EFI_UNSUPPORTED The allocated size of the file is inexpressible in
+ EFI_FILE_INFO.
+
+ @retval EFI_UNSUPPORTED One of the file access times is inexpressible in
+ EFI_FILE_INFO.
+
+ @retval EFI_UNSUPPORTED The file type is inexpressible in EFI_FILE_INFO.
+
+ @retval EFI_UNSUPPORTED The file is a regular file that has multiple names
+ on the host side (i.e., its hard link count is
+ greater than one).
+**/
+EFI_STATUS
+VirtioFsFuseAttrToEfiFileInfo (
+ IN VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr,
+ OUT EFI_FILE_INFO *FileInfo
+ )
+{
+ UINT64 EpochTime[3];
+ EFI_TIME *ConvertedTime[ARRAY_SIZE (EpochTime)];
+ UINTN Idx;
+
+ FileInfo->FileSize = FuseAttr->Size;
+
+ //
+ // The unit for FuseAttr->Blocks is 512B.
+ //
+ if (FuseAttr->Blocks >= BIT55) {
+ return EFI_UNSUPPORTED;
+ }
+ FileInfo->PhysicalSize = LShiftU64 (FuseAttr->Blocks, 9);
+
+ //
+ // Convert the timestamps. File creation time is not tracked by the Virtio
+ // Filesystem device, so set FileInfo->CreateTime from FuseAttr->Mtime as
+ // well.
+ //
+ EpochTime[0] = FuseAttr->Mtime;
+ EpochTime[1] = FuseAttr->Atime;
+ EpochTime[2] = FuseAttr->Mtime;
+ ConvertedTime[0] = &FileInfo->CreateTime;
+ ConvertedTime[1] = &FileInfo->LastAccessTime;
+ ConvertedTime[2] = &FileInfo->ModificationTime;
+
+ for (Idx = 0; Idx < ARRAY_SIZE (EpochTime); Idx++) {
+ //
+ // EpochToEfiTime() takes a UINTN for seconds.
+ //
+ if (EpochTime[Idx] > MAX_UINTN) {
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Set the following fields in the converted time: Year, Month, Day, Hour,
+ // Minute, Second, Nanosecond.
+ //
+ EpochToEfiTime ((UINTN)EpochTime[Idx], ConvertedTime[Idx]);
+ //
+ // The times are all expressed in UTC. Consequently, they are not affected
+ // by daylight saving.
+ //
+ ConvertedTime[Idx]->TimeZone = 0;
+ ConvertedTime[Idx]->Daylight = 0;
+ //
+ // Clear the padding fields.
+ //
+ ConvertedTime[Idx]->Pad1 = 0;
+ ConvertedTime[Idx]->Pad2 = 0;
+ }
+
+ //
+ // Set the attributes.
+ //
+ switch (FuseAttr->Mode & VIRTIO_FS_FUSE_MODE_TYPE_MASK) {
+ case VIRTIO_FS_FUSE_MODE_TYPE_DIR:
+ FileInfo->Attribute = EFI_FILE_DIRECTORY;
+ break;
+ case VIRTIO_FS_FUSE_MODE_TYPE_REG:
+ FileInfo->Attribute = 0;
+ break;
+ default:
+ //
+ // Other file types are not supported.
+ //
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Report the regular file or directory as read-only if all classes lack
+ // write permission.
+ //
+ if ((FuseAttr->Mode & (VIRTIO_FS_FUSE_MODE_PERM_WUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_WGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_WOTH)) == 0) {
+ FileInfo->Attribute |= EFI_FILE_READ_ONLY;
+ }
+
+ //
+ // A hard link count greater than 1 is not supported for regular files.
+ //
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == 0 && FuseAttr->Nlink > 1) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE filename to an EFI_FILE_INFO
+ filename.
+
+ @param[in] FuseDirent The VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE object to
+ convert the filename byte array from. The caller is
+ responsible for ensuring that FuseDirent->Namelen
+ describe valid storage.
+
+ @param[in,out] FileInfo The EFI_FILE_INFO structure to modify. On input, the
+ caller is responsible for setting FileInfo->Size
+ according to the allocated size. On successful
+ return, FileInfo->Size is reduced to reflect the
+ filename converted into FileInfo->FileName.
+ FileInfo->FileName is set from the filename byte
+ array that directly follows the FuseDirent header
+ object. Fields other than FileInfo->Size and
+ FileInfo->FileName are not modified.
+
+ @retval EFI_SUCCESS Conversion successful.
+
+ @retval EFI_INVALID_PARAMETER VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE()
+ returns zero for FuseDirent->Namelen.
+
+ @retval EFI_BUFFER_TOO_SMALL On input, FileInfo->Size does not provide
+ enough room for converting the filename byte
+ array from FuseDirent.
+
+ @retval EFI_UNSUPPORTED The FuseDirent filename byte array contains a
+ byte that falls outside of the printable ASCII
+ range, or is a forward slash or a backslash.
+**/
+EFI_STATUS
+VirtioFsFuseDirentPlusToEfiFileInfo (
+ IN VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE *FuseDirent,
+ IN OUT EFI_FILE_INFO *FileInfo
+ )
+{
+ UINTN DirentSize;
+ UINTN FileInfoSize;
+ UINT8 *DirentName;
+ UINT32 Idx;
+
+ DirentSize = VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE (FuseDirent->Namelen);
+ if (DirentSize == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // We're now safe from overflow in the calculation below.
+ //
+ FileInfoSize = (OFFSET_OF (EFI_FILE_INFO, FileName) +
+ ((UINTN)FuseDirent->Namelen + 1) * sizeof (CHAR16));
+ if (FileInfoSize > FileInfo->Size) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Convert the name.
+ //
+ DirentName = (UINT8 *)(FuseDirent + 1);
+ for (Idx = 0; Idx < FuseDirent->Namelen; Idx++) {
+ UINT8 NameByte;
+
+ NameByte = DirentName[Idx];
+ if (NameByte < 0x20 || NameByte > 0x7E ||
+ NameByte == '/' || NameByte == '\\') {
+ return EFI_UNSUPPORTED;
+ }
+ FileInfo->FileName[Idx] = (CHAR16)NameByte;
+ }
+ FileInfo->FileName[Idx++] = L'\0';
+ //
+ // Set the (possibly reduced) size.
+ //
+ FileInfo->Size = FileInfoSize;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Given an EFI_FILE_INFO object received in an EFI_FILE_PROTOCOL.SetInfo()
+ call, determine whether updating the size of the file is necessary, relative
+ to an EFI_FILE_INFO object describing the current state of the file.
+
+ @param[in] Info The EFI_FILE_INFO describing the current state of the
+ file. The caller is responsible for populating Info on
+ input with VirtioFsFuseAttrToEfiFileInfo(), from the
+ current FUSE attributes of the file. The Info->Size and
+ Info->FileName members are ignored.
+
+ @param[in] NewInfo The EFI_FILE_INFO object received in the
+ EFI_FILE_PROTOCOL.SetInfo() call.
+
+ @param[out] Update Set to TRUE on output if the file size needs to be
+ updated. Set to FALSE otherwise.
+
+ @param[out] Size If Update is set to TRUE, then Size provides the new file
+ size to set. Otherwise, Size is not written to.
+**/
+VOID
+VirtioFsGetFuseSizeUpdate (
+ IN EFI_FILE_INFO *Info,
+ IN EFI_FILE_INFO *NewInfo,
+ OUT BOOLEAN *Update,
+ OUT UINT64 *Size
+ )
+{
+ BOOLEAN IsDirectory;
+
+ IsDirectory = (BOOLEAN)((Info->Attribute & EFI_FILE_DIRECTORY) != 0);
+
+ if (IsDirectory || Info->FileSize == NewInfo->FileSize) {
+ *Update = FALSE;
+ return;
+ }
+ *Update = TRUE;
+ *Size = NewInfo->FileSize;
+}
+
+/**
+ Given an EFI_FILE_INFO object received in an EFI_FILE_PROTOCOL.SetInfo()
+ call, determine whether updating the last access time and/or the last
+ modification time of the file is necessary, relative to an EFI_FILE_INFO
+ object describing the current state of the file.
+
+ @param[in] Info The EFI_FILE_INFO describing the current state of
+ the file. The caller is responsible for populating
+ Info on input with VirtioFsFuseAttrToEfiFileInfo(),
+ from the current FUSE attributes of the file. The
+ Info->Size and Info->FileName members are ignored.
+
+ @param[in] NewInfo The EFI_FILE_INFO object received in the
+ EFI_FILE_PROTOCOL.SetInfo() call.
+
+ @param[out] UpdateAtime Set to TRUE on output if the last access time needs
+ to be updated. Set to FALSE otherwise.
+
+ @param[out] UpdateMtime Set to TRUE on output if the last modification time
+ needs to be updated. Set to FALSE otherwise.
+
+ @param[out] Atime If UpdateAtime is set to TRUE, then Atime provides
+ the last access timestamp to set (as seconds since
+ the Epoch). Otherwise, Atime is not written to.
+
+ @param[out] Mtime If UpdateMtime is set to TRUE, then Mtime provides
+ the last modification timestamp to set (as seconds
+ since the Epoch). Otherwise, Mtime is not written
+ to.
+
+ @retval EFI_SUCCESS Output parameters have been set successfully.
+
+ @retval EFI_INVALID_PARAMETER At least one of the CreateTime, LastAccessTime
+ and ModificationTime fields in NewInfo
+ represents an actual update relative to the
+ current state of the file (expressed in Info),
+ but does not satisfy the UEFI spec
+ requirements on EFI_TIME.
+
+ @retval EFI_ACCESS_DENIED NewInfo requests changing both CreateTime and
+ ModificationTime, but to values that differ
+ from each other. The Virtio Filesystem device
+ does not support this.
+**/
+EFI_STATUS
+VirtioFsGetFuseTimeUpdates (
+ IN EFI_FILE_INFO *Info,
+ IN EFI_FILE_INFO *NewInfo,
+ OUT BOOLEAN *UpdateAtime,
+ OUT BOOLEAN *UpdateMtime,
+ OUT UINT64 *Atime,
+ OUT UINT64 *Mtime
+ )
+{
+ EFI_TIME *Time[3];
+ EFI_TIME *NewTime[ARRAY_SIZE (Time)];
+ UINTN Idx;
+ STATIC CONST EFI_TIME ZeroTime = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ BOOLEAN Change[ARRAY_SIZE (Time)];
+ UINT64 Seconds[ARRAY_SIZE (Time)];
+
+ Time[0] = &Info->CreateTime;
+ Time[1] = &Info->LastAccessTime;
+ Time[2] = &Info->ModificationTime;
+ NewTime[0] = &NewInfo->CreateTime;
+ NewTime[1] = &NewInfo->LastAccessTime;
+ NewTime[2] = &NewInfo->ModificationTime;
+
+ //
+ // Determine which timestamps differ from the current state. (A zero time
+ // means "don't update", per UEFI spec.) For each timestamp that's being
+ // changed, calculate the seconds since the Epoch.
+ //
+ for (Idx = 0; Idx < ARRAY_SIZE (Time); Idx++) {
+ if (CompareMem (NewTime[Idx], &ZeroTime, sizeof (EFI_TIME)) == 0 ||
+ CompareMem (NewTime[Idx], Time[Idx], sizeof (EFI_TIME)) == 0) {
+ Change[Idx] = FALSE;
+ } else {
+ if (!IsTimeValid (NewTime[Idx])) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Change[Idx] = TRUE;
+ Seconds[Idx] = EfiTimeToEpoch (NewTime[Idx]);
+ }
+ }
+
+ //
+ // If a change is requested for exactly one of CreateTime and
+ // ModificationTime, we'll change the last modification time. If changes are
+ // requested for both, and to the same timestamp, we'll similarly update the
+ // last modification time. If changes are requested for both, but to
+ // different timestamps, we reject the request.
+ //
+ if (Change[0] && Change[2] && Seconds[0] != Seconds[2]) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ *UpdateAtime = FALSE;
+ *UpdateMtime = FALSE;
+
+ if (Change[0]) {
+ *UpdateMtime = TRUE;
+ *Mtime = Seconds[0];
+ }
+ if (Change[1]) {
+ *UpdateAtime = TRUE;
+ *Atime = Seconds[1];
+ }
+ if (Change[2]) {
+ *UpdateMtime = TRUE;
+ *Mtime = Seconds[2];
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Given an EFI_FILE_INFO object received in an EFI_FILE_PROTOCOL.SetInfo()
+ call, determine whether updating the file mode bits of the file is necessary,
+ relative to an EFI_FILE_INFO object describing the current state of the file.
+
+ @param[in] Info The EFI_FILE_INFO describing the current state of the
+ file. The caller is responsible for populating Info on
+ input with VirtioFsFuseAttrToEfiFileInfo(), from the
+ current FUSE attributes of the file. The Info->Size and
+ Info->FileName members are ignored.
+
+ @param[in] NewInfo The EFI_FILE_INFO object received in the
+ EFI_FILE_PROTOCOL.SetInfo() call.
+
+ @param[out] Update Set to TRUE on output if the file mode bits need to be
+ updated. Set to FALSE otherwise.
+
+ @param[out] Mode If Update is set to TRUE, then Mode provides the file
+ mode bits to set. Otherwise, Mode is not written to.
+
+ @retval EFI_SUCCESS Output parameters have been set successfully.
+
+ @retval EFI_ACCESS_DENIED NewInfo requests toggling an unknown bit in the
+ Attribute bitmask.
+
+ @retval EFI_ACCESS_DENIED NewInfo requests toggling EFI_FILE_DIRECTORY in
+ the Attribute bitmask.
+**/
+EFI_STATUS
+VirtioFsGetFuseModeUpdate (
+ IN EFI_FILE_INFO *Info,
+ IN EFI_FILE_INFO *NewInfo,
+ OUT BOOLEAN *Update,
+ OUT UINT32 *Mode
+ )
+{
+ UINT64 Toggle;
+ BOOLEAN IsDirectory;
+ BOOLEAN IsWriteable;
+ BOOLEAN WillBeWriteable;
+
+ Toggle = Info->Attribute ^ NewInfo->Attribute;
+ if ((Toggle & ~EFI_FILE_VALID_ATTR) != 0) {
+ //
+ // Unknown attribute requested.
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ if ((Toggle & EFI_FILE_DIRECTORY) != 0) {
+ //
+ // EFI_FILE_DIRECTORY cannot be toggled.
+ //
+ return EFI_ACCESS_DENIED;
+ }
+
+ IsDirectory = (BOOLEAN)((Info->Attribute & EFI_FILE_DIRECTORY) != 0);
+ IsWriteable = (BOOLEAN)((Info->Attribute & EFI_FILE_READ_ONLY) == 0);
+ WillBeWriteable = (BOOLEAN)((NewInfo->Attribute & EFI_FILE_READ_ONLY) == 0);
+
+ if (IsWriteable == WillBeWriteable) {
+ *Update = FALSE;
+ return EFI_SUCCESS;
+ }
+
+ if (IsDirectory) {
+ if (WillBeWriteable) {
+ *Mode = (VIRTIO_FS_FUSE_MODE_PERM_RWXU |
+ VIRTIO_FS_FUSE_MODE_PERM_RWXG |
+ VIRTIO_FS_FUSE_MODE_PERM_RWXO);
+ } else {
+ *Mode = (VIRTIO_FS_FUSE_MODE_PERM_RUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_XUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_RGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_XGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_ROTH |
+ VIRTIO_FS_FUSE_MODE_PERM_XOTH);
+ }
+ } else {
+ if (WillBeWriteable) {
+ *Mode = (VIRTIO_FS_FUSE_MODE_PERM_RUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_WUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_RGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_WGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_ROTH |
+ VIRTIO_FS_FUSE_MODE_PERM_WOTH);
+ } else {
+ *Mode = (VIRTIO_FS_FUSE_MODE_PERM_RUSR |
+ VIRTIO_FS_FUSE_MODE_PERM_RGRP |
+ VIRTIO_FS_FUSE_MODE_PERM_ROTH);
+ }
+ }
+ *Update = TRUE;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsClose.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsClose.c
new file mode 100644
index 00000000000..a26adde9623
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsClose.c
@@ -0,0 +1,68 @@
+/** @file
+ EFI_FILE_PROTOCOL.Close() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // RemoveEntryList()
+#include <Library/MemoryAllocationLib.h> // FreePool()
+
+#include "VirtioFsDxe.h"
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileClose (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // All actions in this function are "best effort"; the UEFI spec requires
+ // EFI_FILE_PROTOCOL.Close() to sync all data to the device, but it also
+ // requires EFI_FILE_PROTOCOL.Close() to release resources unconditionally,
+ // and to return EFI_SUCCESS unconditionally.
+ //
+ // Flush, sync, release, and (if needed) forget. If any action fails, we
+ // still try the others.
+ //
+ if (VirtioFsFile->IsOpenForWriting) {
+ if (!VirtioFsFile->IsDirectory) {
+ VirtioFsFuseFlush (VirtioFs, VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle);
+ }
+
+ VirtioFsFuseFsyncFileOrDir (VirtioFs, VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
+ }
+
+ VirtioFsFuseReleaseFileOrDir (VirtioFs, VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
+
+ //
+ // VirtioFsFile->FuseHandle is gone at this point, but VirtioFsFile->NodeId
+ // is still valid. If we've known VirtioFsFile->NodeId from a lookup, then
+ // now we should ask the server to forget it *once*.
+ //
+ if (VirtioFsFile->NodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, VirtioFsFile->NodeId);
+ }
+
+ //
+ // One fewer file left open for the owner filesystem.
+ //
+ RemoveEntryList (&VirtioFsFile->OpenFilesEntry);
+
+ FreePool (VirtioFsFile->CanonicalPathname);
+ if (VirtioFsFile->FileInfoArray != NULL) {
+ FreePool (VirtioFsFile->FileInfoArray);
+ }
+ FreePool (VirtioFsFile);
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c
new file mode 100644
index 00000000000..f24db606570
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsDelete.c
@@ -0,0 +1,110 @@
+/** @file
+ EFI_FILE_PROTOCOL.Delete() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // RemoveEntryList()
+#include <Library/MemoryAllocationLib.h> // FreePool()
+
+#include "VirtioFsDxe.h"
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileDelete (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // All actions in this function are "best effort"; the UEFI spec requires
+ // EFI_FILE_PROTOCOL.Delete() to release resources unconditionally. If a step
+ // related to removing the file fails, it's only reflected in the return
+ // status (EFI_WARN_DELETE_FAILURE rather than EFI_SUCCESS).
+ //
+ // Release, remove, and (if needed) forget. We don't waste time flushing and
+ // syncing; if the EFI_FILE_PROTOCOL user cares enough, they should keep the
+ // parent directory open until after this function call returns, and then
+ // force a sync on *that* EFI_FILE_PROTOCOL instance, using either the
+ // Flush() member function, or the Close() member function.
+ //
+ // If any action fails below, we still try the others.
+ //
+ VirtioFsFuseReleaseFileOrDir (VirtioFs, VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
+
+ //
+ // VirtioFsFile->FuseHandle is gone at this point, but VirtioFsFile->NodeId
+ // is still valid. Continue with removing the file or directory. The result
+ // of this operation determines the return status of the function.
+ //
+ if (VirtioFsFile->IsOpenForWriting) {
+ UINT64 ParentNodeId;
+ CHAR8 *LastComponent;
+
+ //
+ // Split our canonical pathname into most specific parent directory
+ // (identified by NodeId), and single-component filename within that
+ // directory. If This stands for the root directory "/", then the following
+ // function call will gracefully fail.
+ //
+ Status = VirtioFsLookupMostSpecificParentDir (
+ VirtioFs,
+ VirtioFsFile->CanonicalPathname,
+ &ParentNodeId,
+ &LastComponent
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Attempt the actual removal. Regardless of the outcome, ParentNodeId
+ // must be forgotten right after (unless it stands for the root
+ // directory).
+ //
+ Status = VirtioFsFuseRemoveFileOrDir (
+ VirtioFs,
+ ParentNodeId,
+ LastComponent,
+ VirtioFsFile->IsDirectory
+ );
+ if (ParentNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, ParentNodeId);
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ //
+ // Map any failure to the spec-mandated warning code.
+ //
+ Status = EFI_WARN_DELETE_FAILURE;
+ }
+ } else {
+ Status = EFI_WARN_DELETE_FAILURE;
+ }
+
+ //
+ // Finally, if we've known VirtioFsFile->NodeId from a lookup, then we should
+ // also ask the server to forget it *once*.
+ //
+ if (VirtioFsFile->NodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, VirtioFsFile->NodeId);
+ }
+
+ //
+ // One fewer file left open for the owner filesystem.
+ //
+ RemoveEntryList (&VirtioFsFile->OpenFilesEntry);
+
+ FreePool (VirtioFsFile->CanonicalPathname);
+ if (VirtioFsFile->FileInfoArray != NULL) {
+ FreePool (VirtioFsFile->FileInfoArray);
+ }
+ FreePool (VirtioFsFile);
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsFlush.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsFlush.c
new file mode 100644
index 00000000000..6aeb46a7f8a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsFlush.c
@@ -0,0 +1,42 @@
+/** @file
+ EFI_FILE_PROTOCOL.Flush() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileFlush (
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ if (!VirtioFsFile->IsOpenForWriting) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // FUSE_FLUSH is for regular files only.
+ //
+ if (!VirtioFsFile->IsDirectory) {
+ Status = VirtioFsFuseFlush (VirtioFs, VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ Status = VirtioFsFuseFsyncFileOrDir (VirtioFs, VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle, VirtioFsFile->IsDirectory);
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetInfo.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetInfo.c
new file mode 100644
index 00000000000..1df2e1f22d2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetInfo.c
@@ -0,0 +1,209 @@
+/** @file
+ EFI_FILE_PROTOCOL.GetInfo() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/FileSystemInfo.h> // gEfiFileSystemInfoGuid
+#include <Guid/FileSystemVolumeLabelInfo.h> // gEfiFileSystemVolumeLabelInfo...
+#include <Library/BaseLib.h> // StrSize()
+#include <Library/BaseMemoryLib.h> // CompareGuid()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Provide EFI_FILE_INFO about this particular file.
+**/
+STATIC
+EFI_STATUS
+GetFileInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ UINTN AllocSize;
+ UINTN BasenameSize;
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ AllocSize = *BufferSize;
+
+ //
+ // Calculate the needed size.
+ //
+ BasenameSize = 0;
+ Status = VirtioFsGetBasename (VirtioFsFile->CanonicalPathname, NULL,
+ &BasenameSize);
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ *BufferSize = OFFSET_OF (EFI_FILE_INFO, FileName) + BasenameSize;
+
+ if (*BufferSize > AllocSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Set the structure size, and store the basename.
+ //
+ FileInfo = Buffer;
+ FileInfo->Size = *BufferSize;
+ Status = VirtioFsGetBasename (VirtioFsFile->CanonicalPathname,
+ FileInfo->FileName, &BasenameSize);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Fetch the file attributes, and convert them into the caller's buffer.
+ //
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
+ if (!EFI_ERROR (Status)) {
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, FileInfo);
+ }
+ return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;
+}
+
+/**
+ Provide EFI_FILE_SYSTEM_INFO about the filesystem this file lives on.
+**/
+STATIC
+EFI_STATUS
+GetFileSystemInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ UINTN AllocSize;
+ UINTN LabelSize;
+ EFI_STATUS Status;
+ VIRTIO_FS_FUSE_STATFS_RESPONSE FilesysAttr;
+ UINT64 MaxBlocks;
+ EFI_FILE_SYSTEM_INFO *FilesysInfo;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ AllocSize = *BufferSize;
+
+ //
+ // Calculate the needed size.
+ //
+ LabelSize = StrSize (VirtioFs->Label);
+ *BufferSize = OFFSET_OF (EFI_FILE_SYSTEM_INFO, VolumeLabel) + LabelSize;
+
+ if (*BufferSize > AllocSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Fetch the filesystem attributes.
+ //
+ Status = VirtioFsFuseStatFs (VirtioFs, VirtioFsFile->NodeId, &FilesysAttr);
+ if (EFI_ERROR (Status)) {
+ return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;
+ }
+ //
+ // Sanity checks...
+ //
+ if (FilesysAttr.Frsize != FilesysAttr.Bsize) {
+ return EFI_UNSUPPORTED;
+ }
+ if (FilesysAttr.Frsize == 0 || FilesysAttr.Blocks == 0 ||
+ FilesysAttr.Bavail > FilesysAttr.Blocks) {
+ return EFI_DEVICE_ERROR;
+ }
+ MaxBlocks = DivU64x32 (MAX_UINT64, FilesysAttr.Frsize);
+ if (FilesysAttr.Blocks > MaxBlocks || FilesysAttr.Bavail > MaxBlocks) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Fill in EFI_FILE_SYSTEM_INFO.
+ //
+ FilesysInfo = Buffer;
+ FilesysInfo->Size = *BufferSize;
+ FilesysInfo->ReadOnly = FALSE;
+ FilesysInfo->VolumeSize = MultU64x32 (FilesysAttr.Blocks,
+ FilesysAttr.Frsize);
+ FilesysInfo->FreeSpace = MultU64x32 (FilesysAttr.Bavail,
+ FilesysAttr.Frsize);
+ FilesysInfo->BlockSize = FilesysAttr.Frsize;
+ CopyMem (FilesysInfo->VolumeLabel, VirtioFs->Label, LabelSize);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the filesystem label as EFI_FILE_SYSTEM_VOLUME_LABEL.
+**/
+STATIC
+EFI_STATUS
+GetFileSystemVolumeLabelInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ UINTN AllocSize;
+ UINTN LabelSize;
+ EFI_FILE_SYSTEM_VOLUME_LABEL *FilesysVolumeLabel;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ AllocSize = *BufferSize;
+
+ //
+ // Calculate the needed size.
+ //
+ LabelSize = StrSize (VirtioFs->Label);
+ *BufferSize = (OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL, VolumeLabel) +
+ LabelSize);
+
+ if (*BufferSize > AllocSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Store the label.
+ //
+ FilesysVolumeLabel = Buffer;
+ CopyMem (FilesysVolumeLabel->VolumeLabel, VirtioFs->Label, LabelSize);
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ return GetFileInfo (This, BufferSize, Buffer);
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ return GetFileSystemInfo (This, BufferSize, Buffer);
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ return GetFileSystemVolumeLabelInfo (This, BufferSize, Buffer);
+ }
+
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetPosition.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetPosition.c
new file mode 100644
index 00000000000..dc93207a075
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsGetPosition.c
@@ -0,0 +1,27 @@
+/** @file
+ EFI_FILE_PROTOCOL.GetPosition() member function for the Virtio Filesystem
+ driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileGetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ if (VirtioFsFile->IsDirectory) {
+ return EFI_UNSUPPORTED;
+ }
+ *Position = VirtioFsFile->FilePosition;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c
new file mode 100644
index 00000000000..e9c1b6763e3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpen.c
@@ -0,0 +1,516 @@
+/** @file
+ EFI_FILE_PROTOCOL.Open() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // AsciiStrCmp()
+#include <Library/MemoryAllocationLib.h> // AllocatePool()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Open the root directory, possibly for writing.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device whose root directory
+ should be opened.
+
+ @param[out] NewHandle The new EFI_FILE_PROTOCOL instance through which
+ the root directory can be accessed.
+
+ @param[in] OpenForWriting TRUE if the root directory should be opened for
+ read-write access. FALSE if the root directory
+ should be opened for read-only access. Opening the
+ root directory for read-write access is useful for
+ calling EFI_FILE_PROTOCOL.Flush() or
+ EFI_FILE_PROTOCOL.SetInfo() later, for syncing or
+ touching the root directory, respectively.
+
+ @retval EFI_SUCCESS The root directory has been opened successfully.
+
+ @retval EFI_ACCESS_DENIED OpenForWriting is TRUE, but the root directory is
+ marked as read-only.
+
+ @return Error codes propagated from underlying functions.
+**/
+STATIC
+EFI_STATUS
+OpenRootDirectory (
+ IN OUT VIRTIO_FS *VirtioFs,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN BOOLEAN OpenForWriting
+ )
+{
+ EFI_STATUS Status;
+ VIRTIO_FS_FILE *NewVirtioFsFile;
+
+ //
+ // VirtioFsOpenVolume() opens the root directory for read-only access. If the
+ // current request is to open the root directory for read-write access, so
+ // that EFI_FILE_PROTOCOL.Flush() or EFI_FILE_PROTOCOL.SetInfo()+timestamps
+ // can be used on the root directory later, then we have to check for write
+ // permission first.
+ //
+ if (OpenForWriting) {
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+ EFI_FILE_INFO FileInfo;
+
+ Status = VirtioFsFuseGetAttr (VirtioFs, VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID,
+ &FuseAttr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((FileInfo.Attribute & EFI_FILE_READ_ONLY) != 0) {
+ return EFI_ACCESS_DENIED;
+ }
+ }
+
+ Status = VirtioFsOpenVolume (&VirtioFs->SimpleFs, NewHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ NewVirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (*NewHandle);
+ NewVirtioFsFile->IsOpenForWriting = OpenForWriting;
+ return EFI_SUCCESS;
+}
+
+/**
+ Open an existent regular file or non-root directory.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device on which the
+ regular file or directory should be opened.
+
+ @param[in] DirNodeId The inode number of the immediate parent
+ directory of the regular file or directory to
+ open.
+
+ @param[in] Name The single-component filename of the regular
+ file or directory to open, under the immediate
+ parent directory identified by DirNodeId.
+
+ @param[in] OpenForWriting TRUE if the regular file or directory should be
+ opened for read-write access. FALSE if the
+ regular file or directory should be opened for
+ read-only access. Opening a directory for
+ read-write access is useful for deleting,
+ renaming, syncing or touching the directory
+ later.
+
+ @param[out] NodeId The inode number of the regular file or
+ directory, returned by the Virtio Filesystem
+ device.
+
+ @param[out] FuseHandle The open handle to the regular file or
+ directory, returned by the Virtio Filesystem
+ device.
+
+ @param[out] NodeIsDirectory Set to TRUE on output if Name was found to refer
+ to a directory. Set to FALSE if Name was found
+ to refer to a regular file.
+
+ @retval EFI_SUCCESS The regular file or directory has been looked up
+ and opened successfully.
+
+ @retval EFI_ACCESS_DENIED OpenForWriting is TRUE, but the regular file or
+ directory is marked read-only.
+
+ @retval EFI_NOT_FOUND A directory entry called Name was not found in the
+ directory identified by DirNodeId. (EFI_NOT_FOUND
+ is not returned for any other condition.)
+
+ @return Errors propagated from underlying functions. If
+ the error code to propagate were EFI_NOT_FOUND, it
+ is remapped to EFI_DEVICE_ERROR.
+**/
+STATIC
+EFI_STATUS
+OpenExistentFileOrDirectory (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 DirNodeId,
+ IN CHAR8 *Name,
+ IN BOOLEAN OpenForWriting,
+ OUT UINT64 *NodeId,
+ OUT UINT64 *FuseHandle,
+ OUT BOOLEAN *NodeIsDirectory
+ )
+{
+ EFI_STATUS Status;
+ UINT64 ResolvedNodeId;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+ EFI_FILE_INFO FileInfo;
+ BOOLEAN IsDirectory;
+ UINT64 NewFuseHandle;
+
+ Status = VirtioFsFuseLookup (VirtioFs, DirNodeId, Name, &ResolvedNodeId,
+ &FuseAttr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ goto ForgetResolvedNodeId;
+ }
+
+ if (OpenForWriting && (FileInfo.Attribute & EFI_FILE_READ_ONLY) != 0) {
+ Status = EFI_ACCESS_DENIED;
+ goto ForgetResolvedNodeId;
+ }
+
+ IsDirectory = (BOOLEAN)((FileInfo.Attribute & EFI_FILE_DIRECTORY) != 0);
+ if (IsDirectory) {
+ //
+ // If OpenForWriting is TRUE here, that's not passed to
+ // VirtioFsFuseOpenDir(); it does not affect the FUSE_OPENDIR request we
+ // send. OpenForWriting=TRUE will only permit attempts to delete, rename,
+ // flush (sync), and touch the directory.
+ //
+ Status = VirtioFsFuseOpenDir (VirtioFs, ResolvedNodeId, &NewFuseHandle);
+ } else {
+ Status = VirtioFsFuseOpen (VirtioFs, ResolvedNodeId, OpenForWriting,
+ &NewFuseHandle);
+ }
+ if (EFI_ERROR (Status)) {
+ goto ForgetResolvedNodeId;
+ }
+
+ *NodeId = ResolvedNodeId;
+ *FuseHandle = NewFuseHandle;
+ *NodeIsDirectory = IsDirectory;
+ return EFI_SUCCESS;
+
+ForgetResolvedNodeId:
+ VirtioFsFuseForget (VirtioFs, ResolvedNodeId);
+ return (Status == EFI_NOT_FOUND) ? EFI_DEVICE_ERROR : Status;
+}
+
+/**
+ Create a directory.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device on which the directory
+ should be created.
+
+ @param[in] DirNodeId The inode number of the immediate parent directory
+ of the directory to create.
+
+ @param[in] Name The single-component filename of the directory to
+ create, under the immediate parent directory
+ identified by DirNodeId.
+
+ @param[out] NodeId The inode number of the directory created, returned
+ by the Virtio Filesystem device.
+
+ @param[out] FuseHandle The open handle to the directory created, returned
+ by the Virtio Filesystem device.
+
+ @retval EFI_SUCCESS The directory has been created successfully.
+
+ @return Errors propagated from underlying functions.
+**/
+STATIC
+EFI_STATUS
+CreateDirectory (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 DirNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId,
+ OUT UINT64 *FuseHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NewChildDirNodeId;
+ UINT64 NewFuseHandle;
+
+ Status = VirtioFsFuseMkDir (VirtioFs, DirNodeId, Name, &NewChildDirNodeId);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = VirtioFsFuseOpenDir (VirtioFs, NewChildDirNodeId, &NewFuseHandle);
+ if (EFI_ERROR (Status)) {
+ goto RemoveNewChildDir;
+ }
+
+ *NodeId = NewChildDirNodeId;
+ *FuseHandle = NewFuseHandle;
+ return EFI_SUCCESS;
+
+RemoveNewChildDir:
+ VirtioFsFuseRemoveFileOrDir (VirtioFs, DirNodeId, Name, TRUE /* IsDir */);
+ VirtioFsFuseForget (VirtioFs, NewChildDirNodeId);
+ return Status;
+}
+
+/**
+ Create a regular file.
+
+ @param[in,out] VirtioFs The Virtio Filesystem device on which the regular
+ file should be created.
+
+ @param[in] DirNodeId The inode number of the immediate parent directory
+ of the regular file to create.
+
+ @param[in] Name The single-component filename of the regular file to
+ create, under the immediate parent directory
+ identified by DirNodeId.
+
+ @param[out] NodeId The inode number of the regular file created,
+ returned by the Virtio Filesystem device.
+
+ @param[out] FuseHandle The open handle to the regular file created,
+ returned by the Virtio Filesystem device.
+
+ @retval EFI_SUCCESS The regular file has been created successfully.
+
+ @return Errors propagated from underlying functions.
+**/
+STATIC
+EFI_STATUS
+CreateRegularFile (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 DirNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId,
+ OUT UINT64 *FuseHandle
+ )
+{
+ return VirtioFsFuseOpenOrCreate (VirtioFs, DirNodeId, Name, NodeId,
+ FuseHandle);
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ BOOLEAN OpenForWriting;
+ BOOLEAN PermitCreation;
+ BOOLEAN CreateDirectoryIfCreating;
+ VIRTIO_FS_FILE *NewVirtioFsFile;
+ EFI_STATUS Status;
+ CHAR8 *NewCanonicalPath;
+ BOOLEAN RootEscape;
+ UINT64 DirNodeId;
+ CHAR8 *LastComponent;
+ UINT64 NewNodeId;
+ UINT64 NewFuseHandle;
+ BOOLEAN NewNodeIsDirectory;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // Validate OpenMode.
+ //
+ switch (OpenMode) {
+ case EFI_FILE_MODE_READ:
+ OpenForWriting = FALSE;
+ PermitCreation = FALSE;
+ break;
+ case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
+ OpenForWriting = TRUE;
+ PermitCreation = FALSE;
+ break;
+ case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
+ OpenForWriting = TRUE;
+ PermitCreation = TRUE;
+ break;
+ default:
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set CreateDirectoryIfCreating to suppress incorrect compiler/analyzer
+ // warnings.
+ //
+ CreateDirectoryIfCreating = FALSE;
+
+ //
+ // Validate the Attributes requested for the case when the file ends up being
+ // created, provided creation is permitted.
+ //
+ if (PermitCreation) {
+ if ((Attributes & ~EFI_FILE_VALID_ATTR) != 0) {
+ //
+ // Unknown attribute requested.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ASSERT (OpenForWriting);
+ if ((Attributes & EFI_FILE_READ_ONLY) != 0) {
+ DEBUG ((
+ DEBUG_ERROR,
+ ("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\" "
+ "OpenMode=0x%Lx Attributes=0x%Lx: nonsensical request to possibly "
+ "create a file marked read-only, for read-write access\n"),
+ __FUNCTION__,
+ VirtioFs->Label,
+ VirtioFsFile->CanonicalPathname,
+ FileName,
+ OpenMode,
+ Attributes
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+ CreateDirectoryIfCreating = (BOOLEAN)((Attributes &
+ EFI_FILE_DIRECTORY) != 0);
+ }
+
+ //
+ // Referring to a file relative to a regular file makes no sense (or at least
+ // it cannot be implemented consistently with how a file is referred to
+ // relative to a directory).
+ //
+ if (!VirtioFsFile->IsDirectory) {
+ DEBUG ((
+ DEBUG_ERROR,
+ ("%a: Label=\"%s\" CanonicalPathname=\"%a\" FileName=\"%s\": "
+ "nonsensical request to open a file or directory relative to a regular "
+ "file\n"),
+ __FUNCTION__,
+ VirtioFs->Label,
+ VirtioFsFile->CanonicalPathname,
+ FileName
+ ));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Allocate the new VIRTIO_FS_FILE object.
+ //
+ NewVirtioFsFile = AllocatePool (sizeof *NewVirtioFsFile);
+ if (NewVirtioFsFile == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Create the canonical pathname at which the desired file is expected to
+ // exist.
+ //
+ Status = VirtioFsAppendPath (VirtioFsFile->CanonicalPathname, FileName,
+ &NewCanonicalPath, &RootEscape);
+ if (EFI_ERROR (Status)) {
+ goto FreeNewVirtioFsFile;
+ }
+ if (RootEscape) {
+ Status = EFI_ACCESS_DENIED;
+ goto FreeNewCanonicalPath;
+ }
+
+ //
+ // If the desired file is the root directory, just open the volume one more
+ // time, without looking up anything.
+ //
+ if (AsciiStrCmp (NewCanonicalPath, "/") == 0) {
+ FreePool (NewCanonicalPath);
+ FreePool (NewVirtioFsFile);
+ return OpenRootDirectory (VirtioFs, NewHandle, OpenForWriting);
+ }
+
+ //
+ // Split the new canonical pathname into most specific parent directory
+ // (given by DirNodeId) and last pathname component (i.e., immediate child
+ // within that parent directory).
+ //
+ Status = VirtioFsLookupMostSpecificParentDir (VirtioFs, NewCanonicalPath,
+ &DirNodeId, &LastComponent);
+ if (EFI_ERROR (Status)) {
+ goto FreeNewCanonicalPath;
+ }
+
+ //
+ // Set NewNodeIsDirectory to suppress incorrect compiler/analyzer warnings.
+ //
+ NewNodeIsDirectory = FALSE;
+
+ //
+ // Try to open LastComponent directly under DirNodeId, as an existent regular
+ // file or directory.
+ //
+ Status = OpenExistentFileOrDirectory (VirtioFs, DirNodeId, LastComponent,
+ OpenForWriting, &NewNodeId, &NewFuseHandle, &NewNodeIsDirectory);
+ //
+ // If LastComponent could not be found under DirNodeId, but the request
+ // allows us to create a new entry, attempt creating the requested regular
+ // file or directory.
+ //
+ if (Status == EFI_NOT_FOUND && PermitCreation) {
+ ASSERT (OpenForWriting);
+ if (CreateDirectoryIfCreating) {
+ Status = CreateDirectory (VirtioFs, DirNodeId, LastComponent, &NewNodeId,
+ &NewFuseHandle);
+ } else {
+ Status = CreateRegularFile (VirtioFs, DirNodeId, LastComponent,
+ &NewNodeId, &NewFuseHandle);
+ }
+ NewNodeIsDirectory = CreateDirectoryIfCreating;
+ }
+
+ //
+ // Regardless of the branch taken, we're done with DirNodeId.
+ //
+ if (DirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, DirNodeId);
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto FreeNewCanonicalPath;
+ }
+
+ //
+ // Populate the new VIRTIO_FS_FILE object.
+ //
+ NewVirtioFsFile->Signature = VIRTIO_FS_FILE_SIG;
+ NewVirtioFsFile->SimpleFile.Revision = EFI_FILE_PROTOCOL_REVISION;
+ NewVirtioFsFile->SimpleFile.Open = VirtioFsSimpleFileOpen;
+ NewVirtioFsFile->SimpleFile.Close = VirtioFsSimpleFileClose;
+ NewVirtioFsFile->SimpleFile.Delete = VirtioFsSimpleFileDelete;
+ NewVirtioFsFile->SimpleFile.Read = VirtioFsSimpleFileRead;
+ NewVirtioFsFile->SimpleFile.Write = VirtioFsSimpleFileWrite;
+ NewVirtioFsFile->SimpleFile.GetPosition = VirtioFsSimpleFileGetPosition;
+ NewVirtioFsFile->SimpleFile.SetPosition = VirtioFsSimpleFileSetPosition;
+ NewVirtioFsFile->SimpleFile.GetInfo = VirtioFsSimpleFileGetInfo;
+ NewVirtioFsFile->SimpleFile.SetInfo = VirtioFsSimpleFileSetInfo;
+ NewVirtioFsFile->SimpleFile.Flush = VirtioFsSimpleFileFlush;
+ NewVirtioFsFile->IsDirectory = NewNodeIsDirectory;
+ NewVirtioFsFile->IsOpenForWriting = OpenForWriting;
+ NewVirtioFsFile->OwnerFs = VirtioFs;
+ NewVirtioFsFile->CanonicalPathname = NewCanonicalPath;
+ NewVirtioFsFile->FilePosition = 0;
+ NewVirtioFsFile->NodeId = NewNodeId;
+ NewVirtioFsFile->FuseHandle = NewFuseHandle;
+ NewVirtioFsFile->FileInfoArray = NULL;
+ NewVirtioFsFile->SingleFileInfoSize = 0;
+ NewVirtioFsFile->NumFileInfo = 0;
+ NewVirtioFsFile->NextFileInfo = 0;
+
+ //
+ // One more file is now open for the filesystem.
+ //
+ InsertTailList (&VirtioFs->OpenFiles, &NewVirtioFsFile->OpenFilesEntry);
+
+ *NewHandle = &NewVirtioFsFile->SimpleFile;
+ return EFI_SUCCESS;
+
+FreeNewCanonicalPath:
+ FreePool (NewCanonicalPath);
+
+FreeNewVirtioFsFile:
+ FreePool (NewVirtioFsFile);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c
new file mode 100644
index 00000000000..cdb999bea94
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsOpenVolume.c
@@ -0,0 +1,98 @@
+/** @file
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume() member function for the Virtio
+ Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h> // InsertTailList()
+#include <Library/MemoryAllocationLib.h> // AllocatePool()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Open the root directory on the Virtio Filesystem.
+
+ Refer to EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME for the interface
+ contract.
+**/
+EFI_STATUS
+EFIAPI
+VirtioFsOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ )
+{
+ VIRTIO_FS *VirtioFs;
+ VIRTIO_FS_FILE *VirtioFsFile;
+ EFI_STATUS Status;
+ CHAR8 *CanonicalPathname;
+ UINT64 RootDirHandle;
+
+ VirtioFs = VIRTIO_FS_FROM_SIMPLE_FS (This);
+
+ VirtioFsFile = AllocatePool (sizeof *VirtioFsFile);
+ if (VirtioFsFile == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CanonicalPathname = AllocateCopyPool (sizeof "/", "/");
+ if (CanonicalPathname == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeVirtioFsFile;
+ }
+
+ //
+ // Open the root directory.
+ //
+ Status = VirtioFsFuseOpenDir (VirtioFs, VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID,
+ &RootDirHandle);
+ if (EFI_ERROR (Status)) {
+ goto FreeCanonicalPathname;
+ }
+
+ //
+ // Populate the new VIRTIO_FS_FILE object.
+ //
+ VirtioFsFile->Signature = VIRTIO_FS_FILE_SIG;
+ VirtioFsFile->SimpleFile.Revision = EFI_FILE_PROTOCOL_REVISION;
+ VirtioFsFile->SimpleFile.Open = VirtioFsSimpleFileOpen;
+ VirtioFsFile->SimpleFile.Close = VirtioFsSimpleFileClose;
+ VirtioFsFile->SimpleFile.Delete = VirtioFsSimpleFileDelete;
+ VirtioFsFile->SimpleFile.Read = VirtioFsSimpleFileRead;
+ VirtioFsFile->SimpleFile.Write = VirtioFsSimpleFileWrite;
+ VirtioFsFile->SimpleFile.GetPosition = VirtioFsSimpleFileGetPosition;
+ VirtioFsFile->SimpleFile.SetPosition = VirtioFsSimpleFileSetPosition;
+ VirtioFsFile->SimpleFile.GetInfo = VirtioFsSimpleFileGetInfo;
+ VirtioFsFile->SimpleFile.SetInfo = VirtioFsSimpleFileSetInfo;
+ VirtioFsFile->SimpleFile.Flush = VirtioFsSimpleFileFlush;
+ VirtioFsFile->IsDirectory = TRUE;
+ VirtioFsFile->IsOpenForWriting = FALSE;
+ VirtioFsFile->OwnerFs = VirtioFs;
+ VirtioFsFile->CanonicalPathname = CanonicalPathname;
+ VirtioFsFile->FilePosition = 0;
+ VirtioFsFile->NodeId = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID;
+ VirtioFsFile->FuseHandle = RootDirHandle;
+ VirtioFsFile->FileInfoArray = NULL;
+ VirtioFsFile->SingleFileInfoSize = 0;
+ VirtioFsFile->NumFileInfo = 0;
+ VirtioFsFile->NextFileInfo = 0;
+
+ //
+ // One more file open for the filesystem.
+ //
+ InsertTailList (&VirtioFs->OpenFiles, &VirtioFsFile->OpenFilesEntry);
+
+ *Root = &VirtioFsFile->SimpleFile;
+ return EFI_SUCCESS;
+
+FreeCanonicalPathname:
+ FreePool (CanonicalPathname);
+
+FreeVirtioFsFile:
+ FreePool (VirtioFsFile);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsRead.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsRead.c
new file mode 100644
index 00000000000..9c18970e0e5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsRead.c
@@ -0,0 +1,434 @@
+/** @file
+ EFI_FILE_PROTOCOL.Read() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseMemoryLib.h> // CopyMem()
+#include <Library/MemoryAllocationLib.h> // AllocatePool()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Populate a caller-allocated EFI_FILE_INFO object from
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE.
+
+ @param[in] Dirent The entry read from the directory stream. The
+ caller is responsible for ensuring that
+ Dirent->Namelen describe valid storage.
+
+ @param[in] SingleFileInfoSize The allocated size of FileInfo.
+
+ @param[out] FileInfo The EFI_FILE_INFO object to populate. On
+ success, all fields in FileInfo will be
+ updated, setting FileInfo->Size to the
+ actually used size (which will not exceed
+ SingleFileInfoSize).
+
+ @retval EFI_SUCCESS FileInfo has been filled in.
+
+ @return Error codes propagated from
+ VirtioFsFuseDirentPlusToEfiFileInfo() and
+ VirtioFsFuseAttrToEfiFileInfo(). The contents of
+ FileInfo are indeterminate.
+**/
+STATIC
+EFI_STATUS
+PopulateFileInfo (
+ IN VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE *Dirent,
+ IN UINTN SingleFileInfoSize,
+ OUT EFI_FILE_INFO *FileInfo
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Convert the name, set the actual size.
+ //
+ FileInfo->Size = SingleFileInfoSize;
+ Status = VirtioFsFuseDirentPlusToEfiFileInfo (Dirent, FileInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Populate the scalar fields.
+ //
+ Status = VirtioFsFuseAttrToEfiFileInfo (&Dirent->AttrResp, FileInfo);
+ return Status;
+}
+
+/**
+ Refill the EFI_FILE_INFO cache from the directory stream.
+**/
+STATIC
+EFI_STATUS
+RefillFileInfoCache (
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile
+ )
+{
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ VIRTIO_FS_FUSE_STATFS_RESPONSE FilesysAttr;
+ UINT32 DirentBufSize;
+ UINT8 *DirentBuf;
+ UINTN SingleFileInfoSize;
+ UINT8 *FileInfoArray;
+ UINT64 DirStreamCookie;
+ UINT64 CacheEndsAtCookie;
+ UINTN NumFileInfo;
+
+ //
+ // Allocate a DirentBuf that can receive at least
+ // VIRTIO_FS_FILE_MAX_FILE_INFO directory entries, based on the maximum
+ // filename length supported by the filesystem. Note that the multiplication
+ // is safe from overflow due to the VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE()
+ // check.
+ //
+ VirtioFs = VirtioFsFile->OwnerFs;
+ Status = VirtioFsFuseStatFs (VirtioFs, VirtioFsFile->NodeId, &FilesysAttr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ DirentBufSize = (UINT32)VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE (
+ FilesysAttr.Namelen);
+ if (DirentBufSize == 0) {
+ return EFI_UNSUPPORTED;
+ }
+ DirentBufSize *= VIRTIO_FS_FILE_MAX_FILE_INFO;
+ DirentBuf = AllocatePool (DirentBufSize);
+ if (DirentBuf == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Allocate the EFI_FILE_INFO cache. A single EFI_FILE_INFO element is sized
+ // accordingly to the maximum filename length supported by the filesystem.
+ //
+ // Note that the calculation below cannot overflow, due to the filename limit
+ // imposed by the VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE() check above. The
+ // calculation takes the L'\0' character that we'll need to append into
+ // account.
+ //
+ SingleFileInfoSize = (OFFSET_OF (EFI_FILE_INFO, FileName) +
+ ((UINTN)FilesysAttr.Namelen + 1) * sizeof (CHAR16));
+ FileInfoArray = AllocatePool (
+ VIRTIO_FS_FILE_MAX_FILE_INFO * SingleFileInfoSize
+ );
+ if (FileInfoArray == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto FreeDirentBuf;
+ }
+
+ //
+ // Pick up reading the directory stream where the previous cache ended.
+ //
+ DirStreamCookie = VirtioFsFile->FilePosition;
+ CacheEndsAtCookie = VirtioFsFile->FilePosition;
+ NumFileInfo = 0;
+ do {
+ UINT32 Remaining;
+ UINT32 Consumed;
+
+ //
+ // Fetch a chunk of the directory stream. The chunk may hold more entries
+ // than what we can fit in the cache. The chunk may also not entirely fill
+ // the cache, especially after filtering out entries that cannot be
+ // supported under UEFI (sockets, FIFOs, filenames with backslashes, etc).
+ //
+ Remaining = DirentBufSize;
+ Status = VirtioFsFuseReadFileOrDir (
+ VirtioFs,
+ VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle,
+ TRUE, // IsDir
+ DirStreamCookie, // Offset
+ &Remaining, // Size
+ DirentBuf // Data
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeFileInfoArray;
+ }
+
+ if (Remaining == 0) {
+ //
+ // The directory stream ends.
+ //
+ break;
+ }
+
+ //
+ // Iterate over all records in DirentBuf. Primarily, forget them all.
+ // Secondarily, if a record proves transformable to EFI_FILE_INFO, add it
+ // to the EFI_FILE_INFO cache (unless the cache is full).
+ //
+ Consumed = 0;
+ while (Remaining >= sizeof (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE)) {
+ VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE *Dirent;
+ UINT32 DirentSize;
+
+ Dirent = (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE *)(DirentBuf + Consumed);
+ DirentSize = (UINT32)VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE (
+ Dirent->Namelen);
+ if (DirentSize == 0) {
+ //
+ // This means one of two things: (a) Dirent->Namelen is zero, or (b)
+ // (b) Dirent->Namelen is unsupportably large. (a) is just invalid for
+ // the Virtio Filesystem device to send, while (b) shouldn't happen
+ // because "FilesysAttr.Namelen" -- the maximum filename length
+ // supported by the filesystem -- proved acceptable above.
+ //
+ Status = EFI_PROTOCOL_ERROR;
+ goto FreeFileInfoArray;
+ }
+ if (DirentSize > Remaining) {
+ //
+ // Dirent->Namelen suggests that the filename byte array (plus any
+ // padding) are truncated. This should never happen; the Virtio
+ // Filesystem device is supposed to send complete entries only.
+ //
+ Status = EFI_PROTOCOL_ERROR;
+ goto FreeFileInfoArray;
+ }
+ if (Dirent->Namelen > FilesysAttr.Namelen) {
+ //
+ // This is possible without tripping the truncation check above, due to
+ // how entries are padded. The condition means that Dirent->Namelen is
+ // reportedly larger than the filesystem limit, without spilling into
+ // the next alignment bucket. Should never happen.
+ //
+ Status = EFI_PROTOCOL_ERROR;
+ goto FreeFileInfoArray;
+ }
+
+ //
+ // If we haven't filled the EFI_FILE_INFO cache yet, attempt transforming
+ // Dirent to EFI_FILE_INFO.
+ //
+ if (NumFileInfo < VIRTIO_FS_FILE_MAX_FILE_INFO) {
+ EFI_FILE_INFO *FileInfo;
+
+ FileInfo = (EFI_FILE_INFO *)(FileInfoArray +
+ (NumFileInfo * SingleFileInfoSize));
+ Status = PopulateFileInfo (Dirent, SingleFileInfoSize, FileInfo);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Dirent has been transformed and cached successfully.
+ //
+ NumFileInfo++;
+ //
+ // The next time we refill the cache, restart reading the directory
+ // stream right after the entry that we've just transformed and
+ // cached.
+ //
+ CacheEndsAtCookie = Dirent->CookieForNextEntry;
+ }
+ //
+ // If Dirent wasn't transformable to an EFI_FILE_INFO, we'll just skip
+ // it.
+ //
+ }
+
+ //
+ // Make the Virtio Filesystem device forget the NodeId in this directory
+ // entry, as we'll need it no more. (The "." and ".." entries need no
+ // FUSE_FORGET requests, when returned by FUSE_READDIRPLUS -- and so the
+ // Virtio Filesystem device reports their NodeId fields as zero.)
+ //
+ if (Dirent->NodeResp.NodeId != 0) {
+ VirtioFsFuseForget (VirtioFs, Dirent->NodeResp.NodeId);
+ }
+
+ //
+ // Advance to the next entry in DirentBuf.
+ //
+ DirStreamCookie = Dirent->CookieForNextEntry;
+ Consumed += DirentSize;
+ Remaining -= DirentSize;
+ }
+
+ if (Remaining > 0) {
+ //
+ // This suggests that a VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE header was
+ // truncated. This should never happen; the Virtio Filesystem device is
+ // supposed to send complete entries only.
+ //
+ Status = EFI_PROTOCOL_ERROR;
+ goto FreeFileInfoArray;
+ }
+ //
+ // Fetch another DirentBuf from the directory stream, unless we've filled
+ // the EFI_FILE_INFO cache.
+ //
+ } while (NumFileInfo < VIRTIO_FS_FILE_MAX_FILE_INFO);
+
+ //
+ // Commit the results. (Note that the result may be an empty cache.)
+ //
+ if (VirtioFsFile->FileInfoArray != NULL) {
+ FreePool (VirtioFsFile->FileInfoArray);
+ }
+ VirtioFsFile->FileInfoArray = FileInfoArray;
+ VirtioFsFile->SingleFileInfoSize = SingleFileInfoSize;
+ VirtioFsFile->NumFileInfo = NumFileInfo;
+ VirtioFsFile->NextFileInfo = 0;
+ VirtioFsFile->FilePosition = CacheEndsAtCookie;
+
+ FreePool (DirentBuf);
+ return EFI_SUCCESS;
+
+FreeFileInfoArray:
+ FreePool (FileInfoArray);
+
+FreeDirentBuf:
+ FreePool (DirentBuf);
+
+ return Status;
+}
+
+/**
+ Read an entry from the EFI_FILE_INFO cache.
+**/
+STATIC
+EFI_STATUS
+ReadFileInfoCache (
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_FILE_INFO *FileInfo;
+ UINTN CallerAllocated;
+
+ //
+ // Refill the cache if needed. If the refill doesn't produce any new
+ // EFI_FILE_INFO, report End of Directory, by setting (*BufferSize) to 0.
+ //
+ if (VirtioFsFile->NextFileInfo == VirtioFsFile->NumFileInfo) {
+ EFI_STATUS Status;
+
+ Status = RefillFileInfoCache (VirtioFsFile);
+ if (EFI_ERROR (Status)) {
+ return (Status == EFI_BUFFER_TOO_SMALL) ? EFI_DEVICE_ERROR : Status;
+ }
+ if (VirtioFsFile->NumFileInfo == 0) {
+ *BufferSize = 0;
+ return EFI_SUCCESS;
+ }
+ }
+ FileInfo = (EFI_FILE_INFO *)(VirtioFsFile->FileInfoArray +
+ (VirtioFsFile->NextFileInfo *
+ VirtioFsFile->SingleFileInfoSize));
+
+ //
+ // Check if the caller is ready to accept FileInfo. If not, we'll just
+ // present the required size for now.
+ //
+ // (The (UINTN) cast below is safe because FileInfo->Size has been reduced
+ // from VirtioFsFile->SingleFileInfoSize, in
+ //
+ // RefillFileInfoCache()
+ // PopulateFileInfo()
+ // VirtioFsFuseDirentPlusToEfiFileInfo()
+ //
+ // and VirtioFsFile->SingleFileInfoSize was computed from
+ // FilesysAttr.Namelen, which had been accepted by
+ // VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE_SIZE().)
+ //
+ CallerAllocated = *BufferSize;
+ *BufferSize = (UINTN)FileInfo->Size;
+ if (CallerAllocated < *BufferSize) {
+ return EFI_BUFFER_TOO_SMALL;
+ }
+ //
+ // Output FileInfo, and remove it from the cache.
+ //
+ CopyMem (Buffer, FileInfo, *BufferSize);
+ VirtioFsFile->NextFileInfo++;
+ return EFI_SUCCESS;
+}
+
+/**
+ Read from a regular file.
+**/
+STATIC
+EFI_STATUS
+ReadRegularFile (
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+ UINTN Transferred;
+ UINTN Left;
+
+ VirtioFs = VirtioFsFile->OwnerFs;
+ //
+ // The UEFI spec forbids reads that start beyond the end of the file.
+ //
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
+ if (EFI_ERROR (Status) || VirtioFsFile->FilePosition > FuseAttr.Size) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Status = EFI_SUCCESS;
+ Transferred = 0;
+ Left = *BufferSize;
+ while (Left > 0) {
+ UINT32 ReadSize;
+
+ //
+ // FUSE_READ cannot express a >=4GB buffer size.
+ //
+ ReadSize = (UINT32)MIN ((UINTN)MAX_UINT32, Left);
+ Status = VirtioFsFuseReadFileOrDir (
+ VirtioFs,
+ VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle,
+ FALSE, // IsDir
+ VirtioFsFile->FilePosition + Transferred,
+ &ReadSize,
+ (UINT8 *)Buffer + Transferred
+ );
+ if (EFI_ERROR (Status) || ReadSize == 0) {
+ break;
+ }
+ Transferred += ReadSize;
+ Left -= ReadSize;
+ }
+
+ *BufferSize = Transferred;
+ VirtioFsFile->FilePosition += Transferred;
+ //
+ // If we managed to read some data, return success. If zero bytes were
+ // transferred due to zero-sized buffer on input or due to EOF on first read,
+ // return SUCCESS. Otherwise, return the error due to which zero bytes were
+ // transferred.
+ //
+ return (Transferred > 0) ? EFI_SUCCESS : Status;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ EFI_STATUS Status;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+
+ if (VirtioFsFile->IsDirectory) {
+ Status = ReadFileInfoCache (VirtioFsFile, BufferSize, Buffer);
+ } else {
+ Status = ReadRegularFile (VirtioFsFile, BufferSize, Buffer);
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c
new file mode 100644
index 00000000000..c2fceb8dbde
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetInfo.c
@@ -0,0 +1,582 @@
+/** @file
+ EFI_FILE_PROTOCOL.SetInfo() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Guid/FileSystemInfo.h> // gEfiFileSystemInfoGuid
+#include <Guid/FileSystemVolumeLabelInfo.h> // gEfiFileSystemVolumeLabelInfo...
+#include <Library/BaseLib.h> // StrCmp()
+#include <Library/BaseMemoryLib.h> // CompareGuid()
+#include <Library/MemoryAllocationLib.h> // FreePool()
+
+#include "VirtioFsDxe.h"
+
+/**
+ Validate a buffer that the EFI_FILE_PROTOCOL.SetInfo() caller passes in for a
+ particular InformationType GUID.
+
+ The structure to be validated is supposed to end with a variable-length,
+ NUL-terminated CHAR16 Name string.
+
+ @param[in] SizeByProtocolCaller The BufferSize parameter as provided by the
+ EFI_FILE_PROTOCOL.SetInfo() caller.
+
+ @param[in] MinimumStructSize The minimum structure size that is required
+ for the given InformationType GUID,
+ including a single CHAR16 element from the
+ trailing Name field.
+
+ @param[in] IsSizeByInfoPresent TRUE if and only if the expected structure
+ starts with a UINT64 Size field that reports
+ the actual structure size.
+
+ @param[in] Buffer The Buffer parameter as provided by the
+ EFI_FILE_PROTOCOL.SetInfo() caller.
+
+ @retval EFI_SUCCESS Validation successful, Buffer is well-formed.
+
+ @retval EFI_BAD_BUFFER_SIZE The EFI_FILE_PROTOCOL.SetInfo()
+ caller provided a BufferSize that is smaller
+ than the minimum structure size required for
+ the given InformationType GUID.
+
+ @retval EFI_INVALID_PARAMETER IsSizeByInfoPresent is TRUE, and the leading
+ UINT64 Size field does not match the
+ EFI_FILE_PROTOCOL.SetInfo() caller-provided
+ BufferSize.
+
+ @retval EFI_INVALID_PARAMETER The trailing Name field does not consist of a
+ whole multiple of CHAR16 elements.
+
+ @retval EFI_INVALID_PARAMETER The trailing Name field is not NUL-terminated.
+**/
+STATIC
+EFI_STATUS
+ValidateInfoStructure (
+ IN UINTN SizeByProtocolCaller,
+ IN UINTN MinimumStructSize,
+ IN BOOLEAN IsSizeByInfoPresent,
+ IN VOID *Buffer
+ )
+{
+ UINTN NameFieldByteOffset;
+ UINTN NameFieldBytes;
+ UINTN NameFieldChar16s;
+ CHAR16 *NameField;
+
+ //
+ // Make sure the internal function asking for validation passes in sane
+ // values.
+ //
+ ASSERT (MinimumStructSize >= sizeof (CHAR16));
+ NameFieldByteOffset = MinimumStructSize - sizeof (CHAR16);
+
+ if (IsSizeByInfoPresent) {
+ ASSERT (MinimumStructSize >= sizeof (UINT64) + sizeof (CHAR16));
+ ASSERT (NameFieldByteOffset >= sizeof (UINT64));
+ }
+
+ //
+ // Check whether the protocol caller provided enough bytes for the minimum
+ // size of this info structure.
+ //
+ if (SizeByProtocolCaller < MinimumStructSize) {
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ //
+ // If the info structure starts with a UINT64 Size field, check if that
+ // agrees with the protocol caller-provided size.
+ //
+ if (IsSizeByInfoPresent) {
+ UINT64 *SizeByInfo;
+
+ SizeByInfo = Buffer;
+ if (*SizeByInfo != SizeByProtocolCaller) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // The CHAR16 Name field at the end of the structure must have an even number
+ // of bytes.
+ //
+ // The subtraction below cannot underflow, and yields at least
+ // sizeof(CHAR16).
+ //
+ ASSERT (SizeByProtocolCaller >= NameFieldByteOffset);
+ NameFieldBytes = SizeByProtocolCaller - NameFieldByteOffset;
+ ASSERT (NameFieldBytes >= sizeof (CHAR16));
+ if (NameFieldBytes % sizeof (CHAR16) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The CHAR16 Name field at the end of the structure must be NUL-terminated.
+ //
+ NameFieldChar16s = NameFieldBytes / sizeof (CHAR16);
+ ASSERT (NameFieldChar16s >= 1);
+
+ NameField = (CHAR16 *)((UINT8 *)Buffer + NameFieldByteOffset);
+ if (NameField[NameFieldChar16s - 1] != L'\0') {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Rename a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.FileName.
+
+ @param[in,out] VirtioFsFile The VIRTIO_FS_FILE to rename.
+
+ @param[in] NewFileName The new file name requested by
+ EFI_FILE_PROTOCOL.SetInfo().
+
+ @retval EFI_SUCCESS The canonical format destination path that is
+ determined from the input value of
+ VirtioFsFile->CanonicalPathname and from
+ NewFileName is identical to the input value of
+ VirtioFsFile->CanonicalPathname. This means that
+ EFI_FILE_INFO does not constitute a rename
+ request. VirtioFsFile has not been changed.
+
+ @retval EFI_SUCCESS VirtioFsFile has been renamed.
+ VirtioFsFile->CanonicalPathname has assumed the
+ destination pathname in canonical format.
+
+ @retval EFI_ACCESS_DENIED VirtioFsFile refers to the root directory, and
+ NewFileName expresses an actual rename/move
+ request.
+
+ @retval EFI_ACCESS_DENIED VirtioFsFile is the (possibly indirect) parent
+ directory of at least one other VIRTIO_FS_FILE
+ that is open for the same Virtio Filesystem
+ (identified by VirtioFsFile->OwnerFs). Renaming
+ VirtioFsFile would invalidate the canonical
+ pathnames of those VIRTIO_FS_FILE instances;
+ therefore the request has been rejected.
+
+ @retval EFI_ACCESS_DENIED VirtioFsFile is not open for writing, but
+ NewFileName expresses an actual rename/move
+ request.
+
+ @retval EFI_NOT_FOUND At least one dot-dot component in NewFileName
+ attempted to escape the root directory.
+
+ @return Error codes propagated from underlying functions.
+**/
+STATIC
+EFI_STATUS
+Rename (
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile,
+ IN CHAR16 *NewFileName
+ )
+{
+
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ CHAR8 *Destination;
+ BOOLEAN RootEscape;
+ UINT64 OldParentDirNodeId;
+ CHAR8 *OldLastComponent;
+ UINT64 NewParentDirNodeId;
+ CHAR8 *NewLastComponent;
+
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // The root directory cannot be renamed.
+ //
+ if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, "/") == 0) {
+ if (StrCmp (NewFileName, L"") == 0) {
+ //
+ // Not a rename request anyway.
+ //
+ return EFI_SUCCESS;
+ }
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Compose the canonical pathname for the destination.
+ //
+ Status = VirtioFsComposeRenameDestination (VirtioFsFile->CanonicalPathname,
+ NewFileName, &Destination, &RootEscape);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (RootEscape) {
+ Status = EFI_NOT_FOUND;
+ goto FreeDestination;
+ }
+ //
+ // If the rename would leave VirtioFsFile->CanonicalPathname unchanged, then
+ // EFI_FILE_PROTOCOL.SetInfo() isn't asking for a rename actually.
+ //
+ if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, Destination) == 0) {
+ Status = EFI_SUCCESS;
+ goto FreeDestination;
+ }
+ //
+ // Check if the rename would break the canonical pathnames of other
+ // VIRTIO_FS_FILE instances of the same VIRTIO_FS.
+ //
+ if (VirtioFsFile->IsDirectory) {
+ UINTN PathLen;
+ LIST_ENTRY *OpenFilesEntry;
+
+ PathLen = AsciiStrLen (VirtioFsFile->CanonicalPathname);
+ BASE_LIST_FOR_EACH (OpenFilesEntry, &VirtioFs->OpenFiles) {
+ VIRTIO_FS_FILE *OtherFile;
+
+ OtherFile = VIRTIO_FS_FILE_FROM_OPEN_FILES_ENTRY (OpenFilesEntry);
+ if (OtherFile != VirtioFsFile &&
+ AsciiStrnCmp (VirtioFsFile->CanonicalPathname,
+ OtherFile->CanonicalPathname, PathLen) == 0 &&
+ (OtherFile->CanonicalPathname[PathLen] == '\0' ||
+ OtherFile->CanonicalPathname[PathLen] == '/')) {
+ //
+ // OtherFile refers to the same directory as VirtioFsFile, or is a
+ // (possibly indirect) child of the directory referred to by
+ // VirtioFsFile.
+ //
+ Status = EFI_ACCESS_DENIED;
+ goto FreeDestination;
+ }
+ }
+ }
+ //
+ // From this point on, the file needs to be open for writing.
+ //
+ if (!VirtioFsFile->IsOpenForWriting) {
+ Status = EFI_ACCESS_DENIED;
+ goto FreeDestination;
+ }
+ //
+ // Split both source and destination canonical pathnames into (most specific
+ // parent directory, last component) pairs.
+ //
+ Status = VirtioFsLookupMostSpecificParentDir (VirtioFs,
+ VirtioFsFile->CanonicalPathname, &OldParentDirNodeId,
+ &OldLastComponent);
+ if (EFI_ERROR (Status)) {
+ goto FreeDestination;
+ }
+ Status = VirtioFsLookupMostSpecificParentDir (VirtioFs, Destination,
+ &NewParentDirNodeId, &NewLastComponent);
+ if (EFI_ERROR (Status)) {
+ goto ForgetOldParentDirNodeId;
+ }
+ //
+ // Perform the rename. If the destination path exists, the rename will fail.
+ //
+ Status = VirtioFsFuseRename (VirtioFs, OldParentDirNodeId, OldLastComponent,
+ NewParentDirNodeId, NewLastComponent);
+ if (EFI_ERROR (Status)) {
+ goto ForgetNewParentDirNodeId;
+ }
+
+ //
+ // Swap in the new canonical pathname.
+ //
+ FreePool (VirtioFsFile->CanonicalPathname);
+ VirtioFsFile->CanonicalPathname = Destination;
+ Destination = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // Fall through.
+ //
+ForgetNewParentDirNodeId:
+ if (NewParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, NewParentDirNodeId);
+ }
+
+ForgetOldParentDirNodeId:
+ if (OldParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
+ VirtioFsFuseForget (VirtioFs, OldParentDirNodeId);
+ }
+
+FreeDestination:
+ if (Destination != NULL) {
+ FreePool (Destination);
+ }
+ return Status;
+}
+
+/**
+ Update the attributes of a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.
+
+ @param[in,out] VirtioFsFile The VIRTIO_FS_FILE to update the attributes of.
+
+ @param[in] NewFileInfo The new attributes requested by
+ EFI_FILE_PROTOCOL.SetInfo(). NewFileInfo->Size
+ and NewFileInfo->FileName are ignored.
+
+ @retval EFI_SUCCESS No attributes had to be updated.
+
+ @retval EFI_SUCCESS The required set of attribute updates has been
+ determined and performed successfully.
+
+ @retval EFI_ACCESS_DENIED NewFileInfo requests an update to a property
+ different from the EFI_FILE_READ_ONLY bit in the
+ Attribute field, but VirtioFsFile is not open for
+ writing.
+
+ @return Error codes propagated from underlying functions.
+**/
+STATIC
+EFI_STATUS
+UpdateAttributes (
+ IN OUT VIRTIO_FS_FILE *VirtioFsFile,
+ IN EFI_FILE_INFO *NewFileInfo
+ )
+{
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+ EFI_FILE_INFO FileInfo;
+ BOOLEAN UpdateFileSize;
+ UINT64 FileSize;
+ BOOLEAN UpdateAtime;
+ BOOLEAN UpdateMtime;
+ UINT64 Atime;
+ UINT64 Mtime;
+ BOOLEAN UpdateMode;
+ UINT32 Mode;
+
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // Fetch the current attributes first, so we can build the difference between
+ // them and NewFileInfo.
+ //
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Collect the updates.
+ //
+ if (VirtioFsFile->IsDirectory) {
+ UpdateFileSize = FALSE;
+ } else {
+ VirtioFsGetFuseSizeUpdate (&FileInfo, NewFileInfo, &UpdateFileSize,
+ &FileSize);
+ }
+
+ Status = VirtioFsGetFuseTimeUpdates (&FileInfo, NewFileInfo, &UpdateAtime,
+ &UpdateMtime, &Atime, &Mtime);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = VirtioFsGetFuseModeUpdate (&FileInfo, NewFileInfo, &UpdateMode,
+ &Mode);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If no attribute updates are necessary, we're done.
+ //
+ if (!UpdateFileSize && !UpdateAtime && !UpdateMtime && !UpdateMode) {
+ return EFI_SUCCESS;
+ }
+ //
+ // If the file is not open for writing, then only Mode may be updated (for
+ // toggling EFI_FILE_READ_ONLY).
+ //
+ if (!VirtioFsFile->IsOpenForWriting &&
+ (UpdateFileSize || UpdateAtime || UpdateMtime)) {
+ return EFI_ACCESS_DENIED;
+ }
+ //
+ // Send the FUSE_SETATTR request now.
+ //
+ Status = VirtioFsFuseSetAttr (
+ VirtioFs,
+ VirtioFsFile->NodeId,
+ UpdateFileSize ? &FileSize : NULL,
+ UpdateAtime ? &Atime : NULL,
+ UpdateMtime ? &Mtime : NULL,
+ UpdateMode ? &Mode : NULL
+ );
+ return Status;
+}
+
+/**
+ Process an EFI_FILE_INFO setting request.
+**/
+STATIC
+EFI_STATUS
+SetFileInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+
+ //
+ // Validate if Buffer passes as EFI_FILE_INFO.
+ //
+ Status = ValidateInfoStructure (
+ BufferSize, // SizeByProtocolCaller
+ OFFSET_OF (EFI_FILE_INFO,
+ FileName) + sizeof (CHAR16), // MinimumStructSize
+ TRUE, // IsSizeByInfoPresent
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FileInfo = Buffer;
+
+ //
+ // Perform the rename/move request, if any.
+ //
+ Status = Rename (VirtioFsFile, FileInfo->FileName);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Update any attributes requested.
+ //
+ Status = UpdateAttributes (VirtioFsFile, FileInfo);
+ //
+ // The UEFI spec does not speak about partial failure in
+ // EFI_FILE_PROTOCOL.SetInfo(); we won't try to roll back the rename (if
+ // there was one) in case the attribute updates fail.
+ //
+ return Status;
+}
+
+/**
+ Process an EFI_FILE_SYSTEM_INFO setting request.
+**/
+STATIC
+EFI_STATUS
+SetFileSystemInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ EFI_FILE_SYSTEM_INFO *FileSystemInfo;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // Validate if Buffer passes as EFI_FILE_SYSTEM_INFO.
+ //
+ Status = ValidateInfoStructure (
+ BufferSize, // SizeByProtocolCaller
+ OFFSET_OF (EFI_FILE_SYSTEM_INFO,
+ VolumeLabel) + sizeof (CHAR16), // MinimumStructSize
+ TRUE, // IsSizeByInfoPresent
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FileSystemInfo = Buffer;
+
+ //
+ // EFI_FILE_SYSTEM_INFO fields other than VolumeLabel cannot be changed, per
+ // spec.
+ //
+ // If the label is being changed to its current value, report success;
+ // otherwise, reject the request, as the Virtio Filesystem device does not
+ // support changing the label.
+ //
+ if (StrCmp (FileSystemInfo->VolumeLabel, VirtioFs->Label) == 0) {
+ return EFI_SUCCESS;
+ }
+ return EFI_WRITE_PROTECTED;
+}
+
+/**
+ Process an EFI_FILE_SYSTEM_VOLUME_LABEL setting request.
+**/
+STATIC
+EFI_STATUS
+SetFileSystemVolumeLabelInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ EFI_FILE_SYSTEM_VOLUME_LABEL *FileSystemVolumeLabel;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ //
+ // Validate if Buffer passes as EFI_FILE_SYSTEM_VOLUME_LABEL.
+ //
+ Status = ValidateInfoStructure (
+ BufferSize, // SizeByProtocolCaller
+ OFFSET_OF (EFI_FILE_SYSTEM_VOLUME_LABEL,
+ VolumeLabel) + sizeof (CHAR16), // MinimumStructSize
+ FALSE, // IsSizeByInfoPresent
+ Buffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ FileSystemVolumeLabel = Buffer;
+
+ //
+ // If the label is being changed to its current value, report success;
+ // otherwise, reject the request, as the Virtio Filesystem device does not
+ // support changing the label.
+ //
+ if (StrCmp (FileSystemVolumeLabel->VolumeLabel, VirtioFs->Label) == 0) {
+ return EFI_SUCCESS;
+ }
+ return EFI_WRITE_PROTECTED;
+}
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
+ return SetFileInfo (This, BufferSize, Buffer);
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
+ return SetFileSystemInfo (This, BufferSize, Buffer);
+ }
+
+ if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
+ return SetFileSystemVolumeLabelInfo (This, BufferSize, Buffer);
+ }
+
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c
new file mode 100644
index 00000000000..d287d192f47
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsSetPosition.c
@@ -0,0 +1,67 @@
+/** @file
+ EFI_FILE_PROTOCOL.SetPosition() member function for the Virtio Filesystem
+ driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/MemoryAllocationLib.h> // FreePool()
+
+#include "VirtioFsDxe.h"
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileSetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE FuseAttr;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+
+ //
+ // Directories can only be rewound, per spec.
+ //
+ if (VirtioFsFile->IsDirectory) {
+ if (Position != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ VirtioFsFile->FilePosition = 0;
+ if (VirtioFsFile->FileInfoArray != NULL) {
+ FreePool (VirtioFsFile->FileInfoArray);
+ VirtioFsFile->FileInfoArray = NULL;
+ }
+ VirtioFsFile->SingleFileInfoSize = 0;
+ VirtioFsFile->NumFileInfo = 0;
+ VirtioFsFile->NextFileInfo = 0;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Regular file.
+ //
+ if (Position < MAX_UINT64) {
+ //
+ // Caller is requesting absolute file position.
+ //
+ VirtioFsFile->FilePosition = Position;
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Caller is requesting a seek to EOF.
+ //
+ VirtioFs = VirtioFsFile->OwnerFs;
+ Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ VirtioFsFile->FilePosition = FuseAttr.Size;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c
new file mode 100644
index 00000000000..6c4998116f3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/SimpleFsWrite.c
@@ -0,0 +1,81 @@
+/** @file
+ EFI_FILE_PROTOCOL.Write() member function for the Virtio Filesystem driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "VirtioFsDxe.h"
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ VIRTIO_FS_FILE *VirtioFsFile;
+ VIRTIO_FS *VirtioFs;
+ EFI_STATUS Status;
+ UINTN Transferred;
+ UINTN Left;
+
+ VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
+ VirtioFs = VirtioFsFile->OwnerFs;
+
+ if (VirtioFsFile->IsDirectory) {
+ return EFI_UNSUPPORTED;
+ }
+ if (!VirtioFsFile->IsOpenForWriting) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ Status = EFI_SUCCESS;
+ Transferred = 0;
+ Left = *BufferSize;
+ while (Left > 0) {
+ UINT32 WriteSize;
+
+ //
+ // Honor the write buffer size limit.
+ //
+ WriteSize = (UINT32)MIN ((UINTN)VirtioFs->MaxWrite, Left);
+ Status = VirtioFsFuseWrite (
+ VirtioFs,
+ VirtioFsFile->NodeId,
+ VirtioFsFile->FuseHandle,
+ VirtioFsFile->FilePosition + Transferred,
+ &WriteSize,
+ (UINT8 *)Buffer + Transferred
+ );
+ if (!EFI_ERROR (Status) && WriteSize == 0) {
+ //
+ // Progress should have been made.
+ //
+ Status = EFI_DEVICE_ERROR;
+ }
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ Transferred += WriteSize;
+ Left -= WriteSize;
+ }
+
+ *BufferSize = Transferred;
+ VirtioFsFile->FilePosition += Transferred;
+ //
+ // According to the UEFI spec,
+ //
+ // - 'Partial writes only occur when there has been a data error during the
+ // write attempt (such as "file space full")', and
+ //
+ // - (as an example) EFI_VOLUME_FULL is returned when 'The volume is full'.
+ //
+ // These together imply that after a partial write, we have to return an
+ // error. In other words, (Transferred > 0) is inconsequential for the return
+ // value.
+ //
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
new file mode 100644
index 00000000000..a45391bffef
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.h
@@ -0,0 +1,544 @@
+/** @file
+ Internal macro definitions, type definitions, and function declarations for
+ the Virtio Filesystem device driver.
+
+ Copyright (C) 2020, Red Hat, Inc.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef VIRTIO_FS_DXE_H_
+#define VIRTIO_FS_DXE_H_
+
+#include <Base.h> // SIGNATURE_64()
+#include <Guid/FileInfo.h> // EFI_FILE_INFO
+#include <IndustryStandard/VirtioFs.h> // VIRTIO_FS_TAG_BYTES
+#include <Library/DebugLib.h> // CR()
+#include <Protocol/SimpleFileSystem.h> // EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
+#include <Protocol/VirtioDevice.h> // VIRTIO_DEVICE_PROTOCOL
+#include <Uefi/UefiBaseType.h> // EFI_EVENT
+
+#define VIRTIO_FS_SIG SIGNATURE_64 ('V', 'I', 'R', 'T', 'I', 'O', 'F', 'S')
+
+#define VIRTIO_FS_FILE_SIG \
+ SIGNATURE_64 ('V', 'I', 'O', 'F', 'S', 'F', 'I', 'L')
+
+//
+// The following limit applies to two kinds of pathnames.
+//
+// - The length of a POSIX-style, canonical pathname *at rest* never exceeds
+// VIRTIO_FS_MAX_PATHNAME_LENGTH. (Length is defined as the number of CHAR8
+// elements in the canonical pathname, excluding the terminating '\0'.) This
+// is an invariant that is ensured for canonical pathnames created, and that
+// is assumed about canonical pathname inputs (which all originate
+// internally).
+//
+// - If the length of a UEFI-style pathname *argument*, originating directly or
+// indirectly from the EFI_FILE_PROTOCOL caller, exceeds
+// VIRTIO_FS_MAX_PATHNAME_LENGTH, then the argument is rejected. (Length is
+// defined as the number of CHAR16 elements in the UEFI-style pathname,
+// excluding the terminating L'\0'.) This is a restriction that's checked on
+// external UEFI-style pathname inputs.
+//
+// The limit is not expected to be a practical limitation; it's only supposed
+// to prevent attempts at overflowing size calculations. For both kinds of
+// pathnames, separate limits could be used; a common limit is used purely for
+// simplicity.
+//
+#define VIRTIO_FS_MAX_PATHNAME_LENGTH ((UINTN)65535)
+
+//
+// Maximum value for VIRTIO_FS_FILE.NumFileInfo.
+//
+#define VIRTIO_FS_FILE_MAX_FILE_INFO 256
+
+//
+// Filesystem label encoded in UCS-2, transformed from the UTF-8 representation
+// in "VIRTIO_FS_CONFIG.Tag", and NUL-terminated. Only the printable ASCII code
+// points (U+0020 through U+007E) are supported.
+//
+typedef CHAR16 VIRTIO_FS_LABEL[VIRTIO_FS_TAG_BYTES + 1];
+
+//
+// Main context structure, expressing an EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
+// interface on top of the Virtio Filesystem device.
+//
+typedef struct {
+ //
+ // Parts of this structure are initialized / torn down in various functions
+ // at various call depths. The table to the right should make it easier to
+ // track them.
+ //
+ // field init function init depth
+ // ----------- ------------------ ----------
+ UINT64 Signature; // DriverBindingStart 0
+ VIRTIO_DEVICE_PROTOCOL *Virtio; // DriverBindingStart 0
+ VIRTIO_FS_LABEL Label; // VirtioFsInit 1
+ UINT16 QueueSize; // VirtioFsInit 1
+ VRING Ring; // VirtioRingInit 2
+ VOID *RingMap; // VirtioRingMap 2
+ UINT64 RequestId; // FuseInitSession 1
+ UINT32 MaxWrite; // FuseInitSession 1
+ EFI_EVENT ExitBoot; // DriverBindingStart 0
+ LIST_ENTRY OpenFiles; // DriverBindingStart 0
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFs; // DriverBindingStart 0
+} VIRTIO_FS;
+
+#define VIRTIO_FS_FROM_SIMPLE_FS(SimpleFsReference) \
+ CR (SimpleFsReference, VIRTIO_FS, SimpleFs, VIRTIO_FS_SIG);
+
+//
+// Structure for describing a contiguous buffer, potentially mapped for Virtio
+// transfer.
+//
+typedef struct {
+ //
+ // The following fields originate from the owner of the buffer.
+ //
+ VOID *Buffer;
+ UINTN Size;
+ //
+ // All of the fields below, until the end of the structure, are
+ // zero-initialized when the structure is initially validated.
+ //
+ // Mapped, MappedAddress and Mapping are updated when the buffer is mapped
+ // for VirtioOperationBusMasterRead or VirtioOperationBusMasterWrite. They
+ // are again updated when the buffer is unmapped.
+ //
+ BOOLEAN Mapped;
+ EFI_PHYSICAL_ADDRESS MappedAddress;
+ VOID *Mapping;
+ //
+ // Transferred is updated after VirtioFlush() returns successfully:
+ // - for VirtioOperationBusMasterRead, Transferred is set to Size;
+ // - for VirtioOperationBusMasterWrite, Transferred is calculated from the
+ // UsedLen output parameter of VirtioFlush().
+ //
+ UINTN Transferred;
+} VIRTIO_FS_IO_VECTOR;
+
+//
+// Structure for describing a list of IO Vectors.
+//
+typedef struct {
+ //
+ // The following fields originate from the owner of the buffers.
+ //
+ VIRTIO_FS_IO_VECTOR *IoVec;
+ UINTN NumVec;
+ //
+ // TotalSize is calculated when the scatter-gather list is initially
+ // validated.
+ //
+ UINT32 TotalSize;
+} VIRTIO_FS_SCATTER_GATHER_LIST;
+
+//
+// Private context structure that exposes EFI_FILE_PROTOCOL on top of an open
+// FUSE file reference.
+//
+typedef struct {
+ UINT64 Signature;
+ EFI_FILE_PROTOCOL SimpleFile;
+ BOOLEAN IsDirectory;
+ BOOLEAN IsOpenForWriting;
+ VIRTIO_FS *OwnerFs;
+ LIST_ENTRY OpenFilesEntry;
+ CHAR8 *CanonicalPathname;
+ UINT64 FilePosition;
+ //
+ // In the FUSE wire protocol, every request except FUSE_INIT refers to a
+ // file, namely by the "VIRTIO_FS_FUSE_REQUEST.NodeId" field; that is, by the
+ // inode number of the file. However, some of the FUSE requests that we need
+ // for some of the EFI_FILE_PROTOCOL member functions require an open file
+ // handle *in addition* to the inode number. For simplicity, whenever a
+ // VIRTIO_FS_FILE object is created, primarily defined by its NodeId field,
+ // we also *open* the referenced file at once, and save the returned file
+ // handle in the FuseHandle field. This way, when an EFI_FILE_PROTOCOL member
+ // function must send a FUSE request that needs the file handle *in addition*
+ // to the inode number, FuseHandle will be at our disposal at once.
+ //
+ UINT64 NodeId;
+ UINT64 FuseHandle;
+ //
+ // EFI_FILE_INFO objects cached for an in-flight directory read.
+ //
+ // For reading through a directory stream with tolerable performance, we have
+ // to call FUSE_READDIRPLUS each time with such a buffer that can deliver a
+ // good number of variable size records (VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE
+ // elements). Every time we do that, we turn the whole bunch into an array of
+ // EFI_FILE_INFOs immediately. EFI_FILE_PROTOCOL.Read() invocations (on
+ // directories) will be served from this EFI_FILE_INFO cache.
+ //
+ UINT8 *FileInfoArray;
+ UINTN SingleFileInfoSize;
+ UINTN NumFileInfo;
+ UINTN NextFileInfo;
+} VIRTIO_FS_FILE;
+
+#define VIRTIO_FS_FILE_FROM_SIMPLE_FILE(SimpleFileReference) \
+ CR (SimpleFileReference, VIRTIO_FS_FILE, SimpleFile, VIRTIO_FS_FILE_SIG);
+
+#define VIRTIO_FS_FILE_FROM_OPEN_FILES_ENTRY(OpenFilesEntryReference) \
+ CR (OpenFilesEntryReference, VIRTIO_FS_FILE, OpenFilesEntry, \
+ VIRTIO_FS_FILE_SIG);
+
+//
+// Initialization and helper routines for the Virtio Filesystem device.
+//
+
+EFI_STATUS
+VirtioFsInit (
+ IN OUT VIRTIO_FS *VirtioFs
+ );
+
+VOID
+VirtioFsUninit (
+ IN OUT VIRTIO_FS *VirtioFs
+ );
+
+VOID
+EFIAPI
+VirtioFsExitBoot (
+ IN EFI_EVENT ExitBootEvent,
+ IN VOID *VirtioFsAsVoid
+ );
+
+EFI_STATUS
+VirtioFsSgListsValidate (
+ IN VIRTIO_FS *VirtioFs,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *RequestSgList,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *ResponseSgList OPTIONAL
+ );
+
+EFI_STATUS
+VirtioFsSgListsSubmit (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *RequestSgList,
+ IN OUT VIRTIO_FS_SCATTER_GATHER_LIST *ResponseSgList OPTIONAL
+ );
+
+EFI_STATUS
+VirtioFsFuseNewRequest (
+ IN OUT VIRTIO_FS *VirtioFs,
+ OUT VIRTIO_FS_FUSE_REQUEST *Request,
+ IN UINT32 RequestSize,
+ IN VIRTIO_FS_FUSE_OPCODE Opcode,
+ IN UINT64 NodeId
+ );
+
+EFI_STATUS
+VirtioFsFuseCheckResponse (
+ IN VIRTIO_FS_SCATTER_GATHER_LIST *ResponseSgList,
+ IN UINT64 RequestId,
+ OUT UINTN *TailBufferFill
+ );
+
+EFI_STATUS
+VirtioFsErrnoToEfiStatus (
+ IN INT32 Errno
+ );
+
+EFI_STATUS
+VirtioFsAppendPath (
+ IN CHAR8 *LhsPath8,
+ IN CHAR16 *RhsPath16,
+ OUT CHAR8 **ResultPath8,
+ OUT BOOLEAN *RootEscape
+ );
+
+EFI_STATUS
+VirtioFsLookupMostSpecificParentDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN OUT CHAR8 *Path,
+ OUT UINT64 *DirNodeId,
+ OUT CHAR8 **LastComponent
+ );
+
+EFI_STATUS
+VirtioFsGetBasename (
+ IN CHAR8 *Path,
+ OUT CHAR16 *Basename OPTIONAL,
+ IN OUT UINTN *BasenameSize
+ );
+
+EFI_STATUS
+VirtioFsComposeRenameDestination (
+ IN CHAR8 *LhsPath8,
+ IN CHAR16 *RhsPath16,
+ OUT CHAR8 **ResultPath8,
+ OUT BOOLEAN *RootEscape
+ );
+
+EFI_STATUS
+VirtioFsFuseAttrToEfiFileInfo (
+ IN VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr,
+ OUT EFI_FILE_INFO *FileInfo
+ );
+
+EFI_STATUS
+VirtioFsFuseDirentPlusToEfiFileInfo (
+ IN VIRTIO_FS_FUSE_DIRENTPLUS_RESPONSE *FuseDirent,
+ IN OUT EFI_FILE_INFO *FileInfo
+ );
+
+VOID
+VirtioFsGetFuseSizeUpdate (
+ IN EFI_FILE_INFO *Info,
+ IN EFI_FILE_INFO *NewInfo,
+ OUT BOOLEAN *Update,
+ OUT UINT64 *Size
+ );
+
+EFI_STATUS
+VirtioFsGetFuseTimeUpdates (
+ IN EFI_FILE_INFO *Info,
+ IN EFI_FILE_INFO *NewInfo,
+ OUT BOOLEAN *UpdateAtime,
+ OUT BOOLEAN *UpdateMtime,
+ OUT UINT64 *Atime,
+ OUT UINT64 *Mtime
+ );
+
+EFI_STATUS
+VirtioFsGetFuseModeUpdate (
+ IN EFI_FILE_INFO *Info,
+ IN EFI_FILE_INFO *NewInfo,
+ OUT BOOLEAN *Update,
+ OUT UINT32 *Mode
+ );
+
+//
+// Wrapper functions for FUSE commands (primitives).
+//
+
+EFI_STATUS
+VirtioFsFuseLookup (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 DirNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId,
+ OUT VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr
+ );
+
+EFI_STATUS
+VirtioFsFuseForget (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId
+ );
+
+EFI_STATUS
+VirtioFsFuseGetAttr (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ OUT VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE *FuseAttr
+ );
+
+EFI_STATUS
+VirtioFsFuseSetAttr (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 *Size OPTIONAL,
+ IN UINT64 *Atime OPTIONAL,
+ IN UINT64 *Mtime OPTIONAL,
+ IN UINT32 *Mode OPTIONAL
+ );
+
+EFI_STATUS
+VirtioFsFuseMkDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 ParentNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId
+ );
+
+EFI_STATUS
+VirtioFsFuseRemoveFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 ParentNodeId,
+ IN CHAR8 *Name,
+ IN BOOLEAN IsDir
+ );
+
+EFI_STATUS
+VirtioFsFuseOpen (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN BOOLEAN ReadWrite,
+ OUT UINT64 *FuseHandle
+ );
+
+EFI_STATUS
+VirtioFsFuseReadFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN BOOLEAN IsDir,
+ IN UINT64 Offset,
+ IN OUT UINT32 *Size,
+ OUT VOID *Data
+ );
+
+EFI_STATUS
+VirtioFsFuseWrite (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN UINT64 Offset,
+ IN OUT UINT32 *Size,
+ IN VOID *Data
+ );
+
+EFI_STATUS
+VirtioFsFuseStatFs (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ OUT VIRTIO_FS_FUSE_STATFS_RESPONSE *FilesysAttr
+ );
+
+EFI_STATUS
+VirtioFsFuseReleaseFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN BOOLEAN IsDir
+ );
+
+EFI_STATUS
+VirtioFsFuseFsyncFileOrDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle,
+ IN BOOLEAN IsDir
+ );
+
+EFI_STATUS
+VirtioFsFuseFlush (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ IN UINT64 FuseHandle
+ );
+
+EFI_STATUS
+VirtioFsFuseInitSession (
+ IN OUT VIRTIO_FS *VirtioFs
+ );
+
+EFI_STATUS
+VirtioFsFuseOpenDir (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 NodeId,
+ OUT UINT64 *FuseHandle
+ );
+
+EFI_STATUS
+VirtioFsFuseOpenOrCreate (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 ParentNodeId,
+ IN CHAR8 *Name,
+ OUT UINT64 *NodeId,
+ OUT UINT64 *FuseHandle
+ );
+
+EFI_STATUS
+VirtioFsFuseRename (
+ IN OUT VIRTIO_FS *VirtioFs,
+ IN UINT64 OldParentNodeId,
+ IN CHAR8 *OldName,
+ IN UINT64 NewParentNodeId,
+ IN CHAR8 *NewName
+ );
+
+//
+// EFI_SIMPLE_FILE_SYSTEM_PROTOCOL member functions for the Virtio Filesystem
+// driver.
+//
+
+EFI_STATUS
+EFIAPI
+VirtioFsOpenVolume (
+ IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **Root
+ );
+
+//
+// EFI_FILE_PROTOCOL member functions for the Virtio Filesystem driver.
+//
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileClose (
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileDelete (
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileFlush (
+ IN EFI_FILE_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileGetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileGetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileRead (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileSetInfo (
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileSetPosition (
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ );
+
+EFI_STATUS
+EFIAPI
+VirtioFsSimpleFileWrite (
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+#endif // VIRTIO_FS_DXE_H_
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
new file mode 100644
index 00000000000..afad95616a3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
@@ -0,0 +1,136 @@
+## @file
+# Provide EFI_SIMPLE_FILE_SYSTEM_PROTOCOL instances on virtio-fs devices.
+#
+# Copyright (C) 2020, Red Hat, Inc.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+# Permission Model of this driver:
+#
+# Regardless of the UID and GID values this driver send in the FUSE request
+# header, the daemon (that is, the Virtio Filesystem device) always acts with
+# root privileges on the host side. The only time the daemon considers said UID
+# and GID fields is when creating a new file or directory. Thus, the guest
+# driver cannot rely on the host for enforcing any file mode permissions,
+# regardless of the "personality" that the guest driver poses as, because
+# "root" on the host side ignores all file mode bits.
+#
+# Therefore the guest driver has to do its own permission checking, and use the
+# host-side file mode bits only as a kind of "metadata storage" or "reminder"
+# -- hopefully in a way that makes some sense on the host side too.
+#
+# The complete mapping between the EFI_FILE_PROTOCOL and the host-side file
+# mode bits is described below.
+#
+# - The guest driver poses as UID 0, GID 0, PID 1.
+#
+# - If and only if all "w" bits are missing from a file on the host side, then
+# the file or directory is reported as EFI_FILE_READ_ONLY in the guest. When
+# setting EFI_FILE_READ_ONLY in the guest, all "w" bits (0222) are cleared on
+# the host; when clearing EFI_FILE_READ_ONLY in the guest, all "w" bits are
+# set on the host. Viewed from the host side, this sort of reflects that an
+# EFI_FILE_READ_ONLY file should not be written by anyone.
+#
+# - The attributes EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED, and
+# EFI_FILE_ARCHIVE are never reported in the guest, and they are silently
+# ignored when a SetInfo() call or a file-creating Open() call requests them.
+#
+# - On the host, files are created with 0666 file mode bits, directories are
+# created with 0777 file mode bits.
+#
+# - In the guest, the EFI_FILE_READ_ONLY attribute only controls the permitted
+# open mode. In particular, on directories, the EFI_FILE_READ_ONLY attribute
+# does not prevent the creation or deletion of entries inside the directory;
+# EFI_FILE_READ_ONLY only prevents the renaming, deleting, flushing (syncing)
+# and touching of the directory itself (with "touching" meaning updating the
+# timestamps). The fact that EFI_FILE_READ_ONLY being set on a directory is
+# irrelevant in the guest with regard to entry creation/deletion, is
+# well-mirrored by the fact that virtiofsd -- which runs as root, regardless
+# of guest driver personality -- ignores the absence of "w" permissions on a
+# host-side directory, when creating or removing entries in it.
+#
+# - When an EFI_FILE_PROTOCOL is opened read-only, then the Delete(), Write()
+# and Flush() member functions are disabled for it. Additionally, SetInfo()
+# is restricted to flipping the EFI_FILE_READ_ONLY bit (which takes effect at
+# the next Open()).
+#
+# - As a consequence of the above, for deleting a directory, it must be
+# presented in the guest as openable for writing.
+#
+# - We diverge from the UEFI spec, and permit Flush() on a directory that has
+# been opened read-write; otherwise the only way to invoke FUSE_FSYNCDIR on a
+# directory would be to Close() it.
+#
+# - OpenVolume() opens the root directory for read-only access. The Open()
+# member function may open it for read-write access. While the root directory
+# cannot be renamed or deleted, opening it for read-write access is useful
+# for calling Flush(), according to the previous paragraph, or for updating
+# the root directory's timestamps with SetInfo().
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = VirtioFsDxe
+ FILE_GUID = 7BD9DDF7-8B83-488E-AEC9-24C78610289C
+ MODULE_TYPE = UEFI_DRIVER
+ ENTRY_POINT = VirtioFsEntryPoint
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[Sources]
+ DriverBinding.c
+ FuseFlush.c
+ FuseForget.c
+ FuseFsync.c
+ FuseGetAttr.c
+ FuseInit.c
+ FuseLookup.c
+ FuseMkDir.c
+ FuseOpen.c
+ FuseOpenDir.c
+ FuseOpenOrCreate.c
+ FuseRead.c
+ FuseRelease.c
+ FuseRename.c
+ FuseSetAttr.c
+ FuseStatFs.c
+ FuseUnlink.c
+ FuseWrite.c
+ Helpers.c
+ SimpleFsClose.c
+ SimpleFsDelete.c
+ SimpleFsFlush.c
+ SimpleFsGetInfo.c
+ SimpleFsGetPosition.c
+ SimpleFsOpen.c
+ SimpleFsOpenVolume.c
+ SimpleFsRead.c
+ SimpleFsSetInfo.c
+ SimpleFsSetPosition.c
+ SimpleFsWrite.c
+ VirtioFsDxe.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ TimeBaseLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ VirtioLib
+
+[Protocols]
+ gEfiComponentName2ProtocolGuid ## PRODUCES
+ gEfiDriverBindingProtocolGuid ## PRODUCES
+ gEfiSimpleFileSystemProtocolGuid ## BY_START
+ gVirtioDeviceProtocolGuid ## TO_START
+
+[Guids]
+ gEfiFileInfoGuid
+ gEfiFileSystemInfoGuid
+ gEfiFileSystemVolumeLabelInfoIdGuid
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/AmdSev.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/AmdSev.c
index 339994cfcf3..23b3c020e5e 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/AmdSev.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/AmdSev.c
@@ -1,7 +1,7 @@
/**@file
Initialize Secure Encrypted Virtualization (SEV) support
- Copyright (c) 2017, Advanced Micro Devices. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, Advanced Micro Devices. All rights reserved.<BR>
Copyright (c) 2019, Citrix Systems, Inc.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -14,8 +14,6 @@
#include <Library/MemEncryptSevLib.h>
#include <Library/PcdLib.h>
#include <PiPei.h>
-#include <Register/Amd/Cpuid.h>
-#include <Register/Cpuid.h>
#include "Platform.h"
@@ -30,7 +28,6 @@ AmdSevInitialize (
VOID
)
{
- CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx;
UINT64 EncryptionMask;
RETURN_STATUS PcdStatus;
@@ -42,14 +39,9 @@ AmdSevInitialize (
}
//
- // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position)
- //
- AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL);
- EncryptionMask = LShiftU64 (1, Ebx.Bits.PtePosBits);
-
- //
// Set Memory Encryption Mask PCD
//
+ EncryptionMask = MemEncryptSevGetEncryptionMask ();
PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
ASSERT_RETURN_ERROR (PcdStatus);
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/MemDetect.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/MemDetect.c
index 19c68d5d5ba..e8a7212a2a1 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/MemDetect.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/MemDetect.c
@@ -172,175 +172,33 @@ GetSystemMemorySizeBelow4gb (
return (UINT32) (((UINTN)((Cmos0x35 << 8) + Cmos0x34) << 16) + SIZE_16MB);
}
-
-STATIC
-UINT64
-GetSystemMemorySizeAbove4gb (
- )
-{
- UINT32 Size;
- UINTN CmosIndex;
-
- //
- // In PVH case, there is no CMOS, we have to calculate the memory size
- // from parsing the E820
- //
- if (XenPvhDetected ()) {
- UINT64 HighestAddress;
-
- HighestAddress = GetHighestSystemMemoryAddress (FALSE);
- ASSERT (HighestAddress == 0 || HighestAddress >= BASE_4GB);
-
- if (HighestAddress >= BASE_4GB) {
- HighestAddress -= BASE_4GB;
- }
-
- return HighestAddress;
- }
-
- //
- // CMOS 0x5b-0x5d specifies the system memory above 4GB MB.
- // * CMOS(0x5d) is the most significant size byte
- // * CMOS(0x5c) is the middle size byte
- // * CMOS(0x5b) is the least significant size byte
- // * The size is specified in 64kb chunks
- //
-
- Size = 0;
- for (CmosIndex = 0x5d; CmosIndex >= 0x5b; CmosIndex--) {
- Size = (UINT32) (Size << 8) + (UINT32) CmosRead8 (CmosIndex);
- }
-
- return LShiftU64 (Size, 16);
-}
-
-
-/**
- Return the highest address that DXE could possibly use, plus one.
-**/
-STATIC
-UINT64
-GetFirstNonAddress (
- VOID
- )
-{
- UINT64 FirstNonAddress;
- UINT64 Pci64Base, Pci64Size;
- RETURN_STATUS PcdStatus;
-
- FirstNonAddress = BASE_4GB + GetSystemMemorySizeAbove4gb ();
-
- //
- // If DXE is 32-bit, then we're done; PciBusDxe will degrade 64-bit MMIO
- // resources to 32-bit anyway. See DegradeResource() in
- // "PciResourceSupport.c".
- //
-#ifdef MDE_CPU_IA32
- if (!FeaturePcdGet (PcdDxeIplSwitchToLongMode)) {
- return FirstNonAddress;
- }
-#endif
-
- //
- // Otherwise, in order to calculate the highest address plus one, we must
- // consider the 64-bit PCI host aperture too. Fetch the default size.
- //
- Pci64Size = PcdGet64 (PcdPciMmio64Size);
-
- if (Pci64Size == 0) {
- if (mBootMode != BOOT_ON_S3_RESUME) {
- DEBUG ((DEBUG_INFO, "%a: disabling 64-bit PCI host aperture\n",
- __FUNCTION__));
- PcdStatus = PcdSet64S (PcdPciMmio64Size, 0);
- ASSERT_RETURN_ERROR (PcdStatus);
- }
-
- //
- // There's nothing more to do; the amount of memory above 4GB fully
- // determines the highest address plus one. The memory hotplug area (see
- // below) plays no role for the firmware in this case.
- //
- return FirstNonAddress;
- }
-
- //
- // SeaBIOS aligns both boundaries of the 64-bit PCI host aperture to 1GB, so
- // that the host can map it with 1GB hugepages. Follow suit.
- //
- Pci64Base = ALIGN_VALUE (FirstNonAddress, (UINT64)SIZE_1GB);
- Pci64Size = ALIGN_VALUE (Pci64Size, (UINT64)SIZE_1GB);
-
- //
- // The 64-bit PCI host aperture should also be "naturally" aligned. The
- // alignment is determined by rounding the size of the aperture down to the
- // next smaller or equal power of two. That is, align the aperture by the
- // largest BAR size that can fit into it.
- //
- Pci64Base = ALIGN_VALUE (Pci64Base, GetPowerOfTwo64 (Pci64Size));
-
- if (mBootMode != BOOT_ON_S3_RESUME) {
- //
- // The core PciHostBridgeDxe driver will automatically add this range to
- // the GCD memory space map through our PciHostBridgeLib instance; here we
- // only need to set the PCDs.
- //
- PcdStatus = PcdSet64S (PcdPciMmio64Base, Pci64Base);
- ASSERT_RETURN_ERROR (PcdStatus);
- PcdStatus = PcdSet64S (PcdPciMmio64Size, Pci64Size);
- ASSERT_RETURN_ERROR (PcdStatus);
-
- DEBUG ((DEBUG_INFO, "%a: Pci64Base=0x%Lx Pci64Size=0x%Lx\n",
- __FUNCTION__, Pci64Base, Pci64Size));
- }
-
- //
- // The useful address space ends with the 64-bit PCI host aperture.
- //
- FirstNonAddress = Pci64Base + Pci64Size;
- return FirstNonAddress;
-}
-
-
/**
- Initialize the mPhysMemAddressWidth variable, based on guest RAM size.
+ Initialize the mPhysMemAddressWidth variable, based on CPUID data.
**/
VOID
AddressWidthInitialization (
VOID
)
{
- UINT64 FirstNonAddress;
+ UINT32 RegEax;
- //
- // As guest-physical memory size grows, the permanent PEI RAM requirements
- // are dominated by the identity-mapping page tables built by the DXE IPL.
- // The DXL IPL keys off of the physical address bits advertized in the CPU
- // HOB. To conserve memory, we calculate the minimum address width here.
- //
- FirstNonAddress = GetFirstNonAddress ();
- mPhysMemAddressWidth = (UINT8)HighBitSet64 (FirstNonAddress);
-
- //
- // If FirstNonAddress is not an integral power of two, then we need an
- // additional bit.
- //
- if ((FirstNonAddress & (FirstNonAddress - 1)) != 0) {
- ++mPhysMemAddressWidth;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ mPhysMemAddressWidth = (UINT8) RegEax;
+ } else {
+ mPhysMemAddressWidth = 36;
}
//
- // The minimum address width is 36 (covers up to and excluding 64 GB, which
- // is the maximum for Ia32 + PAE). The theoretical architecture maximum for
- // X64 long mode is 52 bits, but the DXE IPL clamps that down to 48 bits. We
- // can simply assert that here, since 48 bits are good enough for 256 TB.
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
//
- if (mPhysMemAddressWidth <= 36) {
- mPhysMemAddressWidth = 36;
+ ASSERT (mPhysMemAddressWidth <= 52);
+ if (mPhysMemAddressWidth > 48) {
+ mPhysMemAddressWidth = 48;
}
- ASSERT (mPhysMemAddressWidth <= 48);
}
-
/**
Calculate the cap for the permanent PEI memory.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.c
index cec1a8b4485..563529dfa18 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.c
@@ -448,6 +448,7 @@ InitializeXenPlatform (
InitializeRamRegions ();
InitializeXen ();
+ CalibrateLapicTimer ();
if (mBootMode != BOOT_ON_S3_RESUME) {
ReserveEmuVariableNvStore ();
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.h b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.h
index 96dd8e4f36c..006669780b8 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.h
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Platform.h
@@ -127,6 +127,16 @@ XenGetE820Map (
UINT32 *Count
);
+EFI_STATUS
+PhysicalAddressIdentityMapping (
+ IN EFI_PHYSICAL_ADDRESS AddressToMap
+ );
+
+VOID
+CalibrateLapicTimer (
+ VOID
+ );
+
extern EFI_BOOT_MODE mBootMode;
extern UINT8 mPhysMemAddressWidth;
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Xen.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Xen.c
index bdcbb77057c..7963b45c1a4 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Xen.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/Xen.c
@@ -17,14 +17,19 @@
//
// The Library classes this module consumes
//
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuLib.h>
#include <Library/DebugLib.h>
#include <Library/HobLib.h>
+#include <Library/LocalApicLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
+#include <Library/SafeIntLib.h>
#include <Guid/XenInfo.h>
#include <IndustryStandard/E820.h>
#include <Library/ResourcePublicationLib.h>
#include <Library/MtrrLib.h>
+#include <IndustryStandard/PageTable.h>
#include <IndustryStandard/Xen/arch-x86/hvm/start_info.h>
#include <Library/XenHypercallLib.h>
#include <IndustryStandard/Xen/memory.h>
@@ -386,3 +391,250 @@ InitializeXen (
return EFI_SUCCESS;
}
+
+EFI_STATUS
+PhysicalAddressIdentityMapping (
+ IN EFI_PHYSICAL_ADDRESS AddressToMap
+ )
+{
+ INTN Index;
+ PAGE_MAP_AND_DIRECTORY_POINTER *L4, *L3;
+ PAGE_TABLE_ENTRY *PageTable;
+
+ DEBUG ((DEBUG_INFO, "Mapping 1:1 of address 0x%lx\n", (UINT64)AddressToMap));
+
+ // L4 / Top level Page Directory Pointers
+
+ L4 = (VOID*)(UINTN)PcdGet32 (PcdOvmfSecPageTablesBase);
+ Index = PML4_OFFSET (AddressToMap);
+
+ if (!L4[Index].Bits.Present) {
+ L3 = AllocatePages (1);
+ if (L3 == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (L3, EFI_PAGE_SIZE);
+
+ L4[Index].Bits.ReadWrite = 1;
+ L4[Index].Bits.Accessed = 1;
+ L4[Index].Bits.PageTableBaseAddress = (EFI_PHYSICAL_ADDRESS)L3 >> 12;
+ L4[Index].Bits.Present = 1;
+ }
+
+ // L3 / Next level Page Directory Pointers
+
+ L3 = (VOID*)(EFI_PHYSICAL_ADDRESS)(L4[Index].Bits.PageTableBaseAddress << 12);
+ Index = PDP_OFFSET (AddressToMap);
+
+ if (!L3[Index].Bits.Present) {
+ PageTable = AllocatePages (1);
+ if (PageTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (PageTable, EFI_PAGE_SIZE);
+
+ L3[Index].Bits.ReadWrite = 1;
+ L3[Index].Bits.Accessed = 1;
+ L3[Index].Bits.PageTableBaseAddress = (EFI_PHYSICAL_ADDRESS)PageTable >> 12;
+ L3[Index].Bits.Present = 1;
+ }
+
+ // L2 / Page Table Entries
+
+ PageTable = (VOID*)(EFI_PHYSICAL_ADDRESS)(L3[Index].Bits.PageTableBaseAddress << 12);
+ Index = PDE_OFFSET (AddressToMap);
+
+ if (!PageTable[Index].Bits.Present) {
+ PageTable[Index].Bits.ReadWrite = 1;
+ PageTable[Index].Bits.Accessed = 1;
+ PageTable[Index].Bits.Dirty = 1;
+ PageTable[Index].Bits.MustBe1 = 1;
+ PageTable[Index].Bits.PageTableBaseAddress = AddressToMap >> 21;
+ PageTable[Index].Bits.Present = 1;
+ }
+
+ CpuFlushTlb ();
+
+ return EFI_SUCCESS;
+}
+
+STATIC
+EFI_STATUS
+MapSharedInfoPage (
+ IN VOID *PagePtr
+ )
+{
+ xen_add_to_physmap_t Parameters;
+ INTN ReturnCode;
+
+ Parameters.domid = DOMID_SELF;
+ Parameters.space = XENMAPSPACE_shared_info;
+ Parameters.idx = 0;
+ Parameters.gpfn = (UINTN)PagePtr >> EFI_PAGE_SHIFT;
+ ReturnCode = XenHypercallMemoryOp (XENMEM_add_to_physmap, &Parameters);
+ if (ReturnCode != 0) {
+ return EFI_NO_MAPPING;
+ }
+ return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+UnmapXenPage (
+ IN VOID *PagePtr
+ )
+{
+ xen_remove_from_physmap_t Parameters;
+ INTN ReturnCode;
+
+ Parameters.domid = DOMID_SELF;
+ Parameters.gpfn = (UINTN)PagePtr >> EFI_PAGE_SHIFT;
+ ReturnCode = XenHypercallMemoryOp (XENMEM_remove_from_physmap, &Parameters);
+ ASSERT (ReturnCode == 0);
+}
+
+
+STATIC
+UINT64
+GetCpuFreq (
+ IN XEN_VCPU_TIME_INFO *VcpuTime
+ )
+{
+ UINT32 Version;
+ UINT32 TscToSystemMultiplier;
+ INT8 TscShift;
+ UINT64 CpuFreq;
+
+ do {
+ Version = VcpuTime->Version;
+ MemoryFence ();
+ TscToSystemMultiplier = VcpuTime->TscToSystemMultiplier;
+ TscShift = VcpuTime->TscShift;
+ MemoryFence ();
+ } while (((Version & 1) != 0) && (Version != VcpuTime->Version));
+
+ CpuFreq = DivU64x32 (LShiftU64 (1000000000ULL, 32), TscToSystemMultiplier);
+ if (TscShift >= 0) {
+ CpuFreq = RShiftU64 (CpuFreq, TscShift);
+ } else {
+ CpuFreq = LShiftU64 (CpuFreq, -TscShift);
+ }
+ return CpuFreq;
+}
+
+STATIC
+VOID
+XenDelay (
+ IN XEN_VCPU_TIME_INFO *VcpuTimeInfo,
+ IN UINT64 DelayNs
+ )
+{
+ UINT64 Tick;
+ UINT64 CpuFreq;
+ UINT64 Delay;
+ UINT64 DelayTick;
+ UINT64 NewTick;
+ RETURN_STATUS Status;
+
+ Tick = AsmReadTsc ();
+
+ CpuFreq = GetCpuFreq (VcpuTimeInfo);
+ Status = SafeUint64Mult (DelayNs, CpuFreq, &Delay);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "XenDelay (%lu ns): delay too big in relation to CPU freq %lu Hz\n",
+ DelayNs, CpuFreq));
+ ASSERT_EFI_ERROR (Status);
+ CpuDeadLoop ();
+ }
+
+ DelayTick = DivU64x32 (Delay, 1000000000);
+
+ NewTick = Tick + DelayTick;
+
+ //
+ // Check for overflow
+ //
+ if (NewTick < Tick) {
+ //
+ // Overflow, wait for TSC to also overflow
+ //
+ while (AsmReadTsc () >= Tick) {
+ CpuPause ();
+ }
+ }
+
+ while (AsmReadTsc () <= NewTick) {
+ CpuPause ();
+ }
+}
+
+
+/**
+ Calculate the frequency of the Local Apic Timer
+**/
+VOID
+CalibrateLapicTimer (
+ VOID
+ )
+{
+ XEN_SHARED_INFO *SharedInfo;
+ XEN_VCPU_TIME_INFO *VcpuTimeInfo;
+ UINT32 TimerTick, TimerTick2, DiffTimer;
+ UINT64 TscTick, TscTick2;
+ UINT64 Freq;
+ UINT64 Dividend;
+ EFI_STATUS Status;
+
+
+ SharedInfo = (VOID*)((1ULL << mPhysMemAddressWidth) - EFI_PAGE_SIZE);
+ Status = PhysicalAddressIdentityMapping ((EFI_PHYSICAL_ADDRESS)SharedInfo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,
+ "Failed to add page table entry for Xen shared info page: %r\n",
+ Status));
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ Status = MapSharedInfoPage (SharedInfo);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to map Xen's shared info page: %r\n",
+ Status));
+ ASSERT_EFI_ERROR (Status);
+ return;
+ }
+
+ VcpuTimeInfo = &SharedInfo->VcpuInfo[0].Time;
+
+ InitializeApicTimer (1, MAX_UINT32, TRUE, 0);
+ DisableApicTimerInterrupt ();
+
+ TimerTick = GetApicTimerCurrentCount ();
+ TscTick = AsmReadTsc ();
+ XenDelay (VcpuTimeInfo, 1000000ULL);
+ TimerTick2 = GetApicTimerCurrentCount ();
+ TscTick2 = AsmReadTsc ();
+
+
+ DiffTimer = TimerTick - TimerTick2;
+ Status = SafeUint64Mult (GetCpuFreq (VcpuTimeInfo), DiffTimer, &Dividend);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "overflow while calculating APIC frequency\n"));
+ DEBUG ((DEBUG_ERROR, "CPU freq: %lu Hz; APIC timer tick count for 1 ms: %u\n",
+ GetCpuFreq (VcpuTimeInfo), DiffTimer));
+ ASSERT_EFI_ERROR (Status);
+ CpuDeadLoop ();
+ }
+
+ Freq = DivU64x64Remainder (Dividend, TscTick2 - TscTick, NULL);
+ DEBUG ((DEBUG_INFO, "APIC Freq % 8lu Hz\n", Freq));
+
+ ASSERT (Freq <= MAX_UINT32);
+ Status = PcdSet32S (PcdFSBClock, (UINT32)Freq);
+ ASSERT_EFI_ERROR (Status);
+
+ UnmapXenPage (SharedInfo);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/XenPlatformPei.inf b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/XenPlatformPei.inf
index 0aae1f19b4c..1a97234dd22 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/XenPlatformPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPlatformPei/XenPlatformPei.inf
@@ -52,6 +52,7 @@
DebugLib
HobLib
IoLib
+ LocalApicLib
PciLib
ResourcePublicationLib
PeiServicesLib
@@ -59,6 +60,7 @@
MtrrLib
MemEncryptSevLib
PcdLib
+ SafeIntLib
XenHypercallLib
[Pcd]
@@ -66,6 +68,7 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPageTablesBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageBase
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfLockBoxStorageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
@@ -82,6 +85,7 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
+ gEfiMdePkgTokenSpaceGuid.PcdFSBClock
gEfiSecurityPkgTokenSpaceGuid.PcdOptionRomImageVerificationPolicy
gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPvBlkDxe/BlockFront.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPvBlkDxe/BlockFront.c
index 9b8b3eb4391..5d04d3f1f71 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPvBlkDxe/BlockFront.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenPvBlkDxe/BlockFront.c
@@ -155,6 +155,10 @@ XenPvBlockFrontInitialization (
ASSERT (NodeName != NULL);
Dev = AllocateZeroPool (sizeof (XEN_BLOCK_FRONT_DEVICE));
+ if (Dev == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
Dev->Signature = XEN_BLOCK_FRONT_SIGNATURE;
Dev->NodeName = NodeName;
Dev->XenBusIo = XenBusIo;
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm
index 51b60617fda..825df9b60a2 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm
@@ -73,7 +73,7 @@ xenPVHMain:
;
; parameter for Flat32SearchForBfvBase
;
- mov eax, ADDR_OF(fourGigabytes)
+ mov eax, 0 ; ADDR_OF(fourGigabytes)
add eax, edx ; add delta
;
diff --git a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenTimerDxe/XenTimerDxe.c b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenTimerDxe/XenTimerDxe.c
index ad6b9849dd7..cd53c89d3c3 100644
--- a/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenTimerDxe/XenTimerDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/OvmfPkg/XenTimerDxe/XenTimerDxe.c
@@ -61,8 +61,6 @@ TimerInterruptHandler (
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
- SendApicEoi();
-
if (mTimerNotifyFunction != NULL) {
//
// @bug : This does not handle missed timer interrupts
@@ -71,6 +69,9 @@ TimerInterruptHandler (
}
gBS->RestoreTPL (OriginalTPL);
+
+ DisableInterrupts ();
+ SendApicEoi ();
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
index e4ac53fb479..5fe2e865287 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.c
@@ -2,72 +2,14 @@
ACPI Timer implements one instance of Timer Library.
Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiDxe.h>
-#include <Library/TimerLib.h>
-#include <Library/BaseLib.h>
-#include <Library/HobLib.h>
-extern GUID mFrequencyHobGuid;
-
-/**
- The constructor function enables ACPI IO space.
-
- If ACPI I/O space not enabled, this function will enable it.
- It will always return RETURN_SUCCESS.
-
- @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
-
-**/
-RETURN_STATUS
-EFIAPI
-AcpiTimerLibConstructor (
- VOID
- );
-
-/**
- Calculate TSC frequency.
-
- The TSC counting frequency is determined by comparing how far it counts
- during a 101.4 us period as determined by the ACPI timer.
- The ACPI timer is used because it counts at a known frequency.
- The TSC is sampled, followed by waiting 363 counts of the ACPI timer,
- or 101.4 us. The TSC is then sampled again. The difference multiplied by
- 9861 is the TSC frequency. There will be a small error because of the
- overhead of reading the ACPI timer. An attempt is made to determine and
- compensate for this error.
-
- @return The number of TSC counts per second.
-
-**/
-UINT64
-InternalCalculateTscFrequency (
- VOID
- );
-
-//
-// Cached performance counter frequency
-//
-UINT64 mPerformanceCounterFrequency = 0;
-
-/**
- Internal function to retrieves the 64-bit frequency in Hz.
-
- Internal function to retrieves the 64-bit frequency in Hz.
-
- @return The frequency in Hz.
-
-**/
-UINT64
-InternalGetPerformanceCounterFrequency (
- VOID
- )
-{
- return mPerformanceCounterFrequency;
-}
+#include "DxeStandaloneMmAcpiTimerLib.h"
/**
The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency.
@@ -85,22 +27,5 @@ DxeAcpiTimerLibConstructor (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_HOB_GUID_TYPE *GuidHob;
-
- //
- // Enable ACPI IO space.
- //
- AcpiTimerLibConstructor ();
-
- //
- // Initialize PerformanceCounterFrequency
- //
- GuidHob = GetFirstGuidHob (&mFrequencyHobGuid);
- if (GuidHob != NULL) {
- mPerformanceCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
- } else {
- mPerformanceCounterFrequency = InternalCalculateTscFrequency ();
- }
-
- return EFI_SUCCESS;
+ return CommonAcpiTimerLibConstructor ();
}
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
index 81a033aa22d..5568dd3070d 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
@@ -25,6 +25,8 @@
[Sources]
AcpiTimerLib.c
DxeAcpiTimerLib.c
+ DxeStandaloneMmAcpiTimerLib.c
+ DxeStandaloneMmAcpiTimerLib.h
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c
new file mode 100644
index 00000000000..de84d6c4bc1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.c
@@ -0,0 +1,101 @@
+/** @file
+ ACPI Timer implements one instance of Timer Library.
+
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/TimerLib.h>
+#include <Library/BaseLib.h>
+#include <Library/HobLib.h>
+
+extern GUID mFrequencyHobGuid;
+
+/**
+ The constructor function enables ACPI IO space.
+
+ If ACPI I/O space not enabled, this function will enable it.
+ It will always return RETURN_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+RETURN_STATUS
+EFIAPI
+AcpiTimerLibConstructor (
+ VOID
+ );
+
+/**
+ Calculate TSC frequency.
+
+ The TSC counting frequency is determined by comparing how far it counts
+ during a 101.4 us period as determined by the ACPI timer.
+ The ACPI timer is used because it counts at a known frequency.
+ The TSC is sampled, followed by waiting 363 counts of the ACPI timer,
+ or 101.4 us. The TSC is then sampled again. The difference multiplied by
+ 9861 is the TSC frequency. There will be a small error because of the
+ overhead of reading the ACPI timer. An attempt is made to determine and
+ compensate for this error.
+
+ @return The number of TSC counts per second.
+
+**/
+UINT64
+InternalCalculateTscFrequency (
+ VOID
+ );
+
+//
+// Cached performance counter frequency
+//
+UINT64 mPerformanceCounterFrequency = 0;
+
+/**
+ Internal function to retrieves the 64-bit frequency in Hz.
+
+ Internal function to retrieves the 64-bit frequency in Hz.
+
+ @return The frequency in Hz.
+
+**/
+UINT64
+InternalGetPerformanceCounterFrequency (
+ VOID
+ )
+{
+ return mPerformanceCounterFrequency;
+}
+
+/**
+ The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+CommonAcpiTimerLibConstructor (
+ VOID
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+
+ //
+ // Enable ACPI IO space.
+ //
+ AcpiTimerLibConstructor ();
+
+ //
+ // Initialize PerformanceCounterFrequency
+ //
+ GuidHob = GetFirstGuidHob (&mFrequencyHobGuid);
+ if (GuidHob != NULL) {
+ mPerformanceCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
+ } else {
+ mPerformanceCounterFrequency = InternalCalculateTscFrequency ();
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h
new file mode 100644
index 00000000000..981d41e30de
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/DxeStandaloneMmAcpiTimerLib.h
@@ -0,0 +1,24 @@
+/** @file
+ Header file internal to ACPI TimerLib.
+
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#ifndef _DXE_STANDALONE_MM_ACPI_TIMER_LIB_H_
+#define _DXE_STANDALONE_MM_ACPI_TIMER_LIB_H_
+
+/**
+ The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+CommonAcpiTimerLibConstructor (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c
new file mode 100644
index 00000000000..3484eff3bd5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.c
@@ -0,0 +1,31 @@
+/** @file
+ ACPI Timer implements one instance of Timer Library.
+
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include "DxeStandaloneMmAcpiTimerLib.h"
+
+/**
+ The constructor function enables ACPI IO space, and caches PerformanceCounterFrequency.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmAcpiTimerLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return CommonAcpiTimerLibConstructor ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf
new file mode 100644
index 00000000000..2628c744cfe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf
@@ -0,0 +1,53 @@
+## @file
+# Standalone MM ACPI Timer Library
+#
+# Provides basic timer support using the ACPI timer hardware. The performance
+# counter features are provided by the processors time stamp counter.
+#
+# Note: The implementation uses the lower 24-bits of the ACPI timer and
+# is compatible with both 24-bit and 32-bit ACPI timers.
+#
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = StandaloneMmAcpiTimerLib
+ FILE_GUID = C771858D-AF09-4D1A-B2F3-C7F081C3F076
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = TimerLib|MM_CORE_STANDALONE MM_STANDALONE
+ CONSTRUCTOR = StandaloneMmAcpiTimerLibConstructor
+
+[Sources]
+ AcpiTimerLib.c
+ StandaloneMmAcpiTimerLib.c
+ DxeStandaloneMmAcpiTimerLib.c
+ DxeStandaloneMmAcpiTimerLib.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ PcAtChipsetPkg/PcAtChipsetPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ PcdLib
+ PciLib
+ IoLib
+ DebugLib
+ HobLib
+
+[Pcd]
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBusNumber ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciDeviceNumber ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciFunctionNumber ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciEnableRegisterOffset ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoBarEnableMask ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPciBarRegisterOffset ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddress ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiPm1TmrOffset ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdAcpiIoPortBaseAddressMask ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.ci.yaml
index 10d4f746b0b..1e796e8bc87 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.ci.yaml
@@ -2,9 +2,25 @@
# CI configuration for PcAtChipsetPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ ## options defined .pytool/Plugin/LicenseCheck
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
"CompilerPlugin": {
"DscPath": "PcAtChipsetPkg.dsc"
},
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dec b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dec
index e4c30093c48..1fff83651bd 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dec
@@ -6,6 +6,7 @@
#
# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+# Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -41,6 +42,13 @@
# @Prompt Configure HPET to use MSI.
gPcAtChipsetPkgTokenSpaceGuid.PcdHpetMsiEnable|TRUE|BOOLEAN|0x00001000
+ ## Indicates the RTC port registers are in MMIO space, or in I/O space.
+ # Default is I/O space.<BR><BR>
+ # TRUE - RTC port registers are in MMIO space.<BR>
+ # FALSE - RTC port registers are in I/O space.<BR>
+ # @Prompt RTC port registers use MMIO.
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|FALSE|BOOLEAN|0x00000021
+
[PcdsFixedAtBuild, PcdsDynamic, PcdsDynamicEx, PcdsPatchableInModule]
## This PCD specifies the base address of the HPET timer.
# @Prompt HPET base address.
@@ -68,6 +76,14 @@
# @Expression 0x80000001 | gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear < gPcAtChipsetPkgTokenSpaceGuid.PcdMinimalValidYear + 100
gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear|2097|UINT16|0x0000000E
+ ## Specifies RTC Index Register address in MMIO space.
+ # @Prompt RTC Index Register address
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64|0x0|UINT64|0x00000022
+
+ ## Specifies RTC Target Register address in MMIO space.
+ # @Prompt RTC Target Register address
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64|0x0|UINT64|0x00000023
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Defines the ACPI register set base address.
# The invalid 0xFFFF is as its default value. It must be configured to the real value.
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dsc b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dsc
index 466b15a7ccd..b580c93492e 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcAtChipsetPkg.dsc
@@ -1,7 +1,8 @@
## @file
# PC/AT Chipset Package
#
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -17,6 +18,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
@@ -39,6 +42,7 @@
ResetSystemLib|PcAtChipsetPkg/Library/ResetSystemLib/ResetSystemLib.inf
IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf
LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
@@ -51,6 +55,7 @@
PcAtChipsetPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
PcAtChipsetPkg/Library/AcpiTimerLib/DxeAcpiTimerLib.inf
PcAtChipsetPkg/Library/AcpiTimerLib/PeiAcpiTimerLib.inf
+ PcAtChipsetPkg/Library/AcpiTimerLib/StandaloneMmAcpiTimerLib.inf
PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
[BuildOptions]
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
index 7c1f2bd8568..6620d811f51 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
@@ -3,6 +3,7 @@
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,6 +11,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "PcRtc.h"
+extern UINTN mRtcIndexRegister;
+extern UINTN mRtcTargetRegister;
+
//
// Days of month.
//
@@ -54,38 +58,132 @@ IsWithinOneDay (
);
/**
+ Read RTC content through its registers using IO access.
+
+ @param Address Address offset of RTC. It is recommended to use
+ macros such as RTC_ADDRESS_SECONDS.
+
+ @return The data of UINT8 type read from RTC.
+**/
+STATIC
+UINT8
+IoRtcRead (
+ IN UINTN Address
+ )
+{
+ IoWrite8 (
+ PcdGet8 (PcdRtcIndexRegister),
+ (UINT8)(Address | (UINT8)(IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80))
+ );
+ return IoRead8 (PcdGet8 (PcdRtcTargetRegister));
+}
+
+/**
+ Write RTC through its registers using IO access.
+
+ @param Address Address offset of RTC. It is recommended to use
+ macros such as RTC_ADDRESS_SECONDS.
+ @param Data The content you want to write into RTC.
+
+**/
+STATIC
+VOID
+IoRtcWrite (
+ IN UINTN Address,
+ IN UINT8 Data
+ )
+{
+ IoWrite8 (
+ PcdGet8 (PcdRtcIndexRegister),
+ (UINT8)(Address | (UINT8)(IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80))
+ );
+ IoWrite8 (PcdGet8 (PcdRtcTargetRegister), Data);
+}
+
+/**
+ Read RTC content through its registers using MMIO access.
+
+ @param Address Address offset of RTC. It is recommended to use
+ macros such as RTC_ADDRESS_SECONDS.
+
+ @return The data of UINT8 type read from RTC.
+**/
+STATIC
+UINT8
+MmioRtcRead (
+ IN UINTN Address
+ )
+{
+ MmioWrite8 (
+ mRtcIndexRegister,
+ (UINT8)(Address | (UINT8)(MmioRead8 (mRtcIndexRegister) & 0x80))
+ );
+ return MmioRead8 (mRtcTargetRegister);
+}
+
+/**
+ Write RTC through its registers using MMIO access.
+
+ @param Address Address offset of RTC. It is recommended to use
+ macros such as RTC_ADDRESS_SECONDS.
+ @param Data The content you want to write into RTC.
+
+**/
+STATIC
+VOID
+MmioRtcWrite (
+ IN UINTN Address,
+ IN UINT8 Data
+ )
+{
+ MmioWrite8 (
+ mRtcIndexRegister,
+ (UINT8)(Address | (UINT8)(MmioRead8 (mRtcIndexRegister) & 0x80))
+ );
+ MmioWrite8 (mRtcTargetRegister, Data);
+}
+
+/**
Read RTC content through its registers.
- @param Address Address offset of RTC. It is recommended to use macros such as
- RTC_ADDRESS_SECONDS.
+ @param Address Address offset of RTC. It is recommended to use
+ macros such as RTC_ADDRESS_SECONDS.
@return The data of UINT8 type read from RTC.
**/
+STATIC
UINT8
RtcRead (
- IN UINT8 Address
+ IN UINTN Address
)
{
- IoWrite8 (PcdGet8 (PcdRtcIndexRegister), (UINT8) (Address | (UINT8) (IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80)));
- return IoRead8 (PcdGet8 (PcdRtcTargetRegister));
+ if (FeaturePcdGet (PcdRtcUseMmio)) {
+ return MmioRtcRead (Address);
+ }
+
+ return IoRtcRead (Address);
}
/**
Write RTC through its registers.
- @param Address Address offset of RTC. It is recommended to use macros such as
- RTC_ADDRESS_SECONDS.
- @param Data The content you want to write into RTC.
+ @param Address Address offset of RTC. It is recommended to use
+ macros such as RTC_ADDRESS_SECONDS.
+ @param Data The content you want to write into RTC.
**/
+STATIC
VOID
RtcWrite (
- IN UINT8 Address,
+ IN UINTN Address,
IN UINT8 Data
)
{
- IoWrite8 (PcdGet8 (PcdRtcIndexRegister), (UINT8) (Address | (UINT8) (IoRead8 (PcdGet8 (PcdRtcIndexRegister)) & 0x80)));
- IoWrite8 (PcdGet8 (PcdRtcTargetRegister), Data);
+ if (FeaturePcdGet (PcdRtcUseMmio)) {
+ MmioRtcWrite (Address, Data);
+ } else {
+ IoRtcWrite (Address, Data);
+ }
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
index f06c4227ac8..f9b1606efba 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
@@ -2,16 +2,23 @@
Provides Set/Get time operations.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
+#include <Library/DxeServicesTableLib.h>
#include "PcRtc.h"
PC_RTC_MODULE_GLOBALS mModuleGlobal;
EFI_HANDLE mHandle = NULL;
+STATIC EFI_EVENT mVirtualAddrChangeEvent;
+
+UINTN mRtcIndexRegister;
+UINTN mRtcTargetRegister;
+
/**
Returns the current time and date information, and the time-keeping capabilities
of the hardware platform.
@@ -106,6 +113,30 @@ PcRtcEfiSetWakeupTime (
}
/**
+ Fixup internal data so that EFI can be called in virtual mode.
+ Call the passed in Child Notify event and convert any pointers in
+ lib to virtual mode.
+
+ @param[in] Event The Event that is being processed
+ @param[in] Context Event Context
+**/
+VOID
+EFIAPI
+LibRtcVirtualNotifyEvent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ // Only needed if you are going to support the OS calling RTC functions in
+ // virtual mode. You will need to call EfiConvertPointer (). To convert any
+ // stored physical addresses to virtual address. After the OS transitions to
+ // calling in virtual mode, all future runtime calls will be made in virtual
+ // mode.
+ EfiConvertPointer (0x0, (VOID**)&mRtcIndexRegister);
+ EfiConvertPointer (0x0, (VOID**)&mRtcTargetRegister);
+}
+
+/**
The user Entry Point for PcRTC module.
This is the entry point for PcRTC module. It installs the UEFI runtime service
@@ -131,6 +162,11 @@ InitializePcRtc (
EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK);
mModuleGlobal.CenturyRtcAddress = GetCenturyRtcAddress ();
+ if (FeaturePcdGet (PcdRtcUseMmio)) {
+ mRtcIndexRegister = (UINTN)PcdGet64 (PcdRtcIndexRegister64);
+ mRtcTargetRegister = (UINTN)PcdGet64 (PcdRtcTargetRegister64);
+ }
+
Status = PcRtcInit (&mModuleGlobal);
ASSERT_EFI_ERROR (Status);
@@ -165,7 +201,23 @@ InitializePcRtc (
NULL,
NULL
);
- ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ if (FeaturePcdGet (PcdRtcUseMmio)) {
+ // Register for the virtual address change event
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ LibRtcVirtualNotifyEvent,
+ NULL,
+ &gEfiEventVirtualAddressChangeGuid,
+ &mVirtualAddrChangeEvent
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
index ddd6020d2fb..76e87506ed7 100644
--- a/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
@@ -6,6 +6,7 @@
#
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+# Copyright (c) 2018 - 2020, ARM Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -61,6 +62,11 @@
## SOMETIMES_CONSUMES ## SystemTable
gEfiAcpiTableGuid
+ gEfiEventVirtualAddressChangeGuid
+
+[FeaturePcd]
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio ## CONSUMES
+
[FixedPcd]
gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterA ## CONSUMES
gPcAtChipsetPkgTokenSpaceGuid.PcdInitialValueRtcRegisterB ## CONSUMES
@@ -72,6 +78,8 @@
gPcAtChipsetPkgTokenSpaceGuid.PcdMaximalValidYear ## CONSUMES
gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister ## CONSUMES
gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcIndexRegister64 ## CONSUMES
+ gPcAtChipsetPkgTokenSpaceGuid.PcdRtcTargetRegister64 ## CONSUMES
[Depex]
gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/ReadMe.rst b/src/VBox/Devices/EFI/Firmware/ReadMe.rst
index 06fe19d74c3..3cfde0831fb 100644
--- a/src/VBox/Devices/EFI/Firmware/ReadMe.rst
+++ b/src/VBox/Devices/EFI/Firmware/ReadMe.rst
@@ -28,6 +28,8 @@ Microsoft Windows VS2019
============================= ================= ============= ============= ==============
EmulatorPkg_Win_VS2019_ | IA32 |em32d| |em32r| |em32n|
| | X64 |em64d| |em64r| |em64n|
+| | IA32 FULL |em32fd| |em32fr| |em32fn|
+| | X64 FULL |em64fd| |em64fr| |em64fn|
OvmfPkg_Win_VS2019_ | IA32 |op32d| |op32r| |op32n|
| | X64 |op64d| |op64r| |op64n|
| | IA32 X64 |op3264d| |op3264r| |op3264n|
@@ -44,6 +46,8 @@ ArmVirtPkg_Ubuntu_GCC5_ | AARCH64 |avAArch64du| |avAArch64ru| |avA
| | ARM |avArmdu| |avArmru| |avArmnu|
EmulatorPkg_Ubuntu_GCC5_ | IA32 |em32du| |em32ru| |em32nu|
| | X64 |em64du| |em64ru| |em64nu|
+| | IA32 FULL |em32fdu| |em32fru| |em32fnu|
+| | X64 FULL |em64fdu| |em64fru| |em64fnu|
OvmfPkg_Ubuntu_GCC5_ | IA32 |op32du| |op32ru| |op32nu|
| | X64 |op64du| |op64ru| |op64nu|
| | IA32 X64 |op3264du| |op3264ru| |op3264nu|
@@ -69,16 +73,27 @@ The majority of the content in the EDK II open source project uses a
source project contains the following components that are covered by additional
licenses:
-- `BaseTools/Source/C/BrotliCompress/brotli <https://github.com/google/brotli/blob/master/LICENSE>`__
-- `MdeModulePkg/Library/BrotliCustomDecompressLib/brotli <https://github.com/google/brotli/blob/master/LICENSE>`__
- `BaseTools/Source/C/LzmaCompress <BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt>`__
-- `MdeModulePkg/Library/LzmaCustomDecompressLib <MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt>`__
-- `IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/Sdk <IntelFrameworkModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt>`__
- `BaseTools/Source/C/VfrCompile/Pccts <BaseTools/Source/C/VfrCompile/Pccts/RIGHTS>`__
-- `MdeModulePkg/Universal/RegularExpressionDxe/oniguruma <https://github.com/kkos/oniguruma/blob/master/README.md>`__
+- `CryptoPkg\Library\BaseCryptLib\SysCall\inet_pton.c <CryptoPkg\Library\BaseCryptLib\SysCall\inet_pton.c>`__
+- `CryptoPkg\Library\Include\crypto\dso_conf.h <https://github.com/openssl/openssl/blob/e2e09d9fba1187f8d6aafaa34d4172f56f1ffb72/LICENSE>`__
+- `CryptoPkg\Library\Include\openssl\opensslconf.h <https://github.com/openssl/openssl/blob/e2e09d9fba1187f8d6aafaa34d4172f56f1ffb72/LICENSE>`__
+- `EmbeddedPkg/Library/FdtLib <EmbeddedPkg/Library/FdtLib/fdt.c>`__. (EDK II uses BSD License)
+- `EmbeddedPkg/Include/fdt.h <EmbeddedPkg/Include/fdt.h>`__. (EDK II uses BSD Licence)
+- `EmbeddedPkg/Include/libfdt.h <EmbeddedPkg/Include/libfdt.h>`__. (EDK II uses BSD License)
+- `MdeModulePkg/Library/LzmaCustomDecompressLib <MdeModulePkg/Library/LzmaCustomDecompressLib/LZMA-SDK-README.txt>`__
- `OvmfPkg <OvmfPkg/License.txt>`__
-- `CryptoPkg/Library/OpensslLib/openssl <https://github.com/openssl/openssl/blob/50eaac9f3337667259de725451f201e784599687/LICENSE>`__
+
+The EDK II open source project uses content from upstream projects as git submodules
+that are covered by additional licenses.
+
- `ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 <https://github.com/ucb-bar/berkeley-softfloat-3/blob/b64af41c3276f97f0e181920400ee056b9c88037/COPYING.txt>`__
+- `BaseTools/Source/C/BrotliCompress/brotli <https://github.com/google/brotli/blob/666c3280cc11dc433c303d79a83d4ffbdd12cc8d/LICENSE>`__
+- `CryptoPkg/Library/OpensslLib/openssl <https://github.com/openssl/openssl/blob/e2e09d9fba1187f8d6aafaa34d4172f56f1ffb72/LICENSE>`__
+- `MdeModulePkg/Library/BrotliCustomDecompressLib/brotli <https://github.com/google/brotli/blob/666c3280cc11dc433c303d79a83d4ffbdd12cc8d/LICENSE>`__
+- `MdeModulePkg/Universal/RegularExpressionDxe/oniguruma <https://github.com/kkos/oniguruma/blob/abfc8ff81df4067f309032467785e06975678f0d/COPYING>`__
+- `UnitTestFrameworkPkg/Library/CmockaLib/cmocka <https://github.com/tianocore/edk2-cmocka/blob/f5e2cd77c88d9f792562888d2b70c5a396bfbf7a/COPYING>`__
+- `RedfishPkg/Library/JsonLib/jansson <https://github.com/akheron/jansson/blob/2882ead5bb90cf12a01b07b2c2361e24960fae02/LICENSE>`__
The EDK II Project is composed of packages. The maintainers for each package
are listed in `Maintainers.txt <Maintainers.txt>`__.
@@ -309,6 +324,13 @@ use.
.. |em32n| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_NOOPT
.. |em32nu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_NOOPT
+.. |em32fd| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_DEBUG
+.. |em32fdu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_DEBUG
+.. |em32fr| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_RELEASE
+.. |em32fru| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_RELEASE
+.. |em32fn| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_NOOPT
+.. |em32fnu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_IA32_FULL_NOOPT
+
.. |em64d| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_DEBUG
.. |em64du| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_DEBUG
.. |em64r| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_RELEASE
@@ -316,6 +338,13 @@ use.
.. |em64n| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_NOOPT
.. |em64nu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_NOOPT
+.. |em64fd| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_DEBUG
+.. |em64fdu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_DEBUG
+.. |em64fr| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_RELEASE
+.. |em64fru| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_RELEASE
+.. |em64fn| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Windows_VS2019_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_NOOPT
+.. |em64fnu| image:: https://dev.azure.com/tianocore/edk2-ci/_apis/build/status/PlatformCI_EmulatorPkg_Ubuntu_GCC5_CI?branchName=master&jobName=Platform_CI&configuration=Platform_CI%20EmulatorPkg_X64_FULL_NOOPT
+
.. OvmfPkg
.. |TCBZ_2661| image:: https://img.shields.io/bugzilla/2661?baseUrl=https%3A%2F%2Fbugzilla.tianocore.org
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg
new file mode 100644
index 00000000000..76269b787bd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Documents/Media/RedfishDriverStack.svg
@@ -0,0 +1,965 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<!-- Generated by Microsoft Visio, SVG Export RedfishDriverStack.svg Page-1 -->
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events"
+ xmlns:v="http://schemas.microsoft.com/visio/2003/SVGExtensions/" width="14in" height="8.5in" viewBox="0 0 1008 612"
+ xml:space="preserve" color-interpolation-filters="sRGB" class="st63">
+ <title>EDKII Redfish Driver Stack Diagrams</title>
+ <v:documentProperties v:langID="1033" v:viewMarkup="false">
+ <v:userDefs>
+ <v:ud v:nameU="msvNoAutoConnect" v:val="VT0(1):26"/>
+ </v:userDefs>
+ </v:documentProperties>
+
+ <style type="text/css">
+ <![CDATA[
+ .st1 {fill:#ffffff;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st2 {stroke:#7f7f7f;stroke-linecap:round;stroke-linejoin:round;stroke-width:4.5}
+ .st3 {fill:#a5a5a5;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st4 {fill:#000000;font-family:Calibri;font-size:1.16666em;font-weight:bold}
+ .st5 {font-size:0.714294em}
+ .st6 {fill:#0070c0;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st7 {fill:#ffffff;font-family:Calibri;font-size:1.16666em;font-weight:bold}
+ .st8 {fill:#ffffff;font-family:Calibri;font-size:1.08334em;font-weight:bold}
+ .st9 {font-size:1em}
+ .st10 {font-size:0.769226em}
+ .st11 {fill:#339966;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st12 {fill:#ffffff;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st13 {fill:#ffffff;stroke:#0070c0;stroke-linecap:round;stroke-linejoin:round;stroke-width:3}
+ .st14 {fill:#000000;font-family:Calibri;font-size:0.833336em;font-weight:bold}
+ .st15 {marker-end:url(#mrkr4-79);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st16 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.36964980544747}
+ .st17 {marker-end:url(#mrkr4-79);stroke:#000000;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st18 {marker-end:url(#mrkr2-98);marker-start:url(#mrkr2-96);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:7.5}
+ .st19 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.74850299401198}
+ .st20 {marker-end:url(#mrkr2-112);marker-start:url(#mrkr2-110);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:7.5}
+ .st21 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.80645161290323}
+ .st22 {marker-end:url(#mrkr4-118);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st23 {fill:#000000;fill-opacity:1;stroke:#000000;stroke-opacity:1;stroke-width:0.42986425339367}
+ .st24 {marker-end:url(#mrkr4-124);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st25 {fill:#ff1a1a;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st26 {fill:#ffffff;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st27 {fill:none;stroke:#000000;stroke-dasharray:4.5,4.5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st28 {fill:none;stroke:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st29 {fill:#000000;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st30 {marker-end:url(#mrkr2-151);marker-start:url(#mrkr2-149);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:8}
+ .st31 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.76045627376426}
+ .st32 {fill:#000000;font-family:Arial;font-size:1.33333em;font-style:italic;font-weight:bold}
+ .st33 {fill:#ffffff;stroke:#7f7f7f;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.24}
+ .st34 {fill:#a5a5a5;font-family:Arial;font-size:0.916672em}
+ .st35 {fill:#f2dcda;stroke:#a5a5a5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st36 {fill:#a5a5a5;font-family:Calibri;font-size:1.00001em;font-weight:bold}
+ .st37 {fill:none;stroke:#a5a5a5;stroke-dasharray:4.5,4.5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st38 {fill:#000000;font-family:Arial;font-size:0.666664em}
+ .st39 {font-family:Microsoft JhengHei;font-size:1em}
+ .st40 {fill:#dbeef3;stroke:#d8d8d8;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st41 {fill:#000000;font-family:Arial;font-size:1.66667em;font-weight:bold}
+ .st42 {fill:none;stroke:#000000;stroke-dasharray:2.25,2.25;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st43 {visibility:visible}
+ .st44 {fill:none;filter:url(#filter_3.3333334922791);stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:0.4}
+ .st45 {fill:none;stroke:#bfbfbf;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st46 {fill:none;stroke:#a5a5a5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st47 {fill:#ffffff;stroke:#a5a5a5;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5}
+ .st48 {marker-end:url(#mrkr4-118);stroke:#000000;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st49 {marker-end:url(#mrkr4-251);stroke:#a5a5a5;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st50 {fill:#a5a5a5;fill-opacity:1;stroke:#a5a5a5;stroke-opacity:1;stroke-width:0.42986425339367}
+ .st51 {marker-end:url(#mrkr4-257);stroke:#bfbfbf;stroke-dasharray:5.7,5.7;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st52 {fill:#bfbfbf;fill-opacity:1;stroke:#bfbfbf;stroke-opacity:1;stroke-width:0.42986425339367}
+ .st53 {marker-end:url(#mrkr4-265);marker-start:url(#mrkr2-149);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:8}
+ .st54 {marker-end:url(#mrkr2-295);marker-start:url(#mrkr2-293);stroke:#fbd3d0;stroke-linecap:round;stroke-linejoin:round;stroke-width:4.25}
+ .st55 {fill:#fbd3d0;fill-opacity:1;stroke:#fbd3d0;stroke-opacity:1;stroke-width:0.62776957163959}
+ .st56 {marker-end:url(#mrkr2-313);stroke:#d8d8d8;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.9}
+ .st57 {fill:#d8d8d8;fill-opacity:1;stroke:#d8d8d8;stroke-opacity:1;stroke-width:0.36964980544747}
+ .st58 {marker-end:url(#mrkr4-319);stroke:#d8d8d8;stroke-linecap:round;stroke-linejoin:round;stroke-width:0.75}
+ .st59 {fill:#d8d8d8;fill-opacity:1;stroke:#d8d8d8;stroke-opacity:1;stroke-width:0.22935779816514}
+ .st60 {stroke:#000000;stroke-dasharray:0,9;stroke-linecap:round;stroke-linejoin:round;stroke-width:3}
+ .st61 {fill:#000000;font-family:Calibri;font-size:0.833336em}
+ .st62 {fill:#000000;font-family:Arial;font-size:0.916672em;font-weight:bold}
+ .st63 {fill:none;fill-rule:evenodd;font-size:12px;overflow:visible;stroke-linecap:square;stroke-miterlimit:3}
+ ]]>
+ </style>
+
+ <defs id="Markers">
+ <g id="lend4">
+ <path d="M 2 1 L 0 0 L 2 -1 L 2 1 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr4-79" class="st16" v:arrowType="4" v:arrowSize="3" v:setback="5.22105" refX="-5.2210526315789"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.7052631578947,-2.7052631578947) "/>
+ </marker>
+ <g id="lend2">
+ <path d="M 1 1 L 0 0 L 1 -1 L 1 1 " style="stroke:none"/>
+ </g>
+ <marker id="mrkr2-96" class="st19" v:arrowType="2" v:arrowSize="2" v:setback="1.288" refX="1.288" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.336) "/>
+ </marker>
+ <marker id="mrkr2-98" class="st19" v:arrowType="2" v:arrowSize="2" v:setback="1.288" refX="-1.288" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.336,-1.336) "/>
+ </marker>
+ <marker id="mrkr2-110" class="st21" v:arrowType="2" v:arrowSize="1" v:setback="1.192" refX="1.192" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.24) "/>
+ </marker>
+ <marker id="mrkr2-112" class="st21" v:arrowType="2" v:arrowSize="1" v:setback="1.192" refX="-1.192" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.24,-1.24) "/>
+ </marker>
+ <marker id="mrkr4-118" class="st23" v:arrowType="4" v:arrowSize="2" v:setback="4.46316" refX="-4.4631578947368"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr4-124" class="st23" v:arrowType="4" v:arrowSize="2" v:setback="4.65263" refX="-4.6526315789474"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr2-149" class="st31" v:arrowType="2" v:arrowSize="2" v:setback="1.27" refX="1.27" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.315) "/>
+ </marker>
+ <marker id="mrkr2-151" class="st31" v:arrowType="2" v:arrowSize="2" v:setback="1.27" refX="-1.27" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.315,-1.315) "/>
+ </marker>
+ <marker id="mrkr4-251" class="st50" v:arrowType="4" v:arrowSize="2" v:setback="4.46316" refX="-4.4631578947368"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr4-257" class="st52" v:arrowType="4" v:arrowSize="2" v:setback="4.46316" refX="-4.4631578947368"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-2.3263157894737,-2.3263157894737) "/>
+ </marker>
+ <marker id="mrkr4-265" class="st31" v:arrowType="4" v:arrowSize="2" v:setback="2.585" refX="-2.585" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-1.315,-1.315) "/>
+ </marker>
+ <marker id="mrkr2-293" class="st55" v:arrowType="2" v:arrowSize="2" v:setback="1.50824" refX="1.5082352941176"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(1.5929411764706) "/>
+ </marker>
+ <marker id="mrkr2-295" class="st55" v:arrowType="2" v:arrowSize="2" v:setback="1.59294" refX="-1.5929411764706"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-1.5929411764706,-1.5929411764706) "/>
+ </marker>
+ <marker id="mrkr2-313" class="st57" v:arrowType="2" v:arrowSize="3" v:setback="2.51579" refX="-2.5157894736842"
+ orient="auto" markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend2" transform="scale(-2.7052631578947,-2.7052631578947) "/>
+ </marker>
+ <marker id="mrkr4-319" class="st59" v:arrowType="4" v:arrowSize="2" v:setback="8.72" refX="-8.72" orient="auto"
+ markerUnits="strokeWidth" overflow="visible">
+ <use xlink:href="#lend4" transform="scale(-4.36,-4.36) "/>
+ </marker>
+ </defs>
+ <defs id="Filters">
+ <filter id="filter_3.3333334922791">
+ <feGaussianBlur stdDeviation="3.3333334922791"/>
+ </filter>
+ </defs>
+ <g v:mID="4" v:index="1" v:groupContext="backgroundPage">
+ <v:userDefs>
+ <v:ud v:nameU="msvVisioCreated" v:prompt="" v:val="VT0(0):26"/>
+ </v:userDefs>
+ <title>VBackground-1</title>
+ <v:pageProperties width="14" height="8.5" v:drawingScale="1" v:pageScale="1" v:drawingUnits="19" v:shadowOffsetX="9"
+ v:shadowOffsetY="-9"/>
+ <g id="shape1-1" v:mID="1" v:groupContext="shape">
+ <title>Solid</title>
+ <v:userDefs>
+ <v:ud v:nameU="Background" v:val="VT0(0):26"/>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ <v:ud v:nameU="msvShapeCategories" v:prompt="" v:val="VT4(DoNotContain)"/>
+ <v:ud v:nameU="msvVisioCreated" v:prompt="" v:val="VT0(0):26"/>
+ </v:userDefs>
+ <rect x="0" y="0" width="1008" height="612" class="st1"/>
+ </g>
+ </g>
+ <g v:mID="0" v:index="2" v:groupContext="foregroundPage">
+ <title>Page-1</title>
+ <v:pageProperties v:drawingScale="1" v:pageScale="1" v:drawingUnits="19" v:shadowOffsetX="9" v:shadowOffsetY="-9"/>
+ <v:layer v:name="Connector" v:index="0"/>
+ <g id="shape1-3" v:mID="1" v:groupContext="shape" transform="translate(45,-342)">
+ <title>Sheet.1</title>
+ <path d="M0 612 L751.5 612" class="st2"/>
+ </g>
+ <g id="shape2-6" v:mID="2" v:groupContext="shape" transform="translate(211.5,-279)">
+ <title>Sheet.2</title>
+ <desc>RedfishLib (libredfish)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="594" width="135" height="36"/>
+ <rect x="0" y="576" width="135" height="36" class="st3"/>
+ <text x="37.36" y="591" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>RedfishLib<v:lf/><tspan
+ x="44.78" dy="1.5em" class="st5">(</tspan><tspan class="st5">libredfish</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape3-12" v:mID="3" v:groupContext="shape" transform="translate(616.5,-283.5)">
+ <title>Sheet.3</title>
+ <desc>JsonLib (jansson)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st3"/>
+ <text x="55.44" y="591" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>JsonLib<v:lf/><tspan
+ x="57.6" dy="1.5em" class="st5">(</tspan><tspan class="st5">jansson</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape4-18" v:mID="4" v:groupContext="shape" transform="translate(211.5,-216)">
+ <title>Sheet.4</title>
+ <desc>EFI Redfish Discover (UEFI Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="594" width="135" height="36"/>
+ <rect x="0" y="576" width="135" height="36" class="st6"/>
+ <text x="9.2" y="591" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EFI Redfish Discover<v:lf/><tspan
+ x="26.49" dy="1.5em" class="st5">(</tspan><tspan class="st5">UEFI Driver Model</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape5-24" v:mID="5" v:groupContext="shape" transform="translate(211.5,-153)">
+ <title>Sheet.5</title>
+ <desc>EFI REST EX (UEFI Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="594" width="135" height="36"/>
+ <rect x="0" y="576" width="135" height="36" class="st6"/>
+ <text x="34.44" y="591" class="st7" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EFI REST EX<v:lf/><tspan
+ x="26.49" dy="1.5em" class="st5">(</tspan><tspan class="st5">UEFI Driver Model</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape6-30" v:mID="6" v:groupContext="shape" transform="translate(409.5,-279)">
+ <title>Sheet.6</title>
+ <desc>EFI REST JSON to C Structure (DXE Driver)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="589.5" width="153" height="45"/>
+ <rect x="0" y="567" width="153" height="45" class="st6"/>
+ <text x="26.52" y="579.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EFI REST JSON to C <v:newlineChar/><tspan
+ x="51.33" dy="1.058em" class="st9">Structure<v:lf/></tspan><tspan x="51.09" dy="1.25em" class="st10">(</tspan><tspan
+ class="st10">DXE Driver</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape7-37" v:mID="7" v:groupContext="shape" transform="translate(409.5,-225)">
+ <title>Sheet.7</title>
+ <desc>EDKII Redfish Credential (DXE Driver)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st6"/>
+ <text x="11.19" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Redfish Credential<v:lf/><tspan
+ x="51.09" dy="1.3em" class="st10">(</tspan><tspan class="st10">DXE Driver</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape8-43" v:mID="8" v:groupContext="shape" transform="translate(409.5,-171)">
+ <title>Sheet.8</title>
+ <desc>EDKII Platform Content Coding Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st11"/>
+ <text x="13.91" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Platform Content <tspan
+ x="37.7" dy="1em" class="st9">Coding Library</tspan></text> </g>
+ <g id="shape9-47" v:mID="9" v:groupContext="shape" transform="translate(409.5,-117)">
+ <title>Sheet.9</title>
+ <desc>EDKII Network Stacks (UEFI Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st6"/>
+ <text x="18.73" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Network Stacks<v:lf/><tspan
+ x="35.49" dy="1.3em" class="st10">(</tspan><tspan class="st10">UEFI Driver Model</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape10-53" v:mID="10" v:groupContext="shape" transform="translate(409.5,-54)">
+ <title>Sheet.10</title>
+ <desc>EDKII Redfish Host Interface (DXE Driver)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="589.5" width="153" height="45"/>
+ <rect x="0" y="567" width="153" height="45" class="st6"/>
+ <text x="26.68" y="579.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII Redfish Host <tspan
+ x="52.19" dy="1em" class="st9">Interface<v:lf/></tspan><tspan x="51.09" dy="1.3em" class="st10">(</tspan><tspan
+ class="st10">DXE Driver</tspan><tspan class="st10">)</tspan></text> </g>
+ <g id="shape11-60" v:mID="11" v:groupContext="shape" transform="translate(211.5,-94.5)">
+ <title>Sheet.11</title>
+ <desc>SMBIOS Type 42</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="598.5" width="135" height="27"/>
+ <rect x="0" y="585" width="135" height="27" class="st12"/>
+ <text x="19.92" y="602.7" class="st4" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>SMBIOS Type 42</text> </g>
+ <g id="shape12-63" v:mID="12" v:groupContext="shape" transform="translate(616.5,-72)">
+ <title>Sheet.12</title>
+ <desc>RedfishPlatformConfig.efi</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="598.5" width="153" height="27"/>
+ <rect x="0" y="585" width="153" height="27" class="st13"/>
+ <text x="22.93" y="601.5" class="st14" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>RedfishPlatformConfig.efi</text> </g>
+ <g id="shape13-66" v:mID="13" v:groupContext="shape" transform="translate(616.5,-225)">
+ <title>Sheet.13</title>
+ <desc>Platform Redfish Credential Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st11"/>
+ <text x="31.21" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>Platform Redfish <tspan
+ x="28.36" dy="1em" class="st9">Credential Library</tspan></text> </g>
+ <g id="shape14-70" v:mID="14" v:groupContext="shape" transform="translate(618.25,-162)">
+ <title>Sheet.14</title>
+ <desc>Platform Redfish Host Interface Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76.5" cy="594" width="153" height="36"/>
+ <rect x="0" y="576" width="153" height="36" class="st11"/>
+ <text x="17.3" y="590.75" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>Platform Redfish Host <tspan
+ x="31.97" dy="1em" class="st9">Interface Library</tspan></text> </g>
+ <g id="shape20-74" v:mID="20" v:groupContext="shape" transform="translate(108.912,1066.03) rotate(-150.255)">
+ <title>Sheet.20</title>
+ <path d="M0 605.85 C5.2 601.6 11.37 602.58 17.02 603.9 C34.96 608.09 47.6 615.63 63.3 610.33 L63.63 610.17"
+ class="st15"/>
+ </g>
+ <g id="shape26-80" v:mID="26" v:groupContext="shape" transform="translate(798.806,378) rotate(90)">
+ <title>Sheet.26</title>
+ <path d="M0 587.31 C27.48 618.4 91.67 620.3 119.28 595.08 L119.51 594.81" class="st15"/>
+ </g>
+ <g id="shape27-85" v:mID="27" v:groupContext="shape" transform="translate(616.5,980.172) rotate(180)">
+ <title>Sheet.27</title>
+ <path d="M0 611.17 C8.24 606.04 18.13 605.86 27 607.8 C32.73 609.05 38.03 611.18 43.74 611.86 L44.1 611.83"
+ class="st17"/>
+ </g>
+ <g id="shape34-90" v:mID="34" v:groupContext="shape" transform="translate(958.5,315) rotate(90)">
+ <title>Sheet.34</title>
+ <path d="M4.28 603.34 L4.44 603.02 C6.15 598.55 7.91 593.52 10.26 589.58 C10.52 589.15 10.79 588.72 11.06 588.3 C24.98
+ 566.86 47.13 561.26 67.61 562.5 C93.1 564.05 116.01 576.2 123.87 602.21 L123.94 602.56" class="st18"/>
+ </g>
+ <g id="shape35-99" v:mID="35" v:groupContext="shape" transform="translate(868.595,10.4444) rotate(59.7436)">
+ <title>Sheet.35</title>
+ <path d="M0 604.43 C17.43 596.28 35.82 595.77 52.17 599.33 C75.61 604.44 94.87 617.9 116.02 609.38 L116.34 609.21"
+ class="st15"/>
+ </g>
+ <g id="shape42-104" v:mID="42" v:groupContext="shape" transform="translate(511.956,-120.094) rotate(15.9454)">
+ <title>Sheet.42</title>
+ <path d="M8.92 601.65 L9.28 601.63 C11.78 602.35 14.16 603.61 16.51 604.78 C30.56 611.79 43.18 615.49 57.81 607.46 L58.11
+ 607.26" class="st20"/>
+ </g>
+ <g id="shape43-113" v:mID="43" v:groupContext="shape" transform="translate(662.85,-296.1) rotate(9.46232)">
+ <title>Sheet.43</title>
+ <path d="M0 610.4 C16.69 599.74 30.24 612.49 46.06 612.08 L46.42 612.01" class="st22"/>
+ </g>
+ <g id="shape44-119" v:mID="44" v:groupContext="shape" transform="translate(891,396) rotate(90)">
+ <title>Sheet.44</title>
+ <path d="M0 612 L18.16 612" class="st24"/>
+ </g>
+ <g id="group45-125" transform="translate(846,-319.5)" v:mID="45" v:groupContext="group">
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <title>Can</title>
+ <desc>Redfish Service</desc>
+ <g id="shape46-126" v:mID="46" v:groupContext="shape">
+ <title>Sheet.46</title>
+ <v:userDefs>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.125):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT0(1):26"/>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.15625):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT5(#ff1a1a)"/>
+ </v:userDefs>
+ <path d="M0 600.75 A29.25 11.25 -180 1 0 58.5 600.75 L58.5 560.25 L0 560.25 L0 600.75 Z" class="st25"/>
+ </g>
+ <g id="shape45-128" v:mID="45" v:groupContext="groupContent">
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="2"/>
+ <v:textRect cx="29.25" cy="580.5" width="58.5" height="63"/>
+ <ellipse cx="29.25" cy="560.25" rx="29.25" ry="11.25" class="st25"/>
+ <text x="10.65" y="590" class="st26" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Redfish <tspan
+ x="11.42" dy="1.2em" class="st9">Service</tspan></text> </g>
+ </g>
+ <g id="shape47-132" v:mID="47" v:groupContext="shape" transform="translate(837,-315)">
+ <title>Rounded Rectangle</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ </v:userDefs>
+ <path d="M7.65 612 L68.85 612 A7.64987 7.64987 -180 0 0 76.5 604.35 L76.5 511.65 A7.64987 7.64987 -180 0 0 68.85 504
+ L7.65 504 A7.64987 7.64987 -180 0 0 -0 511.65 L0 604.35 A7.64987 7.64987 -180 0 0 7.65 612 Z" class="st27"/>
+ </g>
+ <g id="shape48-134" v:mID="48" v:groupContext="shape" transform="translate(837,-315)">
+ <title>Rounded Rectangle.48</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.175):1"/>
+ </v:userDefs>
+ <path d="M12.6 612 L113.4 612 A12.5998 12.5998 -180 0 0 126 599.4 L126 552.6 A12.5998 12.5998 -180 0 0 113.4 540 L12.6
+ 540 A12.5998 12.5998 -180 0 0 -0 552.6 L0 599.4 A12.5998 12.5998 -180 0 0 12.6 612 Z" class="st27"/>
+ </g>
+ <g id="shape49-136" v:mID="49" v:groupContext="shape" transform="translate(846,-391.5)">
+ <title>Sheet.49</title>
+ <desc>On Network</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="29.25" cy="598.5" width="58.5" height="27"/>
+ <rect x="0" y="585" width="58.5" height="27" class="st28"/>
+ <text x="21.97" y="594.9" class="st29" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>On <tspan x="7.49"
+ dy="1.2em" class="st9">Network</tspan></text> </g>
+ <g id="shape51-140" v:mID="51" v:groupContext="shape" transform="translate(913.5,-333)">
+ <title>Sheet.51</title>
+ <desc>BMC</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="22.5" cy="598.5" width="45" height="27"/>
+ <rect x="0" y="585" width="45" height="27" class="st28"/>
+ <text x="10.72" y="602.1" class="st29" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BMC</text> </g>
+ <g id="shape53-143" v:mID="53" v:groupContext="shape" transform="translate(300.223,21.2932) rotate(-29.9221)">
+ <title>Sheet.53</title>
+ <path d="M8.6 531.2 L8.91 531.39 C45.12 553.68 83.03 571.57 122.32 588.41 C144.61 597.96 167.35 607.17 190.07 610.52
+ C222.93 615.38 255.74 608 284.87 592.4 C310.1 578.89 332.55 559.23 354.13 533.89 L354.36 533.61"
+ class="st30"/>
+ </g>
+ <g id="shape54-152" v:mID="54" v:groupContext="shape" transform="translate(1142.22,727.062) rotate(119.385)">
+ <title>Sheet.54</title>
+ <path d="M0 601.33 C1.8 603.71 4.18 606.09 6.63 607.87 C38.72 631.29 82.4 552.5 108.8 592.25 L108.97 592.57"
+ class="st17"/>
+ </g>
+ <g id="shape55-157" v:mID="55" v:groupContext="shape" transform="translate(189,531) rotate(-90)">
+ <title>Sheet.55</title>
+ <path d="M0 580.5 C3.72 583.62 7.79 589.31 12.01 593.96 C44.21 629.47 84.97 604.53 101.41 588.39 L101.64 588.12"
+ class="st15"/>
+ </g>
+ <g id="shape56-162" v:mID="56" v:groupContext="shape" transform="translate(45,-305)">
+ <title>Sheet.56</title>
+ <desc>EDKII Redfish Foundation</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st32" v:langID="1033"><v:paragraph/><v:tabList/>EDKII Redfish <tspan x="4" dy="1.2em"
+ class="st9">Foundation</tspan></text> </g>
+ <g id="shape57-166" v:mID="57" v:groupContext="shape" transform="translate(45,-351)">
+ <title>Sheet.57</title>
+ <desc>EDKII Redfish Client</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st32" v:langID="1033"><v:paragraph/><v:tabList/>EDKII Redfish <tspan x="4" dy="1.2em"
+ class="st9">Client</tspan></text> </g>
+ <g id="shape58-170" v:mID="58" v:groupContext="shape" transform="translate(54,-198)">
+ <title>Rounded Rectangle.58</title>
+ <desc>SSDP over UDP</desc>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.0625):1"/>
+ </v:userDefs>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="54" cy="598.5" width="108" height="27"/>
+ <path d="M4.5 612 L103.5 612 A4.49993 4.49993 -180 0 0 108 607.5 L108 589.5 A4.49993 4.49993 -180 0 0 103.5 585 L4.5
+ 585 A4.49993 4.49993 -180 0 0 0 589.5 L0 607.5 A4.49993 4.49993 -180 0 0 4.5 612 Z" class="st33"/>
+ <text x="13.65" y="601.81" class="st34" v:langID="1033"><v:paragraph v:horizAlign="1" v:bulletSize="0.166667"/><v:tabList/>SSDP over UDP</text> </g>
+ <g id="group60-173" transform="translate(76.5,-117)" v:mID="60" v:groupContext="group">
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <title>Can.60</title>
+ <desc>Redfish Service</desc>
+ <g id="shape61-174" v:mID="61" v:groupContext="shape">
+ <title>Sheet.61</title>
+ <v:userDefs>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.125):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT0(1):26"/>
+ <v:ud v:nameU="ControlHalfHeight" v:prompt="" v:val="VT0(0.15625):1"/>
+ <v:ud v:nameU="FillForegnd" v:prompt="" v:val="VT5(#f2dcda)"/>
+ </v:userDefs>
+ <path d="M0 600.75 A29.25 11.25 -180 1 0 58.5 600.75 L58.5 560.25 L0 560.25 L0 600.75 Z" class="st35"/>
+ </g>
+ <g id="shape60-176" v:mID="60" v:groupContext="groupContent">
+ <v:textBlock v:margins="rect(4,4,4,4)" v:verticalAlign="2"/>
+ <v:textRect cx="29.25" cy="580.5" width="58.5" height="63"/>
+ <ellipse cx="29.25" cy="560.25" rx="29.25" ry="11.25" class="st35"/>
+ <text x="10.65" y="590" class="st36" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>Redfish <tspan
+ x="11.42" dy="1.2em" class="st9">Service</tspan></text> </g>
+ </g>
+ <g id="shape62-180" v:mID="62" v:groupContext="shape" transform="translate(67.5,-90)">
+ <title>Rounded Rectangle.62</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.10625):1"/>
+ </v:userDefs>
+ <path d="M7.65 612 L68.85 612 A7.64987 7.64987 -180 0 0 76.5 604.35 L76.5 525.15 A7.64987 7.64987 -180 0 0 68.85 517.5
+ L7.65 517.5 A7.64987 7.64987 -180 0 0 -0 525.15 L0 604.35 A7.64987 7.64987 -180 0 0 7.65 612 Z"
+ class="st37"/>
+ </g>
+ <g id="shape63-182" v:mID="63" v:groupContext="shape" transform="translate(81,-90)">
+ <title>Sheet.63</title>
+ <desc>BMC</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="22.5" cy="598.5" width="45" height="27"/>
+ <rect x="0" y="585" width="45" height="27" class="st28"/>
+ <text x="10.72" y="602.1" class="st36" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>BMC</text> </g>
+ <g id="shape64-185" v:mID="64" v:groupContext="shape" transform="translate(614.75,-135)">
+ <title>Sheet.64</title>
+ <desc>Build up Redfish Host Interface</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Build up Redfish Host Interface<v:newlineChar/></text> </g>
+ <g id="shape66-188" v:mID="66" v:groupContext="shape" transform="translate(806,-85.5)">
+ <title>Sheet.66</title>
+ <desc>EFI Shell Application, which builds up Redfish Host interface...</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="589.5" width="152" height="45"/>
+ <rect x="0" y="567" width="152" height="45" class="st28"/>
+ <text x="4" y="577.1" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>EFI Shell Application, which<v:newlineChar/><tspan
+ x="4" dy="1.2em" class="st9">builds up Redfish Host interface<v:newlineChar/><v:paragraph v:spLine="-1"
+ v:bulletSize="0.166667"/></tspan><tspan x="4" dy="1.05em" class="st9">for EDK</tspan>2 emulator platform<v:newlineChar/><tspan
+ x="4" dy="1.375em" class="st9">(</tspan>EmulatorPkg<tspan class="st39" v:langID="1028">)</tspan></text> </g>
+ <g id="shape69-195" v:mID="69" v:groupContext="shape" transform="translate(612,-202.5)">
+ <title>Sheet.69</title>
+ <desc>Get Authentication</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="597.2" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Get Authentication<v:newlineChar/></text> </g>
+ <g id="shape71-198" v:mID="71" v:groupContext="shape" transform="translate(396,-486)">
+ <title>Sheet.71</title>
+ <desc>RedfishBiosDxe</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="130.5" cy="594" width="261" height="36"/>
+ <rect x="0" y="576" width="261" height="36" class="st40"/>
+ <text x="88.66" y="597.25" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>RedfishBiosDxe</text> </g>
+ <g id="shape72-201" v:mID="72" v:groupContext="shape" transform="translate(396,-423)">
+ <title>Sheet.72</title>
+ <desc>RedfishBootInfoDxe</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="130.5" cy="594" width="261" height="36"/>
+ <rect x="0" y="576" width="261" height="36" class="st40"/>
+ <text x="76.33" y="597.25" class="st8" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>RedfishBootInfoDxe</text> </g>
+ <g id="shape73-204" v:mID="73" v:groupContext="shape" transform="translate(396,-441)">
+ <title>Sheet.73</title>
+ <desc>EDKII Redfish Feature DXE Drivers</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="130.5" cy="580.5" width="261" height="63"/>
+ <rect x="0" y="549" width="261" height="63" class="st28"/>
+ <text x="25.48" y="574.5" class="st41" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EDKII Redfish Feature <tspan
+ x="72.69" dy="1.2em" class="st9">DXE Drivers</tspan></text> </g>
+ <g id="shape75-208" v:mID="75" v:groupContext="shape" transform="translate(369,-405)">
+ <title>Rectangle</title>
+ <v:userDefs>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <path d="M0 612 L315 612 L315 477 L0 477 L0 612 Z" class="st42"/>
+ </g>
+ <g id="shape76-210" v:mID="76" v:groupContext="shape" transform="translate(324,-387)">
+ <title>Rounded Rectangle.76</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.23913043478261):1"/>
+ </v:userDefs>
+ <g id="shadow76-211" v:groupContext="shadow" v:shadowOffsetX="7.2E-008" v:shadowOffsetY="0" v:shadowType="1"
+ v:shadowScale="1.02" transform="matrix(1.02,0,0,1.02,-3.96,-10.53)" class="st43">
+ <path d="M17.22 612 L378.78 612 A17.2171 17.2171 -180 0 0 396 594.78 L396 458.22 A17.2171 17.2171 -180 0 0 378.78
+ 441 L17.22 441 A17.2171 17.2171 -180 0 0 0 458.22 L0 594.78 A17.2171 17.2171 -180 0 0 17.22 612 Z"
+ class="st44"/>
+ </g>
+ <path d="M17.22 612 L378.78 612 A17.2171 17.2171 -180 0 0 396 594.78 L396 458.22 A17.2171 17.2171 -180 0 0 378.78 441
+ L17.22 441 A17.2171 17.2171 -180 0 0 0 458.22 L0 594.78 A17.2171 17.2171 -180 0 0 17.22 612 Z"
+ class="st45"/>
+ </g>
+ <g id="shape77-215" v:mID="77" v:groupContext="shape" transform="translate(166.5,-396)">
+ <title>Sheet.77</title>
+ <desc>EDKII RedfishConfigDriver (UEF Driver Model)</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="67.5" cy="589.5" width="135" height="45"/>
+ <rect x="0" y="567" width="135" height="45" class="st6"/>
+ <text x="52.11" y="580" class="st7" v:langID="1033"><v:paragraph v:spLine="-1" v:horizAlign="1"/><v:tabList/>EDKII <tspan
+ x="9.37" dy="1em" class="st9">RedfishConfigDriver<v:lf/></tspan><tspan x="27.82" dy="1.25em" class="st5">(</tspan><tspan
+ class="st5">UEF Driver Model</tspan><tspan class="st5">)</tspan></text> </g>
+ <g id="shape79-222" v:mID="79" v:groupContext="shape" transform="translate(807.666,295.676) rotate(97.9072)">
+ <title>Sheet.79</title>
+ <path d="M0 579.17 C20.49 576.51 31.18 592.91 46.37 602.26 C77.86 621.65 128.73 610.76 156.32 586.48 L156.58 586.22"
+ class="st15"/>
+ </g>
+ <g id="shape80-227" v:mID="80" v:groupContext="shape" transform="translate(198,-522)">
+ <title>Rounded Rectangle.80</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st46"/>
+ </g>
+ <g id="shape81-229" v:mID="81" v:groupContext="shape" transform="translate(189,-513)">
+ <title>Rounded Rectangle.81</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st47"/>
+ </g>
+ <g id="shape90-231" v:mID="90" v:groupContext="shape" transform="translate(-119.157,659.986) rotate(-144.162)">
+ <title>Sheet.90</title>
+ <path d="M0 603.18 C4.15 607.13 9.94 610.11 15.61 611.34 C29.37 614.32 42.44 606.94 53.45 596.49 C61.26 589.09 68.03
+ 580.16 77.42 577.8 C88.41 575.03 102.97 581.29 102.88 593.34 L102.78 593.68" class="st15"/>
+ </g>
+ <g id="shape93-236" v:mID="93" v:groupContext="shape" transform="translate(221.899,727.905) rotate(-165.964)">
+ <title>Sheet.93</title>
+ <path d="M0 606.51 C15.17 612.77 29.52 612.61 44.18 611.2 C63.42 609.36 83.21 605.38 102.5 605.92 L102.86 605.95"
+ class="st48"/>
+ </g>
+ <g id="shape99-241" v:mID="99" v:groupContext="shape" transform="translate(139.354,700.857) rotate(-157.751)">
+ <title>Sheet.99</title>
+ <path d="M0 606.51 C14.58 612.77 28.36 612.61 42.45 611.2 C60.82 609.37 79.72 605.43 98.14 605.91 L98.5 605.94"
+ class="st48"/>
+ </g>
+ <g id="shape100-246" v:mID="100" v:groupContext="shape" transform="translate(5.09146,624.711) rotate(-143.13)">
+ <title>Sheet.100</title>
+ <path d="M0 606.51 C12.27 612.77 23.86 612.61 35.72 611.2 C50.71 609.43 66.12 605.66 81.18 605.88 L81.54 605.91"
+ class="st49"/>
+ </g>
+ <g id="shape108-252" v:mID="108" v:groupContext="shape" v:layerMember="0"
+ transform="translate(-63.7494,572.249) rotate(-135)">
+ <title>Wavy connector 2</title>
+ <v:userDefs>
+ <v:ud v:nameU="Scale" v:val="VT0(1):26"/>
+ <v:ud v:nameU="AntiScale" v:val="VT0(1):26"/>
+ <v:ud v:nameU="visVersion" v:val="VT0(15):26"/>
+ </v:userDefs>
+ <path d="M0 612 L11.04 616.08 L21.88 618.76 L32.52 620.05 L51.73 619.09 L60.91 617.82 L70.5 616.14 L80.5 614.04 L80.85
+ 613.96" class="st51"/>
+ </g>
+ <g id="shape128-258" v:mID="128" v:groupContext="shape" transform="translate(74.6891,-268.274) rotate(-20.6744)">
+ <title>Sheet.128</title>
+ <path d="M7.05 596.86 L7.3 596.6 C41.41 565.41 84.23 581.81 125.37 593.78 C147.72 600.28 169.57 605.47 191.7 609.19 C205.94
+ 611.58 220.3 613.37 234.93 610.75 L235.27 610.64" class="st53"/>
+ </g>
+ <g id="shape129-266" v:mID="129" v:groupContext="shape" transform="translate(913.572,626.328) rotate(137.291)">
+ <title>Sheet.129</title>
+ <path d="M0 570.67 C12.35 560.49 25.47 555.25 38.41 555.6 C60.3 556.19 81.63 572.81 103.52 591.21 C116.04 601.73 128.75
+ 612.82 140.98 612 C156.61 610.95 171.47 590.42 165.19 577.2 L164.94 576.93" class="st22"/>
+ </g>
+ <g id="shape130-271" v:mID="130" v:groupContext="shape" transform="translate(961.972,521.508) rotate(125.838)">
+ <title>Sheet.130</title>
+ <path d="M0 537.17 C5.61 533.31 11.98 533.39 17.86 534.13 C66.05 540.21 81.59 590.84 108.93 606.62 C129.47 618.49 156.66
+ 610.69 176.83 592.27 C191.47 578.9 202.41 559.94 201.92 545.76 L201.83 545.41" class="st22"/>
+ </g>
+ <g id="shape141-276" v:mID="141" v:groupContext="shape" transform="translate(524.018,816.193) rotate(-153.905)">
+ <title>Sheet.141</title>
+ <path d="M0 558.08 C-1.1 562.68 -4.17 567.34 -5.65 572.12 C-8.55 581.49 -5.37 591.37 -0.33 598.33 C22.05 629.26 81.08
+ 602.84 124.62 577.22 C154.8 559.45 177.54 542.06 207.45 539.15 C220.74 537.86 235.46 539.43 242.28 549.86
+ L242.41 550.2" class="st22"/>
+ </g>
+ <g id="shape142-281" v:mID="142" v:groupContext="shape" transform="translate(24.75,-556.75)">
+ <title>Sheet.142</title>
+ <rect x="0" y="604.5" width="22.5" height="7.5" class="st6"/>
+ </g>
+ <g id="shape143-283" v:mID="143" v:groupContext="shape" transform="translate(24.75,-539.5)">
+ <title>Sheet.143</title>
+ <rect x="0" y="604.5" width="22.5" height="7.5" class="st3"/>
+ </g>
+ <g id="shape144-285" v:mID="144" v:groupContext="shape" transform="translate(24.75,-521.5)">
+ <title>Sheet.144</title>
+ <rect x="0" y="604.5" width="22.5" height="7.5" class="st11"/>
+ </g>
+ <g id="shape145-287" v:mID="145" v:groupContext="shape" transform="translate(22.5,-506.5)">
+ <title>Sheet.145</title>
+ <path d="M6.41 612 L6.77 612 L20.23 612" class="st54"/>
+ </g>
+ <g id="shape147-296" v:mID="147" v:groupContext="shape" transform="translate(52.25,-551.5)">
+ <title>Sheet.147</title>
+ <desc>EDKII Open Source</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>EDKII Open Source</text> </g>
+ <g id="shape148-299" v:mID="148" v:groupContext="shape" transform="translate(51.75,-533.5)">
+ <title>Sheet.148</title>
+ <desc>Other Open Source</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Other Open Source</text> </g>
+ <g id="shape149-302" v:mID="149" v:groupContext="shape" transform="translate(51.75,-515.5)">
+ <title>Sheet.149</title>
+ <desc>OEM EDKII Library</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>OEM EDKII Library</text> </g>
+ <g id="shape150-305" v:mID="150" v:groupContext="shape" transform="translate(51.75,-496.5)">
+ <title>Sheet.150</title>
+ <desc>Redfish Payload Flow</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="76" cy="602" width="152" height="20"/>
+ <rect x="0" y="592" width="152" height="20" class="st28"/>
+ <text x="4" y="605.6" class="st38" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>Redfish Payload Flow</text> </g>
+ <g id="shape151-308" v:mID="151" v:groupContext="shape" transform="translate(461.424,927.834) rotate(155.556)">
+ <title>Sheet.151</title>
+ <path d="M0 603.97 C7.28 610.16 18.09 613.87 26.44 611.05 C35.57 607.96 41.76 597.08 50.21 600.96 L50.5 601.17"
+ class="st56"/>
+ </g>
+ <g id="shape153-314" v:mID="153" v:groupContext="shape" transform="translate(711.673,514.612) rotate(99.4623)">
+ <title>Sheet.153</title>
+ <path d="M0 612 L7.15 612" class="st58"/>
+ </g>
+ <g id="shape154-320" v:mID="154" v:groupContext="shape" transform="translate(-161.042,-388.162) rotate(-39.2894)">
+ <title>Sheet.154</title>
+ <path d="M0 612 L21.32 612" class="st60"/>
+ </g>
+ <g id="shape155-323" v:mID="155" v:groupContext="shape" transform="translate(162,-499.5)">
+ <title>Rounded Rectangle.82</title>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st12"/>
+ </g>
+ <g id="shape156-325" v:mID="156" v:groupContext="shape" transform="translate(153,-486)">
+ <title>Rounded Rectangle.83</title>
+ <desc>EDKII Redfish Config Handler Protocol</desc>
+ <v:userDefs>
+ <v:ud v:nameU="CTypeTopLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeTopRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotLeftSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CTypeBotRightSnip" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="CornerLockHoriz" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockVert" v:prompt="" v:val="VT0(1):5"/>
+ <v:ud v:nameU="CornerLockDiag" v:prompt="" v:val="VT0(0):5"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.15):1"/>
+ <v:ud v:nameU="visVersion" v:prompt="" v:val="VT0(15):26"/>
+ <v:ud v:nameU="TopLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="TopRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotLeftOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ <v:ud v:nameU="BotRightOffset" v:prompt="" v:val="VT0(0.065217391304348):1"/>
+ </v:userDefs>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="54" cy="598.5" width="108" height="27"/>
+ <path d="M4.7 612 L103.3 612 A4.69558 4.69558 -180 0 0 108 607.3 L108 589.7 A4.69558 4.69558 -180 0 0 103.3 585 L4.7
+ 585 A4.69558 4.69558 -180 0 0 0 589.7 L0 607.3 A4.69558 4.69558 -180 0 0 4.7 612 Z" class="st12"/>
+ <text x="13.06" y="595.5" class="st61" v:langID="1033"><v:paragraph v:horizAlign="1"/><v:tabList/>EDKII Redfish Config <tspan
+ x="19.55" dy="1.2em" class="st9">Handler Protocol</tspan></text> </g>
+ <g id="shape157-329" v:mID="157" v:groupContext="shape" transform="translate(24.75,-315)">
+ <title>Sheet.157</title>
+ <desc>[1]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[1]</text> </g>
+ <g id="shape158-332" v:mID="158" v:groupContext="shape" transform="translate(24.75,-360)">
+ <title>Sheet.158</title>
+ <desc>[2]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[2]</text> </g>
+ <g id="shape159-335" v:mID="159" v:groupContext="shape" transform="translate(207,-250)">
+ <title>Sheet.159</title>
+ <desc>[3]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[3]</text> </g>
+ <g id="shape160-338" v:mID="160" v:groupContext="shape" transform="translate(207,-188)">
+ <title>Sheet.160</title>
+ <desc>[4]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[4]</text> </g>
+ <g id="shape161-341" v:mID="161" v:groupContext="shape" transform="translate(562.5,-250)">
+ <title>Sheet.161</title>
+ <desc>[5]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[5]</text> </g>
+ <g id="shape162-344" v:mID="162" v:groupContext="shape" transform="translate(562.5,-54)">
+ <title>Sheet.162</title>
+ <desc>[6]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[6]</text> </g>
+ <g id="shape163-347" v:mID="163" v:groupContext="shape" transform="translate(207,-75.5)">
+ <title>Sheet.163</title>
+ <desc>[7]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[7]</text> </g>
+ <g id="shape164-350" v:mID="164" v:groupContext="shape" transform="translate(562.5,-142)">
+ <title>Sheet.164</title>
+ <desc>[8]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[8]</text> </g>
+ <g id="shape165-353" v:mID="165" v:groupContext="shape" transform="translate(562.5,-306)">
+ <title>Sheet.165</title>
+ <desc>[9]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="11.25" cy="602" width="22.5" height="20"/>
+ <rect x="0" y="592" width="22.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[9]</text> </g>
+ <g id="shape166-356" v:mID="166" v:groupContext="shape" transform="translate(612,-259)">
+ <title>Sheet.166</title>
+ <desc>[10]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[10]</text> </g>
+ <g id="shape167-359" v:mID="167" v:groupContext="shape" transform="translate(612,-196)">
+ <title>Sheet.167</title>
+ <desc>[11]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[11]</text> </g>
+ <g id="shape168-362" v:mID="168" v:groupContext="shape" transform="translate(560.25,-189)">
+ <title>Sheet.168</title>
+ <desc>[12]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[12]</text> </g>
+ <g id="shape169-365" v:mID="169" v:groupContext="shape" transform="translate(207,-313)">
+ <title>Sheet.169</title>
+ <desc>[13]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[13]</text> </g>
+ <g id="shape170-368" v:mID="170" v:groupContext="shape" transform="translate(612,-318.5)">
+ <title>Sheet.170</title>
+ <desc>[14]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[14]</text> </g>
+ <g id="shape171-371" v:mID="171" v:groupContext="shape" transform="translate(139.5,-422)">
+ <title>Sheet.171</title>
+ <desc>[15]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[15]</text> </g>
+ <g id="shape172-374" v:mID="172" v:groupContext="shape" transform="translate(135,-511)">
+ <title>Sheet.172</title>
+ <desc>[16]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[16]</text> </g>
+ <g id="shape173-377" v:mID="173" v:groupContext="shape" transform="translate(326.25,-557)">
+ <title>Sheet.173</title>
+ <desc>[17]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[17]</text> </g>
+ <g id="shape174-380" v:mID="174" v:groupContext="shape" transform="translate(54,-225)">
+ <title>Sheet.174</title>
+ <desc>[18]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[18]</text> </g>
+ <g id="shape175-383" v:mID="175" v:groupContext="shape" transform="translate(895.5,-295)">
+ <title>Sheet.175</title>
+ <desc>[19]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[19]</text> </g>
+ <g id="shape176-386" v:mID="176" v:groupContext="shape" transform="translate(612,-99)">
+ <title>Sheet.176</title>
+ <desc>[20]</desc>
+ <v:textBlock v:margins="rect(4,4,4,4)"/>
+ <v:textRect cx="15.75" cy="602" width="31.5" height="20"/>
+ <rect x="0" y="592" width="31.5" height="20" class="st28"/>
+ <text x="4" y="605.39" class="st62" v:langID="1033"><v:paragraph v:bulletSize="0.166667"/><v:tabList/>[20]</text> </g>
+ </g>
+</svg>
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h
new file mode 100644
index 00000000000..44cb0499404
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/IndustryStandard/RedfishHostInterface.h
@@ -0,0 +1,169 @@
+/** @file
+ This file defines the Redfish Interface Specific Data.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef REDFISH_HOST_INTERFACE_
+#define REDFISH_HOST_INTERFACE_
+
+#include <IndustryStandard/SmBios.h>
+
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB 0x02 // We don't support this type of interface.
+ // Use REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 instead.
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE 0x03 // We don't support this type of interface.
+ // Use REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2 instead.
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 0x04
+#define REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2 0x05
+
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_UNKNOWN 0x00
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_STATIC 0x01
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_DHCP 0x02
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_AUTO_CONFIGURE 0x03
+#define REDFISH_HOST_INTERFACE_HOST_IP_ASSIGNMENT_TYPE_HOST_SELECTED 0x04
+
+#define REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_UNKNOWN 0x00
+#define REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP4 0x01
+#define REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6 0x02
+
+#pragma pack(1)
+///
+/// Structure definitions of Host Interface device type 04h (USB Network Interface V2)
+///
+typedef struct {
+ UINT8 Length; ///< Length of the structure, including Device Type
+ ///< and Length fields.
+ UINT16 IdVendor; ///< The Vendor ID of the device, as read from the
+ ///< idVendor field of the USB descriptor.
+ UINT16 IdProduct; ///< The Product ID of the device, as read from the
+ ///< idProduct field of the USB descriptor.
+ UINT8 SecialNumberStr; ///< The string number for the Serial Number of the
+ ///< device. The string data is read from the
+ ///< iSerialNumber.bDescriptorType field of the USB
+ ///< descriptor, and is converted from Unicode to ASCII
+ ///< and is NULL terminated.
+ UINT8 MacAddress [6]; ///< The MAC address of the PCI/PCIe network device.
+} USB_INTERFACE_DEVICE_DESCRIPTOR_V2;
+
+//
+// Structure definitions of Host Interface device type 05h (PCI/PCIE V2)
+//
+typedef struct {
+ UINT8 Length; ///< Length of the structure, including Device Type and Length fields.
+ UINT16 VendorId; ///< The Vendor ID of the PCI/PCIe device.
+ UINT16 DeviceId; ///< The Device ID of the PCI/PCIe device.
+ UINT16 SubsystemVendorId; ///< The Subsystem Vendor ID of the PCI/PCIe device.
+ UINT16 SubsystemId; ///< The Subsystem ID of the PCI/PCIe device.
+ UINT8 MacAddress [6]; ///< The MAC address of the PCI/PCIe network device.
+ UINT16 SegmemtGroupNumber; ///< The Segment Group Number of the PCI/PCIe.
+ UINT8 BusNumber; ///< The Bus Number of the PCI/PCIe device.
+ UINT8 DeviceFunctionNumber; ///< The Device/Function Number of the PCI/PCIe.
+} PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2;
+
+///
+/// Structure definitions of Host Interface device type 80-FFh (OEM)
+///
+typedef struct {
+ UINT32 VendorIana; ///< The IANA code for the vendor (MSB first).
+ UINT8 OemDefinedData[1]; ///< OEM defined data.
+} OEM_DEVICE_DESCRIPTOR;
+
+///
+/// Define union for the Host Interface Device Descriptor
+///
+typedef union {
+ USB_INTERFACE_DEVICE_DESCRIPTOR_V2 UsbDeviceV2; ///< Device type USB V2 device discriptor.
+ PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2 PciPcieDeviceV2; ///< Device type PCI/PCIe V2 device discriptor.
+ OEM_DEVICE_DESCRIPTOR OemDevice; ///< OEM type device discriptor.
+} DEVICE_DESCRITOR; /// Device descriptor data formated based on Device Type.
+
+///
+/// Interface Specific Data starts at offset 06h of the SMBIOS Type 42 struct.
+/// This table defines the Interface Specific data for Interface Type 40h. There
+/// are 3 types of Device Descriptor3 defined , however only 1 may be used in
+/// specific Tape 42 table.
+///
+typedef struct {
+ UINT8 DeviceType; ///< The Device Type of the interface.
+ DEVICE_DESCRITOR DeviceDescriptor; ///< The Device descriptor.
+} REDFISH_INTERFACE_DATA;
+
+//
+// the protocol-specific data for the "Redfish Over IP" protocol
+//
+typedef struct {
+ EFI_GUID ServiceUuid; //same as Redfish Service UUID in Redfish Service Root resource
+
+ //
+ // Unknown=00h,
+ // Static=01h,
+ // DHCP=02h,
+ // AutoConfigure=03h,
+ // HostSelected=04h,
+ // other values reserved
+ //
+ UINT8 HostIpAssignmentType;
+
+ //
+ // Unknown=00h,
+ // Ipv4=01h,
+ // Ipv6=02h,
+ // other values reserved
+ //
+ UINT8 HostIpAddressFormat;
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 HostIpAddress[16];
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 HostIpMask[16];
+
+ //
+ // Unknown=00h,
+ // Static=01h,
+ // DHCP=02h,
+ // AutoConfigure=03h,
+ // HostSelected=04h,
+ // other values reserved
+ //
+ UINT8 RedfishServiceIpDiscoveryType;
+
+ //
+ // Unknown=00h,
+ // Ipv4=01h,
+ // Ipv6=02h,
+ // other values reserved
+ //
+ UINT8 RedfishServiceIpAddressFormat;
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 RedfishServiceIpAddress[16];
+
+ //
+ // Used for Static and AutoConfigure.
+ // For IPV4, use the first 4 Bytes and zero fill the remaining bytes.
+ //
+ UINT8 RedfishServiceIpMask[16];
+
+ UINT16 RedfishServiceIpPort; // Used for Static and AutoConfigure.
+ UINT32 RedfishServiceVlanId; // Used for Static and AutoConfigure.
+ UINT8 RedfishServiceHostnameLength; // length of the following hostname string
+ UINT8 RedfishServiceHostname[1]; // hostname of Redfish Service
+} REDFISH_OVER_IP_PROTOCOL_DATA;
+
+#pragma pack()
+
+#endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h
new file mode 100644
index 00000000000..a17436bb1c2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/BaseUcs2Utf8Lib.h
@@ -0,0 +1,61 @@
+/** @file
+ UCS2 to UTF8 manipulation library header file.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef BASE_UCS2UTF8_LIB_H_
+#define BASE_UCS2UTF8_LIB_H_
+
+///
+/// L"\u0000"
+///
+#define UNICODE_FORMAT_LEN 6
+#define UNICODE_FORMAT_CHAR_LEN 2
+#define UNICODE_FORMAT_CHAR_SIZE 3
+
+#define UTF8_BUFFER_FOR_UCS2_MAX_SIZE 3
+
+/**
+ Convert a UCS2 string to a UTF8 encoded string.
+
+ @param[in] Ucs2Str The provided UCS2 string.
+ @param[out] Utf8StrAddr The converted UTF8 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UTF8 encoded string has been converted.
+
+**/
+EFI_STATUS
+UCS2StrToUTF8 (
+ IN CHAR16 *Ucs2Str,
+ OUT CHAR8 **Utf8StrAddr
+ );
+
+/**
+ Convert a UTF8 encoded string to a UCS2 string.
+
+ @param[in] Utf8Str The provided UTF8 encoded string.
+ @param[out] Ucs2StrAddr The converted UCS2 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER The UTF8 encoded string is not valid to
+ convert to UCS2 string.
+ One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UCS2 string has been converted.
+
+**/
+EFI_STATUS
+UTF8StrToUCS2 (
+ IN CHAR8 *Utf8Str,
+ OUT CHAR16 **Ucs2StrAddr
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h
new file mode 100644
index 00000000000..0b661a0aa04
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/JsonLib.h
@@ -0,0 +1,800 @@
+/** @file
+ APIs for JSON operations.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef JSON_LIB_H_
+#define JSON_LIB_H_
+
+typedef VOID* EDKII_JSON_VALUE;
+typedef VOID* EDKII_JSON_ARRAY;
+typedef VOID* EDKII_JSON_OBJECT;
+
+///
+/// Map to json_int_t in jansson.h
+///
+typedef INT64 EDKII_JSON_INT_T; // #JSON_INTEGER_IS_LONG_LONG is set to 1
+ // in jansson_Config.h
+
+///
+/// Map to the definitions in jansson.h
+/// See below URI for the JSON encoding flags reference.
+/// https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+///
+#define EDKII_JSON_MAX_INDENT 0x1F
+#define EDKII_JSON_INDENT(n) ((n) & EDKII_JSON_MAX_INDENT)
+
+#define EDKII_JSON_COMPACT 0x20
+#define EDKII_JSON_ENSURE_ASCII 0x40
+#define EDKII_JSON_SORT_KEYS 0x80
+#define EDKII_JSON_PRESERVE_ORDER 0x100
+#define EDKII_JSON_ENCODE_ANY 0x200
+#define EDKII_JSON_ESCAPE_SLASH 0x400
+#define EDKII_JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11)
+#define EDKII_JSON_EMBED 0x10000
+
+///
+/// Map to the definitions in jansson.h
+/// See below URI for the JSON decoding flags reference.
+/// https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+///
+#define EDKII_JSON_REJECT_DUPLICATES 0x1
+#define EDKII_JSON_DISABLE_EOF_CHECK 0x2
+#define EDKII_JSON_DECODE_ANY 0x4
+#define EDKII_JSON_DECODE_INT_AS_REAL 0x8
+#define EDKII_JSON_ALLOW_NUL 0x10
+
+#define EDKII_JSON_ARRAY_FOREACH(Array, Index, Value) \
+ for(Index = 0; \
+ Index < JsonArrayCount(Array) && (Value = JsonArrayGetValue(Array, Index)); \
+ Index++)
+
+///
+/// Map to the json_error_t in jansson.h
+///
+#define EDKII_JSON_ERROR_TEXT_LENGTH 160
+#define EDKII_JSON_ERROR_SOURCE_LENGTH 80
+typedef struct {
+ INTN Line;
+ INTN Column;
+ INTN Position;
+ CHAR8 Source [EDKII_JSON_ERROR_SOURCE_LENGTH];
+ CHAR8 Text [EDKII_JSON_ERROR_TEXT_LENGTH];
+} EDKII_JSON_ERROR;
+
+///
+/// Map to the json_type in jansson.h
+///
+typedef enum {
+ EdkiiJsonTypeObject,
+ EdkiiJsonTypeArray,
+ EdkiiJsonTypeString,
+ EdkiiJsonTypeInteger,
+ EdkiiJsonTypeReal,
+ EdkiiJsonTypeTrue,
+ EdkiiJsonTypeFalse,
+ EdkiiJsonTypeNull
+} EDKII_JSON_TYPE;
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON array,
+ or NULL on error. Initially, the array is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitArray (
+ VOID
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON object,
+ or NULL on error. Initially, the object is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitObject (
+ VOID
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input string must be NULL terminated Ascii format, non-Ascii characters will
+ be processed as an error. Unicode characters can also be represented by Ascii string
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Ascii string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitAsciiString (
+ IN CONST CHAR8 *String
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input must be a NULL terminated UCS2 format Unicode string.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Unicode string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitUnicodeString (
+ IN CHAR16 *String
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON integer,
+ or NULL on error.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] Value The integer to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON number or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNumber (
+ IN INT64 Value
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON boolean,
+ or NULL on error.
+
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.
+
+ @param[in] Value The boolean value to initialize.
+
+ @retval The created JSON value which contains a JSON boolean or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitBoolean (
+ IN BOOLEAN Value
+ );
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON NULL,
+ or NULL on error.
+
+ NULL JSON value is kept as static value, and no need to do any cleanup work.
+
+ @retval The created NULL JSON value.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNull (
+ VOID
+ );
+
+/**
+ The function is used to decrease the reference count of a JSON value by one, and once
+ this reference count drops to zero, the value is destroyed and it can no longer be used.
+ If this destroyed value is object type or array type, reference counts for all containing
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed
+ since they are static values kept in memory.
+
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a
+ value is kept for use, its reference count is incremented, and when the value is no longer
+ needed, the reference count is decremented. When the reference count drops to zero, there are
+ no references left, and the value can be destroyed.
+
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message
+ to inform caller the NULL value is passed in.
+
+ @param[in] Json The JSON value to be freed. json_decref may return without any
+ changes if Json is NULL.
+
+**/
+VOID
+EFIAPI
+JsonValueFree (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to create a fresh copy of a JSON value, and all child values are deep
+ copied in a recursive fashion. It should be called when this JSON value might be modified
+ in later use, but the original still wants to be used in somewhere else.
+
+ Reference counts of the returned root JSON value and all child values will be set to 1, and
+ caller needs to cleanup the root value by calling JsonValueFree().
+
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some
+ performance issues, user should avoid unnecessary calls to this function unless it is really
+ needed.
+
+ @param[in] Json The JSON value to be cloned.
+
+ @retval Return the cloned JSON value, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueClone (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON array.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON array.
+ @retval FALSE The JSON value doesn't contain a JSON array.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsArray (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON object.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON object.
+ @retval FALSE The JSON value doesn't contain a JSON object.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsObject (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON Value contains a string, Ascii or
+ Unicode format is not differentiated.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON string.
+ @retval FALSE The JSON value doesn't contain a JSON string.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON number.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value is contains JSON number.
+ @retval FALSE The JSON value doesn't contain a JSON number.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNumber (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON boolean.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON boolean.
+ @retval FALSE The JSON value doesn't contain a JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsBoolean (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to return if the provided JSON value contains a JSON NULL.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON NULL.
+ @retval FALSE The JSON value doesn't contain a JSON NULL.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNull (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated array in an array type JSON value.
+
+ Any changes to the returned array will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated array in JSON value or NULL.
+
+**/
+EDKII_JSON_ARRAY
+EFIAPI
+JsonValueGetArray (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated object in an object type JSON value.
+
+ Any changes to the returned object will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated object in JSON value or NULL.
+
+**/
+EDKII_JSON_OBJECT
+EFIAPI
+JsonValueGetObject (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated Ascii string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL.
+
+**/
+CONST CHAR8 *
+EFIAPI
+JsonValueGetAsciiString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated Unicode string in a string type JSON value.
+
+ Caller can do any changes to the returned string without any impact to the original JSON
+ value, and caller needs to free the returned string using FreePool().
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Unicode string in JSON value or NULL.
+
+**/
+CHAR16*
+EFIAPI
+JsonValueGetUnicodeString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated integer in a number type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will
+ ASSERT() and return 0.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated number in JSON value.
+
+**/
+INT64
+EFIAPI
+JsonValueGetNumber (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated boolean in a boolean type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will
+ ASSERT() and return FALSE.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated value of JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueGetBoolean (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to retrieve the associated string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL on errors.
+
+**/
+CONST CHAR8*
+EFIAPI
+JsonValueGetString (
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or
+ not a JSON object.
+
+ @param[in] JsonObject The provided JSON object.
+
+ @retval Return the number of elements in this JSON object or 0.
+
+**/
+UINTN
+EFIAPI
+JsonObjectSize (
+ IN EDKII_JSON_OBJECT JsonObject
+ );
+
+/**
+ The function is used to enumerate all keys in a JSON object.
+
+ Caller should be responsible to free the returned key array reference using
+ FreePool(). But contained keys are read only and must not be modified or freed.
+
+ @param[in] JsonObj The provided JSON object for enumeration.
+ @param[out] KeyCount The count of keys in this JSON object.
+
+ @retval Return an array of the enumerated keys in this JSON object or NULL if
+ JsonObj is not an JSON object, key count is zero or on other errors.
+
+**/
+CHAR8**
+JsonObjectGetKeys (
+ IN EDKII_JSON_OBJECT JsonObj,
+ OUT UINTN *KeyCount
+ );
+
+/**
+ The function is used to get a JSON value corresponding to the input key from a JSON object.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when
+ Key-Value is not found in this JSON object.
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be retrieved.
+
+ @retval Return the corresponding JSON value to key, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectGetValue (
+ IN CONST EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key
+ );
+
+/**
+ The function is used to set a JSON value corresponding to the input key from a JSON object,
+ and the reference count of this value will be increased by 1.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed
+ from this object and thus its' reference count will be decreased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be set.
+ @param[in] Json The JSON value to set to this JSON object mapped by key.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonObjectSetValue (
+ IN EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key,
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray
+ is NULL or not a JSON array.
+
+ @param[in] JsonArray The provided JSON array.
+
+ @retval Return the number of elements in this JSON array or 0.
+
+**/
+UINTN
+EFIAPI
+JsonArrayCount (
+ IN EDKII_JSON_ARRAY JsonArray
+ );
+
+/**
+ The function is used to return the JSON value in the array at position index. The valid range
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.
+
+ @param[in] JsonArray The provided JSON Array.
+
+ @retval Return the JSON value located in the Index position or
+ NULL if JsonArray is not an array or no items in the array.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonArrayGetValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ );
+
+/**
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of
+ array by 1. The reference count of this value will be increased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON object.
+ @param[in] Json The JSON value to append.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayAppendValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN EDKII_JSON_VALUE Json
+ );
+
+/**
+ The function is used to remove a JSON value at position index, shifting the elements after index
+ one position towards the start of the array. The reference count of this value will be decreased
+ by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON array.
+ @param[in] Index The Index position before removement.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON array has been removed at position index.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayRemoveValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ );
+
+/**
+ Dump JSON to a buffer.
+
+ @param[in] JsonValue The provided JSON value.
+ @param[in] Flags The Index position before removement. The value
+ could be the combination of below flags.
+ - EDKII_JSON_INDENT(n)
+ - EDKII_JSON_COMPACT
+ - EDKII_JSON_ENSURE_ASCII
+ - EDKII_JSON_SORT_KEYS
+ - EDKII_JSON_PRESERVE_ORDER
+ - EDKII_JSON_ENCODE_ANY
+ - EDKII_JSON_ESCAPE_SLASH
+ - EDKII_JSON_REAL_PRECISION(n)
+ - EDKII_JSON_EMBED
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer
+ contain JSON paylaod in ASCII string. The return
+ value must be freed by the caller FreePool().
+**/
+CHAR8 *
+EFIAPI
+JsonDumpString (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN UINTN Flags
+ );
+
+/**
+ Convert a string to JSON object.
+ The function is used to convert a NULL terminated CHAR8 string to a JSON
+ value. Only object and array represented strings can be converted successfully,
+ since they are the only valid root values of a JSON text for UEFI usage.
+
+ Real number and number with exponent part are not supportted by UEFI.
+
+ Caller needs to cleanup the root value by calling JsonValueFree().
+
+ @param[in] String The NULL terminated CHAR8 string to convert.
+
+ @retval Array JSON value or object JSON value, or NULL when any error occurs.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadString (
+ IN CONST CHAR8* String
+ );
+
+/**
+ Load JSON from a buffer.
+
+ @param[in] Buffer Bufffer to the JSON payload
+ @param[in] BufferLen Length of the buffer
+ @param[in] Flags Flag of loading JSON buffer, the value
+ could be the combination of below flags.
+ - EDKII_JSON_REJECT_DUPLICATES
+ - EDKII_JSON_DISABLE_EOF_CHECK
+ - EDKII_JSON_DECODE_ANY
+ - EDKII_JSON_DECODE_INT_AS_REAL
+ - EDKII_JSON_ALLOW_NUL
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure
+
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadBuffer (
+ IN CONST CHAR8 *Buffer,
+ IN UINTN BufferLen,
+ IN UINTN Flags,
+ IN OUT EDKII_JSON_ERROR *Error
+ );
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ when the value is no longer needed, the reference count is decremented.
+ When the reference count drops to zero, there are no references left and the
+ value can be destroyed.
+
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as
+ a call to json_decref() drops the reference count to zero, the value is
+ destroyed and it can no longer be used.
+
+ @param[in] JsonValue JSON value
+**/
+VOID
+EFIAPI
+JsonDecreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),
+ its reference count is incremented.
+
+ This function increment the reference count of json if it's not NULL.
+ Returns EDKII_JSON_VALUE.
+
+ @param[in] JsonValue JSON value
+ @retval EDKII_JSON_VALUE of itself
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonIncreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+/**
+ Returns an opaque iterator which can be used to iterate over all key-value pairs
+ in object, or NULL if object is empty
+
+ @param[in] JsonValue JSON value
+**/
+VOID *
+EFIAPI
+JsonObjectIterator (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+
+/**
+ Extract the associated value from iterator.
+
+ @param[in] Iterator Iterator pointer
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectIteratorValue (
+ IN VOID *Iterator
+ );
+
+/**
+ Returns an iterator pointing to the next key-value pair in object after iter,
+ or NULL if the whole object has been iterated through.
+
+ @param[in] JsonValue JSON value
+ @param[in] Iterator Iterator pointer
+ @retval Iterator pointer
+**/
+VOID *
+JsonObjectIteratorNext (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN VOID *Iterator
+ );
+
+/**
+ Returns the json type of this json value
+
+ @param[in] JsonValue JSON value
+ @retval JSON type returned
+**/
+EDKII_JSON_TYPE
+EFIAPI
+JsonGetType(
+ IN EDKII_JSON_VALUE JsonValue
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h
new file mode 100644
index 00000000000..72d6799b004
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishContentCodingLib.h
@@ -0,0 +1,78 @@
+/** @file
+ Definitinos of RedfishContentCodingLib.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CONTENT_CODING_LIB_H_
+#define REDFISH_CONTENT_CODING_LIB_H_
+
+/**
+ This is the function to encode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] OriginalContent Original content.
+ @param[in] OriginalContentLength The length of original content.
+ @param[out] EncodedContentPointer Pointer to receive the encoded content pointer.
+ @param[out] EncodedContentLength Length of encoded content.
+
+ @retval EFI_SUCCESS Content is encoded successfully.
+ @retval EFI_UNSUPPORTED No supported encoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+
+EFI_STATUS
+RedfishContentEncode (
+ IN CHAR8 *ContentEncodedValue,
+ IN CHAR8 *OriginalContent,
+ IN UINTN OriginalContentLength,
+ OUT VOID **EncodedContentPointer,
+ OUT UINTN *EncodedLength
+ );
+
+/**
+ This is the function to decode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentDecodedValue HTTP conent decoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] ContentPointer Original content.
+ @param[in] ContentLength The length of original content.
+ @param[out] DecodedContentPointer Pointer to receive decoded content pointer.
+ @param[out] DecodedContentLength Length of decoded content.
+
+ @retval EFI_SUCCESS Content is decoded successfully.
+ @retval EFI_UNSUPPORTED No supported decoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+RedfishContentDecode (
+ IN CHAR8 *ContentEncodedValue,
+ IN VOID *ContentPointer,
+ IN UINTN ContentLength,
+ OUT VOID **DecodedContentPointer,
+ OUT UINTN *DecodedLength
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h
new file mode 100644
index 00000000000..f4c788f91e0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishCredentialLib.h
@@ -0,0 +1,91 @@
+/** @file
+ Definitinos of RedfishHostInterfaceDxe driver.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CREDENTIAL_LIB_H_
+#define REDFISH_CREDENTIAL_LIB_H_
+
+#include <Uefi.h>
+
+/**
+ Notification of Exit Boot Service.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialExitBootServicesNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+);
+
+/**
+ Notification of End of DXe.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialEndOfDxeNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+);
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+LibCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+);
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+LibStopRedfishService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+);
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h
new file mode 100644
index 00000000000..aec6de381bf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RedfishHostInterfaceLib.h
@@ -0,0 +1,52 @@
+/** @file
+ Definitinos of RedfishHostInterfaceDxe driver.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_HOST_INTERFACE_LIB_H_
+#define REDFISH_HOST_INTERFACE_LIB_H_
+
+#include <Uefi.h>
+#include <IndustryStandard/RedfishHostInterface.h>
+#include <IndustryStandard/SmBios.h>
+
+#include <Protocol/Smbios.h>
+
+/**
+ Get platform Redfish host interface device descriptor.
+
+ @param[in] DeviceType Pointer to retrieve device type.
+ @param[out] DeviceDescriptor Pointer to retrieve REDFISH_INTERFACE_DATA, caller has to free
+ this memory using FreePool().
+ @retval EFI_SUCCESS Device descriptor is returned successfully in DeviceDescriptor.
+ @retval EFI_NOT_FOUND No Redfish host interface descriptor provided on this platform.
+ @retval Others Fail to get device descriptor.
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceDeviceDescriptor (
+ IN UINT8 *DeviceType,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor
+);
+/**
+ Get platform Redfish host interface protocol data.
+ Caller should pass NULL in ProtocolRecord to retrive the first protocol record.
+ Then continuously pass previous ProtocolRecord for retrieving the next ProtocolRecord.
+
+ @param[in, out] ProtocolRecord Pointer to retrieve the first or the next protocol record.
+ caller has to free the new protocol record returned from
+ this function using FreePool().
+ param[in] IndexOfProtocolData The index of protocol data.
+
+ @retval EFI_SUCESS Protocol records are all returned.
+ @retval EFI_NOT_FOUND No more protocol records.
+ @retval Others Fail to get protocol records.
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceProtocolData (
+ IN OUT MC_HOST_INTERFACE_PROTOCOL_RECORD **ProtocolRecord,
+ IN UINT8 IndexOfProtocolData
+);
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h
new file mode 100644
index 00000000000..38858145ec8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Library/RestExLib.h
@@ -0,0 +1,42 @@
+/** @file
+ This library provides help functions for REST EX Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REST_EX_LIB_H_
+#define REST_EX_LIB_H_
+
+#include <Protocol/RestEx.h>
+
+///
+/// Library class public functions
+///
+
+/**
+ This function allows the caller to create child handle for specific
+ REST server.
+
+ @param[in] Image The image handle used to open service.
+ @param[in] AccessMode Access mode of REST server.
+ @param[in] ConfigType Underlying configuration to communicate with REST server.
+ @param[in] ServiceType REST service type.
+ @param[out] ChildInstanceHandle The handle to receive the create child.
+
+ @retval EFI_SUCCESS Can't create the corresponding REST EX child instance.
+ @retval EFI_INVALID_PARAMETERS Any of input parameters is improper.
+
+**/
+EFI_STATUS
+RestExLibCreateChild (
+ IN EFI_HANDLE Image,
+ IN EFI_REST_EX_SERVICE_ACCESS_MODE AccessMode,
+ IN EFI_REST_EX_CONFIG_TYPE ConfigType,
+ IN EFI_REST_EX_SERVICE_TYPE ServiceType,
+ OUT EFI_HANDLE *ChildInstanceHandle
+);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h
new file mode 100644
index 00000000000..1cfc9fd204a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Pcd/RestExServiceDevicePath.h
@@ -0,0 +1,38 @@
+/** @file
+ This library defines the UEFI device path data of network device for REST
+ service to decide which should be used as the Redfish host interface.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REST_EX_SERVICE_DEVICE_PATH_H_
+#define REST_EX_SERVICE_DEVICE_PATH_H_
+
+#include <Protocol/DevicePath.h>
+
+typedef enum {
+ DEVICE_PATH_MATCH_MAC_NODE = 1,
+ DEVICE_PATH_MATCH_PCI_NODE = 2,
+ DEVICE_PATH_MATCH_MODE_MAX
+} DEVICE_PATH_MATCH_MODE;
+
+typedef struct {
+ UINT32 DevicePathMatchMode;
+ UINT32 DevicePathNum;
+ //
+ // Example:
+ // {DEVICE_PATH("PciRoot(0)/Pci(0,0)/MAC(005056C00002,0x1)")}
+ // DevicePath will be parsed as below:
+ // {0x02,0x01,0x0c,0x00,0xd0,0x41,0x03,0x0a,0x00,0x00,0x00,0x00,
+ // 0x01,0x01,0x06,0x00,0x00,0x00,
+ // 0x03,0x0b,0x25,0x00,0x00,0x50,0x56,0xc0,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ // 0x7f,0xff,0x04,0x00}
+ //
+ EFI_DEVICE_PATH_PROTOCOL DevicePath[];
+} REST_EX_SERVICE_DEVICE_PATH_DATA;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h
new file mode 100644
index 00000000000..297bdb85145
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishConfigHandler.h
@@ -0,0 +1,78 @@
+/** @file
+ This file defines the EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL interface.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_CONFIG_HANDLER_H_
+#define EDKII_REDFISH_CONFIG_HANDLER_H_
+
+typedef struct _EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL;
+
+#define EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_GUID \
+ { \
+ 0xbc0fe6bb, 0x2cc9, 0x463e, { 0x90, 0x82, 0xfa, 0x11, 0x76, 0xfc, 0x67, 0xde } \
+ }
+
+typedef struct {
+ EFI_HANDLE RedfishServiceRestExHandle; ///< REST EX EFI handle associated with this Redfish service.
+ UINTN RedfishServiceVersion; ///< Redfish service version.
+ CHAR16 *RedfishServiceLocation; ///< Redfish service location.
+ CHAR16 *RedfishServiceUuid; ///< Redfish service UUID.
+ CHAR16 *RedfishServiceOs; ///< Redfish service OS.
+ CHAR16 *RedfishServiceOsVersion; ///< Redfish service OS version.
+ CHAR16 *RedfishServiceProduct; ///< Redfish service product name.
+ CHAR16 *RedfishServiceProductVer; ///< Redfish service product version.
+ BOOLEAN RedfishServiceUseHttps; ///< Redfish service uses HTTPS.
+} REDFISH_CONFIG_SERVICE_INFORMATION;
+
+/**
+ Initialize a configure handler of EDKII Redfish feature driver.
+
+ This function will be called by the EDKII Redfish config handler driver to
+ initialize the configure handler of each EDKII Redfish feature driver.
+
+ @param[in] This Pointer to EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+ @param[in] RedfishServiceinfo Redfish service information.
+
+ @retval EFI_SUCCESS The handler has been initialized successfully.
+ @retval EFI_DEVICE_ERROR Failed to create or configure the REST EX protocol instance.
+ @retval EFI_ALREADY_STARTED This handler has already been initialized.
+ @retval Other Error happens during the initialization.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_INIT) (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This,
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishServiceinfo
+ );
+
+/**
+ Stop a Redfish configure handler of EDKII Redfish feature driver.
+
+ @param[in] This Pointer to EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL instance.
+
+ @retval EFI_SUCCESS This handler has been stoped successfully.
+ @retval Others Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_STOP) (
+ IN EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *This
+ );
+
+struct _EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL {
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_INIT Init;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL_STOP Stop;
+};
+
+
+extern EFI_GUID gdkIIRedfishConfigHandlerProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h
new file mode 100644
index 00000000000..40a4231d5ad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Include/Protocol/EdkIIRedfishCredential.h
@@ -0,0 +1,101 @@
+/** @file
+ This file defines the EDKII_REDFISH_CREDENTIAL_PROTOCOL interface.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EDKII_REDFISH_CREDENTIAL_H_
+#define EDKII_REDFISH_CREDENTIAL_H_
+
+typedef struct _EDKII_REDFISH_CREDENTIAL_PROTOCOL EDKII_REDFISH_CREDENTIAL_PROTOCOL;
+
+#define EDKII_REDFISH_CREDENTIAL_PROTOCOL_GUID \
+ { \
+ 0x8804377, 0xaf7a, 0x4496, { 0x8a, 0x7b, 0x17, 0x59, 0x0, 0xe9, 0xab, 0x46 } \
+ }
+
+typedef enum {
+ AuthMethodNone, ///< No authentication is required.
+ AuthMethodHttpBasic, ///< Basic authentication is required.
+ AuthMethodRedfishSession, ///< Session authentication is required.
+ AuthMethodMax
+} EDKII_REDFISH_AUTH_METHOD;
+
+typedef enum {
+ ServiceStopTypeNone = 0, ///< Stop Redfsih service without reason.
+ ServiceStopTypeSecureBootDisabled, ///< Stop Redfsih service becasue EFI
+ ///< Secure Boot is disabled.
+ ServiceStopTypeExitBootService, ///< Stop Redfsih service becasue existing
+ ///< Boot Service.
+ ServiceStopTypeMax
+} EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE;
+
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CREDENTIAL_PROTOCOL_GET_AUTH_INFO) (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ );
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval Others Some error happened.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_REDFISH_CREDENTIAL_PROTOCOL_STOP_SERVICE) (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ );
+
+struct _EDKII_REDFISH_CREDENTIAL_PROTOCOL {
+ EDKII_REDFISH_CREDENTIAL_PROTOCOL_GET_AUTH_INFO GetAuthInfo;
+ EDKII_REDFISH_CREDENTIAL_PROTOCOL_STOP_SERVICE StopService;
+};
+
+extern EFI_GUID gEdkIIRedfishCredentialProtocolGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c
new file mode 100644
index 00000000000..33afadb366d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.c
@@ -0,0 +1,421 @@
+/** @file
+ UCS2 to UTF8 manipulation library.
+
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseUcs2Utf8Lib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Since each UCS2 character can be represented by 1-3 UTF8 encoded characters,
+ this function is used to retrieve the UTF8 encoding size for a UCS2 character.
+
+ @param[in] Utf8Buffer The buffer for UTF8 encoded data.
+
+ @retval Return the size of UTF8 encoding string or 0 if it is not for
+ UCS2 format.
+
+**/
+UINT8
+GetUTF8SizeForUCS2 (
+ IN CHAR8 *Utf8Buffer
+ )
+{
+ CHAR8 TempChar;
+ UINT8 Utf8Size;
+
+ ASSERT (Utf8Buffer != NULL);
+
+ TempChar = *Utf8Buffer;
+ if ((TempChar & 0xF0) == 0xF0) {
+
+ //
+ // This format is not for UCS2.
+ //
+ return 0;
+ }
+
+ Utf8Size = 1;
+ if ((TempChar & 0x80) == 0x80) {
+ if ((TempChar & 0xC0) == 0xC0) {
+
+ Utf8Size ++;
+ if ((TempChar & 0xE0) == 0xE0) {
+
+ Utf8Size ++;
+ }
+ }
+ }
+
+ return Utf8Size;
+}
+
+/**
+ Since each UCS2 character can be represented by the format: \uXXXX, this function
+ is used to retrieve the UCS2 character from a Unicode format.
+ Call MUST make sure there are at least 6 Bytes in the input UTF8 buffer.
+
+ @param[in] Utf8Buffer The buffer for UTF8 encoded data.
+ @param[out] Ucs2Char The converted UCS2 character.
+
+ @retval EFI_INVALID_PARAMETER Non-Ascii characters found in the hexadecimal
+ digits string, and can't be converted to a UCS2
+ character.
+ @retval EFI_SUCCESS The UCS2 character has been retrieved.
+
+**/
+EFI_STATUS
+GetUCS2CharByFormat (
+ IN CHAR8 *Utf8Buffer,
+ OUT CHAR16 *Ucs2Char
+ )
+{
+ UINT8 Num1;
+ UINT8 Num2;
+ UINT8 Index;
+ CHAR8 Ucs2CharFormat[UNICODE_FORMAT_CHAR_SIZE]; /// two Hexadecimal digits Ascii string, like "3F"
+
+ for (Index = 0; Index < 4; Index ++) {
+ if ((*(Utf8Buffer + 2 + Index) & 0x80) != 0x00) {
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ ZeroMem (Ucs2CharFormat, UNICODE_FORMAT_CHAR_SIZE);
+
+ //
+ // Get the First Number, Offset is 2
+ //
+ CopyMem (Ucs2CharFormat, Utf8Buffer + 2, UNICODE_FORMAT_CHAR_LEN);
+ Num1 = (UINT8) AsciiStrHexToUintn (Ucs2CharFormat);
+
+ //
+ // Get the Second Number, Offset is 4
+ //
+ CopyMem (Ucs2CharFormat, Utf8Buffer + 4, UNICODE_FORMAT_CHAR_LEN);
+ Num2 = (UINT8) AsciiStrHexToUintn (Ucs2CharFormat);
+
+ //
+ // Ucs2Char is Little-Endian
+ //
+ *((CHAR8 *) Ucs2Char) = Num2;
+ *(((CHAR8 *) Ucs2Char) + 1) = Num1;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a UCS2 character to UTF8 encoding string.
+
+ @param[in] Ucs2Char The provided UCS2 character.
+ @param[out] Utf8Buffer The converted UTF8 encoded data.
+
+ @retval Return the size of UTF8 encoding data for this UCS2 character.
+
+**/
+UINT8
+UCS2CharToUTF8 (
+ IN CHAR16 Ucs2Char,
+ OUT CHAR8 *Utf8Buffer
+ )
+{
+ UINT16 Ucs2Number;
+
+ ASSERT (Utf8Buffer != NULL);
+
+ Ucs2Number = (UINT16) Ucs2Char;
+ if (Ucs2Number <= 0x007F) {
+
+ //
+ // UTF8 format: 0xxxxxxx
+ //
+ *Utf8Buffer = Ucs2Char & 0x7F;
+ return 1;
+
+ } else if (Ucs2Number >= 0x0080 && Ucs2Number <= 0x07FF) {
+
+ //
+ // UTF8 format: 110xxxxx 10xxxxxx
+ //
+ *(Utf8Buffer + 1) = (Ucs2Char & 0x3F) | 0x80;
+ *Utf8Buffer = ((Ucs2Char >> 6) & 0x1F) | 0xC0;
+ return 2;
+
+ } else { /// Ucs2Number >= 0x0800 && Ucs2Number <= 0xFFFF
+
+ //
+ // UTF8 format: 1110xxxx 10xxxxxx 10xxxxxx
+ //
+ *(Utf8Buffer + 2) = (Ucs2Char & 0x3F) | 0x80;
+ *(Utf8Buffer + 1) = ((Ucs2Char >> 6) & 0x3F) | 0x80;
+ *Utf8Buffer = ((Ucs2Char >> 12) & 0x0F) | 0xE0;
+ return 3;
+ }
+}
+
+/**
+ Convert a UTF8 encoded data to a UCS2 character.
+
+ @param[in] Utf8Buffer The provided UTF8 encoded data.
+ @param[out] Ucs2Char The converted UCS2 character.
+
+ @retval EFI_INVALID_PARAMETER The UTF8 encoded string is not valid or
+ not for UCS2 character.
+ @retval EFI_SUCCESS The converted UCS2 character.
+
+**/
+EFI_STATUS
+UTF8ToUCS2Char (
+ IN CHAR8 *Utf8Buffer,
+ OUT CHAR16 *Ucs2Char
+ )
+{
+ UINT8 Utf8Size;
+ CHAR8 *Ucs2Buffer;
+ CHAR8 TempChar1;
+ CHAR8 TempChar2;
+ CHAR8 TempChar3;
+
+ ASSERT (Utf8Buffer != NULL && Ucs2Char != NULL);
+ ZeroMem (Ucs2Char, sizeof (CHAR16));
+ Ucs2Buffer = (CHAR8 *) Ucs2Char;
+
+ Utf8Size = GetUTF8SizeForUCS2 (Utf8Buffer);
+ switch (Utf8Size) {
+
+ case 1:
+
+ //
+ // UTF8 format: 0xxxxxxx
+ //
+ TempChar1 = *Utf8Buffer;
+ if ((TempChar1 & 0x80) != 0x00) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Ucs2Buffer = TempChar1;
+ *(Ucs2Buffer + 1) = 0;
+ break;
+
+ case 2:
+
+ //
+ // UTF8 format: 110xxxxx 10xxxxxx
+ //
+ TempChar1 = *Utf8Buffer;
+ if ((TempChar1 & 0xE0) != 0xC0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempChar2 = *(Utf8Buffer + 1);
+ if ((TempChar2 & 0xC0) != 0x80) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Ucs2Buffer = (TempChar1 << 6) + (TempChar2 & 0x3F);
+ *(Ucs2Buffer + 1) = (TempChar1 >> 2) & 0x07;
+ break;
+
+ case 3:
+
+ //
+ // UTF8 format: 1110xxxx 10xxxxxx 10xxxxxx
+ //
+ TempChar1 = *Utf8Buffer;
+ if ((TempChar1 & 0xF0) != 0xE0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempChar2 = *(Utf8Buffer + 1);
+ if ((TempChar2 & 0xC0) != 0x80) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ TempChar3 = *(Utf8Buffer + 2);
+ if ((TempChar3 & 0xC0) != 0x80) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Ucs2Buffer = (TempChar2 << 6) + (TempChar3 & 0x3F);
+ *(Ucs2Buffer + 1) = (TempChar1 << 4) + ((TempChar2 >> 2) & 0x0F);
+
+ break;
+
+ default:
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a UCS2 string to a UTF8 encoded string.
+
+ @param[in] Ucs2Str The provided UCS2 string.
+ @param[out] Utf8StrAddr The converted UTF8 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UTF8 encoded string has been converted.
+
+**/
+EFI_STATUS
+UCS2StrToUTF8 (
+ IN CHAR16 *Ucs2Str,
+ OUT CHAR8 **Utf8StrAddr
+ )
+{
+ UINTN Ucs2StrIndex;
+ UINTN Ucs2StrLength;
+ CHAR8 *Utf8Str;
+ UINTN Utf8StrLength;
+ UINTN Utf8StrIndex;
+ CHAR8 Utf8Buffer[UTF8_BUFFER_FOR_UCS2_MAX_SIZE];
+ UINT8 Utf8BufferSize;
+
+ if (Ucs2Str == NULL || Utf8StrAddr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ucs2StrLength = StrLen (Ucs2Str);
+ Utf8StrLength = 0;
+
+ for (Ucs2StrIndex = 0; Ucs2StrIndex < Ucs2StrLength; Ucs2StrIndex ++) {
+
+ ZeroMem (Utf8Buffer, sizeof (Utf8Buffer));
+ Utf8BufferSize = UCS2CharToUTF8 (Ucs2Str[Ucs2StrIndex], Utf8Buffer);
+ Utf8StrLength += Utf8BufferSize;
+ }
+
+ Utf8Str = AllocateZeroPool (Utf8StrLength + 1);
+ if (Utf8Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Utf8StrIndex = 0;
+ for (Ucs2StrIndex = 0; Ucs2StrIndex < Ucs2StrLength; Ucs2StrIndex ++) {
+
+ ZeroMem (Utf8Buffer, sizeof (Utf8Buffer));
+ Utf8BufferSize = UCS2CharToUTF8 (Ucs2Str[Ucs2StrIndex], Utf8Buffer);
+
+ CopyMem (Utf8Str + Utf8StrIndex, Utf8Buffer, Utf8BufferSize);
+ Utf8StrIndex += Utf8BufferSize;
+ }
+
+ Utf8Str[Utf8StrIndex] = '\0';
+ *Utf8StrAddr = Utf8Str;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Convert a UTF8 encoded string to a UCS2 string.
+
+ @param[in] Utf8Str The provided UTF8 encoded string.
+ @param[out] Ucs2StrAddr The converted UCS2 string address. Caller
+ is responsible for Free this string.
+
+ @retval EFI_INVALID_PARAMETER The UTF8 encoded string is not valid to
+ convert to UCS2 string.
+ One or more parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES System runs out of resources.
+ @retval EFI_SUCCESS The UCS2 string has been converted.
+
+**/
+EFI_STATUS
+UTF8StrToUCS2 (
+ IN CHAR8 *Utf8Str,
+ OUT CHAR16 **Ucs2StrAddr
+ )
+{
+ EFI_STATUS Status;
+ UINTN Utf8StrIndex;
+ UINTN Utf8StrLength;
+ UINTN Ucs2StrIndex;
+ UINT8 Utf8BufferSize;
+ CHAR16 *Ucs2StrTemp;
+
+ if (Utf8Str == NULL || Ucs2StrAddr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // It is not an Ascii string, calculate string length.
+ //
+ Utf8StrLength = 0;
+ while (*(Utf8Str + Utf8StrLength) != '\0') {
+ Utf8StrLength ++;
+ }
+
+ //
+ // UCS2 string shall not be longer than the UTF8 string.
+ //
+ Ucs2StrTemp = AllocateZeroPool ((Utf8StrLength + 1) * sizeof (CHAR16));
+ if (Ucs2StrTemp == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Utf8StrIndex = 0;
+ Ucs2StrIndex = 0;
+ while (Utf8Str[Utf8StrIndex] != '\0') {
+
+ if (CompareMem (Utf8Str + Utf8StrIndex, "\\u", 2) == 0 &&
+ Utf8StrLength - Utf8StrIndex >= UNICODE_FORMAT_LEN) {
+
+ Status = GetUCS2CharByFormat (Utf8Str + Utf8StrIndex, Ucs2StrTemp + Ucs2StrIndex);
+ if (!EFI_ERROR (Status)) {
+
+ Utf8StrIndex += UNICODE_FORMAT_LEN;
+ Ucs2StrIndex ++;
+ } else {
+
+ StrCpyS (Ucs2StrTemp + Ucs2StrIndex, 3, L"\\u");
+
+ Ucs2StrIndex += 2;
+ Utf8StrIndex += 2;
+ }
+ } else {
+
+ Utf8BufferSize = GetUTF8SizeForUCS2 (Utf8Str + Utf8StrIndex);
+ if (Utf8BufferSize == 0 || Utf8StrLength - Utf8StrIndex < Utf8BufferSize) {
+
+ FreePool (Ucs2StrTemp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = UTF8ToUCS2Char (Utf8Str + Utf8StrIndex, Ucs2StrTemp + Ucs2StrIndex);
+ if (EFI_ERROR (Status)) {
+
+ FreePool (Ucs2StrTemp);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ucs2StrIndex ++;
+ Utf8StrIndex += Utf8BufferSize;
+ }
+ }
+
+ *Ucs2StrAddr = AllocateZeroPool ((Ucs2StrIndex + 1) * sizeof (CHAR16));
+ if (*Ucs2StrAddr == NULL) {
+
+ FreePool (Ucs2StrTemp);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrCpyS (*Ucs2StrAddr, Ucs2StrIndex + 1, Ucs2StrTemp);
+ *(*Ucs2StrAddr + Ucs2StrIndex) = L'\0';
+ FreePool (Ucs2StrTemp);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
new file mode 100644
index 00000000000..6b1c315100c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
@@ -0,0 +1,31 @@
+## @file
+# UCS2 to UTF8 manipulation library.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = BaseUcs2Utf8Lib
+ FILE_GUID = 536646C3-46D0-4B12-ABC4-CDE1A33B5256
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Ucs2Utf8Lib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ BaseUcs2Utf8Lib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c
new file mode 100644
index 00000000000..4c76166d12f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.c
@@ -0,0 +1,166 @@
+/** @file
+ This library provides help functions for REST EX Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Http.h>
+#include <Protocol/RestEx.h>
+
+#define REST_EX_CONFIG_DATA_LEN_UNKNOWN 0xff
+
+/**
+ This function allows the caller to create child handle for specific
+ REST server.
+
+ @param[in] Image The image handle used to open service.
+ @param[in] AccessMode Access mode of REST server.
+ @param[in] ConfigType Underlying configuration to communicate with REST server.
+ @param[in] ServiceType REST service type.
+ @param[out] ChildInstanceHandle The handle to receive the create child.
+
+ @retval EFI_SUCCESS Can't create the corresponding REST EX child instance.
+ @retval EFI_INVALID_PARAMETERS Any of input parameters is improper.
+
+**/
+EFI_STATUS
+RestExLibCreateChild (
+ IN EFI_HANDLE Image,
+ IN EFI_REST_EX_SERVICE_ACCESS_MODE AccessMode,
+ IN EFI_REST_EX_CONFIG_TYPE ConfigType,
+ IN EFI_REST_EX_SERVICE_TYPE ServiceType,
+ OUT EFI_HANDLE *ChildInstanceHandle
+)
+{
+ EFI_STATUS Status;
+ UINTN NoBuffer;
+ EFI_HANDLE *Handle;
+ EFI_HANDLE ChildHandle;
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_REST_EX_SERVICE_INFO *RestExServiceInfo;
+ UINT8 LenOfConfig;
+
+ if (Image == NULL ||
+ AccessMode >= EfiRestExServiceModeMax ||
+ ConfigType >= EfiRestExConfigTypeMax ||
+ ServiceType >= EfiRestExServiceTypeMax ||
+ ChildInstanceHandle == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ChildInstanceHandle = NULL;
+ //
+ // Locate all REST EX binding service.
+ //
+ Handle = NULL;
+ NoBuffer = 0;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiRestExServiceBindingProtocolGuid,
+ NULL,
+ &NoBuffer,
+ &Handle
+ );
+ if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+ return Status;
+ }
+ Handle = (EFI_HANDLE *)AllocateZeroPool (sizeof(EFI_HANDLE) * NoBuffer);
+ if (Handle == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiRestExServiceBindingProtocolGuid,
+ NULL,
+ &NoBuffer,
+ &Handle
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (Handle);
+ return Status;
+ }
+
+ //
+ // Search for the proper REST EX instance.
+ //
+ while (NoBuffer != 0) {
+ ChildHandle = NULL;
+ Status = NetLibCreateServiceChild (
+ *(Handle + (NoBuffer - 1)),
+ Image,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &ChildHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **)&RestEx,
+ Image,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the information of REST service provided by this EFI REST EX driver
+ //
+ Status = RestEx->GetService (
+ RestEx,
+ &RestExServiceInfo
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Check REST EX property.
+ //
+ switch (ConfigType) {
+ case EfiRestExConfigHttp:
+ LenOfConfig = sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);
+ break;
+
+ case EfiRestExConfigUnspecific:
+ LenOfConfig = REST_EX_CONFIG_DATA_LEN_UNKNOWN;
+ break;
+
+ default:
+ goto ON_ERROR;
+ }
+ if (RestExServiceInfo->EfiRestExServiceInfoV10.RestServiceAccessMode != AccessMode ||
+ RestExServiceInfo->EfiRestExServiceInfoV10.RestServiceType != ServiceType ||
+ RestExServiceInfo->EfiRestExServiceInfoV10.RestExConfigType != ConfigType ||
+ ((LenOfConfig != REST_EX_CONFIG_DATA_LEN_UNKNOWN) && (RestExServiceInfo->EfiRestExServiceInfoV10.RestExConfigDataLength != LenOfConfig))) {
+ goto ON_ERROR;
+ }
+ }
+ //
+ // This is proper REST EX instance.
+ //
+ *ChildInstanceHandle = ChildHandle;
+ FreePool (Handle);
+ return EFI_SUCCESS;
+
+ON_ERROR:;
+ NetLibDestroyServiceChild (
+ *(Handle + (NoBuffer - 1)),
+ Image,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ChildHandle
+ );
+ NoBuffer --;
+ };
+ FreePool (Handle);
+ return EFI_NOT_FOUND;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
new file mode 100644
index 00000000000..416dc630510
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Library for REST EX Protocol
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = DxeRestExLib
+ FILE_GUID = E9CBF727-8AF3-4602-9DBD-A3942869B5AE
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RestExLib | DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC RISCV64
+#
+
+[Sources.common]
+ DxeRestExLib.c
+
+[Packages]
+ NetworkPkg/NetworkPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ NetLib
+ PrintLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## PROTOCOL ALWAYS_CONSUMED
+ gEfiRestExProtocolGuid ## PROTOCOL ALWAYS_CONSUMED
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c
new file mode 100644
index 00000000000..c05ba965390
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.c
@@ -0,0 +1,983 @@
+/** @file
+ APIs for JSON operations. The fuctions provided by this library are the
+ wrapper to native open source jansson library. See below document for
+ the API reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html
+
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Uefi.h>
+#include <Library/JsonLib.h>
+#include <Library/BaseUcs2Utf8Lib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "jansson.h"
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON array,
+ or NULL on error. Initially, the array is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON array or NULL if intial a JSON array
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitArray (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_array();
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON object,
+ or NULL on error. Initially, the object is empty.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @retval The created JSON value which contains a JSON object or NULL if intial a JSON object
+ is failed.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitObject (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_object();
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input string must be NULL terminated Ascii format, non-Ascii characters will
+ be processed as an error. Unicode characters can also be represented by Ascii string
+ as the format: \u + 4 hexadecimal digits, like \u3E5A, or \u003F.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Ascii string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitAsciiString (
+ IN CONST CHAR8 *String
+ )
+{
+ UINTN Index;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ while (*(String + Index) != '\0') {
+ if (((*(String + Index)) & 0x80) != 0x00) {
+ return NULL;
+ }
+
+ Index++;
+ }
+
+ return (EDKII_JSON_VALUE)json_string (String);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON string,
+ or NULL on error.
+
+ The input must be a NULL terminated UCS2 format Unicode string.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] String The Unicode string to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON string or NULL. Select a
+ Getter API for a specific encoding format.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitUnicodeString (
+ IN CHAR16 *String
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *Utf8Str;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ Utf8Str = NULL;
+ Status = UCS2StrToUTF8 (String, &Utf8Str);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_VALUE)json_string (Utf8Str);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON integer,
+ or NULL on error.
+
+ The reference count of this value will be set to 1, and caller needs to cleanup the
+ value by calling JsonValueFree().
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] Value The integer to initialize to JSON value
+
+ @retval The created JSON value which contains a JSON number or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNumber (
+ IN INT64 Value
+ )
+{
+ return (EDKII_JSON_VALUE)json_integer (Value);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON boolean,
+ or NULL on error.
+
+ Boolean JSON value is kept as static value, and no need to do any cleanup work.
+
+ @param[in] Value The boolean value to initialize.
+
+ @retval The created JSON value which contains a JSON boolean or NULL.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitBoolean (
+ IN BOOLEAN Value
+ )
+{
+ return (EDKII_JSON_VALUE)json_boolean (Value);
+}
+
+/**
+ The function is used to initialize a JSON value which contains a new JSON NULL,
+ or NULL on error.
+
+ NULL JSON value is kept as static value, and no need to do any cleanup work.
+
+ @retval The created NULL JSON value.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueInitNull (
+ VOID
+ )
+{
+ return (EDKII_JSON_VALUE)json_null();
+}
+
+/**
+ The function is used to decrease the reference count of a JSON value by one, and once
+ this reference count drops to zero, the value is destroyed and it can no longer be used.
+ If this destroyed value is object type or array type, reference counts for all containing
+ JSON values will be decreased by 1. Boolean JSON value and NULL JSON value won't be destroyed
+ since they are static values kept in memory.
+
+ Reference Count Strategy: BaseJsonLib uses this strategy to track whether a value is still
+ in use or not. When a value is created, it's reference count is set to 1. If a reference to a
+ value is kept for use, its reference count is incremented, and when the value is no longer
+ needed, the reference count is decremented. When the reference count drops to zero, there are
+ no references left, and the value can be destroyed.
+
+ The given JSON value maybe NULL and not causing any problem. Just output the debug message
+ to inform caller the NULL value is passed in.
+
+ @param[in] Json The JSON value to be freed. json_decref may return without any
+ changes if Json is NULL.
+
+**/
+VOID
+EFIAPI
+JsonValueFree (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ json_decref((json_t *)Json);
+}
+
+/**
+ The function is used to create a fresh copy of a JSON value, and all child values are deep
+ copied in a recursive fashion. It should be called when this JSON value might be modified
+ in later use, but the original still wants to be used in somewhere else.
+
+ Reference counts of the returned root JSON value and all child values will be set to 1, and
+ caller needs to cleanup the root value by calling JsonValueFree().
+
+ * Note: Since this function performs a copy from bottom to up, too many calls may cause some
+ performance issues, user should avoid unnecessary calls to this function unless it is really
+ needed.
+
+ @param[in] Json The JSON value to be cloned.
+
+ @retval Return the cloned JSON value, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonValueClone (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return (EDKII_JSON_VALUE)json_deep_copy ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON array.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON array.
+ @retval FALSE The JSON value doesn't contain a JSON array.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsArray (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_array ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON object.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON object.
+ @retval FALSE The JSON value doesn't contain a JSON object.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsObject (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_object ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON Value contains a string, Ascii or
+ Unicode format is not differentiated.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON string.
+ @retval FALSE The JSON value doesn't contain a JSON string.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_string ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON number.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value is contains JSON number.
+ @retval FALSE The JSON value doesn't contain a JSON number.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNumber (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_integer ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON boolean.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON boolean.
+ @retval FALSE The JSON value doesn't contain a JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsBoolean (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_boolean ((json_t *) Json);
+}
+
+/**
+ The function is used to return if the provided JSON value contains a JSON NULL.
+
+ @param[in] Json The provided JSON value.
+
+ @retval TRUE The JSON value contains a JSON NULL.
+ @retval FALSE The JSON value doesn't contain a JSON NULL.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueIsNull (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_is_null ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated array in an array type JSON value.
+
+ Any changes to the returned array will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated array in JSON value or NULL.
+
+**/
+EDKII_JSON_ARRAY
+EFIAPI
+JsonValueGetArray (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (Json == NULL || !JsonValueIsArray (Json)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_ARRAY)Json;
+}
+
+/**
+ The function is used to retrieve the associated object in an object type JSON value.
+
+ Any changes to the returned object will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated object in JSON value or NULL.
+
+**/
+EDKII_JSON_OBJECT
+EFIAPI
+JsonValueGetObject (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (Json == NULL || !JsonValueIsObject (Json)) {
+ return NULL;
+ }
+
+ return (EDKII_JSON_OBJECT)Json;
+}
+
+/**
+ The function is used to retrieve the associated Ascii string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL.
+
+**/
+CONST CHAR8 *
+EFIAPI
+JsonValueGetAsciiString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ CONST CHAR8 *AsciiStr;
+ UINTN Index;
+
+ AsciiStr = json_string_value ((json_t *) Json);
+ if (AsciiStr == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ while (*(AsciiStr + Index) != '\0') {
+ if (((*(AsciiStr + Index)) & 0x80) != 0x00) {
+ return NULL;
+ }
+
+ Index++;
+ }
+
+ return AsciiStr;
+}
+
+/**
+ The function is used to retrieve the associated Unicode string in a string type JSON value.
+
+ Caller can do any changes to the returned string without any impact to the original JSON
+ value, and caller needs to free the returned string using FreePool().
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Unicode string in JSON value or NULL.
+
+**/
+CHAR16*
+EFIAPI
+JsonValueGetUnicodeString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR8 *Utf8Str;
+ CHAR16 *Ucs2Str;
+
+ Utf8Str = json_string_value ((json_t *) Json);
+ if (Utf8Str == NULL) {
+ return NULL;
+ }
+
+ Status = UTF8StrToUCS2 ((CHAR8*)Utf8Str, &Ucs2Str);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return Ucs2Str;
+}
+
+/**
+ The function is used to retrieve the associated integer in a number type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON number, otherwise it will
+ ASSERT() and return 0.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated number in JSON value.
+
+**/
+INT64
+EFIAPI
+JsonValueGetNumber (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ ASSERT (Json != NULL && JsonValueIsNumber (Json));
+ if (Json == NULL || !JsonValueIsNumber (Json)) {
+ return 0;
+ }
+
+ return json_integer_value ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated boolean in a boolean type JSON value.
+
+ The input JSON value should not be NULL or contain no JSON boolean, otherwise it will
+ ASSERT() and return FALSE.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated value of JSON boolean.
+
+**/
+BOOLEAN
+EFIAPI
+JsonValueGetBoolean (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ ASSERT (Json != NULL && JsonValueIsBoolean (Json));
+ if (Json == NULL || !JsonValueIsBoolean (Json)) {
+ return FALSE;
+ }
+
+ return json_is_true ((json_t *) Json);
+}
+
+/**
+ The function is used to retrieve the associated string in a string type JSON value.
+
+ Any changes to the returned string will impact the original JSON value.
+
+ @param[in] Json The provided JSON value.
+
+ @retval Return the associated Ascii string in JSON value or NULL on errors.
+
+**/
+CONST CHAR8*
+EFIAPI
+JsonValueGetString (
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ return json_string_value ((const json_t *)Json);
+}
+
+/**
+ The function is used to get the number of elements in a JSON object, or 0 if it is NULL or
+ not a JSON object.
+
+ @param[in] JsonObject The provided JSON object.
+
+ @retval Return the number of elements in this JSON object or 0.
+
+**/
+UINTN
+EFIAPI
+JsonObjectSize (
+ IN EDKII_JSON_OBJECT JsonObject
+ )
+{
+ return json_object_size ((json_t *) JsonObject);
+}
+
+/**
+ The function is used to enumerate all keys in a JSON object.
+
+ Caller should be responsible to free the returned key array reference using
+ FreePool(). But contained keys are read only and must not be modified or freed.
+
+ @param[in] JsonObj The provided JSON object for enumeration.
+ @param[out] KeyCount The count of keys in this JSON object.
+
+ @retval Return an array of the enumerated keys in this JSON object or NULL if
+ JsonObj is not an JSON object, key count is zero or on other errors.
+
+**/
+CHAR8**
+JsonObjectGetKeys (
+ IN EDKII_JSON_OBJECT JsonObj,
+ OUT UINTN *KeyCount
+ )
+{
+
+ UINTN Index;
+ CONST CHAR8 **KeyArray;
+ CONST CHAR8 *Key;
+ EDKII_JSON_VALUE Value;
+
+ if (JsonObj == NULL || KeyCount == NULL) {
+ return NULL;
+ }
+
+ Index = 0;
+ json_object_foreach(JsonObj, Key, Value) {
+ Index++;
+ }
+ if (Index == 0) {
+ *KeyCount = 0;
+ return NULL;
+ }
+
+ *KeyCount = Index;
+ KeyArray = (CONST CHAR8 **) AllocateZeroPool (*KeyCount * sizeof (CHAR8 *));
+ if (KeyArray == NULL) {
+ return NULL;
+ }
+
+ Key = NULL;
+ Value = NULL;
+ Index = 0;
+ json_object_foreach((json_t *) JsonObj, Key, Value) {
+ KeyArray[Index] = Key;
+ Index++;
+ }
+
+ return (CHAR8 **)KeyArray;
+}
+
+/**
+ The function is used to get a JSON value corresponding to the input key from a JSON object.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. NULL will be returned when
+ Key-Value is not found in this JSON object.
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be retrieved.
+
+ @retval Return the corresponding JSON value to key, or NULL on error.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectGetValue (
+ IN CONST EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key
+ )
+{
+ return (EDKII_JSON_VALUE)json_object_get ((const json_t *)JsonObj, (const char *)Key);
+}
+
+/**
+ The function is used to set a JSON value corresponding to the input key from a JSON object,
+ and the reference count of this value will be increased by 1.
+
+ Input key must be a valid NULL terminated UTF8 encoded string. If there already is a value for
+ this key, this key will be assigned to the new JSON value. The old JSON value will be removed
+ from this object and thus its' reference count will be decreased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonObj The provided JSON object.
+ @param[in] Key The key of the JSON value to be set.
+ @param[in] Json The JSON value to set to this JSON object mapped by key.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON value has been set to this JSON object.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonObjectSetValue (
+ IN EDKII_JSON_OBJECT JsonObj,
+ IN CONST CHAR8 *Key,
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (json_object_set ((json_t *) JsonObj, Key, (json_t *) Json) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ The function is used to get the number of elements in a JSON array. Returns or 0 if JsonArray
+ is NULL or not a JSON array.
+
+ @param[in] JsonArray The provided JSON array.
+
+ @retval Return the number of elements in this JSON array or 0.
+
+**/
+UINTN
+EFIAPI
+JsonArrayCount (
+ IN EDKII_JSON_ARRAY JsonArray
+ )
+{
+ return json_array_size ((json_t *) JsonArray);
+}
+
+/**
+ The function is used to return the JSON value in the array at position index. The valid range
+ for this index is from 0 to the return value of JsonArrayCount() minus 1.
+
+ It only returns a reference to this value and any changes on this value will impact the
+ original JSON object. If that is not expected, please call JsonValueClone() to clone it to
+ use.
+
+ If this array is NULL or not a JSON array, or if index is out of range, NULL will be returned.
+
+ @param[in] JsonArray The provided JSON Array.
+
+ @retval Return the JSON value located in the Index position or
+ NULL if JsonArray is not an array or no items in the array.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonArrayGetValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ )
+{
+ return (EDKII_JSON_VALUE)json_array_get ((json_t *) JsonArray, Index);
+}
+
+/**
+ The function is used to append a JSON value to the end of the JSON array, and grow the size of
+ array by 1. The reference count of this value will be increased by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON object.
+ @param[in] Json The JSON value to append.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS JSON value has been appended to the end of the JSON array.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayAppendValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN EDKII_JSON_VALUE Json
+ )
+{
+ if (json_array_append ((json_t *) JsonArray, (json_t *) Json) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ The function is used to remove a JSON value at position index, shifting the elements after index
+ one position towards the start of the array. The reference count of this value will be decreased
+ by 1.
+
+ More details for reference count strategy can refer to the API description for JsonValueFree().
+
+ @param[in] JsonArray The provided JSON array.
+ @param[in] Index The Index position before removement.
+
+ @retval EFI_ABORTED Some error occur and operation aborted.
+ @retval EFI_SUCCESS The JSON array has been removed at position index.
+
+**/
+EFI_STATUS
+EFIAPI
+JsonArrayRemoveValue (
+ IN EDKII_JSON_ARRAY JsonArray,
+ IN UINTN Index
+ )
+{
+ if (json_array_remove ((json_t *) JsonArray, Index) != 0) {
+ return EFI_ABORTED;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+/**
+ Dump JSON to a buffer.
+
+ @param[in] JsonValue The provided JSON value.
+ @param[in] Flags The Index position before removement. The value
+ could be the combination of below flags.
+ - EDKII_JSON_INDENT(n)
+ - EDKII_JSON_COMPACT
+ - EDKII_JSON_ENSURE_ASCII
+ - EDKII_JSON_SORT_KEYS
+ - EDKII_JSON_PRESERVE_ORDER
+ - EDKII_JSON_ENCODE_ANY
+ - EDKII_JSON_ESCAPE_SLASH
+ - EDKII_JSON_REAL_PRECISION(n)
+ - EDKII_JSON_EMBED
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html#encoding
+
+ @retval CHAR8 * Dump fail if NULL returned, otherwise the buffer
+ contain JSON paylaod in ASCII string. The return
+ value must be freed by the caller using FreePool().
+**/
+CHAR8 *
+EFIAPI
+JsonDumpString (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN UINTN Flags
+ )
+{
+ if (JsonValue == NULL) {
+ return NULL;
+ }
+ return json_dumps((json_t *)JsonValue, Flags);
+}
+
+/**
+ Convert a string to JSON object.
+ The function is used to convert a NULL terminated CHAR8 string to a JSON
+ value. Only object and array represented strings can be converted successfully,
+ since they are the only valid root values of a JSON text for UEFI usage.
+
+ Real number and number with exponent part are not supportted by UEFI.
+
+ Caller needs to cleanup the root value by calling JsonValueFree().
+
+ @param[in] String The NULL terminated CHAR8 string to convert.
+
+ @retval Array JSON value or object JSON value, or NULL when any error occurs.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadString (
+ IN CONST CHAR8* String
+ )
+{
+ json_error_t JsonError;
+
+ return (EDKII_JSON_VALUE) json_loads ((const char *)String, 0, &JsonError);
+}
+
+/**
+ Load JSON from a buffer.
+
+ @param[in] Buffer Bufffer to the JSON payload
+ @param[in] BufferLen Length of the buffer
+ @param[in] Flags Flag of loading JSON buffer, the value
+ could be the combination of below flags.
+ - EDKII_JSON_REJECT_DUPLICATES
+ - EDKII_JSON_DISABLE_EOF_CHECK
+ - EDKII_JSON_DECODE_ANY
+ - EDKII_JSON_DECODE_INT_AS_REAL
+ - EDKII_JSON_ALLOW_NUL
+ See below URI for the JSON encoding flags reference.
+ https://jansson.readthedocs.io/en/2.13/apiref.html?highlight=json_loadb#decoding
+
+ @param[in,out] Error Pointer EDKII_JSON_ERROR structure
+
+ @retval EDKII_JSON_VALUE NULL means fail to load JSON payload.
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonLoadBuffer (
+ IN CONST CHAR8 *Buffer,
+ IN UINTN BufferLen,
+ IN UINTN Flags,
+ IN OUT EDKII_JSON_ERROR *Error
+ )
+{
+ return json_loadb(Buffer, BufferLen, Flags, (json_error_t *)Error);
+}
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ when the value is no longer needed, the reference count is decremented.
+ When the reference count drops to zero, there are no references left and the
+ value can be destroyed.
+
+ This funciton decrement the reference count of EDKII_JSON_VALUE. As soon as
+ a call to json_decref() drops the reference count to zero, the value is
+ destroyed and it can no longer be used.
+
+ @param[in] JsonValue JSON value
+**/
+VOID
+EFIAPI
+JsonDecreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ json_decref (JsonValue);
+}
+
+/**
+ The reference count is used to track whether a value is still in use or not.
+ When a value is created, it's reference count is set to 1.
+ If a reference to a value is kept (e.g. a value is stored somewhere for later use),
+ its reference count is incremented.
+
+ This function increment the reference count of json if it's not NULL.
+ Returns EDKII_JSON_VALUE.
+
+ @param[in] JsonValue JSON value
+ @retval EDKII_JSON_VALUE of itself
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonIncreaseReference (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return json_incref (JsonValue);
+}
+
+/**
+ Returns an opaque iterator which can be used to iterate over all key-value pairs
+ in object, or NULL if object is empty.
+
+ @param[in] JsonValue JSON value
+ @retval Iterator pointer
+**/
+VOID *
+EFIAPI
+JsonObjectIterator (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return json_object_iter (JsonValue);
+}
+
+/**
+ Extract the associated value from iterator.
+
+ @param[in] Iterator Iterator pointer
+ @retval EDKII_JSON_VALUE
+**/
+EDKII_JSON_VALUE
+EFIAPI
+JsonObjectIteratorValue (
+ IN VOID *Iterator
+ )
+{
+ return json_object_iter_value(Iterator);
+}
+
+/**
+ Returns an iterator pointing to the next key-value pair in object after iter,
+ or NULL if the whole object has been iterated through.
+
+ @param[in] JsonValue JSON value
+ @param[in] Iterator Iterator pointer
+ @retval Iterator pointer
+**/
+VOID *
+JsonObjectIteratorNext (
+ IN EDKII_JSON_VALUE JsonValue,
+ IN VOID *Iterator
+ )
+{
+ return json_object_iter_next(JsonValue, Iterator);
+}
+
+/**
+ Returns the json type of this json value.
+
+ @param[in] JsonValue JSON value
+ @retval JSON type returned
+**/
+EDKII_JSON_TYPE
+EFIAPI
+JsonGetType (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ return ((json_t *)JsonValue)->type;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf
new file mode 100644
index 00000000000..bcc93550c86
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/JsonLib.inf
@@ -0,0 +1,87 @@
+## @file
+# Thirty party Jansson library for JSON operations.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = JsonLib
+ FILE_GUID = F5E36815-305A-4C5A-9D75-4F2149E45255
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = JsonLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ #
+ # Below are the source code of third
+ # party jansson library.
+ #
+ jansson/src/dump.c
+ jansson/src/error.c
+ jansson/src/hashtable.c
+ jansson/src/hashtable_seed.c
+ jansson/src/memory.c
+ jansson/src/pack_unpack.c
+ jansson/src/strbuffer.c
+ jansson/src/strconv.c
+ jansson/src/utf.c
+ jansson/src/value.c
+ jansson/src/version.c
+ #
+ # Below are the source of edk2 JsonLib.
+ #
+ JsonLib.c
+ jansson_config.h
+ jansson_private_config.h
+ #
+ # Below is the source code override to fix the build issue.
+ # Add code in load.c to conditionally use stdin according
+ # to HAVE_UNISTD_H macro. The PR is submitted to jansson
+ # open source community.
+ # https://github.com/akheron/jansson/pull/558
+ #
+ load.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ Ucs2Utf8Lib
+ RedfishCrtLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ UefiRuntimeServicesTableLib
+ UefiLib
+
+[BuildOptions]
+ #
+ # Disables the following Visual Studio compiler warnings
+ # so we do not break the build with /WX option:
+ # C4090: 'function' : different 'const' qualifiers
+ # C4244: conversion from type1 to type2, possible loss of data
+ # C4334: 32-bit shift implicitly converted to 64-bit
+ # C4204: nonstandard extension used: non-constant aggregate initializer
+ # C4706: assignment within conditional expression
+ #
+ # Define macro HAVE_CONFIG_H to include jansson_private_config.h to build.
+ # Undefined _WIN32, WIN64, _MSC_VER macros
+ # On GCC, no error on the unused-function and unused-but-set-variable.
+ #
+ MSFT:*_*_X64_CC_FLAGS = /wd4204 /wd4244 /wd4090 /wd4334 /wd4706 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER
+ MSFT:*_*_IA32_CC_FLAGS = /wd4204 /wd4244 /wd4090 /wd4706 /DHAVE_CONFIG_H=1 /U_WIN32 /UWIN64 /U_MSC_VER
+ GCC:*_*_*_CC_FLAGS = -Wno-unused-function -Wno-unused-but-set-variable
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst
new file mode 100644
index 00000000000..75e7cc437fd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/Readme.rst
@@ -0,0 +1,35 @@
+=============================================================================
+ Introduction
+=============================================================================
+ Jansson is a C library for encoding, decoding and manipulating JSON data.
+Its main features and design principles are:
+
+ - Simple and intuitive API and data model
+ - Comprehensive documentation
+ - No dependencies on other libraries
+ - Full Unicode support (UTF-8)
+ - Extensive test suite
+
+ Jansson is licensed under the MIT license(refer to ReadMe.rst under edk2).
+It is used in production and its API is stable. It works on numerous
+platforms, including numerous Unix like systems and Windows. It's suitable
+for use on any system, including desktop, server, and small embedded systems.
+
+ In UEFI/EDKII environment, Redfish project consumes jansson to achieve JSON
+operations.
+
+* Jansson version on edk2: 2.13.1, API reference is on the below URL,
+ https://jansson.readthedocs.io/en/2.13/apiref.html
+
+* EDKII jansson library wrapper:
+ - JsonLib.h:
+ This is the denifitions of EDKII JSON APIs which are mapped to
+ jannson funcitons accordingly.
+
+*Known issue:
+ Build fail with jansson/src/load.c, add code in load.c to conditionally
+ use stdin according to HAVE_UNISTD_H macro. The PR is submitted to
+ jansson open source community.
+ https://github.com/akheron/jansson/pull/558
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h
new file mode 100644
index 00000000000..09cc2992fed
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_config.h
@@ -0,0 +1,41 @@
+/** @file This is the configuration file for building jansson library.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+ **/
+
+#ifndef JANSSON_CONFIG_H_
+#define JANSSON_CONFIG_H_
+
+///
+/// We don't support inline JSON on edk2
+///
+#define JSON_INLINE
+
+///
+/// We support long long on edk2
+///
+#define JSON_INTEGER_IS_LONG_LONG 1
+
+///
+/// We don't support locale on edk2
+///
+#define JSON_HAVE_LOCALECONV 0
+
+///
+/// We don't support atomic builtins on edk2
+///
+#define JSON_HAVE_ATOMIC_BUILTINS 0
+
+///
+/// We don't support sync builtins on edk2
+///
+#define JSON_HAVE_SYNC_BUILTINS 0
+
+///
+/// Mzximum deepth is set to 2048
+///
+#define JSON_PARSER_MAX_DEPTH 2048
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h
new file mode 100644
index 00000000000..893a3c76c86
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/jansson_private_config.h
@@ -0,0 +1,19 @@
+/** @file
+ Jansson private configurations for UEFI support.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef JANSSON_PRIVATE_CONFIG_H_
+#define JANSSON_PRIVATE_CONFIG_H_
+
+#define HAVE_SYS_TIME_H 1
+#define HAVE_SYS_TYPES_H 1
+
+#define INITIAL_HASHTABLE_ORDER 3
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c
new file mode 100644
index 00000000000..41d6a034779
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/JsonLib/load.c
@@ -0,0 +1,1111 @@
+/*
+ * Copyright (c) 2009-2016 Petri Lehtinen <petri@digip.org>
+ *
+ * Jansson is free software; you can redistribute it and/or modify
+ * it under the terms of the MIT license. See LICENSE for details.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent AND MIT
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "jansson_private.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "jansson.h"
+#include "strbuffer.h"
+#include "utf.h"
+
+#define STREAM_STATE_OK 0
+#define STREAM_STATE_EOF -1
+#define STREAM_STATE_ERROR -2
+
+#define TOKEN_INVALID -1
+#define TOKEN_EOF 0
+#define TOKEN_STRING 256
+#define TOKEN_INTEGER 257
+#define TOKEN_REAL 258
+#define TOKEN_TRUE 259
+#define TOKEN_FALSE 260
+#define TOKEN_NULL 261
+
+/* Locale independent versions of isxxx() functions */
+#define l_isupper(c) ('A' <= (c) && (c) <= 'Z')
+#define l_islower(c) ('a' <= (c) && (c) <= 'z')
+#define l_isalpha(c) (l_isupper(c) || l_islower(c))
+#define l_isdigit(c) ('0' <= (c) && (c) <= '9')
+#define l_isxdigit(c) \
+ (l_isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f'))
+
+/* Read one byte from stream, convert to unsigned char, then int, and
+ return. return EOF on end of file. This corresponds to the
+ behaviour of fgetc(). */
+typedef int (*get_func)(void *data);
+
+typedef struct {
+ get_func get;
+ void *data;
+ char buffer[5];
+ size_t buffer_pos;
+ int state;
+ int line;
+ int column, last_column;
+ size_t position;
+} stream_t;
+
+typedef struct {
+ stream_t stream;
+ strbuffer_t saved_text;
+ size_t flags;
+ size_t depth;
+ int token;
+ union {
+ struct {
+ char *val;
+ size_t len;
+ } string;
+ json_int_t integer;
+ double real;
+ } value;
+} lex_t;
+
+#define stream_to_lex(stream) container_of(stream, lex_t, stream)
+
+/*** error reporting ***/
+
+static void error_set(json_error_t *error, const lex_t *lex, enum json_error_code code,
+ const char *msg, ...) {
+ va_list ap;
+ char msg_text[JSON_ERROR_TEXT_LENGTH];
+ char msg_with_context[JSON_ERROR_TEXT_LENGTH];
+
+ int line = -1, col = -1;
+ size_t pos = 0;
+ const char *result = msg_text;
+
+ if (!error)
+ return;
+
+ va_start(ap, msg);
+ vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap);
+ msg_text[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ va_end(ap);
+
+ if (lex) {
+ const char *saved_text = strbuffer_value(&lex->saved_text);
+
+ line = lex->stream.line;
+ col = lex->stream.column;
+ pos = lex->stream.position;
+
+ if (saved_text && saved_text[0]) {
+ if (lex->saved_text.length <= 20) {
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'",
+ msg_text, saved_text);
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ result = msg_with_context;
+ }
+ } else {
+ if (code == json_error_invalid_syntax) {
+ /* More specific error code for premature end of file. */
+ code = json_error_premature_end_of_input;
+ }
+ if (lex->stream.state == STREAM_STATE_ERROR) {
+ /* No context for UTF-8 decoding errors */
+ result = msg_text;
+ } else {
+ snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file",
+ msg_text);
+ msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0';
+ result = msg_with_context;
+ }
+ }
+ }
+
+ jsonp_error_set(error, line, col, pos, code, "%s", result);
+}
+
+/*** lexical analyzer ***/
+
+static void stream_init(stream_t *stream, get_func get, void *data) {
+ stream->get = get;
+ stream->data = data;
+ stream->buffer[0] = '\0';
+ stream->buffer_pos = 0;
+
+ stream->state = STREAM_STATE_OK;
+ stream->line = 1;
+ stream->column = 0;
+ stream->position = 0;
+}
+
+static int stream_get(stream_t *stream, json_error_t *error) {
+ int c;
+
+ if (stream->state != STREAM_STATE_OK)
+ return stream->state;
+
+ if (!stream->buffer[stream->buffer_pos]) {
+ c = stream->get(stream->data);
+ if (c == EOF) {
+ stream->state = STREAM_STATE_EOF;
+ return STREAM_STATE_EOF;
+ }
+
+ stream->buffer[0] = c;
+ stream->buffer_pos = 0;
+
+ if (0x80 <= c && c <= 0xFF) {
+ /* multi-byte UTF-8 sequence */
+ size_t i, count;
+
+ count = utf8_check_first(c);
+ if (!count)
+ goto out;
+
+ assert(count >= 2);
+
+ for (i = 1; i < count; i++)
+ stream->buffer[i] = stream->get(stream->data);
+
+ if (!utf8_check_full(stream->buffer, count, NULL))
+ goto out;
+
+ stream->buffer[count] = '\0';
+ } else
+ stream->buffer[1] = '\0';
+ }
+
+ c = stream->buffer[stream->buffer_pos++];
+
+ stream->position++;
+ if (c == '\n') {
+ stream->line++;
+ stream->last_column = stream->column;
+ stream->column = 0;
+ } else if (utf8_check_first(c)) {
+ /* track the Unicode character column, so increment only if
+ this is the first character of a UTF-8 sequence */
+ stream->column++;
+ }
+
+ return c;
+
+out:
+ stream->state = STREAM_STATE_ERROR;
+ error_set(error, stream_to_lex(stream), json_error_invalid_utf8,
+ "unable to decode byte 0x%x", c);
+ return STREAM_STATE_ERROR;
+}
+
+static void stream_unget(stream_t *stream, int c) {
+ if (c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR)
+ return;
+
+ stream->position--;
+ if (c == '\n') {
+ stream->line--;
+ stream->column = stream->last_column;
+ } else if (utf8_check_first(c))
+ stream->column--;
+
+ assert(stream->buffer_pos > 0);
+ stream->buffer_pos--;
+ assert(stream->buffer[stream->buffer_pos] == c);
+}
+
+static int lex_get(lex_t *lex, json_error_t *error) {
+ return stream_get(&lex->stream, error);
+}
+
+static void lex_save(lex_t *lex, int c) { strbuffer_append_byte(&lex->saved_text, c); }
+
+static int lex_get_save(lex_t *lex, json_error_t *error) {
+ int c = stream_get(&lex->stream, error);
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR)
+ lex_save(lex, c);
+ return c;
+}
+
+static void lex_unget(lex_t *lex, int c) { stream_unget(&lex->stream, c); }
+
+static void lex_unget_unsave(lex_t *lex, int c) {
+ if (c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) {
+/* Since we treat warnings as errors, when assertions are turned
+ * off the "d" variable would be set but never used. Which is
+ * treated as an error by GCC.
+ */
+#ifndef NDEBUG
+ char d;
+#endif
+ stream_unget(&lex->stream, c);
+#ifndef NDEBUG
+ d =
+#endif
+ strbuffer_pop(&lex->saved_text);
+ assert(c == d);
+ }
+}
+
+static void lex_save_cached(lex_t *lex) {
+ while (lex->stream.buffer[lex->stream.buffer_pos] != '\0') {
+ lex_save(lex, lex->stream.buffer[lex->stream.buffer_pos]);
+ lex->stream.buffer_pos++;
+ lex->stream.position++;
+ }
+}
+
+static void lex_free_string(lex_t *lex) {
+ jsonp_free(lex->value.string.val);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+}
+
+/* assumes that str points to 'u' plus at least 4 valid hex digits */
+static int32_t decode_unicode_escape(const char *str) {
+ int i;
+ int32_t value = 0;
+
+ assert(str[0] == 'u');
+
+ for (i = 1; i <= 4; i++) {
+ char c = str[i];
+ value <<= 4;
+ if (l_isdigit(c))
+ value += c - '0';
+ else if (l_islower(c))
+ value += c - 'a' + 10;
+ else if (l_isupper(c))
+ value += c - 'A' + 10;
+ else
+ return -1;
+ }
+
+ return value;
+}
+
+static void lex_scan_string(lex_t *lex, json_error_t *error) {
+ int c;
+ const char *p;
+ char *t;
+ int i;
+
+ lex->value.string.val = NULL;
+ lex->token = TOKEN_INVALID;
+
+ c = lex_get_save(lex, error);
+
+ while (c != '"') {
+ if (c == STREAM_STATE_ERROR)
+ goto out;
+
+ else if (c == STREAM_STATE_EOF) {
+ error_set(error, lex, json_error_premature_end_of_input,
+ "premature end of input");
+ goto out;
+ }
+
+ else if (0 <= c && c <= 0x1F) {
+ /* control character */
+ lex_unget_unsave(lex, c);
+ if (c == '\n')
+ error_set(error, lex, json_error_invalid_syntax, "unexpected newline");
+ else
+ error_set(error, lex, json_error_invalid_syntax, "control character 0x%x",
+ c);
+ goto out;
+ }
+
+ else if (c == '\\') {
+ c = lex_get_save(lex, error);
+ if (c == 'u') {
+ c = lex_get_save(lex, error);
+ for (i = 0; i < 4; i++) {
+ if (!l_isxdigit(c)) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid escape");
+ goto out;
+ }
+ c = lex_get_save(lex, error);
+ }
+ } else if (c == '"' || c == '\\' || c == '/' || c == 'b' || c == 'f' ||
+ c == 'n' || c == 'r' || c == 't')
+ c = lex_get_save(lex, error);
+ else {
+ error_set(error, lex, json_error_invalid_syntax, "invalid escape");
+ goto out;
+ }
+ } else
+ c = lex_get_save(lex, error);
+ }
+
+ /* the actual value is at most of the same length as the source
+ string, because:
+ - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte
+ - a single \uXXXX escape (length 6) is converted to at most 3 bytes
+ - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair
+ are converted to 4 bytes
+ */
+ t = jsonp_malloc(lex->saved_text.length + 1);
+ if (!t) {
+ /* this is not very nice, since TOKEN_INVALID is returned */
+ goto out;
+ }
+ lex->value.string.val = t;
+
+ /* + 1 to skip the " */
+ p = strbuffer_value(&lex->saved_text) + 1;
+
+ while (*p != '"') {
+ if (*p == '\\') {
+ p++;
+ if (*p == 'u') {
+ size_t length;
+ int32_t value;
+
+ value = decode_unicode_escape(p);
+ if (value < 0) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
+ p += 5;
+
+ if (0xD800 <= value && value <= 0xDBFF) {
+ /* surrogate pair */
+ if (*p == '\\' && *(p + 1) == 'u') {
+ int32_t value2 = decode_unicode_escape(++p);
+ if (value2 < 0) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode escape '%.6s'", p - 1);
+ goto out;
+ }
+ p += 5;
+
+ if (0xDC00 <= value2 && value2 <= 0xDFFF) {
+ /* valid second surrogate */
+ value =
+ ((value - 0xD800) << 10) + (value2 - 0xDC00) + 0x10000;
+ } else {
+ /* invalid second surrogate */
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X\\u%04X'", value, value2);
+ goto out;
+ }
+ } else {
+ /* no second surrogate */
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X'", value);
+ goto out;
+ }
+ } else if (0xDC00 <= value && value <= 0xDFFF) {
+ error_set(error, lex, json_error_invalid_syntax,
+ "invalid Unicode '\\u%04X'", value);
+ goto out;
+ }
+
+ if (utf8_encode(value, t, &length))
+ assert(0);
+ t += length;
+ } else {
+ switch (*p) {
+ case '"':
+ case '\\':
+ case '/':
+ *t = *p;
+ break;
+ case 'b':
+ *t = '\b';
+ break;
+ case 'f':
+ *t = '\f';
+ break;
+ case 'n':
+ *t = '\n';
+ break;
+ case 'r':
+ *t = '\r';
+ break;
+ case 't':
+ *t = '\t';
+ break;
+ default:
+ assert(0);
+ }
+ t++;
+ p++;
+ }
+ } else
+ *(t++) = *(p++);
+ }
+ *t = '\0';
+ lex->value.string.len = t - lex->value.string.val;
+ lex->token = TOKEN_STRING;
+ return;
+
+out:
+ lex_free_string(lex);
+}
+
+#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */
+#if JSON_INTEGER_IS_LONG_LONG
+#ifdef _MSC_VER /* Microsoft Visual Studio */
+#define json_strtoint _strtoi64
+#else
+#define json_strtoint strtoll
+#endif
+#else
+#define json_strtoint strtol
+#endif
+#endif
+
+static int lex_scan_number(lex_t *lex, int c, json_error_t *error) {
+ const char *saved_text;
+ char *end;
+ double doubleval;
+
+ lex->token = TOKEN_INVALID;
+
+ if (c == '-')
+ c = lex_get_save(lex, error);
+
+ if (c == '0') {
+ c = lex_get_save(lex, error);
+ if (l_isdigit(c)) {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+ } else if (l_isdigit(c)) {
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ } else {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+
+ if (!(lex->flags & JSON_DECODE_INT_AS_REAL) && c != '.' && c != 'E' && c != 'e') {
+ json_int_t intval;
+
+ lex_unget_unsave(lex, c);
+
+ saved_text = strbuffer_value(&lex->saved_text);
+
+ errno = 0;
+ intval = json_strtoint(saved_text, &end, 10);
+ if (errno == ERANGE) {
+ if (intval < 0)
+ error_set(error, lex, json_error_numeric_overflow,
+ "too big negative integer");
+ else
+ error_set(error, lex, json_error_numeric_overflow, "too big integer");
+ goto out;
+ }
+
+ assert(end == saved_text + lex->saved_text.length);
+
+ lex->token = TOKEN_INTEGER;
+ lex->value.integer = intval;
+ return 0;
+ }
+
+ if (c == '.') {
+ c = lex_get(lex, error);
+ if (!l_isdigit(c)) {
+ lex_unget(lex, c);
+ goto out;
+ }
+ lex_save(lex, c);
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ }
+
+ if (c == 'E' || c == 'e') {
+ c = lex_get_save(lex, error);
+ if (c == '+' || c == '-')
+ c = lex_get_save(lex, error);
+
+ if (!l_isdigit(c)) {
+ lex_unget_unsave(lex, c);
+ goto out;
+ }
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isdigit(c));
+ }
+
+ lex_unget_unsave(lex, c);
+
+ if (jsonp_strtod(&lex->saved_text, &doubleval)) {
+ error_set(error, lex, json_error_numeric_overflow, "real number overflow");
+ goto out;
+ }
+
+ lex->token = TOKEN_REAL;
+ lex->value.real = doubleval;
+ return 0;
+
+out:
+ return -1;
+}
+
+static int lex_scan(lex_t *lex, json_error_t *error) {
+ int c;
+
+ strbuffer_clear(&lex->saved_text);
+
+ if (lex->token == TOKEN_STRING)
+ lex_free_string(lex);
+
+ do
+ c = lex_get(lex, error);
+ while (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+
+ if (c == STREAM_STATE_EOF) {
+ lex->token = TOKEN_EOF;
+ goto out;
+ }
+
+ if (c == STREAM_STATE_ERROR) {
+ lex->token = TOKEN_INVALID;
+ goto out;
+ }
+
+ lex_save(lex, c);
+
+ if (c == '{' || c == '}' || c == '[' || c == ']' || c == ':' || c == ',')
+ lex->token = c;
+
+ else if (c == '"')
+ lex_scan_string(lex, error);
+
+ else if (l_isdigit(c) || c == '-') {
+ if (lex_scan_number(lex, c, error))
+ goto out;
+ }
+
+ else if (l_isalpha(c)) {
+ /* eat up the whole identifier for clearer error messages */
+ const char *saved_text;
+
+ do
+ c = lex_get_save(lex, error);
+ while (l_isalpha(c));
+ lex_unget_unsave(lex, c);
+
+ saved_text = strbuffer_value(&lex->saved_text);
+
+ if (strcmp(saved_text, "true") == 0)
+ lex->token = TOKEN_TRUE;
+ else if (strcmp(saved_text, "false") == 0)
+ lex->token = TOKEN_FALSE;
+ else if (strcmp(saved_text, "null") == 0)
+ lex->token = TOKEN_NULL;
+ else
+ lex->token = TOKEN_INVALID;
+ }
+
+ else {
+ /* save the rest of the input UTF-8 sequence to get an error
+ message of valid UTF-8 */
+ lex_save_cached(lex);
+ lex->token = TOKEN_INVALID;
+ }
+
+out:
+ return lex->token;
+}
+
+static char *lex_steal_string(lex_t *lex, size_t *out_len) {
+ char *result = NULL;
+ if (lex->token == TOKEN_STRING) {
+ result = lex->value.string.val;
+ *out_len = lex->value.string.len;
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ }
+ return result;
+}
+
+static int lex_init(lex_t *lex, get_func get, size_t flags, void *data) {
+ stream_init(&lex->stream, get, data);
+ if (strbuffer_init(&lex->saved_text))
+ return -1;
+
+ lex->flags = flags;
+ lex->token = TOKEN_INVALID;
+ return 0;
+}
+
+static void lex_close(lex_t *lex) {
+ if (lex->token == TOKEN_STRING)
+ lex_free_string(lex);
+ strbuffer_close(&lex->saved_text);
+}
+
+/*** parser ***/
+
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error);
+
+static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *object = json_object();
+ if (!object)
+ return NULL;
+
+ lex_scan(lex, error);
+ if (lex->token == '}')
+ return object;
+
+ while (1) {
+ char *key;
+ size_t len;
+ json_t *value;
+
+ if (lex->token != TOKEN_STRING) {
+ error_set(error, lex, json_error_invalid_syntax, "string or '}' expected");
+ goto error;
+ }
+
+ key = lex_steal_string(lex, &len);
+ if (!key)
+ return NULL;
+ if (memchr(key, '\0', len)) {
+ jsonp_free(key);
+ error_set(error, lex, json_error_null_byte_in_key,
+ "NUL byte in object key not supported");
+ goto error;
+ }
+
+ if (flags & JSON_REJECT_DUPLICATES) {
+ if (json_object_get(object, key)) {
+ jsonp_free(key);
+ error_set(error, lex, json_error_duplicate_key, "duplicate object key");
+ goto error;
+ }
+ }
+
+ lex_scan(lex, error);
+ if (lex->token != ':') {
+ jsonp_free(key);
+ error_set(error, lex, json_error_invalid_syntax, "':' expected");
+ goto error;
+ }
+
+ lex_scan(lex, error);
+ value = parse_value(lex, flags, error);
+ if (!value) {
+ jsonp_free(key);
+ goto error;
+ }
+
+ if (json_object_set_new_nocheck(object, key, value)) {
+ jsonp_free(key);
+ goto error;
+ }
+
+ jsonp_free(key);
+
+ lex_scan(lex, error);
+ if (lex->token != ',')
+ break;
+
+ lex_scan(lex, error);
+ }
+
+ if (lex->token != '}') {
+ error_set(error, lex, json_error_invalid_syntax, "'}' expected");
+ goto error;
+ }
+
+ return object;
+
+error:
+ json_decref(object);
+ return NULL;
+}
+
+static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *array = json_array();
+ if (!array)
+ return NULL;
+
+ lex_scan(lex, error);
+ if (lex->token == ']')
+ return array;
+
+ while (lex->token) {
+ json_t *elem = parse_value(lex, flags, error);
+ if (!elem)
+ goto error;
+
+ if (json_array_append_new(array, elem)) {
+ goto error;
+ }
+
+ lex_scan(lex, error);
+ if (lex->token != ',')
+ break;
+
+ lex_scan(lex, error);
+ }
+
+ if (lex->token != ']') {
+ error_set(error, lex, json_error_invalid_syntax, "']' expected");
+ goto error;
+ }
+
+ return array;
+
+error:
+ json_decref(array);
+ return NULL;
+}
+
+static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *json;
+
+ lex->depth++;
+ if (lex->depth > JSON_PARSER_MAX_DEPTH) {
+ error_set(error, lex, json_error_stack_overflow, "maximum parsing depth reached");
+ return NULL;
+ }
+
+ switch (lex->token) {
+ case TOKEN_STRING: {
+ const char *value = lex->value.string.val;
+ size_t len = lex->value.string.len;
+
+ if (!(flags & JSON_ALLOW_NUL)) {
+ if (memchr(value, '\0', len)) {
+ error_set(error, lex, json_error_null_character,
+ "\\u0000 is not allowed without JSON_ALLOW_NUL");
+ return NULL;
+ }
+ }
+
+ json = jsonp_stringn_nocheck_own(value, len);
+ lex->value.string.val = NULL;
+ lex->value.string.len = 0;
+ break;
+ }
+
+ case TOKEN_INTEGER: {
+ json = json_integer(lex->value.integer);
+ break;
+ }
+
+ case TOKEN_REAL: {
+ json = json_real(lex->value.real);
+ break;
+ }
+
+ case TOKEN_TRUE:
+ json = json_true();
+ break;
+
+ case TOKEN_FALSE:
+ json = json_false();
+ break;
+
+ case TOKEN_NULL:
+ json = json_null();
+ break;
+
+ case '{':
+ json = parse_object(lex, flags, error);
+ break;
+
+ case '[':
+ json = parse_array(lex, flags, error);
+ break;
+
+ case TOKEN_INVALID:
+ error_set(error, lex, json_error_invalid_syntax, "invalid token");
+ return NULL;
+
+ default:
+ error_set(error, lex, json_error_invalid_syntax, "unexpected token");
+ return NULL;
+ }
+
+ if (!json)
+ return NULL;
+
+ lex->depth--;
+ return json;
+}
+
+static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error) {
+ json_t *result;
+
+ lex->depth = 0;
+
+ lex_scan(lex, error);
+ if (!(flags & JSON_DECODE_ANY)) {
+ if (lex->token != '[' && lex->token != '{') {
+ error_set(error, lex, json_error_invalid_syntax, "'[' or '{' expected");
+ return NULL;
+ }
+ }
+
+ result = parse_value(lex, flags, error);
+ if (!result)
+ return NULL;
+
+ if (!(flags & JSON_DISABLE_EOF_CHECK)) {
+ lex_scan(lex, error);
+ if (lex->token != TOKEN_EOF) {
+ error_set(error, lex, json_error_end_of_input_expected,
+ "end of file expected");
+ json_decref(result);
+ return NULL;
+ }
+ }
+
+ if (error) {
+ /* Save the position even though there was no error */
+ error->position = (int)lex->stream.position;
+ }
+
+ return result;
+}
+
+typedef struct {
+ const char *data;
+ size_t pos;
+} string_data_t;
+
+static int string_get(void *data) {
+ char c;
+ string_data_t *stream = (string_data_t *)data;
+ c = stream->data[stream->pos];
+ if (c == '\0')
+ return EOF;
+ else {
+ stream->pos++;
+ return (unsigned char)c;
+ }
+}
+
+json_t *json_loads(const char *string, size_t flags, json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+ string_data_t stream_data;
+
+ jsonp_error_init(error, "<string>");
+
+ if (string == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ stream_data.data = string;
+ stream_data.pos = 0;
+
+ if (lex_init(&lex, string_get, flags, (void *)&stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+typedef struct {
+ const char *data;
+ size_t len;
+ size_t pos;
+} buffer_data_t;
+
+static int buffer_get(void *data) {
+ char c;
+ buffer_data_t *stream = data;
+ if (stream->pos >= stream->len)
+ return EOF;
+
+ c = stream->data[stream->pos];
+ stream->pos++;
+ return (unsigned char)c;
+}
+
+json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+ buffer_data_t stream_data;
+
+ jsonp_error_init(error, "<buffer>");
+
+ if (buffer == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ stream_data.data = buffer;
+ stream_data.pos = 0;
+ stream_data.len = buflen;
+
+ if (lex_init(&lex, buffer_get, flags, (void *)&stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) {
+ lex_t lex;
+ const char *source;
+ json_t *result;
+#ifdef HAVE_UNISTD_H
+ if (input == stdin)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)fgetc, flags, input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+static int fd_get_func(int *fd) {
+#ifdef HAVE_UNISTD_H
+ uint8_t c;
+ if (read(*fd, &c, 1) == 1)
+ return c;
+#endif
+ return EOF;
+}
+
+json_t *json_loadfd(int input, size_t flags, json_error_t *error) {
+ lex_t lex;
+ const char *source;
+ json_t *result;
+
+#ifdef HAVE_UNISTD_H
+ if (input == STDIN_FILENO)
+ source = "<stdin>";
+ else
+#endif
+ source = "<stream>";
+
+ jsonp_error_init(error, source);
+
+ if (input < 0) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)fd_get_func, flags, &input))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
+
+json_t *json_load_file(const char *path, size_t flags, json_error_t *error) {
+ json_t *result;
+ FILE *fp;
+
+ jsonp_error_init(error, path);
+
+ if (path == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ fp = fopen(path, "rb");
+ if (!fp) {
+ error_set(error, NULL, json_error_cannot_open_file, "unable to open %s: %s", path,
+ strerror(errno));
+ return NULL;
+ }
+
+ result = json_loadf(fp, flags, error);
+
+ fclose(fp);
+ return result;
+}
+
+#define MAX_BUF_LEN 1024
+
+typedef struct {
+ char data[MAX_BUF_LEN];
+ size_t len;
+ size_t pos;
+ json_load_callback_t callback;
+ void *arg;
+} callback_data_t;
+
+static int callback_get(void *data) {
+ char c;
+ callback_data_t *stream = data;
+
+ if (stream->pos >= stream->len) {
+ stream->pos = 0;
+ stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg);
+ if (stream->len == 0 || stream->len == (size_t)-1)
+ return EOF;
+ }
+
+ c = stream->data[stream->pos];
+ stream->pos++;
+ return (unsigned char)c;
+}
+
+json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags,
+ json_error_t *error) {
+ lex_t lex;
+ json_t *result;
+
+ callback_data_t stream_data;
+
+ memset(&stream_data, 0, sizeof(stream_data));
+ stream_data.callback = callback;
+ stream_data.arg = arg;
+
+ jsonp_error_init(error, "<callback>");
+
+ if (callback == NULL) {
+ error_set(error, NULL, json_error_invalid_argument, "wrong arguments");
+ return NULL;
+ }
+
+ if (lex_init(&lex, (get_func)callback_get, flags, &stream_data))
+ return NULL;
+
+ result = parse_json(&lex, flags, error);
+
+ lex_close(&lex);
+ return result;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c
new file mode 100644
index 00000000000..19fe2e20210
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.c
@@ -0,0 +1,101 @@
+/** @file
+ NULL instace of RedfishPlatformCredentialLib
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Protocol/EdkIIRedfishCredential.h>
+/**
+ Notification of Exit Boot Service.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialExitBootServicesNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+)
+{
+ return;
+}
+
+/**
+ Notification of End of DXe.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL.
+**/
+VOID
+EFIAPI
+LibCredentialEndOfDxeNotify (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This
+)
+{
+ return;
+}
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+LibCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+)
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL or given the worng ServiceStopType.
+ @retval EFI_UNSUPPORTED Not support to stop Redfish service.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+LibStopRedfishService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
new file mode 100644
index 00000000000..ddad90c042b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
@@ -0,0 +1,30 @@
+## @file
+# NULL instance of RedfishPlatformCredentialLib
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishPlatformCredentialLibNull
+ FILE_GUID = CA3BD843-0BDD-4EE0-A38A-B45CA663114F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishPlatformCredentialLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ PlatformCredentialLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c
new file mode 100644
index 00000000000..598c7f1ed3a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.c
@@ -0,0 +1,52 @@
+/** @file
+ NULL instace of RedfishPlatformHostInterfaceLib
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/RedfishHostInterfaceLib.h>
+#include <Library/UefiLib.h>
+
+/**
+ Get platform Redfish host interface device descriptor.
+
+ @param[in] DeviceType Pointer to retrieve device type.
+ @param[out] DeviceDescriptor Pointer to retrieve REDFISH_INTERFACE_DATA, caller has to free
+ this memory using FreePool().
+
+ @retval EFI_NOT_FOUND No Redfish host interface descriptor provided on this platform.
+
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceDeviceDescriptor (
+ IN UINT8 *DeviceType,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor
+)
+{
+ return EFI_NOT_FOUND;
+}
+/**
+ Get platform Redfish host interface protocol data.
+ Caller should pass NULL in ProtocolRecord to retrive the first protocol record.
+ Then continuously pass previous ProtocolRecord for retrieving the next ProtocolRecord.
+
+ @param[in, out] ProtocolRecord Pointer to retrieve the first or the next protocol record.
+ caller has to free the new protocol record returned from
+ this function using FreePool().
+ @param[in] IndexOfProtocolData The index of protocol data.
+
+ @retval EFI_NOT_FOUND No more protocol records.
+
+**/
+EFI_STATUS
+RedfishPlatformHostInterfaceProtocolData (
+ IN OUT MC_HOST_INTERFACE_PROTOCOL_RECORD **ProtocolRecord,
+ IN UINT8 IndexOfProtocolData
+)
+{
+ return EFI_NOT_FOUND;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
new file mode 100644
index 00000000000..fe60ad49fc9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
@@ -0,0 +1,33 @@
+## @file
+# NULL instance of RedfishPlatformHostInterfaceLib
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishPlatformHostInterfaceLibNull
+ FILE_GUID = 851229BF-4D8B-30F3-DD0D-20AFAF99A77B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishPlatformHostInterfaceLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ PlatformHostInterfaceLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ UefiLib
+ BaseLib
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c
new file mode 100644
index 00000000000..0264b365a14
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.c
@@ -0,0 +1,81 @@
+/** @file
+ NULL instace of RedfishContentCodingLib
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+
+/**
+ This is the function to encode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] OriginalContent Original content.
+ @param[in] OriginalContentLength The length of original content.
+ @param[out] EncodedContentPointer Pointer to receive the encoded content pointer.
+ @param[out] EncodedContentLength Length of encoded content.
+
+ @retval EFI_SUCCESS Content is encoded successfully.
+ @retval EFI_UNSUPPORTED No supported encoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+RedfishContentEncode (
+ IN CHAR8 *ContentEncodedValue,
+ IN CHAR8 *OriginalContent,
+ IN UINTN OriginalContentLength,
+ OUT VOID **EncodedContentPointer,
+ OUT UINTN *EncodedContentLength
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This is the function to decode the content use the
+ algorithm indicated in ContentEncodedValue. The naming of
+ ContentEncodedValue is follow HTTP spec or could be a
+ platform-specific value.
+
+ @param[in] ContentDecodedValue HTTP conent decoded value.
+ The value could be one of below
+ or any which is platform-specific.
+ - HTTP_CONTENT_ENCODING_IDENTITY "identity"
+ - HTTP_CONTENT_ENCODING_GZIP "gzip"
+ - HTTP_CONTENT_ENCODING_COMPRESS "compress"
+ - HTTP_CONTENT_ENCODING_DEFLATE "deflate"
+ - HTTP_CONTENT_ENCODING_BROTLI "br"
+ @param[in] ContentPointer Original content.
+ @param[in] ContentLength The length of original content.
+ @param[out] DecodedContentPointer Pointer to receive decoded content pointer.
+ @param[out] DecodedContentLength Length of decoded content.
+
+ @retval EFI_SUCCESS Content is decoded successfully.
+ @retval EFI_UNSUPPORTED No supported decoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+RedfishContentDecode (
+ IN CHAR8 *ContentDecodedValue,
+ IN VOID *ContentPointer,
+ IN UINTN ContentLength,
+ OUT VOID **DecodedContentPointer,
+ OUT UINTN *DecodedContentLength
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
new file mode 100644
index 00000000000..2a74d7fab31
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
@@ -0,0 +1,31 @@
+## @file
+# NULL instance of RedfishContentCodingLibNull
+# This library is used to encode/decode Redfish payload.
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishContentCodingLibNull
+ FILE_GUID = 06B10249-4D38-FF37-0CA5-13AFB6D625CC
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishContentCodingLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishContentCodingLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h
new file mode 100644
index 00000000000..778f142ed61
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/assert.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_ASSERT_H_
+#define REDFISH_CRT_ASSERT_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h
new file mode 100644
index 00000000000..98a9979d912
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/errno.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_ERRNO_H_
+#define REDFISH_CRT_ERRNO_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h
new file mode 100644
index 00000000000..1b97a3cc505
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/limits.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_LIMITS_H_
+#define REDFISH_CRT_LIMITS_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h
new file mode 100644
index 00000000000..503f844a82b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/math.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_MATH_H_
+#define REDFISH_CRT_MATH_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h
new file mode 100644
index 00000000000..e4ea626b142
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdarg.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_STDARG_H_
+#define REDFISH_CRT_STDARG_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h
new file mode 100644
index 00000000000..35ed2e975af
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stddef.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STDDEF_H_
+#define REDFISH_CRT_STDDEF_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h
new file mode 100644
index 00000000000..4ee8889bb52
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdio.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_STDIO_H_
+#define REDFISH_CRT_STDIO_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h
new file mode 100644
index 00000000000..db7a3e64646
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/stdlib.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STDLIB_H_
+#define REDFISH_CRT_STDLIB_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h
new file mode 100644
index 00000000000..af23842a69a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/string.h
@@ -0,0 +1,16 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_STRING_H_
+#define REDFISH_CRT_STRING_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h
new file mode 100644
index 00000000000..324c6ba72ea
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/time.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_SYS_TIME_H_
+#define REDFISH_CRT_SYS_TIME_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h
new file mode 100644
index 00000000000..df46193d675
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/sys/types.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_SYS_TYPES_H_
+#define REDFISH_CRT_SYS_TYPES_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h
new file mode 100644
index 00000000000..1f7a698b26a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Crt/time.h
@@ -0,0 +1,15 @@
+/** @file
+ Include file to support building the third-party jansson library.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef REDFISH_CRT_TIME_H_
+#define REDFISH_CRT_TIME_H_
+
+#include <Library/RedfishCrtLib.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
new file mode 100644
index 00000000000..9ad28dc76b2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishCrtLib.h
@@ -0,0 +1,242 @@
+/** @file
+ Redfish CRT wrapper functions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_CRT_LIB_H_
+#define REDFISH_CRT_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+
+#define MAX_STRING_SIZE 0x10000000
+
+// Minimum value for an object of type long long int.
+#define LLONG_MIN MIN_INT64
+
+// Maximum value for an object of type long long int.
+#define LLONG_MAX MAX_INT64
+
+// We dont support double on edk2
+#define HUGE_VAL 0
+
+#if defined(MDE_CPU_X64) || defined(MDE_CPU_AARCH64) || defined(MDE_CPU_RISCV64)
+//
+// With GCC we would normally use SIXTY_FOUR_BIT_LONG, but MSVC needs
+// SIXTY_FOUR_BIT, because 'long' is 32-bit and only 'long long' is
+// 64-bit. Since using 'long long' works fine on GCC too, just do that.
+//
+#define SIXTY_FOUR_BIT
+#elif defined(MDE_CPU_IA32) || defined(MDE_CPU_ARM) || defined(MDE_CPU_EBC)
+#define THIRTY_TWO_BIT
+#endif
+
+//
+// Map all va_xxxx elements to VA_xxx defined in MdePkg/Include/Base.h
+//
+#if !defined(__CC_ARM) // if va_list is not already defined
+#define va_list VA_LIST
+#define va_arg VA_ARG
+#define va_start VA_START
+#define va_end VA_END
+#else // __CC_ARM
+#define va_start(Marker, Parameter) __va_start(Marker, Parameter)
+#define va_arg(Marker, TYPE) __va_arg(Marker, TYPE)
+#define va_end(Marker) ((void)0)
+#endif
+
+//
+// Definitions for global constants used by CRT library routines
+//
+#define INT_MAX MAX_INT32 /* Maximum (signed) int value */
+#define LONG_MAX 0X7FFFFFFFL /* max value for a long */
+#define LONG_MIN (-LONG_MAX-1) /* min value for a long */
+#define ULONG_MAX 0xFFFFFFFF /* Maximum unsigned long value */
+#define CHAR_BIT 8 /* Number of bits in a char */
+
+// Maximum value for an object of type unsigned long long int.
+#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL // 2^64 - 1
+// Maximum value for an object of type unsigned char.
+#define UCHAR_MAX 255 // 2^8 - 1
+
+//
+// Basic types mapping
+//
+typedef UINTN size_t;
+typedef INTN ssize_t;
+typedef INT32 time_t;
+typedef UINT8 __uint8_t;
+typedef UINT8 sa_family_t;
+typedef UINT32 uid_t;
+typedef UINT32 gid_t;
+typedef INT32 int32_t;
+typedef UINT32 uint32_t;
+typedef UINT16 uint16_t;
+typedef UINT8 uint8_t;
+typedef enum {false, true} bool;
+
+//
+// File operations are not required for EFI building,
+// so FILE is mapped to VOID * to pass build
+//
+typedef VOID *FILE;
+
+/**
+ This is the Redfish version of CRT snprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiSPrint(). That is becasue "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on snprintf().
+ See definitions of AsciiSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param ... Variable argument list whose contents are accessed based on the
+ format string specified by FormatString.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator. Zero means no string is produced or the error happens.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ );
+
+/**
+ This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on vsnprintf().
+ See definitions of AsciiVSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ );
+
+//
+// Global variables
+//
+extern int errno;
+extern FILE *stderr;
+
+//
+// Function prototypes of CRT Library routines
+//
+void *malloc (size_t);
+void *realloc (void *, size_t);
+void *calloc (size_t Num, size_t Size);
+void free (void *);
+void *memset (void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+int isdigit (int);
+int isspace (int);
+int tolower (int);
+int isupper (int);
+int isxdigit (int);
+int isalnum (int);
+void *memcpy (void *, const void *, size_t);
+void *memset (void *, int, size_t);
+void *memchr (const void *, int, size_t);
+int memcmp (const void *, const void *, size_t);
+void *memmove (void *, const void *, size_t);
+int strcmp (const char *, const char *);
+int strncmp (const char *, const char *, size_t);
+char *strcpy (char *, const char *);
+size_t strlen (const char *);
+char *strcat (char *, const char *);
+char *strchr (const char *, int);
+int strcasecmp (const char *, const char *);
+int strncasecmp (const char *, const char *, size_t);
+char *strncpy (char *, size_t, const char *, size_t);
+int strncmp (const char *, const char *, size_t);
+char *strrchr (const char *, int);
+unsigned long strtoul (const char *, char **, int);
+char * strstr (const char *s1 , const char *s2);
+long strtol (const char *, char **, int);
+char *strerror (int);
+size_t strspn (const char *, const char *);
+char * strdup (const char *str);
+char * strpbrk (const char *s1, const char *s2);
+unsigned long long strtoull(const char * nptr, char ** endptr, int base);
+long long strtoll (const char * nptr, char ** endptr, int base);
+long strtol (const char * nptr, char ** endptr, int base);
+double strtod (const char * __restrict nptr, char ** __restrict endptr);
+size_t strcspn (const char *, const char *);
+int printf (const char *, ...);
+int sscanf (const char *, const char *, ...);
+FILE *fopen (const char *, const char *);
+size_t fread (void *, size_t, size_t, FILE *);
+size_t fwrite (const void *, size_t, size_t, FILE *);
+int fclose (FILE *);
+int fprintf (FILE *, const char *, ...);
+int fgetc (FILE * _File);
+uid_t getuid (void);
+uid_t geteuid (void);
+gid_t getgid (void);
+gid_t getegid (void);
+void qsort (void *, size_t, size_t, int (*)(const void *, const void *));
+char *getenv (const char *);
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+void abort (void) __attribute__((__noreturn__));
+#else
+void abort (void);
+#endif
+int toupper (int);
+int Digit2Val (int);
+time_t time (time_t *);
+
+//
+// Macros that directly map functions to BaseLib, BaseMemoryLib, and DebugLib functions
+//
+#define strcmp AsciiStrCmp
+#define memcpy(dest,source,count) CopyMem(dest,source,(UINTN)(count))
+#define memset(dest,ch,count) SetMem(dest,(UINTN)(count),(UINT8)(ch))
+#define memchr(buf,ch,count) ScanMem8(buf,(UINTN)(count),(UINT8)ch)
+#define memcmp(buf1,buf2,count) (int)(CompareMem(buf1,buf2,(UINTN)(count)))
+#define memmove(dest,source,count) CopyMem(dest,source,(UINTN)(count))
+#define strlen(str) (size_t)(AsciiStrnLenS(str,MAX_STRING_SIZE))
+#define strcpy(strDest,strSource) AsciiStrCpyS(strDest,(strlen(strSource)+1),strSource)
+#define strncpy(strDest,strSource,count) AsciiStrnCpyS(strDest,(UINTN)count,strSource,(UINTN)count)
+#define strncpys(strDest, DestLen, strSource,count) AsciiStrnCpyS(strDest,DestLen,strSource,(UINTN)count)
+#define strcat(strDest,strSource) AsciiStrCatS(strDest,(strlen(strSource)+strlen(strDest)+1),strSource)
+#define strchr(str,ch) ScanMem8((VOID *)(str),AsciiStrSize(str),(UINT8)ch)
+#define strcasecmp(str1,str2) (int)AsciiStriCmp(str1,str2)
+#define strstr(s1,s2) AsciiStrStr(s1,s2)
+#define snprintf(buf,len,...) RedfishAsciiSPrint(buf,len,__VA_ARGS__)
+#define vsnprintf(buf,len,format,marker) RedfishAsciiVSPrint((buf),(len),(format),(marker))
+#define assert(expression) ASSERT(expression)
+#define offsetof(type,member) OFFSET_OF(type,member)
+
+#define EOF (-1)
+
+extern int errno;
+
+#define ERANGE 34 /* 34 Result too large */
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h
new file mode 100644
index 00000000000..c3069f0dd4c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateInclude/Library/RedfishLib.h
@@ -0,0 +1,611 @@
+/** @file
+ This library provides a set of utility APIs that allow to create/read/update/delete
+ (CRUD) Redfish resources and provide basic query abilities by using [URI/RedPath]
+ (https://github.com/DMTF/libredfish).
+
+ The query language is based on XPath (https://www.w3.org/TR/1999/REC-xpath-19991116/).
+ This library and query language essentially treat the entire Redfish Service like it
+ was a single JSON document. In other words whenever it encounters an odata.id in JSON
+ document, it will retrieve the new JSON document (if needed). We name the path as
+ RedPath:
+
+ Expression Description
+
+ nodename Selects the JSON entity with the name "nodename".
+ If the value of nodename is an object with "@odata.id",
+ it will continue get the value from "@odata.id".
+
+ / Selects from the root node
+
+ [index] Selects the index number JSON entity from an array or
+ object. If the JSON entity is one collection (has
+ Members & Members@odata.count), means to get the index
+ member in "Members". Index number >=1, 1 means to return
+ the first instance.
+
+ [XXX] Operation on JSON entity.
+ If the JSON entity is one collection (has Members &
+ Members@odata.count), means to get all elements in
+ "Members". If the JSON entity is one array, means to
+ get all elements in array. Others will match the nodename
+ directly (e.g. JSON_OBJECT, JSON_STRING, JSON_TRUE,
+ JSON_FALSE, JSON_INTEGER).
+
+ [nodename] Selects all the elements from an JSON entity that
+ contain a property named "nodename"
+
+ [name=value] Selects all the elements from an JSON entity where
+ the property "name" is equal to "value"
+
+ [name~value] Selects all the elements from an JSON entity where
+ the string property "name" is equal to "value" using
+ case insensitive comparison.
+
+ [name<value] Selects all the elements from an JSON entity where
+ the property "name" is less than "value"
+
+ [name<=value] Selects all the elements from an JSON entity where
+ the property "name" is less than or equal to "value"
+
+ [name>value] Selects all the elements from an JSON entity where
+ the property "name" is greater than "value"
+
+ [name>=value] Selects all the elements from an JSON entity where
+ the property "name" is greater than or equal to "value"
+
+ Some examples:
+
+ /v1/Chassis[1] - Will return the first Chassis instance.
+ /v1/Chassis[SKU=1234] - Will return all Chassis instances with a SKU field equal to 1234.
+ /v1/Systems[Storage] - Will return all the System instances that have Storage field populated.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef REDFISH_LIB_H_
+#define REDFISH_LIB_H_
+
+#include <Library/JsonLib.h>
+
+#include <Protocol/Http.h>
+#include <Protocol/EdkIIRedfishConfigHandler.h>
+
+#define ODATA_TYPE_NAME_MAX_SIZE 128
+#define ODATA_TYPE_MAX_SIZE 128
+
+///
+/// Library class public defines
+///
+typedef VOID* REDFISH_SERVICE;
+typedef VOID* REDFISH_PAYLOAD;
+
+///
+/// Library class public structures/unions
+///
+typedef struct {
+ EFI_HTTP_STATUS_CODE *StatusCode;
+ UINTN HeaderCount;
+ EFI_HTTP_HEADER *Headers;
+ REDFISH_PAYLOAD Payload;
+} REDFISH_RESPONSE;
+
+///
+/// Odata type-name mapping structure.
+///
+typedef struct {
+ CONST CHAR8 OdataTypeName [ODATA_TYPE_NAME_MAX_SIZE];
+ CONST CHAR8 OdataType [ODATA_TYPE_MAX_SIZE];
+} REDFISH_ODATA_TYPE_MAPPING;
+
+/**
+ This function uses REST EX protocol provided in RedfishConfigServiceInfo.
+ The service enumerator will also handle the authentication flow automatically
+ if HTTP basic auth or Redfish session login is configured to use.
+
+ Callers are responsible for freeing the returned service by RedfishCleanupService().
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+
+ @return New created Redfish Service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+EFIAPI
+RedfishCreateService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo
+ );
+
+/**
+ Free the Service and all its related resources.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupService (
+ IN REDFISH_SERVICE RedfishService
+ );
+
+/**
+ Create REDFISH_PAYLOAD instance in local with JSON represented resource value and
+ the Redfish Service.
+
+ The returned REDFISH_PAYLOAD can be used to create or update Redfish resource in
+ server side.
+
+ Callers are responsible for freeing the returned payload by RedfishCleanupPayload().
+
+ @param[in] Value JSON Value of the redfish resource.
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+ @return REDFISH_PAYLOAD instance of the resource, or NULL if error happens.
+
+**/
+REDFISH_PAYLOAD
+EFIAPI
+RedfishCreatePayload (
+ IN EDKII_JSON_VALUE Value,
+ IN REDFISH_SERVICE RedfishService
+ );
+
+/**
+ Free the RedfishPayload and all its related resources.
+
+ @param[in] Payload Payload to be freed.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupPayload (
+ IN REDFISH_PAYLOAD Payload
+ );
+
+/**
+ This function returns the decoded JSON value of a REDFISH_PAYLOAD.
+
+ Caller doesn't need to free the returned JSON value because it will be released
+ in corresponding RedfishCleanupPayload() function.
+
+ @param[in] Payload A REDFISH_PAYLOAD instance.
+
+ @return Decoded JSON value of the payload.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+RedfishJsonInPayload (
+ IN REDFISH_PAYLOAD Payload
+ );
+
+/**
+ Fill the input RedPath string with system UUID from SMBIOS table or use the customized
+ ID if FromSmbios == FALSE.
+
+ This is a helper function to build a RedPath string which can be used to address
+ a Redfish resource for this computer system. The input PathString must have a Systems
+ note in format of "Systems[UUID=%g]" or "Systems[UUID~%g]" to fill the UUID value.
+
+ Example:
+ Use "/v1/Systems[UUID=%g]/Bios" to build a RedPath to address the "Bios" resource
+ for this computer system.
+
+ @param[in] RedPath RedPath format to be build.
+ @param[in] FromSmbios Get system UUID from SMBIOS as computer system instance ID.
+ @param[in] IdString The computer system instance ID.
+
+ @return Full RedPath with system UUID inside, or NULL if error happens.
+
+**/
+CHAR8 *
+EFIAPI
+RedfishBuildPathWithSystemUuid (
+ IN CONST CHAR8 *RedPath,
+ IN BOOLEAN FromSmbios,
+ IN CHAR8 *IdString OPTIONAL
+ );
+
+/**
+ Get a redfish response addressed by a RedPath string, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] RedPath RedPath string to address a resource, must start
+ from the root node.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByService (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Get a redfish response addressed by URI, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the URI resources.
+ @param[in] URI String to address a resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Get a redfish response addressed by the input Payload and relative RedPath string,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Payload A existing REDFISH_PAYLOAD instance.
+ @param[in] RedPath Relative RedPath string to address a resource inside Payload.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful:
+ 1. The HTTP StatusCode is NULL and the returned Payload in
+ RedResponse is not NULL, indicates the Redfish resource has
+ been parsed from the input payload directly.
+ 2. The HTTP StatusCode is not NULL and the value is 2XX,
+ indicates the corresponding redfish resource has been returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER Payload, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If StatusCode is not NULL and the returned value of StatusCode
+ is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByPayload (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP PATCH to perform updates on pre-existing Redfish resource.
+
+ This function uses the RedfishService to patch a Redfish resource addressed by
+ Uri (only the relative path is required). Changes to one or more properties within
+ the target resource are represented in the input Content, properties not specified
+ in Content won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[in] Content JSON represented properties to be update.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ IN CONST CHAR8 *Content,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP PATCH to perform updates on target payload. Patch to odata.id in Payload directly.
+
+ This function uses the Payload to patch the Target. Changes to one or more properties
+ within the target resource are represented in the input Payload, properties not specified
+ in Payload won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target The target payload to be updated.
+ @param[in] Payload Palyoad with properties to be changed.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP POST to create a new resource in target payload.
+
+ The POST request should be submitted to the Resource Collection in which the new resource
+ is to belong. The Resource Collection is addressed by Target payload. The Redfish may
+ ignore any service controlled properties. The corresponding redfish response will returned,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target Target payload of the Resource Collection.
+ @param[in] Payload The new resource to be created.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPostToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Use HTTP DELETE to remove a resource.
+
+ This function uses the RedfishService to remove a Redfish resource which is addressed
+ by input Uri (only the relative path is required). The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX, the Redfish resource has been removed.
+ If there is any message returned from server, it will be returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDeleteByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ );
+
+/**
+ Dump text in fractions.
+
+ @param[in] String ASCII string to dump.
+
+**/
+VOID
+RedfishDumpJsonStringFractions (
+ IN CHAR8 *String
+ );
+
+/**
+ Extract the JSON text content from REDFISH_PAYLOAD and dump to debug console.
+
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishDumpPayload (
+ IN REDFISH_PAYLOAD Payload
+ );
+/**
+ Dump text in JSON value.
+
+ @param[in] JsonValue The Redfish JSON value to dump.
+
+**/
+VOID
+RedfishDumpJson (
+ IN EDKII_JSON_VALUE JsonValue
+ );
+/**
+ This function will cleanup the HTTP header and Redfish payload resources.
+
+ @param[in] StatusCode The status code in HTTP response message.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishFreeResponse (
+ IN EFI_HTTP_STATUS_CODE *StatusCode,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN REDFISH_PAYLOAD Payload
+ );
+
+/**
+ Check if the "@odata.type" in Payload is valid or not.
+
+ @param[in] Payload The Redfish payload to be checked.
+ @param[in] OdataTypeName OdataType will be retrived from mapping list.
+ @param[in] OdataTypeMappingList The list of OdataType.
+ @param[in] OdataTypeMappingListSize The number of mapping list
+
+ @return TRUE if the "@odata.type" in Payload is valid, otherwise FALSE.
+
+**/
+BOOLEAN
+RedfishIsValidOdataType (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *OdataTypeName,
+ IN REDFISH_ODATA_TYPE_MAPPING *OdataTypeMappingList,
+ IN UINTN OdataTypeMappingListSize
+ );
+
+/**
+ Check if the payload is collection
+
+ @param[in] Payload The Redfish payload to be checked.
+
+ @return TRUE if the payload is collection.
+
+**/
+BOOLEAN
+RedfishIsPayloadCollection (
+ IN REDFISH_PAYLOAD Payload
+);
+/**
+ Get collection size.
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] CollectionSize Size of this collection
+
+ @return EFI_SUCCESS Coolection size is returned in CollectionSize
+ @return EFI_INVALID_PARAMETER The payload is not a collection.
+**/
+EFI_STATUS
+RedfishGetCollectionSize(
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN *CollectionSize
+);
+/**
+ Get Redfish payload of collection member
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] Index Index of collection member
+
+ @return NULL Fail to get collection member.
+ @return Non NULL Payload is returned.
+**/
+REDFISH_PAYLOAD
+RedfishGetPayloadByIndex (
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN Index
+);
+
+/**
+ Check and return Redfish resource of the given Redpath.
+
+ @param[in] RedfishService Pointer to REDFISH_SERVICE
+ @param[in] Redpath Redpath of the resource.
+ @param[in] Response Optional return the resource.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+RedfishCheckIfRedpathExist (
+ IN REDFISH_SERVICE RedfishService,
+ IN CHAR8 *Redpath,
+ IN REDFISH_RESPONSE *Response OPTIONAL
+);
+
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] RedfishService Redfish service instance.
+ @param[out] ServiceVersionStr Redfish service string.
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishGetServiceVersion(
+ IN REDFISH_SERVICE RedfishService,
+ OUT CHAR8 **ServiceVersionStr
+ );
+
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] ServiceVerisonStr The string of Redfish service version.
+ @param[in] Url The URL to build Redpath with ID.
+ Start with "/", for example "/Registries"
+ @param[in] Id ID string
+ @param[out] Redpath Pointer to retrive Redpath, caller has to free
+ the memory allocated for this string.
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishBuildRedpathUseId (
+ IN CHAR8 *ServiceVerisonStr,
+ IN CHAR8 *Url,
+ IN CHAR8 *Id,
+ OUT CHAR8 **Redpath
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
new file mode 100644
index 00000000000..401c8084b8b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c
@@ -0,0 +1,929 @@
+/** @file
+ CRT wrapper functions for system call,the string operation functions
+ are remodeled after edk2-libc.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/RedfishCrtLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+int errno = 0;
+char errnum_message [] = "We don't support to map errnum to the error message on edk2 Redfish\n";
+
+// This is required to keep VC++ happy if you use floating-point
+int _fltused = 1;
+
+/**
+ Determine if a particular character is an alphanumeric character
+ @return Returns 1 if c is an alphanumeric character, otherwise returns 0.
+**/
+int isalnum (int c)
+{
+ //
+ // <alnum> ::= [0-9] | [a-z] | [A-Z]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (('a' <= (c)) && ((c) <= 'z')) ||
+ (('A' <= (c)) && ((c) <= 'Z')));
+}
+
+/**
+ Determine if a particular character is a digital character
+
+ @return Returns 1 if c is an digital character, otherwise returns 0.
+**/
+int isdchar (int c)
+{
+ //
+ // [0-9] | [e +-.]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (c == 'e') || (c == 'E') ||
+ (c == '+') || (c == '-') ||
+ (c == '.'));
+}
+
+/**
+ Determine if a particular character is a space character
+
+ @return Returns 1 if c is a space character
+**/
+int isspace (int c)
+{
+ //
+ // <space> ::= [ ]
+ //
+ return ((c) == ' ') || ((c) == '\t') || ((c) == '\r') || ((c) == '\n') || ((c) == '\v') || ((c) == '\f');
+}
+
+/**
+ Allocates memory blocks
+*/
+void *malloc (size_t size)
+{
+ return AllocatePool ((UINTN) size);
+}
+
+/**
+ De-allocates or frees a memory block
+*/
+void free (void *ptr)
+{
+ //
+ // In Standard C, free() handles a null pointer argument transparently. This
+ // is not true of FreePool() below, so protect it.
+ //
+ if (ptr != NULL) {
+ FreePool (ptr);
+ }
+}
+
+/**
+ NetBSD Compatibility Function strdup creates a duplicate copy of a string.
+
+ @return Returns the pointer to duplicated string.
+**/
+char * strdup(const char *str)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if ((copy = malloc(len)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
+}
+
+/** The toupper function converts a lowercase letter to a corresponding
+ uppercase letter.
+
+ @param[in] c The character to be converted.
+
+ @return If the argument is a character for which islower is true and
+ there are one or more corresponding characters, as specified by
+ the current locale, for which isupper is true, the toupper
+ function returns one of the corresponding characters (always the
+ same one for any given locale); otherwise, the argument is
+ returned unchanged.
+**/
+int
+toupper(
+ IN int c
+ )
+{
+ if ( (c >= 'a') && (c <= 'z') ) {
+ c = c - ('a' - 'A');
+ }
+ return c;
+}
+
+/**
+ Digit to a value.
+
+ @return Returns the value of digit.
+**/
+int
+Digit2Val( int c)
+{
+ if (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))) { /* If c is one of [A-Za-z]... */
+ c = toupper(c) - 7; // Adjust so 'A' is ('9' + 1)
+ }
+ return c - '0'; // Value returned is between 0 and 35, inclusive.
+}
+
+
+/** The strtoll function converts the initial portion of the string pointed to
+ by nptr to long long int representation.
+
+ See the description for strtol for more information.
+
+ @return The strtoll function returns the converted value, if any. If no
+ conversion could be performed, zero is returned. If the correct
+ value is outside the range of representable values, LLONG_MIN or
+ LLONG_MAX is returned (according to the sign of the value, if any),
+ and the value of the macro ERANGE is stored in errno.
+**/
+long long
+strtoll(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ long long Result = 0;
+ long long Previous;
+ int temp;
+ BOOLEAN Negative = FALSE;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional sign followed by digits.
+ if(*nptr == '+') {
+ Negative = FALSE;
+ ++nptr;
+ }
+ else if(*nptr == '-') {
+ Negative = TRUE;
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = MultS64x64 (Result, base) + (long long int)temp;
+ if( Result <= Previous) { // Detect Overflow
+ if(Negative) {
+ Result = LLONG_MIN;
+ }
+ else {
+ Result = LLONG_MAX;
+ }
+ Negative = FALSE;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+ if(Negative) {
+ Result = -Result;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/** The strtol, strtoll, strtoul, and strtoull functions convert the initial
+ portion of the string pointed to by nptr to long int, long long int,
+ unsigned long int, and unsigned long long int representation, respectively.
+ First, they decompose the input string into three parts: an initial,
+ possibly empty, sequence of white-space characters (as specified by the
+ isspace function), a subject sequence resembling an integer represented in
+ some radix determined by the value of base, and a final string of one or
+ more unrecognized characters, including the terminating null character of
+ the input string. Then, they attempt to convert the subject sequence to an
+ integer, and return the result.
+
+ If the value of base is zero, the expected form of the subject sequence is
+ that of an integer constant, optionally preceded
+ by a plus or minus sign, but not including an integer suffix. If the value
+ of base is between 2 and 36 (inclusive), the expected form of the subject
+ sequence is a sequence of letters and digits representing an integer with
+ the radix specified by base, optionally preceded by a plus or minus sign,
+ but not including an integer suffix. The letters from a (or A) through z
+ (or Z) are ascribed the values 10 through 35; only letters and digits whose
+ ascribed values are less than that of base are permitted. If the value of
+ base is 16, the characters 0x or 0X may optionally precede the sequence of
+ letters and digits, following the sign if present.
+
+ The subject sequence is defined as the longest initial subsequence of the
+ input string, starting with the first non-white-space character, that is of
+ the expected form. The subject sequence contains no characters if the input
+ string is empty or consists entirely of white space, or if the first
+ non-white-space character is other than a sign or a permissible letter or digit.
+
+ If the subject sequence has the expected form and the value of base is
+ zero, the sequence of characters starting with the first digit is
+ interpreted as an integer constant. If the subject sequence has the
+ expected form and the value of base is between 2 and 36, it is used as the
+ base for conversion, ascribing to each letter its value as given above. If
+ the subject sequence begins with a minus sign, the value resulting from the
+ conversion is negated (in the return type). A pointer to the final string
+ is stored in the object pointed to by endptr, provided that endptr is
+ not a null pointer.
+
+ In other than the "C" locale, additional locale-specific subject sequence
+ forms may be accepted.
+
+ If the subject sequence is empty or does not have the expected form, no
+ conversion is performed; the value of nptr is stored in the object pointed
+ to by endptr, provided that endptr is not a null pointer.
+
+ @return The strtol, strtoll, strtoul, and strtoull functions return the
+ converted value, if any. If no conversion could be performed, zero
+ is returned. If the correct value is outside the range of
+ representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX,
+ ULONG_MAX, or ULLONG_MAX is returned (according to the return type
+ and sign of the value, if any), and the value of the macro ERANGE
+ is stored in errno.
+**/
+long
+strtol(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ long Result = 0;
+ long Previous;
+ int temp;
+ BOOLEAN Negative = FALSE;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional sign followed by digits.
+ if(*nptr == '+') {
+ Negative = FALSE;
+ ++nptr;
+ }
+ else if(*nptr == '-') {
+ Negative = TRUE;
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = (Result * base) + (long int)temp;
+ if( Result <= Previous) { // Detect Overflow
+ if(Negative) {
+ Result = LONG_MIN;
+ }
+ else {
+ Result = LONG_MAX;
+ }
+ Negative = FALSE;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+ if(Negative) {
+ Result = -Result;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/** The strtoull function converts the initial portion of the string pointed to
+ by nptr to unsigned long long int representation.
+
+ See the description for strtol for more information.
+
+ @return The strtoull function returns the converted value, if any. If no
+ conversion could be performed, zero is returned. If the correct
+ value is outside the range of representable values, ULLONG_MAX is
+ returned and the value of the macro ERANGE is stored in errno.
+**/
+unsigned long long
+strtoull(const char * nptr, char ** endptr, int base)
+{
+ const char *pEnd;
+ unsigned long long Result = 0;
+ unsigned long long Previous;
+ int temp;
+
+ pEnd = nptr;
+
+ if((base < 0) || (base == 1) || (base > 36)) {
+ if(endptr != NULL) {
+ *endptr = NULL;
+ }
+ return 0;
+ }
+ // Skip leading spaces.
+ while(isspace(*nptr)) ++nptr;
+
+ // Process Subject sequence: optional + sign followed by digits.
+ if(*nptr == '+') {
+ ++nptr;
+ }
+
+ if(*nptr == '0') { /* Might be Octal or Hex */
+ if(toupper(nptr[1]) == 'X') { /* Looks like Hex */
+ if((base == 0) || (base == 16)) {
+ nptr += 2; /* Skip the "0X" */
+ base = 16; /* In case base was 0 */
+ }
+ }
+ else { /* Looks like Octal */
+ if((base == 0) || (base == 8)) {
+ ++nptr; /* Skip the leading "0" */
+ base = 8; /* In case base was 0 */
+ }
+ }
+ }
+ if(base == 0) { /* If still zero then must be decimal */
+ base = 10;
+ }
+ if(*nptr == '0') {
+ for( ; *nptr == '0'; ++nptr); /* Skip any remaining leading zeros */
+ pEnd = nptr;
+ }
+
+ while( isalnum(*nptr) && ((temp = Digit2Val(*nptr)) < base)) {
+ Previous = Result;
+ Result = DivU64x32 (Result, base) + (unsigned long long)temp;
+ if( Result < Previous) { // If we overflowed
+ Result = ULLONG_MAX;
+ errno = ERANGE;
+ break;
+ }
+ pEnd = ++nptr;
+ }
+
+ // Save pointer to final sequence
+ if(endptr != NULL) {
+ *endptr = (char *)pEnd;
+ }
+ return Result;
+}
+
+/**
+ edk2 Jansson port does not support doubles, simply return 0.
+
+ These conversion functions convert the initial portion of the string
+ pointed to by nptr to double, float, and long double representation,
+ respectively.
+
+ The strtod(), strtof(), and strtold() functions return the converted
+ value, if any.
+
+ If endptr is not NULL, a pointer to the character after the last charac-
+ ter used in the conversion is stored in the location referenced by
+ endptr.
+
+ If no conversion is performed, zero is returned and the value of nptr is
+ stored in the location referenced by endptr.
+
+ If the correct value would cause overflow, plus or minus HUGE_VAL,
+ HUGE_VALF, or HUGE_VALL is returned (according to the sign and type of
+ the return value), and ERANGE is stored in errno. If the correct value
+ would cause underflow, zero is returned and ERANGE is stored in errno.
+
+ @return Return 0.
+**/
+double
+strtod (const char * __restrict nptr, char ** __restrict endptr) {
+
+ DEBUG((DEBUG_INFO, "We don't supprot double type on edk2 yet!"));
+ ASSERT(FALSE);
+ return (double)0;
+}
+
+static UINT8 BitMask[] = {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
+ };
+
+#define WHICH8(c) ((unsigned char)(c) >> 3)
+#define WHICH_BIT(c) (BitMask[((c) & 0x7)])
+#define BITMAP64 ((UINT64 *)bitmap)
+
+static
+void
+BuildBitmap(unsigned char * bitmap, const char *s2, int n)
+{
+ unsigned char bit;
+ int index;
+
+ // Initialize bitmap. Bit 0 is always 1 which corresponds to '\0'
+ for (BITMAP64[0] = index = 1; index < n; index++) {
+ BITMAP64[index] = 0;
+ }
+
+ // Set bits in bitmap corresponding to the characters in s2
+ for (; *s2 != '\0'; s2++) {
+ index = WHICH8(*s2);
+ bit = WHICH_BIT(*s2);
+ bitmap[index] = bitmap[index] | bit;
+ }
+}
+
+/** The strpbrk function locates the first occurrence in the string pointed to
+ by s1 of any character from the string pointed to by s2.
+
+ @return The strpbrk function returns a pointer to the character, or a
+ null pointer if no character from s2 occurs in s1.
+**/
+char *
+strpbrk(const char *s1, const char *s2)
+{
+ UINT8 bitmap[ (((UCHAR_MAX + 1) / CHAR_BIT) + (CHAR_BIT - 1)) & ~7U];
+ UINT8 bit;
+ int index;
+
+ BuildBitmap( bitmap, s2, sizeof(bitmap) / sizeof(UINT64));
+
+ for( ; *s1 != '\0'; ++s1) {
+ index = WHICH8(*s1);
+ bit = WHICH_BIT(*s1);
+ if( (bitmap[index] & bit) != 0) {
+ return (char *)s1;
+ }
+ }
+ return NULL;
+}
+
+/** The strerror function maps the number in errnum to a message string.
+ Typically, the values for errnum come from errno, but strerror shall map
+ any value of type int to a message.
+
+ The implementation shall behave as if no library function calls the
+ strerror function.
+
+ @return The strerror function returns a pointer to the string, the
+ contents of which are locale specific. The array pointed to
+ shall not be modified by the program, but may be overwritten by
+ a subsequent call to the strerror function.
+**/
+char *
+strerror(int errnum)
+{
+ return errnum_message;
+}
+
+/**
+ Allocate and zero-initialize array.
+**/
+void *
+calloc(size_t Num, size_t Size)
+{
+ void *RetVal;
+ size_t NumSize;
+
+ NumSize = Num * Size;
+ RetVal = NULL;
+ if (NumSize != 0) {
+ RetVal = malloc(NumSize);
+ if( RetVal != NULL) {
+ (VOID)ZeroMem( RetVal, NumSize);
+ }
+ }
+ DEBUG((DEBUG_POOL, "0x%p = calloc(%d, %d)\n", RetVal, Num, Size));
+
+ return RetVal;
+}
+
+//
+// The arrays give the cumulative number of days up to the first of the
+// month number used as the index (1 -> 12) for regular and leap years.
+// The value at index 13 is for the whole year.
+//
+UINTN CumulativeDays[2][14] = {
+ {
+ 0,
+ 0,
+ 31,
+ 31 + 28,
+ 31 + 28 + 31,
+ 31 + 28 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
+ },
+ {
+ 0,
+ 0,
+ 31,
+ 31 + 29,
+ 31 + 29 + 31,
+ 31 + 29 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+ 31 + 29 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31
+ }
+};
+
+#define IsLeap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#define SECSPERMIN (60)
+#define SECSPERHOUR (60 * 60)
+#define SECSPERDAY (24 * SECSPERHOUR)
+
+/**
+ Get the system time as seconds elapsed since midnight, January 1, 1970.
+**/
+time_t time (time_t *timer)
+{
+ EFI_TIME Time;
+ time_t CalTime;
+ UINTN Year;
+
+ //
+ // Get the current time and date information
+ //
+ gRT->GetTime (&Time, NULL);
+
+ //
+ // Years Handling
+ // UTime should now be set to 00:00:00 on Jan 1 of the current year.
+ //
+ for (Year = 1970, CalTime = 0; Year != Time.Year; Year++) {
+ CalTime = CalTime + (time_t)(CumulativeDays[IsLeap(Year)][13] * SECSPERDAY);
+ }
+
+ //
+ // Add in number of seconds for current Month, Day, Hour, Minute, Seconds, and TimeZone adjustment
+ //
+ CalTime = CalTime +
+ (time_t)((Time.TimeZone != EFI_UNSPECIFIED_TIMEZONE) ? (Time.TimeZone * 60) : 0) +
+ (time_t)(CumulativeDays[IsLeap(Time.Year)][Time.Month] * SECSPERDAY) +
+ (time_t)(((Time.Day > 0) ? Time.Day - 1 : 0) * SECSPERDAY) +
+ (time_t)(Time.Hour * SECSPERHOUR) +
+ (time_t)(Time.Minute * 60) +
+ (time_t)Time.Second;
+
+ if (timer != NULL) {
+ *timer = CalTime;
+ }
+
+ return CalTime;
+}
+
+/**
+ Performs a quick sort
+**/
+void qsort (void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
+{
+
+ ASSERT (base != NULL);
+ ASSERT (compare != NULL);
+
+ PerformQuickSort (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare);
+ return;
+}
+
+/**
+ Get character from stream, we don't support file operastion on edk2 JSON library.
+
+ @return Returns the character currently pointed by the internal file position indicator of the specified stream
+
+**/
+int fgetc(FILE * _File){
+ return EOF;
+}
+/**
+ Open stream file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+FILE *fopen (const char *filename, const char *mode) {
+ return NULL;
+}
+/**
+ Read stream from file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+size_t fread (void * ptr, size_t size, size_t count, FILE * stream) {
+ return 0;
+}
+/**
+ Write stream from file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream) {
+ return 0;
+}
+/**
+ Close file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+int fclose (FILE * stream) {
+ return EOF;
+}
+/**
+ Write the formatted string to file, we don't support file operastion on edk2 JSON library.
+
+ @return 0 Unsupported
+
+**/
+int fprintf (FILE * stream, const char * format, ...) {
+ return -1;
+}
+/**
+ This function check if this is the formating string specifier.
+
+ @param[in] FormatString A Null-terminated ASCII format string.
+ @param[in,out] CurrentPosition The starting position at the given string to check for
+ "[flags][width][.precision][length]s" string specifier.
+ @param[in] StrLength Maximum string length.
+
+ @return BOOLEAN TRUE means this is the formating string specifier. CurrentPosition is
+ returned at the position of "s".
+ FALSE means this is not the formating string specifier.. CurrentPosition is
+ returned at the position of failed character.
+
+**/
+BOOLEAN
+CheckFormatingString (
+ IN CONST CHAR8 *FormatString,
+ IN OUT UINTN *CurrentPosition,
+ IN UINTN StrLength
+ )
+{
+ CHAR8 FormatStringParamater;
+
+ while (*(FormatString + *CurrentPosition) != 's') {
+ //
+ // Loop until reach character 's' if the formating string is
+ // compliant with "[flags][width][.precision][length]" format for
+ // the string specifier.
+ //
+ FormatStringParamater = *(FormatString + *CurrentPosition);
+ if ((FormatStringParamater != '-') &&
+ (FormatStringParamater != '+') &&
+ (FormatStringParamater != '*') &&
+ (FormatStringParamater != '.') &&
+ !(((UINTN)FormatStringParamater >= (UINTN)'0') && ((UINTN)FormatStringParamater <= (UINTN)'9'))
+ ) {
+ return FALSE;
+ }
+ (*CurrentPosition)++;
+ if (*CurrentPosition >= StrLength) {
+ return FALSE;
+ }
+ };
+ return TRUE;
+}
+
+/**
+ This function clones *FormatString however replaces "%s" with "%a" in the
+ returned string.
+
+ @param[in] A Null-terminated ASCII format string.
+
+ @return The new format string. Caller has to free the memory of this string
+ using FreePool().
+
+**/
+CHAR8 *
+ReplaceUnicodeToAsciiStrFormat (
+ IN CONST CHAR8 *FormatString
+)
+{
+ UINTN FormatStrSize;
+ UINTN FormatStrIndex;
+ UINTN FormatStrSpecifier;
+ BOOLEAN PercentageMark;
+ CHAR8 *TempFormatBuffer;
+ BOOLEAN IsFormatString;
+
+ //
+ // Error checking.
+ //
+ if (FormatString == NULL) {
+ return NULL;
+ }
+ FormatStrSize = AsciiStrSize(FormatString);
+ if (FormatStrSize == 0) {
+ return NULL;
+ }
+ TempFormatBuffer = AllocatePool(FormatStrSize); // Allocate memory for the
+ // new string.
+ if (TempFormatBuffer== NULL) {
+ return NULL;
+ }
+ //
+ // Clone *FormatString but replace "%s" wih "%a".
+ // "%%" is not considered as the format tag.
+ //
+ PercentageMark = FALSE;
+ FormatStrIndex = 0;
+ while (FormatStrIndex < FormatStrSize) {
+ if (PercentageMark == TRUE) {
+ //
+ // Previous character is "%".
+ //
+ PercentageMark = FALSE;
+ if (*(FormatString + FormatStrIndex) != '%') { // Check if this is double "%".
+ FormatStrSpecifier = FormatStrIndex;
+ //
+ // Check if this is the formating string specifier.
+ //
+ IsFormatString = CheckFormatingString (FormatString, &FormatStrSpecifier, FormatStrSize);
+ if ((FormatStrSpecifier - FormatStrIndex) != 0) {
+ CopyMem((VOID *)(TempFormatBuffer + FormatStrIndex),
+ (VOID *)(FormatString + FormatStrIndex),
+ FormatStrSpecifier - FormatStrIndex
+ );
+ }
+ FormatStrIndex = FormatStrSpecifier;
+ if (IsFormatString == TRUE) {
+ //
+ // Replace 's' with 'a' which is printed in ASCII
+ // format on edk2 environment.
+ //
+ *(TempFormatBuffer + FormatStrSpecifier) = 'a';
+ FormatStrIndex ++;
+ }
+ continue;
+ }
+ goto ContinueCheck;
+ }
+ if (*(FormatString + FormatStrIndex) == '%') {
+ //
+ // This character is "%", set the flag.
+ //
+ PercentageMark = TRUE;
+ }
+ContinueCheck:
+ //
+ // Clone character to the new string and advance FormatStrIndex
+ // to process next character.
+ //
+ *(TempFormatBuffer + FormatStrIndex) = *(FormatString + FormatStrIndex);
+ FormatStrIndex++;
+ };
+ return TempFormatBuffer;
+}
+
+/**
+ This is the Redfish version of CRT vsnprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiVSPrint(). That is because "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on vsnprintf().
+ See definitions of AsciiVSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param Marker VA_LIST marker for the variable argument list.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiVSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ IN VA_LIST Marker
+ )
+{
+ CHAR8 *TempFormatBuffer;
+ UINTN LenStrProduced;
+
+ //
+ // Looking for "%s" in the format string and replace it
+ // with "%a" for printing ASCII code characters on edk2
+ // environment.
+ //
+ TempFormatBuffer = ReplaceUnicodeToAsciiStrFormat (FormatString);
+ if (TempFormatBuffer == NULL) {
+ return 0;
+ }
+ LenStrProduced = AsciiVSPrint (StartOfBuffer, BufferSize, (CONST CHAR8 *)TempFormatBuffer, Marker);
+ FreePool (TempFormatBuffer);
+ return LenStrProduced;
+}
+
+/**
+ This is the Redfish version of CRT snprintf function, this function replaces "%s" to
+ "%a" before invoking AsciiSPrint(). That is because "%s" is unicode base on edk2
+ environment however "%s" is ascii code base on snprintf().
+ See definitions of AsciiSPrint() for the details.
+
+ @param StartOfBuffer A pointer to the output buffer for the produced Null-terminated
+ ASCII string.
+ @param BufferSize The size, in bytes, of the output buffer specified by StartOfBuffer.
+ @param FormatString A Null-terminated ASCII format string.
+ @param ... Variable argument list whose contents are accessed based on the
+ format string specified by FormatString.
+
+ @return The number of ASCII characters in the produced output buffer not including the
+ Null-terminator.
+
+**/
+UINTN
+EFIAPI
+RedfishAsciiSPrint (
+ OUT CHAR8 *StartOfBuffer,
+ IN UINTN BufferSize,
+ IN CONST CHAR8 *FormatString,
+ ...
+ )
+{
+ VA_LIST Marker;
+ UINTN LenStrProduced;
+
+ VA_START(Marker, FormatString);
+ LenStrProduced = RedfishAsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker);
+ return LenStrProduced;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
new file mode 100644
index 00000000000..4dc6be764b0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Redfish C Runtime Library for opensource projects.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishCrtLib
+ FILE_GUID = 8263B8AC-D021-425D-B337-3EC96F5DC19B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishCrtLib|DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishCrtLib.c
+
+[LibraryClasses]
+ BaseLib
+ BaseSortLib
+ DebugLib
+ MemoryAllocationLib
+ UefiRuntimeServicesTableLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c
new file mode 100644
index 00000000000..3a50f3dc946
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.c
@@ -0,0 +1,993 @@
+/** @file
+ Provides a set of utility APIs that allow to create/read/update/delete
+ (CRUD) Redfish resources and provide basic query.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishMisc.h"
+
+/**
+ This function uses REST EX protocol provided in RedfishConfigServiceInfo.
+ The service enumerator will also handle the authentication flow automatically
+ if HTTP basic auth or Redfish session login is configured to use.
+
+ Callers are responsible for freeing the returned service by RedfishCleanupService().
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+
+ @return New created Redfish Service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+EFIAPI
+RedfishCreateService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo
+ )
+{
+ REDFISH_SERVICE RedfishService;
+ EDKII_REDFISH_AUTH_METHOD AuthMethod;
+ CHAR8 *UserId;
+ CHAR8 *Password;
+ EFI_STATUS Status;
+
+ RedfishService = NULL;
+ UserId = NULL;
+ Password = NULL;
+
+ //
+ // Check Input Parameters.
+ //
+ if (RedfishConfigServiceInfo == NULL) {
+ return NULL;
+ }
+
+ //
+ // Get Authentication Configuration.
+ //
+ Status = RedfishGetAuthInfo (&AuthMethod, &UserId, &Password);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // Create a redfish service node based on Redfish network host interface.
+ //
+ RedfishService = RedfishCreateLibredfishService (
+ RedfishConfigServiceInfo,
+ AuthMethod,
+ UserId,
+ Password
+ );
+
+ON_EXIT:
+ if (UserId != NULL) {
+ FreePool (UserId);
+ }
+ if (Password!= NULL) {
+ FreePool (Password);
+ }
+
+ return RedfishService;
+}
+
+/**
+ Free the Service and all its related resources.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupService (
+ IN REDFISH_SERVICE RedfishService
+ )
+{
+ if (RedfishService == NULL) {
+ return;
+ }
+
+ cleanupServiceEnumerator (RedfishService);
+}
+/**
+ Create REDFISH_PAYLOAD instance in local with JSON represented resource value and
+ the Redfish Service.
+
+ The returned REDFISH_PAYLOAD can be used to create or update Redfish resource in
+ server side.
+
+ Callers are responsible for freeing the returned payload by RedfishCleanupPayload().
+
+ @param[in] Value JSON Value of the redfish resource.
+ @param[in] RedfishService The Service to access the Redfish resources.
+
+ @return REDFISH_PAYLOAD instance of the resource, or NULL if error happens.
+
+**/
+REDFISH_PAYLOAD
+EFIAPI
+RedfishCreatePayload (
+ IN EDKII_JSON_VALUE Value,
+ IN REDFISH_SERVICE RedfishService
+ )
+{
+ EDKII_JSON_VALUE CopyValue;
+
+ CopyValue = JsonValueClone (Value);
+ return createRedfishPayload (CopyValue, RedfishService);
+}
+
+/**
+ Free the RedfishPayload and all its related resources.
+
+ @param[in] Payload Payload to be freed.
+
+**/
+VOID
+EFIAPI
+RedfishCleanupPayload (
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ if (Payload == NULL) {
+ return;
+ }
+
+ cleanupPayload ((redfishPayload *) Payload);
+}
+
+/**
+ This function returns the decoded JSON value of a REDFISH_PAYLOAD.
+
+ Caller doesn't need to free the returned JSON value because it will be released
+ in corresponding RedfishCleanupPayload() function.
+
+ @param[in] Payload A REDFISH_PAYLOAD instance.
+
+ @return Decoded JSON value of the payload.
+
+**/
+EDKII_JSON_VALUE
+EFIAPI
+RedfishJsonInPayload (
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ if (Payload == NULL) {
+ return NULL;
+ }
+
+ return ((redfishPayload*)Payload)->json;
+}
+
+/**
+ Fill the input RedPath string with system UUID from SMBIOS table or use the customized
+ ID if FromSmbios == FALSE.
+
+ This is a helper function to build a RedPath string which can be used to address
+ a Redfish resource for this computer system. The input PathString must have a Systems
+ note in format of "Systems[UUID=%g]" or "Systems[UUID~%g]" to fill the UUID value.
+
+ Example:
+ Use "/v1/Systems[UUID=%g]/Bios" to build a RedPath to address the "Bios" resource
+ for this computer system.
+
+ @param[in] RedPath RedPath format to be build.
+ @param[in] FromSmbios Get system UUID from SMBIOS as computer system instance ID.
+ @param[in] IdString The computer system instance ID.
+
+ @return Full RedPath with system UUID inside, or NULL if error happens.
+
+**/
+CHAR8 *
+EFIAPI
+RedfishBuildPathWithSystemUuid (
+ IN CONST CHAR8 *RedPath,
+ IN BOOLEAN FromSmbios,
+ IN CHAR8 *IdString OPTIONAL
+ )
+{
+ UINTN BufSize;
+ CHAR8* RetRedPath;
+ EFI_GUID SystemUuid;
+ EFI_STATUS Status;
+
+ if (RedPath == NULL) {
+ return NULL;
+ }
+
+ //
+ // Find system UUID from SMBIOS table.
+ //
+ if (FromSmbios) {
+ Status = NetLibGetSystemGuid(&SystemUuid);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+ // AsciiStrLen ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx") = 36
+ BufSize = AsciiStrSize (RedPath) + AsciiStrLen ("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX");
+ } else {
+ BufSize = AsciiStrSize (RedPath) + AsciiStrLen (IdString);
+ }
+
+ RetRedPath = AllocateZeroPool (BufSize);
+ if (RetRedPath == NULL) {
+ return NULL;
+ }
+ if (FromSmbios) {
+ AsciiSPrint (RetRedPath, BufSize, RedPath, &SystemUuid);
+ } else {
+ AsciiSPrint (RetRedPath, BufSize, RedPath, IdString);
+ }
+ return RetRedPath;
+}
+/**
+ Get a redfish response addressed by a RedPath string, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] RedPath RedPath string to address a resource, must start
+ from the root node.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByService (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (RedfishService == NULL || RedPath == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) getPayloadByPath (RedfishService, RedPath, &(RedResponse->StatusCode));
+
+ //
+ // 1. If the returned Payload is NULL, indicates any error happen.
+ // 2. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->Payload == NULL || RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 3. If the returned StatusCode is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Get a redfish response addressed by URI, including HTTP StatusCode, Headers
+ and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the URI resources.
+ @param[in] Uri String to address a resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The corresponding redfish resource has
+ been returned in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If the returned StatusCode is NULL, indicates any error happen.
+ 3. If the returned StatusCode is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ EDKII_JSON_VALUE JsonValue;
+
+ if (RedfishService == NULL || Uri == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ JsonValue = getUriFromService (RedfishService, Uri, &RedResponse->StatusCode);
+ RedResponse->Payload = createRedfishPayload(JsonValue, RedfishService);
+
+ //
+ // 1. If the returned Payload is NULL, indicates any error happen.
+ // 2. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->Payload == NULL || RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 3. If the returned StatusCode is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+ return EFI_SUCCESS;
+}
+/**
+ Get a redfish response addressed by the input Payload and relative RedPath string,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Payload A existing REDFISH_PAYLOAD instance.
+ @param[in] RedPath Relative RedPath string to address a resource inside Payload.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful:
+ 1. The HTTP StatusCode is NULL and the returned Payload in
+ RedResponse is not NULL, indicates the Redfish resource has
+ been parsed from the input payload directly.
+ 2. The HTTP StatusCode is not NULL and the value is 2XX,
+ indicates the corresponding redfish resource has been returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER Payload, RedPath, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned Payload is NULL, indicates any error happen.
+ 2. If StatusCode is not NULL and the returned value of StatusCode
+ is not 2XX, indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishGetByPayload (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *RedPath,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (Payload == NULL || RedPath == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) getPayloadForPathString (Payload, RedPath, &(RedResponse->StatusCode));
+
+ //
+ // 1. If the returned Payload is NULL, indicates any error happen.
+ //
+ if (RedResponse->Payload == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 2. If StatusCode is not NULL and the returned value of StatusCode is not 2XX, indicates any
+ // error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (RedResponse->StatusCode != NULL && \
+ (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT
+ )) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Use HTTP PATCH to perform updates on pre-existing Redfish resource.
+
+ This function uses the RedfishService to patch a Redfish resource addressed by
+ Uri (only the relative path is required). Changes to one or more properties within
+ the target resource are represented in the input Content, properties not specified
+ in Content won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[in] Content JSON represented properties to be update.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, Content, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ IN CONST CHAR8 *Content,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ EFI_STATUS Status;
+ EDKII_JSON_VALUE JsonValue;
+
+ Status = EFI_SUCCESS;
+ JsonValue = NULL;
+
+ if (RedfishService == NULL || Uri == NULL || Content == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ JsonValue = (EDKII_JSON_VALUE) patchUriFromService (
+ RedfishService,
+ Uri,
+ Content,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ON_EXIT:
+ if (JsonValue != NULL) {
+ RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
+ if (RedResponse->Payload == NULL) {
+ //
+ // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
+ // we care about if the returned StatusCode is 2XX.
+ //
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ return Status;
+}
+/**
+ Use HTTP PATCH to perform updates on target payload. Patch to odata.id in Payload directly.
+
+ This function uses the Payload to patch the Target. Changes to one or more properties
+ within the target resource are represented in the input Payload, properties not specified
+ in Payload won't be changed by this request. The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target The target payload to be updated.
+ @param[in] Payload Palyoad with properties to be changed.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPatchToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (Target == NULL || Payload == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) patchPayload (
+ Target,
+ Payload,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Use HTTP POST to create a new resource in target payload.
+
+ The POST request should be submitted to the Resource Collection in which the new resource
+ is to belong. The Resource Collection is addressed by Target payload. The Redfish may
+ ignore any service controlled properties. The corresponding redfish response will returned,
+ including HTTP StatusCode, Headers and Payload which record any HTTP response messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] Target Target payload of the Resource Collection.
+ @param[in] Payload The new resource to be created.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX. The Redfish resource will be returned
+ in Payload within RedResponse if server send it back in the HTTP
+ response message body.
+ @retval EFI_INVALID_PARAMETER Target, Payload, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishPostToPayload (
+ IN REDFISH_PAYLOAD Target,
+ IN REDFISH_PAYLOAD Payload,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ if (Target == NULL || Payload == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ RedResponse->Payload = (REDFISH_PAYLOAD) postPayload (
+ Target,
+ Payload,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Use HTTP DELETE to remove a resource.
+
+ This function uses the RedfishService to remove a Redfish resource which is addressed
+ by input Uri (only the relative path is required). The corresponding redfish response will
+ returned, including HTTP StatusCode, Headers and Payload which record any HTTP response
+ messages.
+
+ Callers are responsible for freeing the HTTP StatusCode, Headers and Payload returned in
+ redfish response data.
+
+ @param[in] RedfishService The Service to access the Redfish resources.
+ @param[in] Uri Relative path to address the resource.
+ @param[out] RedResponse Pointer to the Redfish response data.
+
+ @retval EFI_SUCCESS The opeartion is successful, indicates the HTTP StatusCode is not
+ NULL and the value is 2XX, the Redfish resource has been removed.
+ If there is any message returned from server, it will be returned
+ in Payload within RedResponse.
+ @retval EFI_INVALID_PARAMETER RedfishService, Uri, or RedResponse is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. Callers can get
+ more error info from returned HTTP StatusCode, Headers and Payload
+ within RedResponse:
+ 1. If the returned StatusCode is NULL, indicates any error happen.
+ 2. If the returned StatusCode is not NULL and the value is not 2XX,
+ indicates any error happen.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDeleteByUri (
+ IN REDFISH_SERVICE RedfishService,
+ IN CONST CHAR8 *Uri,
+ OUT REDFISH_RESPONSE *RedResponse
+ )
+{
+ EFI_STATUS Status;
+ EDKII_JSON_VALUE JsonValue;
+
+ Status = EFI_SUCCESS;
+ JsonValue = NULL;
+
+ if (RedfishService == NULL || Uri == NULL || RedResponse == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ZeroMem (RedResponse, sizeof (REDFISH_RESPONSE));
+
+ JsonValue = (EDKII_JSON_VALUE) deleteUriFromService (
+ RedfishService,
+ Uri,
+ &(RedResponse->StatusCode)
+ );
+
+ //
+ // 1. If the returned StatusCode is NULL, indicates any error happen.
+ //
+ if (RedResponse->StatusCode == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ //
+ // 2. If the returned StatusCode is not NULL and the value is not 2XX, indicates any error happen.
+ // NOTE: If there is any error message returned from server, it will be returned in
+ // Payload within RedResponse.
+ //
+ if (*(RedResponse->StatusCode) < HTTP_STATUS_200_OK || \
+ *(RedResponse->StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ON_EXIT:
+ if (JsonValue != NULL) {
+ RedResponse->Payload = createRedfishPayload (JsonValue, RedfishService);
+ if (RedResponse->Payload == NULL) {
+ //
+ // Ignore the error when create RedfishPayload, just free the JsonValue since it's not what
+ // we care about if the returned StatusCode is 2XX.
+ //
+ JsonValueFree (JsonValue);
+ }
+ }
+
+ return Status;
+}
+/**
+ Dump text in fractions.
+
+ @param[in] String ASCII string to dump.
+
+**/
+VOID
+RedfishDumpJsonStringFractions (
+ IN CHAR8 *String
+ )
+{
+ CHAR8 *NextFraction;
+ UINTN StringFractionSize;
+ UINTN StrLen;
+ UINTN Count;
+ CHAR8 BackupChar;
+
+ StringFractionSize = 200;
+ if (String == NULL) {
+ return ;
+ }
+
+ DEBUG((DEBUG_INFO, "JSON text:\n"));
+ NextFraction = String;
+ StrLen = AsciiStrLen (String);
+ if (StrLen == 0) {
+ return;
+ }
+ for (Count = 0; Count < (StrLen / StringFractionSize); Count++) {
+ BackupChar = *(NextFraction + StringFractionSize);
+ *(NextFraction + StringFractionSize) = 0;
+ DEBUG((DEBUG_INFO, "%a", NextFraction));
+ *(NextFraction + StringFractionSize) = BackupChar;
+ NextFraction += StringFractionSize;
+ }
+ if ((StrLen % StringFractionSize) != 0) {
+ DEBUG((DEBUG_INFO, "%a\n\n", NextFraction));
+ }
+}
+/**
+ Dump text in JSON value.
+
+ @param[in] JsonValue The Redfish JSON value to dump.
+
+**/
+VOID
+RedfishDumpJson (
+ IN EDKII_JSON_VALUE JsonValue
+ )
+{
+ CHAR8 *String;
+
+ String = JsonDumpString (JsonValue, 0);
+ if (String == NULL) {
+ return;
+ }
+ RedfishDumpJsonStringFractions (String);
+ FreePool(String);
+}
+/**
+ Extract the JSON text content from REDFISH_PAYLOAD and dump to debug console.
+
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishDumpPayload (
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ EDKII_JSON_VALUE JsonValue;
+ CHAR8 *String;
+
+ JsonValue = NULL;
+ String = NULL;
+
+ if (Payload == NULL) {
+ return;
+ }
+
+ JsonValue = RedfishJsonInPayload (Payload);
+ if (JsonValue == NULL) {
+ return;
+ }
+
+ String = JsonDumpString (JsonValue, 0);
+ if (String == NULL) {
+ return;
+ }
+
+ RedfishDumpJsonStringFractions (String);
+ FreePool(String);
+}
+/**
+ This function will cleanup the HTTP header and Redfish payload resources.
+
+ @param[in] StatusCode The status code in HTTP response message.
+ @param[in] HeaderCount Number of HTTP header structures in Headers list.
+ @param[in] Headers Array containing list of HTTP headers.
+ @param[in] Payload The Redfish payload to dump.
+
+**/
+VOID
+RedfishFreeResponse (
+ IN EFI_HTTP_STATUS_CODE *StatusCode,
+ IN UINTN HeaderCount,
+ IN EFI_HTTP_HEADER *Headers,
+ IN REDFISH_PAYLOAD Payload
+ )
+{
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ StatusCode = NULL;
+ }
+
+ if (HeaderCount != 0 && Headers != NULL) {
+ HttpFreeHeaderFields(Headers, HeaderCount);
+ Headers = NULL;
+ }
+
+ if (Payload != NULL) {
+ RedfishCleanupPayload (Payload);
+ Payload = NULL;
+ }
+}
+/**
+ Check if the "@odata.type" in Payload is valid or not.
+
+ @param[in] Payload The Redfish payload to be checked.
+ @param[in] OdataTypeName OdataType will be retrived from mapping list.
+ @param[in] OdataTypeMappingList The list of OdataType.
+ @param[in] OdataTypeMappingListSize The number of mapping list
+
+ @return TRUE if the "@odata.type" in Payload is valid, otherwise FALSE.
+
+**/
+BOOLEAN
+RedfishIsValidOdataType (
+ IN REDFISH_PAYLOAD Payload,
+ IN CONST CHAR8 *OdataTypeName,
+ IN REDFISH_ODATA_TYPE_MAPPING *OdataTypeMappingList,
+ IN UINTN OdataTypeMappingListSize
+ )
+{
+ UINTN Index;
+ EDKII_JSON_VALUE OdataType;
+ EDKII_JSON_VALUE JsonValue;
+
+ if (Payload == NULL || OdataTypeName == NULL) {
+ return FALSE;
+ }
+
+ JsonValue = RedfishJsonInPayload (Payload);
+ if (!JsonValueIsObject (JsonValue)) {
+ return FALSE;
+ }
+
+ OdataType = JsonObjectGetValue (JsonValueGetObject (JsonValue), "@odata.type");
+ if (!JsonValueIsString (OdataType) || JsonValueGetAsciiString (OdataType) == NULL) {
+ return FALSE;
+ }
+
+ for (Index = 0; Index < OdataTypeMappingListSize; Index ++) {
+ if (AsciiStrCmp (OdataTypeMappingList[Index].OdataTypeName, OdataTypeName) == 0 &&
+ AsciiStrCmp (OdataTypeMappingList[Index].OdataType, JsonValueGetAsciiString (OdataType)) == 0) {
+ return TRUE;
+ }
+ }
+ DEBUG ((DEBUG_INFO, "%a: This Odata type is not in the list.\n", __FUNCTION__));
+ return FALSE;
+}
+/**
+ Check if the payload is collection
+
+ @param[in] Payload The Redfish payload to be checked.
+
+ @return TRUE if the payload is collection.
+
+**/
+BOOLEAN
+RedfishIsPayloadCollection (
+ IN REDFISH_PAYLOAD Payload
+)
+{
+ return isPayloadCollection (Payload);
+}
+/**
+ Get collection size.
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] CollectionSize Size of this collection
+
+ @return EFI_SUCCESS Coolection size is returned in CollectionSize
+ @return EFI_INVALID_PARAMETER The payload is not a collection.
+**/
+EFI_STATUS
+RedfishGetCollectionSize(
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN *CollectionSize
+ )
+{
+ if (Payload == NULL || CollectionSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ if (!RedfishIsPayloadCollection(Payload)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *CollectionSize = (UINTN)getCollectionSize(Payload);
+ return EFI_SUCCESS;
+}
+/**
+ Get Redfish payload of collection member
+
+ @param[in] Payload The Redfish collection payload
+ @param[in] Index Index of collection member
+
+ @return NULL Fail to get collection member.
+ @return Non NULL Payload is returned.
+**/
+REDFISH_PAYLOAD
+RedfishGetPayloadByIndex (
+ IN REDFISH_PAYLOAD Payload,
+ IN UINTN Index
+)
+{
+ REDFISH_RESPONSE RedfishResponse;
+ REDFISH_PAYLOAD PayloadReturn;
+
+ PayloadReturn = (VOID *)getPayloadByIndex (Payload, Index, &RedfishResponse.StatusCode);
+ if(PayloadReturn == NULL ||
+ (*(RedfishResponse.StatusCode) < HTTP_STATUS_200_OK && *(RedfishResponse.StatusCode) > HTTP_STATUS_206_PARTIAL_CONTENT)){
+ return NULL;
+ }
+ return PayloadReturn;
+}
+/**
+ Check and return Redfish resource of the given Redpath.
+
+ @param[in] RedfishService Pointer to REDFISH_SERVICE
+ @param[in] Redpath Redpath of the resource.
+ @param[in] Response Optional return the resource.
+
+ @return EFI_STATUS
+**/
+EFI_STATUS
+RedfishCheckIfRedpathExist (
+ IN REDFISH_SERVICE RedfishService,
+ IN CHAR8 *Redpath,
+ IN REDFISH_RESPONSE *Response OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ REDFISH_RESPONSE TempResponse;
+
+ if (Redpath == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = RedfishGetByService (RedfishService, Redpath, &TempResponse);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (Response == NULL) {
+ RedfishFreeResponse(
+ TempResponse.StatusCode,
+ TempResponse.HeaderCount,
+ TempResponse.Headers,
+ TempResponse.Payload
+ );
+ } else {
+ CopyMem ((VOID *)Response, (VOID *)&TempResponse, sizeof (REDFISH_RESPONSE));
+ }
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
new file mode 100644
index 00000000000..6afabd6d132
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
@@ -0,0 +1,60 @@
+## @file
+# RedfishLib Library implementation.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = DxeRedfishLib
+ FILE_GUID = 9C2CA9CF-4F79-11E8-A7D1-8CDCD426C973
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = RedfishLib| DXE_DRIVER UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ edk2libredfish/src/redpath.c
+ edk2libredfish/src/service.c
+ edk2libredfish/src/payload.c
+ edk2libredfish/include/redfish.h
+ edk2libredfish/include/redfishPayload.h
+ edk2libredfish/include/redfishService.h
+ edk2libredfish/include/redpath.h
+ RedfishLib.c
+ RedfishMisc.h
+ RedfishMisc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HttpLib
+ MemoryAllocationLib
+ NetLib
+ RedfishContentCodingLib
+ RedfishCrtLib
+ UefiBootServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## Consumed
+ gEfiRestExProtocolGuid ## Consumed
+ gEdkIIRedfishCredentialProtocolGuid ## Consumed
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /U_WIN32 /UWIN64 /U_MSC_VER
+ GCC:*_*_*_CC_FLAGS = -Wno-unused-function -Wno-unused-but-set-variable
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
new file mode 100644
index 00000000000..324811532e2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.c
@@ -0,0 +1,201 @@
+/** @file
+ Internal Functions for RedfishLib.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishMisc.h"
+
+EDKII_REDFISH_CREDENTIAL_PROTOCOL *mCredentialProtocol = NULL;
+
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] RedfishService Redfish service instance.
+ @param[out] ServiceVersionStr Redfish service string.
+
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishGetServiceVersion (
+ IN REDFISH_SERVICE RedfishService,
+ OUT CHAR8 **ServiceVersionStr
+ )
+{
+ redfishService *Redfish;
+ CHAR8 **KeysArray;
+ UINTN KeysNum;
+
+ if (RedfishService == NULL || ServiceVersionStr == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Redfish = (redfishService *)RedfishService;
+ if (Redfish->versions == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ KeysArray = JsonObjectGetKeys (Redfish->versions, &KeysNum);
+ if (KeysNum == 0 || KeysArray == NULL) {
+ return EFI_NOT_FOUND;
+ }
+ *ServiceVersionStr = *KeysArray;
+ return EFI_SUCCESS;
+}
+
+/**
+ Creates a REDFISH_SERVICE which can be later used to access the Redfish resources.
+
+ This function will configure REST EX child according to parameters described in
+ Redfish network host interface in SMBIOS type 42 record. The service enumerator will also
+ handle the authentication flow automatically if HTTP basic auth or Redfish session
+ login is configured to use.
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+ @param[in] AuthMethod None, HTTP basic auth, or Redfish session login.
+ @param[in] UserId User Name used for authentication.
+ @param[in] Password Password used for authentication.
+
+ @return New created Redfish service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+RedfishCreateLibredfishService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
+ IN EDKII_REDFISH_AUTH_METHOD AuthMethod,
+ IN CHAR8 *UserId,
+ IN CHAR8 *Password
+ )
+{
+
+ UINTN Flags;
+ enumeratorAuthentication Auth;
+ redfishService* Redfish;
+
+ Redfish = NULL;
+
+ ZeroMem (&Auth, sizeof (Auth));
+ if (AuthMethod == AuthMethodHttpBasic) {
+ Auth.authType = REDFISH_AUTH_BASIC;
+ } else if (AuthMethod == AuthMethodRedfishSession) {
+ Auth.authType = REDFISH_AUTH_SESSION;
+ }
+ Auth.authCodes.userPass.username = UserId;
+ Auth.authCodes.userPass.password = Password;
+
+ Flags = REDFISH_FLAG_SERVICE_NO_VERSION_DOC;
+
+ if (AuthMethod != AuthMethodNone) {
+ Redfish = createServiceEnumerator(RedfishConfigServiceInfo, NULL, &Auth, (unsigned int ) Flags);
+ } else {
+ Redfish = createServiceEnumerator(RedfishConfigServiceInfo, NULL, NULL, (unsigned int) Flags);
+ }
+
+ //
+ // Zero the Password after use.
+ //
+ if (Password != NULL) {
+ ZeroMem (Password, AsciiStrLen(Password));
+ }
+
+ return (REDFISH_SERVICE) Redfish;
+}
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user
+ Id and password.
+ For AuthMethodNone, UserId and Password will point to NULL which means authentication
+ is not required to access the Redfish service.
+ For AuthMethodHttpBasic, the UserId and Password could be used for
+ HTTP header authentication as defined by RFC7235. For AuthMethodRedfishSession,
+ the UserId and Password could be used for Redfish session login as defined by
+ Redfish API specification (DSP0266).
+
+ Callers are responsible for freeing the returned string storage pointed by UserId
+ and Password.
+
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_INVALID_PARAMETER AuthMethod or UserId or Password is NULL.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+**/
+EFI_STATUS
+RedfishGetAuthInfo (
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ )
+{
+ EFI_STATUS Status;
+
+ if (AuthMethod == NULL || UserId == NULL || Password == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate Redfish Credential Protocol.
+ //
+ if (mCredentialProtocol == NULL) {
+ Status = gBS->LocateProtocol (&gEdkIIRedfishCredentialProtocolGuid, NULL, (VOID **)&mCredentialProtocol);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ ASSERT (mCredentialProtocol != NULL);
+
+ Status = mCredentialProtocol->GetAuthInfo (mCredentialProtocol, AuthMethod, UserId, Password);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "RedfishGetAuthInfo: failed to retrieve Redfish credential - %r\n", Status));
+ return Status;
+ }
+
+ return Status;
+}
+/**
+ This function returns the string of Redfish service version.
+
+ @param[in] ServiceVerisonStr The string of Redfish service version.
+ @param[in] Url The URL to build Redpath with ID.
+ Start with "/", for example "/Registries"
+ @param[in] Id ID string
+ @param[out] Redpath Pointer to retrive Redpath, caller has to free
+ the memory allocated for this string.
+ @return EFI_STATUS
+
+**/
+EFI_STATUS
+RedfishBuildRedpathUseId (
+ IN CHAR8 *ServiceVerisonStr,
+ IN CHAR8 *Url,
+ IN CHAR8 *Id,
+ OUT CHAR8 **Redpath
+ )
+{
+ UINTN RedpathSize;
+
+ if (Redpath == NULL || ServiceVerisonStr == NULL || Url == NULL || Id == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RedpathSize = AsciiStrLen ("/") +
+ AsciiStrLen (ServiceVerisonStr) +
+ AsciiStrLen (Url) +
+ AsciiStrLen ("[Id=]") +
+ AsciiStrLen (Id) + 1;
+ *Redpath = AllocatePool(RedpathSize);
+ if (*Redpath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ AsciiSPrint (*Redpath, RedpathSize, "/%a%a[Id=%a]", ServiceVerisonStr, Url, Id);
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h
new file mode 100644
index 00000000000..19710398663
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/RedfishMisc.h
@@ -0,0 +1,82 @@
+/** @file
+ Internal Functions for RedfishLib.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef DXE_REDFISH_MISC_LIB_H_
+#define DXE_REDFISH_MISC_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/JsonLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RedfishLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/EdkIIRedfishCredential.h>
+#include <redfish.h>
+
+#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0]))
+
+/**
+ Creates a REDFISH_SERVICE which can be later used to access the Redfish resources.
+
+ This function will configure REST EX child according to parameters described in
+ Redfish network host interface in SMBIOS type 42 record. The service enumerator will also
+ handle the authentication flow automatically if HTTP basic auth or Redfish session
+ login is configured to use.
+
+ @param[in] RedfishConfigServiceInfo Redfish service information the EFI Redfish
+ feature driver communicates with.
+ @param[in] AuthMethod None, HTTP basic auth, or Redfish session login.
+ @param[in] UserId User Name used for authentication.
+ @param[in] Password Password used for authentication.
+
+ @return New created Redfish service, or NULL if error happens.
+
+**/
+REDFISH_SERVICE
+RedfishCreateLibredfishService (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
+ IN EDKII_REDFISH_AUTH_METHOD AuthMethod,
+ IN CHAR8 *UserId,
+ IN CHAR8 *Password
+ );
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user
+ Id and password.
+ For AuthMethodNone, UserId and Password will point to NULL which means authentication
+ is not required to access the Redfish service.
+ For AuthMethodHttpBasic, the UserId and Password could be used for
+ HTTP header authentication as defined by RFC7235. For AuthMethodRedfishSession,
+ the UserId and Password could be used for Redfish session login as defined by
+ Redfish API specification (DSP0266).
+
+ Callers are responsible for freeing the returned string storage pointed by UserId
+ and Password.
+
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_INVALID_PARAMETER AuthMethod or UserId or Password is NULL.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+**/
+EFI_STATUS
+RedfishGetAuthInfo (
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h
new file mode 100644
index 00000000000..5804379b1e7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h
@@ -0,0 +1,24 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef LIBREDFISH_REDFISH_H_
+#define LIBREDFISH_REDFISH_H_
+
+#include <redfishService.h>
+#include <redfishPayload.h>
+#include <redpath.h>
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h
new file mode 100644
index 00000000000..778aff55224
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h
@@ -0,0 +1,39 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef LIBREDFISH_REDFISH_PAYLOAD_H_
+#define LIBREDFISH_REDFISH_PAYLOAD_H_
+
+#include <PrivateInclude/Library/RedfishCrtLib.h>
+
+#include <jansson.h>
+#include <redfishService.h>
+#include <redpath.h>
+
+redfishPayload* createRedfishPayload(json_t* value, redfishService* service);
+redfishPayload* getPayloadByNodeName(redfishPayload* payload, const char* nodeName, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* getPayloadByIndex(redfishPayload* payload, size_t index, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* getPayloadForPath(redfishPayload* payload, redPathNode* redpath, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* getPayloadForPathString(redfishPayload* payload, const char* string, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* patchPayload(redfishPayload* target, redfishPayload* payload, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* postContentToPayload(redfishPayload* target, const char* data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* postPayload(redfishPayload* target, redfishPayload* payload, EFI_HTTP_STATUS_CODE** StatusCode);
+void cleanupPayload(redfishPayload* payload);
+bool isPayloadCollection (redfishPayload *Payload);
+size_t getCollectionSize(redfishPayload* payload);
+redfishPayload* getPayloadByIndex (redfishPayload* payload, size_t index, EFI_HTTP_STATUS_CODE** StatusCode);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h
new file mode 100644
index 00000000000..13a6db5b11a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h
@@ -0,0 +1,101 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef LIBREDFISH_REDFISH_SERVICE_H_
+#define LIBREDFISH_REDFISH_SERVICE_H_
+
+#include <IndustryStandard/Http11.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HttpLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/RedfishContentCodingLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <PrivateInclude/Library/RedfishCrtLib.h>
+
+#include <Protocol/EdkIIRedfishConfigHandler.h>
+#include <Protocol/RestEx.h>
+
+#include <jansson.h>
+
+typedef struct {
+ char* host;
+ json_t* versions;
+ unsigned int flags;
+ char* sessionToken;
+ char* basicAuthStr;
+ //
+ // point to the <HOST> part in above "host" field, which will be put into
+ // the "Host" header of HTTP request message.
+ //
+ char* HostHeaderValue;
+ EFI_REST_EX_PROTOCOL *RestEx;
+} redfishService;
+
+typedef struct {
+ json_t* json;
+ redfishService* service;
+} redfishPayload;
+
+#define REDFISH_AUTH_BASIC 0
+#define REDFISH_AUTH_BEARER_TOKEN 1
+#define REDFISH_AUTH_SESSION 2
+
+#define REDFISH_HTTP_RESPONSE_TIMEOUT 5000 /// 5 seconds in uints of millisecond.
+
+///
+/// Library class public defines
+///
+#define HTTP_FLAG L"http://"
+#define HTTPS_FLAG L"https://"
+
+///
+/// The redfish first URL should be "/redfish/v1/", while we use "/redfish/v1" here without "/"
+/// in the end is to avoid the 301 Perment redirect response from Redfish profile simulator.
+///
+#define REDFISH_FIRST_URL L"/redfish/v1"
+
+typedef struct {
+ unsigned int authType;
+ union {
+ struct {
+ char* username;
+ char* password;
+ } userPass;
+ struct {
+ char* token;
+ } authToken;
+ } authCodes;
+} enumeratorAuthentication;
+
+//Values for flags
+#define REDFISH_FLAG_SERVICE_NO_VERSION_DOC 0x00000001 //The Redfish Service lacks the version document (in violation of the Redfish spec)
+redfishService* createServiceEnumerator(REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo, const char* rootUri, enumeratorAuthentication* auth, unsigned int flags);
+json_t* getUriFromService(redfishService* service, const char* uri, EFI_HTTP_STATUS_CODE** StatusCode);
+json_t* patchUriFromService(redfishService* service, const char* uri, const char* content, EFI_HTTP_STATUS_CODE** StatusCode);
+json_t* postUriFromService(redfishService* service, const char* uri, const char* content, size_t contentLength, const char* contentType, EFI_HTTP_STATUS_CODE** StatusCode);
+json_t* deleteUriFromService(redfishService* service, const char* uri, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* getRedfishServiceRoot(redfishService* service, const char* version, EFI_HTTP_STATUS_CODE** StatusCode);
+redfishPayload* getPayloadByPath(redfishService* service, const char* path, EFI_HTTP_STATUS_CODE** StatusCode);
+void cleanupServiceEnumerator(redfishService* service);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h
new file mode 100644
index 00000000000..f9e9c182713
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h
@@ -0,0 +1,42 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef LIBREDFISH_REDPATH_H_
+#define LIBREDFISH_REDPATH_H_
+
+#include <PrivateInclude/Library/RedfishCrtLib.h>
+
+#include <jansson.h>
+
+typedef struct _redPathNode
+{
+ bool isRoot;
+ bool isIndex;
+
+ char* version;
+ char* nodeName;
+ size_t index;
+ char* op;
+ char* propName;
+ char* value;
+
+ struct _redPathNode* next;
+} redPathNode;
+
+redPathNode* parseRedPath(const char* path);
+void cleanupRedPath(redPathNode* node);
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
new file mode 100644
index 00000000000..f9f2294eff6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c
@@ -0,0 +1,732 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <redfishPayload.h>
+
+static redfishPayload* getOpResult(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode);
+static redfishPayload* collectionEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode);
+static redfishPayload* arrayEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode);
+static redfishPayload* createCollection(redfishService* service, size_t count, redfishPayload** payloads);
+static json_t* json_object_get_by_index(json_t* json, size_t index);
+
+bool isPayloadCollection(redfishPayload* payload)
+{
+ json_t* members;
+ json_t* count;
+
+ if(!payload || !json_is_object(payload->json))
+ {
+ return false;
+ }
+ members = json_object_get(payload->json, "Members");
+ count = json_object_get(payload->json, "Members@odata.count");
+ return ((members != NULL) && (count != NULL));
+}
+
+size_t getCollectionSize(redfishPayload* payload)
+{
+ json_t* members;
+ json_t* count;
+
+ if(!payload || !json_is_object(payload->json))
+ {
+ return 0;
+ }
+ members = json_object_get(payload->json, "Members");
+ count = json_object_get(payload->json, "Members@odata.count");
+ if(!members || !count)
+ {
+ return 0;
+ }
+ return (size_t)json_integer_value(count);
+}
+
+bool isPayloadArray(redfishPayload* payload)
+{
+ if(!payload || !json_is_array(payload->json))
+ {
+ return false;
+ }
+ return true;
+}
+
+char* payloadToString(redfishPayload* payload, bool prettyPrint)
+{
+ size_t flags = 0;
+ if(!payload)
+ {
+ return NULL;
+ }
+ if(prettyPrint)
+ {
+ flags = JSON_INDENT(2);
+ }
+ return json_dumps(payload->json, flags);
+}
+
+redfishPayload* createRedfishPayload(json_t* value, redfishService* service)
+{
+ redfishPayload* payload;
+ payload = (redfishPayload*)malloc(sizeof(redfishPayload));
+ if(payload != NULL)
+ {
+ payload->json = value;
+ payload->service = service;
+ }
+ return payload;
+}
+
+redfishPayload* getPayloadByNodeName(redfishPayload* payload, const char* nodeName, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* value;
+ json_t* odataId;
+ const char* uri;
+
+ if(!payload || !nodeName || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ value = json_object_get(payload->json, nodeName);
+ if(value == NULL)
+ {
+ return NULL;
+ }
+ json_incref(value);
+ if(json_object_size(value) == 1)
+ {
+ odataId = json_object_get(value, "@odata.id");
+ if(odataId != NULL)
+ {
+ json_incref(odataId);
+ uri = json_string_value(odataId);
+ json_decref(value);
+ value = getUriFromService(payload->service, uri, StatusCode);
+ json_decref(odataId);
+ if(value == NULL || *StatusCode == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+ if (*StatusCode == NULL || (**StatusCode >= HTTP_STATUS_200_OK && **StatusCode <= HTTP_STATUS_206_PARTIAL_CONTENT)) {
+ if(json_is_string(value))
+ {
+ odataId = json_object();
+ json_object_set(odataId, nodeName, value);
+ json_decref(value);
+ value = odataId;
+ }
+ }
+
+ return createRedfishPayload(value, payload->service);
+}
+
+redfishPayload* getPayloadByIndex(redfishPayload* payload, size_t index, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* value = NULL;
+ json_t* odataId;
+ const char* uri;
+ BOOLEAN FromServerFlag = FALSE;
+
+ if(!payload || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ if(isPayloadCollection(payload))
+ {
+ redfishPayload* members = getPayloadByNodeName(payload, "Members", StatusCode);
+ if ((*StatusCode == NULL && members == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return members;
+ }
+
+ if (*StatusCode != NULL) {
+ //
+ // The Payload (members) are retrived from server.
+ //
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ FromServerFlag = TRUE;
+ }
+
+ redfishPayload* ret = getPayloadByIndex(members, index, StatusCode);
+ if (*StatusCode == NULL && ret != NULL && FromServerFlag) {
+ //
+ // In such a case, the Redfish resource is parsed from the input payload (members) directly.
+ // Since the members are retrived from server, we still return HTTP_STATUS_200_OK.
+ //
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ } else {
+ **StatusCode = HTTP_STATUS_200_OK;
+ }
+ }
+
+ cleanupPayload(members);
+ return ret;
+ }
+
+ if(json_is_array(payload->json))
+ {
+ //
+ // The valid range for index is from 0 to the return value of json_array_size() minus 1
+ //
+ value = json_array_get(payload->json, index);
+ }
+ else if(json_is_object(payload->json))
+ {
+ value = json_object_get_by_index(payload->json, index);
+ }
+
+ if(value == NULL)
+ {
+ return NULL;
+ }
+
+ json_incref(value);
+ if(json_object_size(value) == 1)
+ {
+ odataId = json_object_get(value, "@odata.id");
+ if(odataId != NULL)
+ {
+ uri = json_string_value(odataId);
+ json_decref(value);
+ value = getUriFromService(payload->service, uri, StatusCode);
+ if(value == NULL)
+ {
+ return NULL;
+ }
+ }
+ }
+ return createRedfishPayload(value, payload->service);
+}
+
+redfishPayload* getPayloadForPath(redfishPayload* payload, redPathNode* redpath, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redfishPayload* ret = NULL;
+ redfishPayload* tmp;
+
+ if(!payload || !redpath || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+ BOOLEAN FromServerFlag = FALSE;
+
+ if(redpath->nodeName)
+ {
+ ret = getPayloadByNodeName(payload, redpath->nodeName, StatusCode);
+ if ((*StatusCode == NULL && ret == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ //
+ // Any error happen, return directly.
+ //
+ return ret;
+ }
+ }
+ else if(redpath->isIndex)
+ {
+ ASSERT (redpath->index >= 1);
+ ret = getPayloadByIndex(payload, redpath->index - 1, StatusCode);
+ if ((*StatusCode == NULL && ret == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ //
+ // Any error happen, return directly.
+ //
+ return ret;
+ }
+ }
+ else if(redpath->op)
+ {
+ ret = getOpResult(payload, redpath->propName, redpath->op, redpath->value, StatusCode);
+ if ((*StatusCode == NULL && ret == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ //
+ // Any error happen, return directly.
+ //
+ return ret;
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ if(redpath->next == NULL || ret == NULL)
+ {
+ return ret;
+ }
+ else
+ {
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ FromServerFlag = TRUE;
+ }
+
+ tmp = getPayloadForPath(ret, redpath->next, StatusCode);
+ if (*StatusCode == NULL && tmp != NULL && FromServerFlag) {
+ //
+ // In such a case, the Redfish resource is parsed from the input payload (ret) directly.
+ // Since the ret are retrived from server, we still return HTTP_STATUS_200_OK.
+ //
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ tmp = NULL;
+ } else {
+ **StatusCode = HTTP_STATUS_200_OK;
+ }
+ }
+
+ cleanupPayload(ret);
+ return tmp;
+ }
+}
+
+redfishPayload* getPayloadForPathString(redfishPayload* payload, const char* string, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redPathNode* redpath;
+ redfishPayload* ret;
+
+ if(!string || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ redpath = parseRedPath(string);
+ if(redpath == NULL)
+ {
+ return NULL;
+ }
+ ret = getPayloadForPath(payload, redpath, StatusCode);
+ cleanupRedPath(redpath);
+ return ret;
+}
+
+redfishPayload* patchPayload(redfishPayload* target, redfishPayload* payload, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* json;
+ char* content;
+ char* uri;
+
+ if(!target || !payload || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ json = json_object_get(target->json, "@odata.id");
+ if(json == NULL)
+ {
+ return NULL;
+ }
+ uri = strdup(json_string_value(json));
+
+ content = json_dumps(payload->json, 0);
+ json_decref(json);
+
+ json = patchUriFromService(target->service, uri, content, StatusCode);
+ free(uri);
+ free(content);
+ if(json == NULL)
+ {
+ return NULL;
+ }
+
+ return createRedfishPayload(json, target->service);
+}
+
+redfishPayload* postContentToPayload(redfishPayload* target, const char* data, size_t dataSize, const char* contentType, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* json;
+ char* uri;
+
+ if(!target || !data || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ json = json_object_get(target->json, "@odata.id");
+ if(json == NULL)
+ {
+ json = json_object_get(target->json, "target");
+ if(json == NULL)
+ {
+ return NULL;
+ }
+ }
+ uri = strdup(json_string_value(json));
+ json = postUriFromService(target->service, uri, data, dataSize, contentType, StatusCode);
+ free(uri);
+ if(json == NULL)
+ {
+ return NULL;
+ }
+
+ return createRedfishPayload(json, target->service);
+}
+
+redfishPayload* postPayload(redfishPayload* target, redfishPayload* payload, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ char* content;
+ redfishPayload* ret;
+
+ if(!target || !payload || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ if(!json_is_object(payload->json))
+ {
+ return NULL;
+ }
+ content = payloadToString(payload, false);
+ ret = postContentToPayload(target, content, strlen(content), NULL, StatusCode);
+ free(content);
+ return ret;
+}
+
+void cleanupPayload(redfishPayload* payload)
+{
+ if(!payload)
+ {
+ return;
+ }
+ json_decref(payload->json);
+ //Don't free payload->service, let the caller handle cleaning up the service
+ free(payload);
+}
+
+static redfishPayload* getOpResult(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ const char* propStr;
+ json_t* stringProp;
+ bool ret = false;
+ redfishPayload* prop;
+ long long intVal, intPropVal;
+ json_type jsonType;
+
+ if(isPayloadCollection(payload))
+ {
+ return collectionEvalOp(payload, propName, op, value, StatusCode);
+ }
+ if(isPayloadArray(payload))
+ {
+ return arrayEvalOp(payload, propName, op, value, StatusCode);
+ }
+
+ prop = getPayloadByNodeName(payload, propName, StatusCode);
+ if ((*StatusCode == NULL && prop == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return prop;
+ }
+ stringProp = prop->json;
+ jsonType = prop->json->type;
+ switch(jsonType)
+ {
+ case JSON_OBJECT:
+ stringProp = json_object_get(prop->json, propName);
+ case JSON_STRING:
+ if(strcmp(op, "=") == 0)
+ {
+ propStr = json_string_value(stringProp);
+ if(propStr == NULL)
+ {
+ cleanupPayload(prop);
+ return NULL;
+ }
+ ret = (strcmp(propStr, value) == 0);
+ } else if(strcmp(op, "~") == 0)
+ {
+ propStr = json_string_value(stringProp);
+ if(propStr == NULL)
+ {
+ cleanupPayload(prop);
+ return NULL;
+ }
+ ret = (strcasecmp(propStr, value) == 0);
+ }
+ break;
+ case JSON_TRUE:
+ if(strcmp(op, "=") == 0)
+ {
+ ret = (strcmp(value, "true") == 0);
+ }
+ break;
+ case JSON_FALSE:
+ if(strcmp(op, "=") == 0)
+ {
+ ret = (strcmp(value, "false") == 0);
+ }
+ break;
+ case JSON_INTEGER:
+ intPropVal = json_integer_value(prop->json);
+ intVal = strtoll(value, NULL, 0);
+ if(strcmp(op, "=") == 0)
+ {
+ ret = (intPropVal == intVal);
+ }
+ else if(strcmp(op, "<") == 0)
+ {
+ ret = (intPropVal < intVal);
+ }
+ else if(strcmp(op, ">") == 0)
+ {
+ ret = (intPropVal > intVal);
+ }
+ else if(strcmp(op, "<=") == 0)
+ {
+ ret = (intPropVal <= intVal);
+ }
+ else if(strcmp(op, ">=") == 0)
+ {
+ ret = (intPropVal >= intVal);
+ }
+ break;
+ default:
+ break;
+ }
+ cleanupPayload(prop);
+ if(ret)
+ {
+ return payload;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+static redfishPayload* collectionEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redfishPayload* ret;
+ redfishPayload* tmp;
+ redfishPayload* members;
+ redfishPayload** valid;
+ size_t validMax;
+ size_t validCount = 0;
+ size_t i;
+
+ validMax = getCollectionSize(payload);
+ if(validMax == 0)
+ {
+ return NULL;
+ }
+
+ valid = (redfishPayload**)calloc(validMax, sizeof(redfishPayload*));
+ if(valid == NULL)
+ {
+ return NULL;
+ }
+ /*Technically getPayloadByIndex would do this, but this optimizes things*/
+ members = getPayloadByNodeName(payload, "Members", StatusCode);
+ if ((*StatusCode == NULL && members == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return members;
+ }
+
+ for(i = 0; i < validMax; i++)
+ {
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ tmp = getPayloadByIndex(members, i, StatusCode);
+ if ((*StatusCode == NULL && tmp == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return tmp;
+ }
+
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ valid[validCount] = getOpResult(tmp, propName, op, value, StatusCode);
+ /*
+ if ((*StatusCode == NULL && valid[validCount] == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return valid[validCount];
+ }
+ */
+ if(valid[validCount] != NULL)
+ {
+ validCount++;
+ }
+ else
+ {
+ cleanupPayload(tmp);
+ }
+ }
+ cleanupPayload(members);
+ if(validCount == 0)
+ {
+ free(valid);
+ return NULL;
+ }
+ if(validCount == 1)
+ {
+ ret = valid[0];
+ free(valid);
+ return ret;
+ }
+ else
+ {
+ ret = createCollection(payload->service, validCount, valid);
+ free(valid);
+ return ret;
+ }
+}
+
+static redfishPayload* arrayEvalOp(redfishPayload* payload, const char* propName, const char* op, const char* value, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redfishPayload* ret;
+ redfishPayload* tmp;
+ redfishPayload** valid;
+ size_t validMax;
+ size_t validCount = 0;
+ size_t i;
+
+ validMax = json_array_size(payload->json);
+ if(validMax == 0)
+ {
+ return NULL;
+ }
+
+ valid = (redfishPayload**)calloc(validMax, sizeof(redfishPayload*));
+ if(valid == NULL)
+ {
+ return NULL;
+ }
+ for(i = 0; i < validMax; i++)
+ {
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ tmp = getPayloadByIndex(payload, i, StatusCode);
+ if ((*StatusCode == NULL && tmp == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return tmp;
+ }
+
+ if (*StatusCode != NULL) {
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+ }
+
+ valid[validCount] = getOpResult(tmp, propName, op, value, StatusCode);
+ /*
+ if ((*StatusCode == NULL && valid[validCount] == NULL) ||
+ (*StatusCode != NULL && (**StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT))) {
+ return valid[validCount];
+ }
+ */
+
+ if(valid[validCount] != NULL)
+ {
+ validCount++;
+ }
+ else
+ {
+ cleanupPayload(tmp);
+ }
+ }
+ if(validCount == 0)
+ {
+ free(valid);
+ return NULL;
+ }
+ if(validCount == 1)
+ {
+ ret = valid[0];
+ free(valid);
+ return ret;
+ }
+ else
+ {
+ ret = createCollection(payload->service, validCount, valid);
+ free(valid);
+ return ret;
+ }
+}
+
+static redfishPayload* createCollection(redfishService* service, size_t count, redfishPayload** payloads)
+{
+ redfishPayload* ret;
+ json_t* collectionJson = json_object();
+ json_t* jcount = json_integer((json_int_t)count);
+ json_t* members = json_array();
+ size_t i;
+
+ if(!collectionJson)
+ {
+ return NULL;
+ }
+ if(!members)
+ {
+ json_decref(collectionJson);
+ return NULL;
+ }
+ json_object_set(collectionJson, "Members@odata.count", jcount);
+ json_decref(jcount);
+ for(i = 0; i < count; i++)
+ {
+ json_array_append(members, payloads[i]->json);
+ cleanupPayload(payloads[i]);
+ }
+ json_object_set(collectionJson, "Members", members);
+ json_decref(members);
+
+ ret = createRedfishPayload(collectionJson, service);
+ return ret;
+}
+
+static json_t* json_object_get_by_index(json_t* json, size_t index)
+{
+ void* iter;
+ size_t i;
+
+ iter = json_object_iter(json);
+ for(i = 0; i < index; i++)
+ {
+ iter = json_object_iter_next(json, iter);
+ if(iter == NULL) break;
+ }
+ if(iter == NULL)
+ {
+ return NULL;
+ }
+ return json_object_iter_value(iter);
+}
+/* vim: set tabstop=4 shiftwidth=4 expandtab: */
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c
new file mode 100644
index 00000000000..28291426153
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c
@@ -0,0 +1,192 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <redpath.h>
+
+static char* getVersion(const char* path, char** end);
+static void parseNode(const char* path, redPathNode* node, redPathNode** end);
+
+static char* getStringTill(const char* string, const char* terminator, char** retEnd);
+
+redPathNode* parseRedPath(const char* path)
+{
+ redPathNode* node;
+ redPathNode* endNode;
+ char* curPath;
+ char* end;
+
+ if(!path || strlen(path) == 0)
+ {
+ return NULL;
+ }
+
+ node = (redPathNode*)calloc(1, sizeof(redPathNode));
+ if(!node)
+ {
+ return NULL;
+ }
+ if(path[0] == '/')
+ {
+ node->isRoot = true;
+ if(path[1] == 'v')
+ {
+ node->version = getVersion(path+1, &curPath);
+ if(curPath == NULL)
+ {
+ return node;
+ }
+ if(curPath[0] == '/')
+ {
+ curPath++;
+ }
+ node->next = parseRedPath(curPath);
+ }
+ else
+ {
+ node->next = parseRedPath(path+1);
+ }
+ return node;
+ }
+ node->isRoot = false;
+ curPath = getStringTill(path, "/", &end);
+ endNode = node;
+ parseNode(curPath, node, &endNode);
+ free(curPath);
+ if(end != NULL)
+ {
+ endNode->next = parseRedPath(end+1);
+ }
+ return node;
+}
+
+void cleanupRedPath(redPathNode* node)
+{
+ if(!node)
+ {
+ return;
+ }
+ cleanupRedPath(node->next);
+ node->next = NULL;
+ if(node->version)
+ {
+ free(node->version);
+ }
+ if(node->nodeName)
+ {
+ free(node->nodeName);
+ }
+ if(node->op)
+ {
+ free(node->op);
+ }
+ if(node->propName)
+ {
+ free(node->propName);
+ }
+ if(node->value)
+ {
+ free(node->value);
+ }
+ free(node);
+}
+
+static char* getVersion(const char* path, char** end)
+{
+ return getStringTill(path, "/", end);
+}
+
+static void parseNode(const char* path, redPathNode* node, redPathNode** end)
+{
+ char* indexStart;
+ char* index;
+ char* indexEnd;
+ char* nodeName = getStringTill(path, "[", &indexStart);
+ size_t tmpIndex;
+ char* opChars;
+
+ node->nodeName = nodeName;
+ if(indexStart == NULL)
+ {
+ *end = node;
+ return;
+ }
+ node->next = (redPathNode*)calloc(1, sizeof(redPathNode));
+ if(!node->next)
+ {
+ return;
+ }
+ //Skip past [
+ indexStart++;
+ *end = node->next;
+ index = getStringTill(indexStart, "]", NULL);
+ tmpIndex = (size_t)strtoull(index, &indexEnd, 0);
+ if(indexEnd != index)
+ {
+ free(index);
+ node->next->index = tmpIndex;
+ node->next->isIndex = true;
+ return;
+ }
+ opChars = strpbrk(index, "<>=~");
+ if(opChars == NULL)
+ {
+ //TODO handle last() and position()
+ node->next->op = strdup("exists");
+ node->next->propName = index;
+ return;
+ }
+ node->next->propName = (char*)malloc((opChars - index)+1);
+ memcpy(node->next->propName, index, (opChars - index));
+ node->next->propName[(opChars - index)] = 0;
+
+ tmpIndex = 1;
+ while(1)
+ {
+ if(opChars[tmpIndex] == '=' || opChars[tmpIndex] == '<' || opChars[tmpIndex] == '>' || opChars[tmpIndex] == '~')
+ {
+ tmpIndex++;
+ continue;
+ }
+ break;
+ }
+
+ node->next->op = (char*)malloc(tmpIndex+1);
+ memcpy(node->next->op, opChars, tmpIndex);
+ node->next->op[tmpIndex] = 0;
+
+ node->next->value = strdup(opChars+tmpIndex);
+ free(index);
+}
+
+static char* getStringTill(const char* string, const char* terminator, char** retEnd)
+{
+ char* ret;
+ char* end;
+ end = strstr((char*)string, terminator);
+ if(retEnd)
+ {
+ *retEnd = end;
+ }
+ if(end == NULL)
+ {
+ //No terminator
+ return strdup(string);
+ }
+ ret = (char*)malloc((end-string)+1);
+ memcpy(ret, string, (end-string));
+ ret[(end-string)] = 0;
+ return ret;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
new file mode 100644
index 00000000000..7139a2e2e9c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/PrivateLibrary/RedfishLib/edk2libredfish/src/service.c
@@ -0,0 +1,1396 @@
+/** @file
+ This file is cloned from DMTF libredfish library tag v1.0.0 and maintained
+ by EDKII.
+
+//----------------------------------------------------------------------------
+// Copyright Notice:
+// Copyright 2017 Distributed Management Task Force, Inc. All rights reserved.
+// License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libredfish/LICENSE.md
+//----------------------------------------------------------------------------
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <redfishService.h>
+#include <redfishPayload.h>
+#include <redpath.h>
+
+static int initRest(redfishService* service, void * restProtocol);
+static redfishService* createServiceEnumeratorNoAuth(const char* host, const char* rootUri, bool enumerate, unsigned int flags, void * restProtocol);
+static redfishService* createServiceEnumeratorBasicAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol);
+static redfishService* createServiceEnumeratorSessionAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol);
+static char* makeUrlForService(redfishService* service, const char* uri);
+static json_t* getVersions(redfishService* service, const char* rootUri);
+static void addStringToJsonObject(json_t* object, const char* key, const char* value);
+
+CHAR16*
+C8ToC16 (CHAR8 *AsciiStr)
+{
+ CHAR16 *Str;
+ UINTN BufLen;
+
+ BufLen = (AsciiStrLen (AsciiStr) + 1) * 2;
+ Str = AllocatePool (BufLen);
+ ASSERT (Str != NULL);
+
+ AsciiStrToUnicodeStrS (AsciiStr, Str, AsciiStrLen (AsciiStr) + 1);
+
+ return Str;
+}
+
+VOID
+RestConfigFreeHttpRequestData (
+ IN EFI_HTTP_REQUEST_DATA *RequestData
+ )
+{
+ if (RequestData == NULL) {
+ return ;
+ }
+
+ if (RequestData->Url != NULL) {
+ FreePool (RequestData->Url);
+ }
+
+ FreePool (RequestData);
+}
+
+VOID
+RestConfigFreeHttpMessage (
+ IN EFI_HTTP_MESSAGE *Message,
+ IN BOOLEAN IsRequest
+ )
+{
+ if (Message == NULL) {
+ return ;
+ }
+
+ if (IsRequest) {
+ RestConfigFreeHttpRequestData (Message->Data.Request);
+ Message->Data.Request = NULL;
+ } else {
+ if (Message->Data.Response != NULL) {
+ FreePool (Message->Data.Response);
+ Message->Data.Response = NULL;
+ }
+ }
+
+ if (Message->Headers != NULL) {
+ FreePool (Message->Headers);
+ Message->Headers = NULL;
+ }
+ if (Message->Body != NULL) {
+ FreePool (Message->Body);
+ Message->Body = NULL;
+ }
+}
+
+/**
+ Converts the Unicode string to ASCII string to a new allocated buffer.
+
+ @param[in] String Unicode string to be converted.
+
+ @return Buffer points to ASCII string, or NULL if error happens.
+
+**/
+
+CHAR8 *
+UnicodeStrDupToAsciiStr (
+ CONST CHAR16 *String
+ )
+{
+ CHAR8 *AsciiStr;
+ UINTN BufLen;
+ EFI_STATUS Status;
+
+ BufLen = StrLen (String) + 1;
+ AsciiStr = AllocatePool (BufLen);
+ if (AsciiStr == NULL) {
+ return NULL;
+ }
+
+ Status = UnicodeStrToAsciiStrS (String, AsciiStr, BufLen);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return AsciiStr;
+}
+/**
+ This function encodes the content.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ @param[in] OriginalContent Original content.
+ @param[out] EncodedContent Pointer to receive encoded content.
+ @param[out] EncodedContentLength Length of encoded content.
+
+ @retval EFI_SUCCESS Content encoded successfully.
+ @retval EFI_UNSUPPORTED No source encoding funciton,
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+EncodeRequestContent (
+ IN CHAR8 *ContentEncodedValue,
+ IN CHAR8 *OriginalContent,
+ OUT VOID **EncodedContent,
+ OUT UINTN *EncodedContentLength
+)
+{
+ EFI_STATUS Status;
+ VOID *EncodedPointer;
+ UINTN EncodedLength;
+
+ if (OriginalContent == NULL || EncodedContent == NULL || EncodedContentLength == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = RedfishContentEncode (
+ ContentEncodedValue,
+ OriginalContent,
+ AsciiStrLen (OriginalContent),
+ &EncodedPointer,
+ &EncodedLength
+ );
+ if (Status == EFI_SUCCESS) {
+ *EncodedContent = EncodedPointer;
+ *EncodedContentLength = EncodedLength;
+ return EFI_SUCCESS;
+ }
+ return Status;
+}
+
+/**
+ This function decodes the content. The Memory block pointed by
+ ContentPointer would be freed and replaced with the cooked Redfish
+ payload.
+
+ @param[in] ContentEncodedValue HTTP conent encoded value.
+ @param[in, out] ContentPointer Pointer to encoded content.
+ Pointer of decoded content when out.
+ @param[in, out] ContentLength Pointer to the length of encoded content.
+ Length of decoded content when out.
+
+ @retval EFI_SUCCESS Functinos found.
+ @retval EFI_UNSUPPORTED No functions found.
+ @retval EFI_INVALID_PARAMETER One of the given parameter is invalid.
+
+**/
+EFI_STATUS
+DecodeResponseContent (
+ IN CHAR8 *ContentEncodedValue,
+ IN OUT VOID **ContentPointer,
+ IN OUT UINTN *ContentLength
+)
+{
+ EFI_STATUS Status;
+ VOID *DecodedPointer;
+ UINTN DecodedLength;
+
+ if (ContentEncodedValue == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = RedfishContentDecode (
+ ContentEncodedValue,
+ *ContentPointer,
+ *ContentLength,
+ &DecodedPointer,
+ &DecodedLength
+ );
+ if (Status == EFI_SUCCESS) {
+ FreePool (*ContentPointer);
+ *ContentPointer = DecodedPointer;
+ *ContentLength = DecodedLength;
+ }
+ return Status;
+}
+
+/**
+ Create a HTTP URL string for specific Redfish resource.
+
+ This function build a URL string from the Redfish Host interface record and caller specified
+ relative path of the resource.
+
+ Callers are responsible for freeing the returned string storage pointed by HttpUrl.
+
+ @param[in] RedfishData Redfish network host interface record.
+ @param[in] RelativePath Relative path of a resource.
+ @param[out] HttpUrl The pointer to store the returned URL string.
+
+ @retval EFI_SUCCESS Build the URL string successfully.
+ @retval EFI_INVALID_PARAMETER RedfishData or HttpUrl is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+
+**/
+EFI_STATUS
+RedfishBuildUrl (
+ IN REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo,
+ IN CHAR16 *RelativePath, OPTIONAL
+ OUT CHAR16 **HttpUrl
+ )
+{
+ CHAR16 *Url;
+ CHAR16 *UrlHead;
+ UINTN UrlLength;
+ UINTN PathLen;
+
+ if ((RedfishConfigServiceInfo == NULL) || (HttpUrl == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // RFC2616: http_URL = "http(s):" "//" host [ ":" port ] [ abs_path [ "?" query ]]
+ //
+ if (RelativePath == NULL) {
+ PathLen = 0;
+ } else {
+ PathLen = StrLen (RelativePath);
+ }
+ UrlLength = StrLen (HTTPS_FLAG) + StrLen (REDFISH_FIRST_URL) + 1 + StrLen(RedfishConfigServiceInfo->RedfishServiceLocation) + PathLen;
+ Url = AllocateZeroPool (UrlLength * sizeof (CHAR16));
+ if (Url == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UrlHead = Url;
+ //
+ // Copy "http://" or "https://" according RedfishServiceIpPort.
+ //
+ if (!RedfishConfigServiceInfo->RedfishServiceUseHttps) {
+ StrCpyS (Url, StrLen (HTTPS_FLAG) + 1, HTTP_FLAG);
+ Url = Url + StrLen (HTTP_FLAG);
+ } else {
+ StrCpyS (Url, StrLen (HTTPS_FLAG) + 1, HTTPS_FLAG);
+ Url = Url + StrLen (HTTPS_FLAG);
+ }
+
+ StrCpyS (Url, StrLen (RedfishConfigServiceInfo->RedfishServiceLocation) + 1, RedfishConfigServiceInfo->RedfishServiceLocation);
+ Url = Url + StrLen (RedfishConfigServiceInfo->RedfishServiceLocation);
+
+ //
+ // Copy abs_path
+ //
+ if (RelativePath != NULL && PathLen != 0 ) {
+ StrnCpyS (Url, UrlLength, RelativePath, PathLen);
+ }
+ *HttpUrl = UrlHead;
+ return EFI_SUCCESS;
+}
+
+redfishService* createServiceEnumerator(REDFISH_CONFIG_SERVICE_INFORMATION *RedfishConfigServiceInfo, const char* rootUri, enumeratorAuthentication* auth, unsigned int flags)
+{
+ EFI_STATUS Status;
+ CHAR16 *HttpUrl;
+ CHAR8 *AsciiHost;
+ EFI_REST_EX_PROTOCOL *RestEx;
+ redfishService *ret;
+
+ HttpUrl = NULL;
+ AsciiHost = NULL;
+ RestEx = NULL;
+ ret = NULL;
+
+ if (RedfishConfigServiceInfo->RedfishServiceRestExHandle == NULL) {
+ goto ON_EXIT;
+ }
+ Status = RedfishBuildUrl(RedfishConfigServiceInfo, NULL, &HttpUrl);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ ASSERT (HttpUrl != NULL);
+
+ AsciiHost = UnicodeStrDupToAsciiStr (HttpUrl);
+ if (AsciiHost == NULL) {
+ goto ON_EXIT;
+ }
+
+ Status = gBS->HandleProtocol (
+ RedfishConfigServiceInfo->RedfishServiceRestExHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **)&RestEx
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ if(auth == NULL) {
+ ret = createServiceEnumeratorNoAuth(AsciiHost, rootUri, true, flags, RestEx);
+ } else if(auth->authType == REDFISH_AUTH_BASIC) {
+ ret = createServiceEnumeratorBasicAuth(AsciiHost, rootUri, auth->authCodes.userPass.username, auth->authCodes.userPass.password, flags, RestEx);
+ } else if(auth->authType == REDFISH_AUTH_SESSION) {
+ ret = createServiceEnumeratorSessionAuth(AsciiHost, rootUri, auth->authCodes.userPass.username, auth->authCodes.userPass.password, flags, RestEx);
+ } else {
+ goto ON_EXIT;
+ }
+
+ ret->RestEx = RestEx;
+ON_EXIT:
+ if (HttpUrl != NULL) {
+ FreePool (HttpUrl);
+ }
+
+ if (AsciiHost != NULL) {
+ FreePool (AsciiHost);
+ }
+
+ return ret;
+}
+
+json_t* getUriFromService(redfishService* service, const char* uri, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ char* url;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+ EFI_HTTP_HEADER *ContentEncodedHeader;
+
+ if(service == NULL || uri == NULL || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: getUriFromService(): %a\n", url));
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 6 : 5);
+ if (HttpIoHeader == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
+ if (RequestData == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodGet;
+ RequestData->Url = C8ToC16 (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
+ if (RequestMsg == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestMsg->Data.Request = RequestData;
+ RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);
+ if (EFI_ERROR (Status)) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ //
+ // Check if data is encoded.
+ //
+ ContentEncodedHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, HTTP_HEADER_CONTENT_ENCODING);
+ if (ContentEncodedHeader != NULL) {
+ //
+ // The content is encoded.
+ //
+ Status = DecodeResponseContent (ContentEncodedHeader->FieldValue, &ResponseMsg.Body, &ResponseMsg.BodyLength);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to decompress the response content %r\n.", __FUNCTION__, Status));
+ ret = NULL;
+ goto ON_EXIT;
+ }
+ }
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);
+ } else {
+ //
+ // There is no message body returned from server.
+ //
+ ret = NULL;
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData);
+ }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
+json_t* patchUriFromService(redfishService* service, const char* uri, const char* content, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ char* url;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+ CHAR8 ContentLengthStr[80];
+ CHAR8 *EncodedContent;
+ UINTN EncodedContentLen;
+
+ if(service == NULL || uri == NULL || content == NULL || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: patchUriFromService(): %a\n", url));
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 9 : 8);
+ if (HttpIoHeader == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
+ ASSERT_EFI_ERROR (Status);
+
+ AsciiSPrint(
+ ContentLengthStr,
+ sizeof (ContentLengthStr),
+ "%lu",
+ (UINT64) strlen(content)
+ );
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengthStr);
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
+ if (RequestData == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodPatch;
+ RequestData->Url = C8ToC16 (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
+ if (RequestMsg == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ EncodedContent = (CHAR8 *)content;
+ EncodedContentLen = strlen(content);
+ //
+ // We currently only support gzip Content-Encoding.
+ //
+ Status = EncodeRequestContent ((CHAR8 *)HTTP_CONTENT_ENCODING_GZIP, (CHAR8 *)content, (VOID **)&EncodedContent, &EncodedContentLen);
+ if (Status == EFI_INVALID_PARAMETER) {
+ DEBUG((DEBUG_ERROR, "%a: Error to encode content.\n", __FUNCTION__));
+ ret = NULL;
+ goto ON_EXIT;
+ } else if (Status == EFI_UNSUPPORTED) {
+ DEBUG((DEBUG_INFO, "No content coding for %a! Use raw data instead.\n", HTTP_CONTENT_ENCODING_GZIP));
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding", HTTP_CONTENT_ENCODING_IDENTITY);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Encoding", HTTP_CONTENT_ENCODING_GZIP);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ RequestMsg->Data.Request = RequestData;
+ RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+ RequestMsg->BodyLength = EncodedContentLen;
+ RequestMsg->Body = (VOID*) EncodedContent;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);
+ if (EFI_ERROR (Status)) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (EncodedContent != content) {
+ FreePool (EncodedContent);
+ }
+
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);
+ } else {
+ //
+ // There is no message body returned from server.
+ //
+ ret = NULL;
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData);
+ }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
+json_t* postUriFromService(redfishService* service, const char* uri, const char* content, size_t contentLength, const char* contentType, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ char* url = NULL;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+ CHAR8 ContentLengthStr[80];
+ EFI_HTTP_HEADER *HttpHeader = NULL;
+
+ ret = NULL;
+
+ if(service == NULL || uri == NULL || content == NULL || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: postUriFromService(): %a\n", url));
+
+ if(contentLength == 0)
+ {
+ contentLength = strlen(content);
+ }
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 8 : 7);
+ if (HttpIoHeader == NULL) {
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ if(contentType == NULL) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", "application/json");
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Type", (CHAR8 *) contentType);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Accept", "application/json");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
+ ASSERT_EFI_ERROR (Status);
+ AsciiSPrint(
+ ContentLengthStr,
+ sizeof (ContentLengthStr),
+ "%lu",
+ (UINT64) contentLength
+ );
+ Status = HttpIoSetHeader (HttpIoHeader, "Content-Length", ContentLengthStr);
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
+ if (RequestData == NULL) {
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodPost;
+ RequestData->Url = C8ToC16 (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
+ if (RequestMsg == NULL) {
+ goto ON_EXIT;
+ }
+
+ RequestMsg->Data.Request = RequestData;
+ RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+ RequestMsg->BodyLength = contentLength;
+ RequestMsg->Body = (VOID*) content;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);
+ }
+
+ //
+ // Step 6: Parsing the HttpHeader to retrive the X-Auth-Token if the HTTP StatusCode is correct.
+ //
+ if (ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_200_OK ||
+ ResponseMsg.Data.Response->StatusCode == HTTP_STATUS_204_NO_CONTENT) {
+ HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, "X-Auth-Token");
+ if (HttpHeader != NULL) {
+ if(service->sessionToken)
+ {
+ free(service->sessionToken);
+ }
+ service->sessionToken = AllocateCopyPool (AsciiStrSize (HttpHeader->FieldValue), HttpHeader->FieldValue);
+ }
+
+ /*
+ //
+ // Below opeation seems to be unnecessary.
+ // Besides, the FieldValue for the Location is the full HTTP URI (Http://0.0.0.0:5000/XXX), so we can't use it as the
+ // parameter of getUriFromService () directly.
+ //
+ HttpHeader = HttpFindHeader (ResponseMsg.HeaderCount, ResponseMsg.Headers, "Location");
+ if (HttpHeader != NULL) {
+ ret = getUriFromService(service, HttpHeader->FieldValue);
+ goto ON_EXIT;
+ }
+ */
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData);
+ }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
+json_t* deleteUriFromService(redfishService* service, const char* uri, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ char* url;
+ json_t* ret;
+ HTTP_IO_HEADER *HttpIoHeader = NULL;
+ EFI_STATUS Status;
+ EFI_HTTP_REQUEST_DATA *RequestData = NULL;
+ EFI_HTTP_MESSAGE *RequestMsg = NULL;
+ EFI_HTTP_MESSAGE ResponseMsg;
+
+ ret = NULL;
+
+ if(service == NULL || uri == NULL || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ url = makeUrlForService(service, uri);
+ if(!url)
+ {
+ return NULL;
+ }
+
+ DEBUG((DEBUG_INFO, "libredfish: deleteUriFromService(): %a\n", url));
+
+ //
+ // Step 1: Create HTTP request message with 4 headers:
+ //
+ HttpIoHeader = HttpIoCreateHeader ((service->sessionToken || service->basicAuthStr) ? 5 : 4);
+ if (HttpIoHeader == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ if(service->sessionToken)
+ {
+ Status = HttpIoSetHeader (HttpIoHeader, "X-Auth-Token", service->sessionToken);
+ ASSERT_EFI_ERROR (Status);
+ } else if (service->basicAuthStr) {
+ Status = HttpIoSetHeader (HttpIoHeader, "Authorization", service->basicAuthStr);
+ ASSERT_EFI_ERROR (Status);
+ }
+ Status = HttpIoSetHeader (HttpIoHeader, "Host", service->HostHeaderValue);
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "User-Agent", "libredfish");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "OData-Version", "4.0");
+ ASSERT_EFI_ERROR (Status);
+ Status = HttpIoSetHeader (HttpIoHeader, "Connection", "Keep-Alive");
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Step 2: build the rest of HTTP request info.
+ //
+ RequestData = AllocateZeroPool (sizeof (EFI_HTTP_REQUEST_DATA));
+ if (RequestData == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestData->Method = HttpMethodDelete;
+ RequestData->Url = C8ToC16 (url);
+
+ //
+ // Step 3: fill in EFI_HTTP_MESSAGE
+ //
+ RequestMsg = AllocateZeroPool (sizeof (EFI_HTTP_MESSAGE));
+ if (RequestMsg == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ RequestMsg->Data.Request = RequestData;
+ RequestMsg->HeaderCount = HttpIoHeader->HeaderCount;
+ RequestMsg->Headers = HttpIoHeader->Headers;
+
+ ZeroMem (&ResponseMsg, sizeof (ResponseMsg));
+
+ //
+ // Step 4: call RESTEx to get response from REST service.
+ //
+ Status = service->RestEx->SendReceive (service->RestEx, RequestMsg, &ResponseMsg);
+ if (EFI_ERROR (Status)) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // Step 5: Return the HTTP StatusCode and Body message.
+ //
+ if (ResponseMsg.Data.Response != NULL) {
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ goto ON_EXIT;
+ }
+
+ //
+ // The caller shall take the responsibility to free the buffer.
+ //
+ **StatusCode = ResponseMsg.Data.Response->StatusCode;
+ }
+
+ if (ResponseMsg.BodyLength != 0 && ResponseMsg.Body != NULL) {
+ ret = json_loadb (ResponseMsg.Body, ResponseMsg.BodyLength, 0, NULL);
+ }
+
+ON_EXIT:
+ if (url != NULL) {
+ free (url);
+ }
+
+ if (HttpIoHeader != NULL) {
+ HttpIoFreeHeader (HttpIoHeader);
+ }
+
+ if (RequestData != NULL) {
+ RestConfigFreeHttpRequestData (RequestData);
+ }
+
+ if (RequestMsg != NULL) {
+ FreePool (RequestMsg);
+ }
+
+ RestConfigFreeHttpMessage (&ResponseMsg, FALSE);
+
+ return ret;
+}
+
+redfishPayload* getRedfishServiceRoot(redfishService* service, const char* version, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ json_t* value;
+ json_t* versionNode;
+ const char* verUrl;
+
+ if(version == NULL)
+ {
+ versionNode = json_object_get(service->versions, "v1");
+ }
+ else
+ {
+ versionNode = json_object_get(service->versions, version);
+ }
+ if(versionNode == NULL)
+ {
+ return NULL;
+ }
+ verUrl = json_string_value(versionNode);
+ if(verUrl == NULL)
+ {
+ return NULL;
+ }
+ value = getUriFromService(service, verUrl, StatusCode);
+ if(value == NULL)
+ {
+ if((service->flags & REDFISH_FLAG_SERVICE_NO_VERSION_DOC) == 0)
+ {
+ json_decref(versionNode);
+ }
+ return NULL;
+ }
+ return createRedfishPayload(value, service);
+}
+
+redfishPayload* getPayloadByPath(redfishService* service, const char* path, EFI_HTTP_STATUS_CODE** StatusCode)
+{
+ redPathNode* redpath;
+ redfishPayload* root;
+ redfishPayload* ret;
+
+ if(!service || !path || StatusCode == NULL)
+ {
+ return NULL;
+ }
+
+ *StatusCode = NULL;
+
+ redpath = parseRedPath(path);
+ if(!redpath)
+ {
+ return NULL;
+ }
+ if(!redpath->isRoot)
+ {
+ cleanupRedPath(redpath);
+ return NULL;
+ }
+ root = getRedfishServiceRoot(service, redpath->version, StatusCode);
+ if (*StatusCode == NULL || **StatusCode < HTTP_STATUS_200_OK || **StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ cleanupRedPath(redpath);
+ return root;
+ }
+
+ if(redpath->next == NULL)
+ {
+ cleanupRedPath(redpath);
+ return root;
+ }
+
+ FreePool (*StatusCode);
+ *StatusCode = NULL;
+
+ ret = getPayloadForPath(root, redpath->next, StatusCode);
+ if (*StatusCode == NULL && ret != NULL) {
+ //
+ // In such a case, the Redfish resource is parsed from the input payload (root) directly.
+ // So, we still return HTTP_STATUS_200_OK.
+ //
+ *StatusCode = AllocateZeroPool (sizeof (EFI_HTTP_STATUS_CODE));
+ if (*StatusCode == NULL) {
+ ret = NULL;
+ } else {
+ **StatusCode = HTTP_STATUS_200_OK;
+ }
+ }
+ cleanupPayload(root);
+ cleanupRedPath(redpath);
+ return ret;
+}
+
+void cleanupServiceEnumerator(redfishService* service)
+{
+ if(!service)
+ {
+ return;
+ }
+ free(service->host);
+ json_decref(service->versions);
+ if(service->sessionToken != NULL)
+ {
+ ZeroMem (service->sessionToken, (UINTN)strlen(service->sessionToken));
+ FreePool(service->sessionToken);
+ }
+ if (service->basicAuthStr != NULL) {
+ ZeroMem (service->basicAuthStr, (UINTN)strlen(service->basicAuthStr));
+ FreePool (service->basicAuthStr);
+ }
+ free(service);
+}
+
+static int initRest(redfishService* service, void * restProtocol)
+{
+ service->RestEx = restProtocol;
+ return 0;
+}
+
+static redfishService* createServiceEnumeratorNoAuth(const char* host, const char* rootUri, bool enumerate, unsigned int flags, void * restProtocol)
+{
+ redfishService* ret;
+ char *HostStart;
+
+ ret = (redfishService*)calloc(1, sizeof(redfishService));
+ ZeroMem (ret, sizeof(redfishService));
+ if(initRest(ret, restProtocol) != 0)
+ {
+ free(ret);
+ return NULL;
+ }
+ ret->host = AllocateCopyPool(AsciiStrSize(host), host);
+ ret->flags = flags;
+ if(enumerate)
+ {
+ ret->versions = getVersions(ret, rootUri);
+ }
+ HostStart = strstr (ret->host, "//");
+ if (HostStart != NULL && (*(HostStart + 2) != '\0')) {
+ ret->HostHeaderValue = HostStart + 2;
+ }
+
+ return ret;
+}
+
+EFI_STATUS
+createBasicAuthStr (
+ IN redfishService* service,
+ IN CONST CHAR8 *UserId,
+ IN CONST CHAR8 *Password
+ )
+{
+ EFI_STATUS Status;
+ CHAR8 *RawAuthValue;
+ UINTN RawAuthBufSize;
+ CHAR8 *EnAuthValue;
+ UINTN EnAuthValueSize;
+ CHAR8 *BasicWithEnAuthValue;
+ UINTN BasicBufSize;
+
+ EnAuthValue = NULL;
+ EnAuthValueSize = 0;
+
+ RawAuthBufSize = AsciiStrLen (UserId) + AsciiStrLen (Password) + 2;
+ RawAuthValue = AllocatePool (RawAuthBufSize);
+ if (RawAuthValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Build raw AuthValue (UserId:Password).
+ //
+ AsciiSPrint (
+ RawAuthValue,
+ RawAuthBufSize,
+ "%a:%a",
+ UserId,
+ Password
+ );
+
+ //
+ // Encoding RawAuthValue into Base64 format.
+ //
+ Status = Base64Encode (
+ (CONST UINT8 *) RawAuthValue,
+ AsciiStrLen (RawAuthValue),
+ EnAuthValue,
+ &EnAuthValueSize
+ );
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ EnAuthValue = (CHAR8 *) AllocateZeroPool (EnAuthValueSize);
+ if (EnAuthValue == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ return Status;
+ }
+
+ Status = Base64Encode (
+ (CONST UINT8 *) RawAuthValue,
+ AsciiStrLen (RawAuthValue),
+ EnAuthValue,
+ &EnAuthValueSize
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
+
+ BasicBufSize = AsciiStrLen ("Basic ") + AsciiStrLen(EnAuthValue) + 2;
+ BasicWithEnAuthValue = AllocatePool (BasicBufSize);
+ if (BasicWithEnAuthValue == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Exit;
+ }
+
+ //
+ // Build encoded EnAuthValue with Basic (Basic EnAuthValue).
+ //
+ AsciiSPrint (
+ BasicWithEnAuthValue,
+ BasicBufSize,
+ "%a %a",
+ "Basic",
+ EnAuthValue
+ );
+
+ service->basicAuthStr = BasicWithEnAuthValue;
+
+Exit:
+ if (RawAuthValue != NULL) {
+ ZeroMem (RawAuthValue, RawAuthBufSize);
+ FreePool (RawAuthValue);
+ }
+
+ if (EnAuthValue != NULL) {
+ ZeroMem (EnAuthValue, EnAuthValueSize);
+ FreePool (EnAuthValue);
+ }
+
+ return Status;
+}
+
+static redfishService* createServiceEnumeratorBasicAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol)
+{
+ redfishService* ret;
+ EFI_STATUS Status;
+
+ ret = createServiceEnumeratorNoAuth(host, rootUri, false, flags, restProtocol);
+
+ // add basic auth str
+ Status = createBasicAuthStr (ret, username, password);
+ if (EFI_ERROR(Status)) {
+ cleanupServiceEnumerator (ret);
+ return NULL;
+ }
+
+ ret->versions = getVersions(ret, rootUri);
+ return ret;
+}
+
+static redfishService* createServiceEnumeratorSessionAuth(const char* host, const char* rootUri, const char* username, const char* password, unsigned int flags, void * restProtocol)
+{
+ redfishService* ret;
+ redfishPayload* payload;
+ redfishPayload* links;
+ json_t* sessionPayload;
+ json_t* session;
+ json_t* odataId;
+ const char* uri;
+ json_t* post;
+ char* content;
+ EFI_HTTP_STATUS_CODE *StatusCode;
+
+ content = NULL;
+ StatusCode = NULL;
+
+ ret = createServiceEnumeratorNoAuth(host, rootUri, true, flags, restProtocol);
+ if(ret == NULL)
+ {
+ return NULL;
+ }
+ payload = getRedfishServiceRoot(ret, NULL, &StatusCode);
+ if(StatusCode == NULL || *StatusCode < HTTP_STATUS_200_OK || *StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)
+ {
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ }
+
+ if (payload != NULL) {
+ cleanupPayload(payload);
+ }
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ StatusCode = NULL;
+ }
+
+ links = getPayloadByNodeName(payload, "Links", &StatusCode);
+ cleanupPayload(payload);
+ if(links == NULL)
+ {
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+ session = json_object_get(links->json, "Sessions");
+ if(session == NULL)
+ {
+ cleanupPayload(links);
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+ odataId = json_object_get(session, "@odata.id");
+ if(odataId == NULL)
+ {
+ cleanupPayload(links);
+ cleanupServiceEnumerator(ret);
+ return NULL;
+ }
+ uri = json_string_value(odataId);
+ post = json_object();
+ addStringToJsonObject(post, "UserName", username);
+ addStringToJsonObject(post, "Password", password);
+ content = json_dumps(post, 0);
+ json_decref(post);
+ sessionPayload = postUriFromService(ret, uri, content, 0, NULL, &StatusCode);
+
+ if (content != NULL) {
+ ZeroMem (content, (UINTN)strlen(content));
+ free(content);
+ }
+
+ if(sessionPayload == NULL || StatusCode == NULL || *StatusCode < HTTP_STATUS_200_OK || *StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT)
+ {
+ //Failed to create session!
+
+ cleanupPayload(links);
+ cleanupServiceEnumerator(ret);
+
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ }
+
+ if (sessionPayload != NULL) {
+ json_decref(sessionPayload);
+ }
+
+ return NULL;
+ }
+ json_decref(sessionPayload);
+ cleanupPayload(links);
+ FreePool (StatusCode);
+ return ret;
+}
+
+static char* makeUrlForService(redfishService* service, const char* uri)
+{
+ char* url;
+ if(service->host == NULL)
+ {
+ return NULL;
+ }
+ url = (char*)malloc(strlen(service->host)+strlen(uri)+1);
+ strcpy(url, service->host);
+ strcat(url, uri);
+ return url;
+}
+
+static json_t* getVersions(redfishService* service, const char* rootUri)
+{
+ json_t* ret = NULL;
+ EFI_HTTP_STATUS_CODE* StatusCode = NULL;
+
+ if(service->flags & REDFISH_FLAG_SERVICE_NO_VERSION_DOC)
+ {
+ service->versions = json_object();
+ if(service->versions == NULL)
+ {
+ return NULL;
+ }
+ addStringToJsonObject(service->versions, "v1", "/redfish/v1");
+ return service->versions;
+ }
+ if(rootUri != NULL)
+ {
+ ret = getUriFromService(service, rootUri, &StatusCode);
+ }
+ else
+ {
+ ret = getUriFromService(service, "/redfish", &StatusCode);
+ }
+
+ if (ret == NULL || StatusCode == NULL || *StatusCode < HTTP_STATUS_200_OK || *StatusCode > HTTP_STATUS_206_PARTIAL_CONTENT) {
+ if (ret != NULL) {
+ json_decref(ret);
+ }
+ ret = NULL;
+ }
+
+ if (StatusCode != NULL) {
+ FreePool (StatusCode);
+ }
+
+ return ret;
+}
+
+static void addStringToJsonObject(json_t* object, const char* key, const char* value)
+{
+ json_t* jValue = json_string(value);
+
+ json_object_set(object, key, jValue);
+
+ json_decref(jValue);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md
new file mode 100644
index 00000000000..4503ed3f167
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Readme.md
@@ -0,0 +1,117 @@
+# UEFI Redfish EDK2 Implementation
+
+## Introduction
+UEFI Redfish EDK2 solution is an efficient and secure solution for the end-users to remote configure (in Out-of-band) UEFI platform configurations by leveraging the Redfish RESTful API. It's simple for end-users to access the configurations of UEFI firmware which have the equivalent properties defined in Redfish schema.
+
+Below are the block diagrams of UEFI Redfish EDK2 Implementation. ***[EDK2 Redfish Foundation[1]](#[0])*** in the lower part of the figure refers to the EDK2 Redfish Foundation, which provides the fundamental EDK2 drivers to communicate with Redfish service ***([[19]](#[0]) in the above figure)***. The Redfish service could be implemented in BMC to manage the system, or on the network for managing multiple systems.
+
+***[EDK2 Redfish Client[2]](#[0])*** in the upper part of the figure refers to the EDK2 Redfish client, which is the EDK2 Redfish application used to configure platform configurations by consuming the Redfish properties. The EDK2 Redfish client can also provision the UEFI platform-owned Redfish properties, consume and update Redfish properties as well. The ***[EDK2 Redfish Feature DXE Drivers [17]](#[0])*** is the next project after EDK2 Redfish Foundation. Each EDK2 Redfish Feature DXE Driver is designed to communicate with the particular Redfish data model defined in the Redfish schema *(e.g. Edk2RedfishBiosDxe driver manipulates the properties defined in Redfish BIOS data model)*.
+
+## <a name="[0]">EDK2 Redfish Implementation Diagrams</a>
+![UEFI Redfish Implementation](https://github.com/tianocore/edk2/blob/master/RedfishPkg/Documents/Media/RedfishDriverStack.svg?raw=true)
+
+## EFI EDK2 Redfish Driver Stack
+Below are the EDK2 drivers implemented on EDK2,
+
+### EDK2 Redfish Host Interface DXE Driver ***[[6]](#[0])***
+
+The abstract EDK2 DXE driver to create SMBIOS type 42 record through EFI SMBIOS protocol according to the device descriptor and protocol type data (defined in SMBIOS type 42h ***[[7]](#[0])***) provided by platform level Redfish host interface library. On EDK2 open source implementation (**EmulatorPkg**), SMBIOS type 42 data is retrieved from EFI variables created by RedfishPlatformConfig.efi ***[[20]](#[0])*** under EFI shell. OEM may provide its own PlatformHostInterfaceLib ***[[11]](#[0])*** instance for the platform-specific implementation.
+
+### EDK2 Refish Credential DXE Driver ***[[5]](#[0])***
+
+The abstract DXE driver which incorporates with RedfishPlatformCredentialLib ***[[10]](#[0])*** to acquire the credential of Redfish service. On edk2 EmulatorPkg implementation, the credential is hardcoded using the fixed Account/Password in order to connect to Redfish service established by [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator). OEM may provide its own RedfishPlatformCredentialLib instance for the platform-specific implementation.
+
+### EFI REST EX UEFI Driver for Redfish service ***[[4]](#[0])***
+
+This is the network-based driver instance of EFI_REST_EX protocol [(UEFI spec 2.8, section 29.7.2)](http://uefi.org/specifications) for communicating with Redfish service using the HTTP protocol. OEM may have its own EFI REST EX UEFI Driver instance on which the underlying transport to Redfish service could be proprietary.
+
+### EFI Redfish Discover UEFI Driver ***[[3]](#[0])***
+
+EFI Redfish Discover Protocol implementation (UEFI spec 2.8, section 31.1). Only support Redfish service discovery through Redfish Host Interface. The Redfish service discovery using SSDP over UDP ***[[18]](#[0])*** is not implemented at the moment.
+
+### EFI REST JSON Structure DXE Driver ***[[9]](#[0])***
+
+EFI REST JSON Structure DXE implementation (UEFI spec 2.8, section 29.7.3). This could be used by EDK2 Redfish Feature DXE Drivers ***[[17]](#[0])***. The EDK2 Redfish feature drivers manipulate platform-owned Redfish properties in C structure format and convert them into the payload in JSON format through this protocol. This driver leverages the effort of [Redfish Schema to C Generator](https://github.com/DMTF/Redfish-Schema-C-Struct-Generator) to have the "C Structure" <-> "JSON" conversion.
+
+### EDK2 Redfish Config Handler UEFI Driver ***[[15]](#[0])***
+
+This is the centralized manager of EDK2 Redfish feature drivers, it initiates EDK2 Redfish feature drivers by invoking init() function of EDK2 Redfish Config Handler Protocol ***[[16]](#[0])*** installed by each EDK2 Redfish feature driver. EDK2 Redfish Config Handler driver is an UEFI driver which has the dependency with EFI REST EX protocol and utilizes EFI Redfish Discover protocol to discover Redfish service that manages this system.
+
+### EDK2 Content Coding Library ***[[12]](#[0])***
+The library is incorporated with RedfishLib ***[[13]](#[0])*** to encode and decode Redfish JSON payload. This is the platform library to support HTTP Content-Encoding/Accept-Encoding headers. EumlatorPkg use the NULL instance of this library because [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator) supports neither HTTP Content-Encoding header on the payload returned to Redfish client nor HTTP Accept-Encoding header.
+
+## Other Open Source Projects
+ The following libraries are the wrappers of other open source projects used in RedfishPkg
+
+ * **RedfishPkg\PrivateLibrary\RedfishLib** ***[[13]](#[0])***
+ This is the wrapper of open source project ***[libredfish](https://github.com/DMTF/libredfish)***,
+ which is the library to initialize the connection to Redfish service with the proper credential and execute Create/Read/Update/Delete (CRUD) HTTP methods on Redfish properties.
+
+ * **RedfishPkg\Library\JsonLib** ***[[14]](#[0])***
+ This is the wrapper of open source project ***[Jansson](https://digip.org/jansson)***, which is the library that provides APIs to manipulate JSON payload.
+
+## Platform Components for EDK2 EmulatorPkg:
+ * **RedfishPlatformCredentialLib**
+ the EDK2 Emulator platform implementation of acquiring credential to build up the communication between UEFI firmware and Redfish service. ***[[10]](#[0])***
+
+ * **RedfishPlatformHostInterfaceLib**
+ EDK2 Emulator platform implementation which provides the information of building up SMBIOS type 42h record. ***[[11]](#[0])***
+
+## Miscellaneous:
+
+ * **EFI Shell Application**
+ RedfishPlatformConfig.exe is an EFI Shell application used to set up the Redfish service information for the EDK2 Emulator platform. The information such as IP address, subnet, and port.
+ ```C
+ For example, run shell command "RedfishPlatformConfig.efi -s 192.168.10.101 255.255.255.0 192.168.10.123 255.255.255.0", which means
+ the source IP address is 192.168.10.101, and the Redfish Server IP address is 192.168.10.123.
+ ```
+
+ * **Redfish Profile Simulator**
+ Refer to [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator) to set up the Redfish service.
+ We are also in the progress to contribute bug fixes and enhancements to the mainstream Redfish Profile Simulator in order to incorporate with EDK2 Redfish solution.
+
+## Connect to Redfish Service on EDK2 Emulator Platform
+ 1. Install the WinpCap and copy [SnpNt32Io.dll](https://github.com/tianocore/edk2-NetNt32Io) to the building directory of the Emulator platform. This is the emulated network interface for EDK2 Emulator Platform.
+ ```C
+ e.g. %WORKSPACE%/Build/EmulatorX64/DEBUG_VS2015x86/X64
+ ```
+
+ 2. Enable below macros in EmulatorPkg.dsc
+ ```C
+ NETWORK_HTTP_ENABLE = TRUE
+ SECURE_BOOT_ENABLE = TRUE
+ REDFISH_ENABLE = TRUE
+ ```
+
+ 3. Allow HTTP connection
+ Enable below macro to allow HTTP connection on EDK2 network stack for connecting to [Redfish Profile Simulator](https://github.com/DMTF/Redfish-Profile-Simulator) becasue Redfish Profile Simulator doesn't support HTTPS.
+ ```C
+ NETWORK_ALLOW_HTTP_CONNECTIONS = TRUE
+ ```
+
+ 4. Assign the correct MAC Address
+ Assign the correct MAC address of the network interface card emulated by WinpCap.
+ - Rebuild EmulatorPkg and boot to EFI shell once SnpNt32Io.dll is copied to the building directory and the macros mentioned in #2 are all set to TURE.
+ - Execute the EFI shell command "ifconfig -l" under EFI shell and look for MAC address information, then assign the MAC address to below PCD.
+ ```c
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath.DevicePath|{DEVICE_PATH("MAC(000000000000,0x1)")}
+ ```
+
+ 5. Configure the Redfish service on the EDK2 Emulator platform
+
+ Execute RedfishPlatformConfig.efi under EFI shell to configure the Redfish service information. The EFI variables are created for storing Redfish service information and is consumed by RedfishPlatformHostInterfaceLib under EmulatorPkg.
+
+## Related Materials
+1. [DSP0270](https://www.dmtf.org/sites/default/files/standards/documents/DSP0270_1.3.0.pdf) - Redfish Host Interface Specification, 1.3.0
+2. [DSP0266](https://www.dmtf.org/sites/default/files/standards/documents/DSP0266_1.12.0.pdf) - Redfish Specification, 1.12.0
+3. Redfish Schemas - https://redfish.dmtf.org/schemas/v1/
+4. UEFI Specification - http://uefi.org/specifications
+
+## The Contributors
+Thanks to the below predecessors who contributed to the UEFI EDK2 Redfish Prove of Concept code.\
+Fu, Siyuan <siyuan.fu@intel.com>\
+Ye, Ting <ting.ye@intel.com>\
+Wang, Fan <fan.wang@intel.com>\
+Wu, Jiaxin <jiaxin.wu@intel.com>\
+Yao, Jiewen <jiewen.yao@intel.com>\
+Shia, Cinnamon <cinnamon.shia@hpe.com>
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc
new file mode 100644
index 00000000000..da8a4a9b277
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.dsc.inc
@@ -0,0 +1,21 @@
+## @file
+# Redfish DSC include file for Platform DSC
+#
+# This file includes all required information to enable Redfish features.
+# It can be included to a platform DSC file by using "!include RedfishPkg/Redfish.dsc.inc".
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ !include RedfishPkg/RedfishDefines.dsc.inc
+
+[LibraryClasses]
+ !include RedfishPkg/RedfishLibs.dsc.inc
+
+[Components]
+ !include RedfishPkg/RedfishComponents.dsc.inc
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc
new file mode 100644
index 00000000000..21754f008c6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/Redfish.fdf.inc
@@ -0,0 +1,20 @@
+## @file
+# Redfish FDF include file for [FV*] section of all Architectures.
+#
+# This file can be included to the [FV*] section(s) of a platform FDF file
+# by using "!include RedfishPkg/RedfisLibs.fdf.inc" to specify the module instances
+# to be built in the firmware volume.
+#
+# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+!if $(REDFISH_ENABLE) == TRUE
+ INF RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
+ INF RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
+ INF RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
+ INF RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
+ INF RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
+ INF RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc
new file mode 100644
index 00000000000..81b5e6b8f58
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishComponents.dsc.inc
@@ -0,0 +1,22 @@
+## @file
+# Redfish DSC include file for [Components*] section of all Architectures.
+#
+# This file can be included to the [Components*] section(s) of a platform DSC file
+# by using "!include RedfishPkg/RedfishComponents.dsc.inc" to specify the INF files
+# of EDKII Redfish drivers according to the value of flags described in
+# "RedfishDefines.dsc.inc".
+#
+# (C) Copyright 2020-2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!if $(REDFISH_ENABLE) == TRUE
+ RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
+ RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
+ RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
+ RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
+ RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
+ RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
+!endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c
new file mode 100644
index 00000000000..ca10a84daea
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.c
@@ -0,0 +1,265 @@
+/** @file
+ The common code of EDKII Redfish Configuration Handler driver.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishConfigHandlerCommon.h"
+
+REDFISH_CONFIG_DRIVER_DATA gRedfishConfigData; // Only one Redfish service supproted
+ // on platform for the BIOS
+ // Redfish configuration.
+EFI_EVENT gEndOfDxeEvent = NULL;
+EFI_EVENT gExitBootServiceEvent = NULL;
+EDKII_REDFISH_CREDENTIAL_PROTOCOL *gCredential = NULL;
+
+/**
+ Callback function executed when the EndOfDxe event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer.
+
+**/
+VOID
+EFIAPI
+RedfishConfigOnEndOfDxe (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gCredential->StopService (gCredential, ServiceStopTypeSecureBootDisabled);
+ if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "Redfish credential protocol faied to stop service on EndOfDxe: %r", Status));
+ }
+
+ //
+ // Close event, so it will not be invoked again.
+ //
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+}
+
+/**
+ Callback function executed when the ExitBootService event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer
+
+**/
+VOID
+EFIAPI
+RedfishConfigOnExitBootService (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gCredential->StopService (gCredential, ServiceStopTypeExitBootService);
+ if (EFI_ERROR(Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "Redfish credential protocol faied to stop service on ExitBootService: %r", Status));
+ }
+}
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+RedfishConfigDriverCommonUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ if (gEndOfDxeEvent != NULL) {
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+ }
+
+ if (gExitBootServiceEvent != NULL) {
+ gBS->CloseEvent (gExitBootServiceEvent);
+ gExitBootServiceEvent = NULL;
+ }
+
+ if (gRedfishConfigData.Event != NULL) {
+ gBS->CloseEvent (gRedfishConfigData.Event);
+ gRedfishConfigData.Event = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the common code for Redfish configuration UEFI and DXE driver
+ initialization.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ //
+ // Locate Redfish Credential Protocol to get credential for
+ // accessing to Redfish service.
+ //
+ Status = gBS->LocateProtocol (&gEdkIIRedfishCredentialProtocolGuid, NULL, (VOID **) &gCredential);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "%a: No Redfish Credential Protocol is installed on system.", __FUNCTION__));
+ return Status;
+ }
+ //
+ // Create EndOfDxe Event.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishConfigOnEndOfDxe,
+ NULL,
+ &gEfiEndOfDxeEventGroupGuid,
+ &gEndOfDxeEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to register End Of DXE event.", __FUNCTION__));
+ return Status;
+ }
+ //
+ // Create Exit Boot Service event.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishConfigOnExitBootService,
+ NULL,
+ &gEfiEventExitBootServicesGuid,
+ &gExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to register Exit Boot Service event.", __FUNCTION__));
+ return Status;
+ }
+ return EFI_SUCCESS;
+}
+/**
+ This is the common code to stop EDK2 Redfish feature driver.
+
+ @retval EFI_SUCCESS All EDK2 Redfish feature drivers are
+ stopped.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonStop (
+ VOID
+)
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ UINTN Index;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ return Status;
+ }
+
+ Status = EFI_SUCCESS;
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID**) &ConfigHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = ConfigHandler->Stop (ConfigHandler);
+ if (EFI_ERROR (Status) && Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Failed to stop Redfish config handler %p.\n", ConfigHandler));
+ break;
+ }
+ }
+ return Status;
+}
+/**
+ Callback function executed when a Redfish Config Handler Protocol is installed
+ by EDK2 Redfish Feature Drivers.
+
+**/
+VOID
+RedfishConfigHandlerInitialization (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN NumberOfHandles;
+ EDKII_REDFISH_CONFIG_HANDLER_PROTOCOL *ConfigHandler;
+ UINTN Index;
+ UINT32 Id;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ NULL,
+ &NumberOfHandles,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+
+ for (Index = 0; Index < NumberOfHandles; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer [Index],
+ &gEfiCallerIdGuid,
+ (VOID **) &Id
+ );
+ if (!EFI_ERROR (Status)) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer [Index],
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ (VOID**) &ConfigHandler
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = ConfigHandler->Init (ConfigHandler, &gRedfishConfigData.RedfishServiceInfo);
+ if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Failed to init Redfish config handler %p.\n", ConfigHandler));
+ }
+ //
+ // Install caller ID to indicate Redfish Configure Handler is initialized.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &HandleBuffer [Index],
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&gRedfishConfigData.CallerId
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h
new file mode 100644
index 00000000000..32a3cace4bd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerCommon.h
@@ -0,0 +1,101 @@
+/** @file
+ Common Header file for Redfish Configuration Handler UEFI driver
+ and DXE driver.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_CONFIG_HANDLER_COMMON_H_
+#define EFI_REDFISH_CONFIG_HANDLER_COMMON_H_
+
+#include <Uefi.h>
+
+//
+// Libraries
+//
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiLib.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/EdkIIRedfishCredential.h>
+#include <Protocol/EdkIIRedfishConfigHandler.h>
+
+//
+// Driver Version
+//
+#define REDFISH_CONFIG_VERSION 0x00000001
+
+///
+/// Internal structure used by Redfish Config DXE driver.
+///
+typedef struct {
+ UINT32 CallerId; ///< Caller ID used to indicate Redfish Config Handler
+ ///< has been initiated
+ EFI_HANDLE Image; ///< Image handle of Redfish Config Driver
+ EFI_EVENT Event; ///< Event for the notification of EFI_REDFISH_CONFIG_HANDLER_PROTOCOL
+ REDFISH_CONFIG_SERVICE_INFORMATION RedfishServiceInfo; /// Redfish Service information discovered
+} REDFISH_CONFIG_DRIVER_DATA;
+
+/**
+ Common code of unloading image for both UEFI/DXE Redfish Configuration drivers.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+RedfishConfigDriverCommonUnload (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ This is the common code for Redfish configuration UEFI and DXE driver
+ initialization.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonInit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This is the common code to stop EDK2 Redfish feature driver.
+
+ @retval EFI_SUCCESS All EDK2 Redfish feature drivers are
+ stopped.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+RedfishConfigCommonStop (
+ VOID
+);
+
+/**
+ Callback function executed when a Redfish Config Handler Protocol is installed
+ by EDK2 Redfish Feature Drivers.
+
+**/
+VOID
+RedfishConfigHandlerInitialization (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c
new file mode 100644
index 00000000000..c988140a0e6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.c
@@ -0,0 +1,587 @@
+/** @file
+ The UEFI driver model driver which is responsible for locating the
+ Redfish service through Redfish host interface and executing EDKII
+ Redfish feature drivers.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishConfigHandlerDriver.h"
+
+EFI_EVENT gEfiRedfishDiscoverProtocolEvent = NULL;
+
+//
+// Variables for using RFI Redfish Discover Protocol
+//
+VOID *gEfiRedfishDiscoverRegistration;
+EFI_HANDLE gEfiRedfishDiscoverControllerHandle = NULL;
+EFI_REDFISH_DISCOVER_PROTOCOL *gEfiRedfishDiscoverProtocol = NULL;
+BOOLEAN gRedfishDiscoverActivated = FALSE;
+BOOLEAN gRedfishServiceDiscovered = FALSE;
+//
+// Network interfaces discovered by EFI Redfish Discover Protocol.
+//
+UINTN gNumberOfNetworkInterfaces;
+EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *gNetworkInterfaceInstances = NULL;
+EFI_REDFISH_DISCOVERED_TOKEN *gRedfishDiscoveredToken = NULL;
+
+///
+/// Driver Binding Protocol instance
+///
+EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding = {
+ RedfishConfigDriverBindingSupported,
+ RedfishConfigDriverBindingStart,
+ RedfishConfigDriverBindingStop,
+ REDFISH_CONFIG_VERSION,
+ NULL,
+ NULL
+};
+
+/**
+ Stop acquiring Redfish service.
+
+**/
+VOID
+RedfishConfigStopRedfishDiscovery (
+ VOID
+)
+{
+ if (gRedfishDiscoverActivated) {
+ //
+ // No more EFI Discover Protocol.
+ //
+ if (gEfiRedfishDiscoverProtocolEvent != NULL) {
+ gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
+ }
+ //
+ // Stop Redfish service discovery.
+ //
+ gEfiRedfishDiscoverProtocol->AbortAcquireRedfishService (
+ gEfiRedfishDiscoverProtocol,
+ gNetworkInterfaceInstances
+ );
+ gEfiRedfishDiscoverControllerHandle = NULL;
+ gEfiRedfishDiscoverProtocol = NULL;
+ gRedfishDiscoverActivated = FALSE;
+ gRedfishServiceDiscovered = FALSE;
+ }
+}
+
+/**
+ Callback function executed when a Redfish Config Handler Protocol is installed.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[in] Context Pointer to the REDFISH_CONFIG_DRIVER_DATA buffer.
+
+**/
+VOID
+EFIAPI
+RedfishConfigHandlerInstalledCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ if (!gRedfishDiscoverActivated) {
+ //
+ // No Redfish service is discovered yet.
+ //
+ return;
+ }
+
+ RedfishConfigHandlerInitialization ();
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_STATUS Status;
+ EFI_HANDLE ChildHandle;
+
+ ChildHandle = NULL;
+
+ //
+ // Check if REST EX is ready. This just makes sure
+ // the network stack is brought up.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &ChildHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Test if REST EX protocol is ready.
+ //
+ Status = gBS->OpenProtocol(
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID**) &RestEx,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Status = EFI_UNSUPPORTED;
+ }
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ChildHandle
+ );
+ return Status;
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The driver is started.
+ @retval EFI_ALREADY_STARTED The driver was already started.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ VOID *ConfigHandlerRegistration;
+
+ if (gRedfishConfigData.Event != NULL) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ gRedfishConfigData.Event = EfiCreateProtocolNotifyEvent (
+ &gEdkIIRedfishConfigHandlerProtocolGuid,
+ TPL_CALLBACK,
+ RedfishConfigHandlerInstalledCallback,
+ (VOID *)&gRedfishConfigData,
+ &ConfigHandlerRegistration
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if (ControllerHandle == gEfiRedfishDiscoverControllerHandle) {
+ RedfishConfigStopRedfishDiscovery ();
+ }
+ gBS->CloseProtocol (
+ ControllerHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ gRedfishConfigData.Image,
+ gRedfishConfigData.Image
+ );
+
+ Status = RedfishConfigCommonStop ();
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if (gRedfishConfigData.Event != NULL) {
+ gBS->CloseEvent (gRedfishConfigData.Event);
+ gRedfishConfigData.Event = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Callback function when Redfish service is discovered.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer
+
+**/
+VOID
+EFIAPI
+RedfishServiceDiscoveredCallback (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_REDFISH_DISCOVERED_TOKEN *RedfishDiscoveredToken;
+ EFI_REDFISH_DISCOVERED_INSTANCE *RedfishInstance;
+
+ if (gRedfishServiceDiscovered) {
+ //
+ // Only support one Redfish service on platform.
+ //
+ return;
+ }
+
+ RedfishDiscoveredToken = (EFI_REDFISH_DISCOVERED_TOKEN *)Context;
+ RedfishInstance = RedfishDiscoveredToken->DiscoverList.RedfishInstances;
+ //
+ // Only pick up the first found Redfish service.
+ //
+ if (RedfishInstance->Status == EFI_SUCCESS) {
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceRestExHandle = RedfishInstance->Information.RedfishRestExHandle;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceVersion = RedfishInstance->Information.RedfishVersion;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceLocation = RedfishInstance->Information.Location;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceUuid = RedfishInstance->Information.Uuid;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceOs = RedfishInstance->Information.Os;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceOsVersion = RedfishInstance->Information.OsVersion;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceProduct = RedfishInstance->Information.Product;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceProductVer = RedfishInstance->Information.ProductVer;
+ gRedfishConfigData.RedfishServiceInfo.RedfishServiceUseHttps = RedfishInstance->Information.UseHttps;
+ gRedfishServiceDiscovered = TRUE;
+ }
+
+ //
+ // Invoke RedfishConfigHandlerInstalledCallback to execute
+ // the initialization of Redfish Configure Handler instance.
+ //
+ RedfishConfigHandlerInstalledCallback (gRedfishConfigData.Event, &gRedfishConfigData);
+}
+
+/**
+ Callback function executed when the EFI_REDFISH_DISCOVER_PROTOCOL
+ protocol interface is installed.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the Context buffer
+
+**/
+VOID
+EFIAPI
+RedfishDiscoverProtocolInstalled (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HANDLE HandleBuffer;
+ UINTN NetworkInterfaceIndex;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
+ EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken;
+
+ DEBUG((DEBUG_INFO, "%a: New network interface is installed on system by EFI Redfish discover driver.\n", __FUNCTION__));
+
+ BufferSize = sizeof (EFI_HANDLE);
+ Status = gBS->LocateHandle (
+ ByRegisterNotify,
+ NULL,
+ gEfiRedfishDiscoverRegistration,
+ &BufferSize,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Can't locate handle with EFI_REDFISH_DISCOVER_PROTOCOL installed.\n", __FUNCTION__));
+ }
+ gRedfishDiscoverActivated = TRUE;
+ if (gEfiRedfishDiscoverProtocol == NULL) {
+ gEfiRedfishDiscoverControllerHandle = HandleBuffer;
+ //
+ // First time to open EFI_REDFISH_DISCOVER_PROTOCOL.
+ //
+ Status = gBS->OpenProtocol(
+ gEfiRedfishDiscoverControllerHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID **)&gEfiRedfishDiscoverProtocol,
+ gRedfishConfigData.Image,
+ gRedfishConfigData.Image,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ gEfiRedfishDiscoverProtocol = NULL;
+ gRedfishDiscoverActivated = FALSE;
+ DEBUG((DEBUG_ERROR, "%a: Can't locate EFI_REDFISH_DISCOVER_PROTOCOL.\n", __FUNCTION__));
+ return;
+ }
+ }
+ //
+ // Check the new found network interface.
+ //
+ if (gNetworkInterfaceInstances != NULL) {
+ FreePool (gNetworkInterfaceInstances);
+ }
+ Status = gEfiRedfishDiscoverProtocol->GetNetworkInterfaceList(
+ gEfiRedfishDiscoverProtocol,
+ gRedfishConfigData.Image,
+ &gNumberOfNetworkInterfaces,
+ &gNetworkInterfaceInstances
+ );
+ if (EFI_ERROR (Status) || gNumberOfNetworkInterfaces == 0) {
+ DEBUG((DEBUG_ERROR, "%a: No network interfaces found on the handle.\n", __FUNCTION__));
+ return;
+ }
+
+ gRedfishDiscoveredToken = AllocateZeroPool (gNumberOfNetworkInterfaces * sizeof (EFI_REDFISH_DISCOVERED_TOKEN));
+ if (gRedfishDiscoveredToken == NULL) {
+ DEBUG((DEBUG_ERROR, "%a: Not enough memory for EFI_REDFISH_DISCOVERED_TOKEN.\n", __FUNCTION__));
+ return;
+ }
+
+ ThisNetworkInterface = gNetworkInterfaceInstances;
+ ThisRedfishDiscoveredToken = gRedfishDiscoveredToken;
+ //
+ // Loop to discover Redfish service on each network interface.
+ //
+ for (NetworkInterfaceIndex = 0; NetworkInterfaceIndex < gNumberOfNetworkInterfaces; NetworkInterfaceIndex ++) {
+ //
+ // Initial this Redfish Discovered Token
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishServiceDiscoveredCallback,
+ (VOID *)ThisRedfishDiscoveredToken,
+ &ThisRedfishDiscoveredToken->Event
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Failed to create event for Redfish discovered token.\n", __FUNCTION__));
+ goto ErrorReturn;
+ }
+ ThisRedfishDiscoveredToken->Signature = REDFISH_DISCOVER_TOKEN_SIGNATURE;
+ ThisRedfishDiscoveredToken->DiscoverList.NumberOfServiceFound = 0;
+ ThisRedfishDiscoveredToken->DiscoverList.RedfishInstances = NULL;
+ //
+ // Acquire for Redfish service which is reported by
+ // Redfish Host Interface.
+ //
+ Status = gEfiRedfishDiscoverProtocol->AcquireRedfishService(
+ gEfiRedfishDiscoverProtocol,
+ gRedfishConfigData.Image,
+ ThisNetworkInterface,
+ EFI_REDFISH_DISCOVER_HOST_INTERFACE,
+ ThisRedfishDiscoveredToken
+ );
+ ThisNetworkInterface ++;
+ ThisRedfishDiscoveredToken ++;
+ }
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Acquire Redfish service fail.\n", __FUNCTION__));
+ goto ErrorReturn;
+ }
+ return;
+
+ErrorReturn:
+ if (gRedfishDiscoveredToken != NULL) {
+ FreePool(gRedfishDiscoveredToken);
+ }
+}
+
+/**
+ Unloads an image.
+
+ @param[in] ImageHandle Handle that identifies the image to be unloaded.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigHandlerDriverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_REDFISH_DISCOVERED_TOKEN *ThisRedfishDiscoveredToken;
+ UINTN NumberOfNetworkInterfacesIndex;
+
+ RedfishConfigDriverCommonUnload (ImageHandle);
+
+ RedfishConfigStopRedfishDiscovery ();
+ if (gRedfishDiscoveredToken != NULL) {
+ ThisRedfishDiscoveredToken = gRedfishDiscoveredToken;
+ for (NumberOfNetworkInterfacesIndex = 0; NumberOfNetworkInterfacesIndex < gNumberOfNetworkInterfaces; NumberOfNetworkInterfacesIndex ++) {
+ if (ThisRedfishDiscoveredToken->Event != NULL) {
+ gBS->CloseEvent (ThisRedfishDiscoveredToken->Event);
+ }
+ FreePool (ThisRedfishDiscoveredToken);
+ ThisRedfishDiscoveredToken ++;
+ }
+ gRedfishDiscoveredToken = NULL;
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigHandlerDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem ((VOID *)&gRedfishConfigData, sizeof (REDFISH_CONFIG_DRIVER_DATA));
+ gRedfishConfigData.Image = ImageHandle;
+ //
+ // Register event for EFI_REDFISH_DISCOVER_PROTOCOL protocol install
+ // notification.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishDiscoverProtocolInstalled,
+ NULL,
+ &gEfiRedfishDiscoverProtocolGuid,
+ &gEfiRedfishDiscoverProtocolEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to create event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __FUNCTION__));
+ return Status;
+ }
+ Status = gBS->RegisterProtocolNotify (
+ &gEfiRedfishDiscoverProtocolGuid,
+ gEfiRedfishDiscoverProtocolEvent,
+ &gEfiRedfishDiscoverRegistration
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to register event for the installation of EFI_REDFISH_DISCOVER_PROTOCOL.", __FUNCTION__));
+ return Status;
+ }
+
+ Status = RedfishConfigCommonInit (ImageHandle, SystemTable);
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
+ gEfiRedfishDiscoverProtocolEvent = NULL;
+ return Status;
+ }
+
+ //
+ // Install UEFI Driver Model protocol(s).
+ //
+ Status = EfiLibInstallDriverBinding (
+ ImageHandle,
+ SystemTable,
+ &gRedfishConfigDriverBinding,
+ ImageHandle
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (gEndOfDxeEvent);
+ gEndOfDxeEvent = NULL;
+ gBS->CloseEvent (gExitBootServiceEvent);
+ gExitBootServiceEvent = NULL;
+ gBS->CloseEvent (gEfiRedfishDiscoverProtocolEvent);
+ gEfiRedfishDiscoverProtocolEvent = NULL;
+ DEBUG ((DEBUG_ERROR, "%a: Fail to install EFI Binding Protocol of EFI Redfish Config driver.", __FUNCTION__));
+ return Status;
+ }
+ return Status;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h
new file mode 100644
index 00000000000..d0ee0adecfd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.h
@@ -0,0 +1,159 @@
+/** @file
+ Header file of Redfish Configuration Handler UEFI driver.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_CONFIG_HANDLER_DRIVER_H_
+#define EFI_REDFISH_CONFIG_HANDLER_DRIVER_H_
+
+#include "RedfishConfigHandlerCommon.h"
+
+//
+// UEFI Driver Model Protocols
+//
+
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RedfishDiscover.h>
+#include <Protocol/RestEx.h>
+
+//
+// Protocol instances
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gRedfishConfigDriverBinding;
+
+extern REDFISH_CONFIG_DRIVER_DATA gRedfishConfigData;
+extern EDKII_REDFISH_CREDENTIAL_PROTOCOL *gCredential;
+extern EFI_EVENT gEndOfDxeEvent;
+extern EFI_EVENT gExitBootServiceEvent;
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The driver is started.
+ @retval EFI_ALREADY_STARTED The driver was already started.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishConfigDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
new file mode 100644
index 00000000000..782e8e62489
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishConfigHandler/RedfishConfigHandlerDriver.inf
@@ -0,0 +1,60 @@
+## @file
+# INF file for the UEFI driver model Redfish Configuration Handler
+# Driver.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishConfigHandlerDriver
+ FILE_GUID = 6e881000-5749-11e8-9bf0-8cdcd426c973
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishConfigHandlerDriverEntryPoint
+ UNLOAD_IMAGE = RedfishConfigHandlerDriverUnload
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ RedfishConfigHandlerDriver.h
+ RedfishConfigHandlerDriver.c
+ RedfishConfigHandlerCommon.h
+ RedfishConfigHandlerCommon.c
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ UefiLib
+ MemoryAllocationLib
+ NetLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiRedfishDiscoverProtocolGuid ## CONSUMES
+ gEfiRestExServiceBindingProtocolGuid
+ gEfiRestExProtocolGuid ## CONSUMES
+ gEdkIIRedfishCredentialProtocolGuid ## CONSUMES
+ gEdkIIRedfishConfigHandlerProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+
+[Depex]
+ TRUE
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c
new file mode 100644
index 00000000000..5039522f3ec
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.c
@@ -0,0 +1,209 @@
+/** @file
+ RedfishCrentialDxe produces the EdkIIRedfishCredentialProtocol for the consumer
+ to get the Redfish credential Info and to restrict Redfish access from UEFI side.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <RedfishCredentialDxe.h>
+
+EDKII_REDFISH_CREDENTIAL_PROTOCOL mRedfishCredentialProtocol = {
+ RedfishCredentialGetAuthInfo,
+ RedfishCredentialStopService
+};
+
+/**
+ Callback function executed when the ExitBootServices event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the buffer pass in.
+**/
+VOID
+EFIAPI
+RedfishCredentialExitBootServicesEventNotify (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ LibCredentialExitBootServicesNotify ((EDKII_REDFISH_CREDENTIAL_PROTOCOL *)Context);
+}
+
+/**
+ Callback function executed when the EndOfDxe event group is signaled.
+
+ @param[in] Event Event whose notification function is being invoked.
+ @param[out] Context Pointer to the buffer pass in.
+**/
+VOID
+EFIAPI
+RedfishCredentialEndOfDxeEventNotify (
+ IN EFI_EVENT Event,
+ OUT VOID *Context
+ )
+{
+ LibCredentialEndOfDxeNotify ((EDKII_REDFISH_CREDENTIAL_PROTOCOL *)Context);
+
+ //
+ // Close event, so it will not be invoked again.
+ //
+ gBS->CloseEvent (Event);
+}
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ )
+{
+ if (This == NULL || AuthMethod == NULL || UserId == NULL || Password == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return LibCredentialGetAuthInfo (This, AuthMethod, UserId,Password);
+}
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[in] ServiceStopType Reason of stopping Redfish service.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL or given the worng ServiceStopType.
+ @retval EFI_UNSUPPORTED Not support to stop Redfish service.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialStopService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ )
+{
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return LibStopRedfishService (This, ServiceStopType);
+}
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialDxeDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_EVENT EndOfDxeEvent;
+ EFI_EVENT ExitBootServiceEvent;
+
+ Handle = NULL;
+
+ //
+ // Install the RedfishCredentialProtocol onto Handle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Handle,
+ &gEdkIIRedfishCredentialProtocolGuid,
+ &mRedfishCredentialProtocol,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // After EndOfDxe, if SecureBoot is disabled, Redfish Credential Protocol should return
+ // error code to caller to avoid the 3rd code to bypass Redfish Credential Protocol and
+ // retrieve userid/pwd directly. So, here, we create EndOfDxe Event to check SecureBoot
+ // status.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishCredentialEndOfDxeEventNotify,
+ (VOID *)&mRedfishCredentialProtocol,
+ &gEfiEndOfDxeEventGroupGuid,
+ &EndOfDxeEvent
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // After ExitBootServices, Redfish Credential Protocol should stop the service.
+ // So, here, we create ExitBootService Event to stop service.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RedfishCredentialExitBootServicesEventNotify,
+ (VOID *)&mRedfishCredentialProtocol,
+ &gEfiEventExitBootServicesGuid,
+ &ExitBootServiceEvent
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (EndOfDxeEvent);
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Handle,
+ &gEdkIIRedfishCredentialProtocolGuid,
+ &mRedfishCredentialProtocol,
+ NULL
+ );
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h
new file mode 100644
index 00000000000..aee5c67ffb7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.h
@@ -0,0 +1,75 @@
+/** @file
+ Definition of Redfish Credential DXE driver.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef EDKII_REDFISH_CREDENTIAL_DXE_H_
+#define EDKII_REDFISH_CREDENTIAL_DXE_H_
+
+#include <Protocol/EdkIIRedfishCredential.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RedfishCredentialLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Retrieve platform's Redfish authentication information.
+
+ This functions returns the Redfish authentication method together with the user Id and
+ password.
+ - For AuthMethodNone, the UserId and Password could be used for HTTP header authentication
+ as defined by RFC7235.
+ - For AuthMethodRedfishSession, the UserId and Password could be used for Redfish
+ session login as defined by Redfish API specification (DSP0266).
+
+ Callers are responsible for and freeing the returned string storage.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+ @param[out] AuthMethod Type of Redfish authentication method.
+ @param[out] UserId The pointer to store the returned UserId string.
+ @param[out] Password The pointer to store the returned Password string.
+
+ @retval EFI_SUCCESS Get the authentication information successfully.
+ @retval EFI_ACCESS_DENIED SecureBoot is disabled after EndOfDxe.
+ @retval EFI_INVALID_PARAMETER This or AuthMethod or UserId or Password is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough memory resources.
+ @retval EFI_UNSUPPORTED Unsupported authentication method is found.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialGetAuthInfo (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ OUT EDKII_REDFISH_AUTH_METHOD *AuthMethod,
+ OUT CHAR8 **UserId,
+ OUT CHAR8 **Password
+ );
+
+/**
+ Notify the Redfish service provide to stop provide configuration service to this platform.
+
+ This function should be called when the platfrom is about to leave the safe environment.
+ It will notify the Redfish service provider to abort all logined session, and prohibit
+ further login with original auth info. GetAuthInfo() will return EFI_UNSUPPORTED once this
+ function is returned.
+
+ @param[in] This Pointer to EDKII_REDFISH_CREDENTIAL_PROTOCOL instance.
+
+ @retval EFI_SUCCESS Service has been stoped successfully.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval Others Some error happened.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishCredentialStopService (
+ IN EDKII_REDFISH_CREDENTIAL_PROTOCOL *This,
+ IN EDKII_REDFISH_CREDENTIAL_STOP_SERVICE_TYPE ServiceStopType
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
new file mode 100644
index 00000000000..479e1eb868a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishCredentialDxe/RedfishCredentialDxe.inf
@@ -0,0 +1,51 @@
+## @file
+# RedfishCredentialDxe is required to produce the
+# EdkII RedfishCredentialProtocol for the consumer to get the Redfish
+# credential Info and to restrict Redfish access from UEFI side.
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishCredentialDxe
+ FILE_GUID = 458CE95A-4942-09A9-5D21-A6B16D5DAD7F
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishCredentialDxeDriverEntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishCredentialDxe.c
+ RedfishCredentialDxe.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PrintLib
+ RedfishPlatformCredentialLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+ UefiLib
+
+[Protocols]
+ gEdkIIRedfishCredentialProtocolGuid ## BY_START
+
+
+[Guids]
+ gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+ gEfiEventExitBootServicesGuid ## CONSUMES ## Event
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc
new file mode 100644
index 00000000000..29a826b726f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDefines.dsc.inc
@@ -0,0 +1,27 @@
+## @file
+# RedfishPkg DSC include file for [Defines] section of all Architectures.
+#
+# This file can be included to the [Defines] section of a platform DSC file by
+# using "!include RedfishPkg/RedfishDefines.dsc.inc" to set value of
+# flags.
+#
+# These flags can be defined before the !include line, or changed on the command
+# line to enable or disable related feature support.
+# -D FLAG=VALUE
+#
+# The default value of these flags are:
+# DEFINE REDFISH_ENABLE = TRUE
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+!ifndef REDFISH_ENABLE
+ #
+ # This flag is to enable or disable the whole Redfish support.
+ #
+ DEFINE REDFISH_ENABLE = TRUE
+!endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c
new file mode 100644
index 00000000000..932d668bd4d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/ComponentName.c
@@ -0,0 +1,218 @@
+/** @file
+ Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL protocol.
+ for EFI Refish Discover Protocol
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gRedfishDiscoverComponentName = {
+ RedfishDiscoverComponentNameGetDriverName,
+ RedfishDiscoverComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishDiscoverComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishDiscoverComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mRedfishDiscoverDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"Redfish Discover UEFI Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable = NULL;
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mRedfishDiscoverDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gRedfishDiscoverComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
new file mode 100644
index 00000000000..5e390ca8adc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.c
@@ -0,0 +1,1910 @@
+/** @file
+
+ The implementation of EFI Redfidh Discover Protocol.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+LIST_ENTRY mRedfishDiscoverList;
+LIST_ENTRY mRedfishInstanceList;
+EFI_SMBIOS_PROTOCOL *mSmbios = NULL;
+
+UINTN mNumNetworkInterface = 0;
+UINTN mNumRestExInstance = 0;
+LIST_ENTRY mEfiRedfishDiscoverNetworkInterface;
+LIST_ENTRY mEfiRedfishDiscoverRestExInstance;
+
+EFI_GUID mRedfishDiscoverTcp4InstanceGuid = EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID;
+EFI_GUID mRedfishDiscoverTcp6InstanceGuid = EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID;
+EFI_GUID mRedfishDiscoverRestExInstanceGuid = EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID;
+
+EFI_HANDLE EfiRedfishDiscoverProtocolHandle = NULL;
+
+EFI_STATUS
+EFIAPI
+Tcp4GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+);
+
+EFI_STATUS
+EFIAPI
+Tcp6GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+);
+
+static REDFISH_DISCOVER_REQUIRED_PROTOCOL gRequiredProtocol[] = {
+ {
+ ProtocolTypeTcp4,
+ L"TCP4 Service Binding Protocol",
+ &gEfiTcp4ProtocolGuid,
+ &gEfiTcp4ServiceBindingProtocolGuid,
+ &mRedfishDiscoverTcp4InstanceGuid,
+ Tcp4GetSubnetInfo
+ },
+ {
+ ProtocolTypeTcp6,
+ L"TCP6 Service Binding Protocol",
+ &gEfiTcp6ProtocolGuid,
+ &gEfiTcp6ServiceBindingProtocolGuid,
+ &mRedfishDiscoverTcp6InstanceGuid,
+ Tcp6GetSubnetInfo
+ },
+ {
+ ProtocolTypeRestEx,
+ L"REST EX Service Binding Protocol",
+ &gEfiRestExProtocolGuid,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &mRedfishDiscoverRestExInstanceGuid,
+ NULL
+ }
+};
+
+/**
+ This function creates REST EX instance for the found Resfish service.
+ by known owner handle.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+ @param[in] Token Client token.
+
+ @retval NULL Instance not found.
+ @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
+
+**/
+EFI_STATUS
+CreateRestExInstance (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN EFI_REDFISH_DISCOVERED_TOKEN *Token
+ )
+{
+ EFI_STATUS Status;
+
+ Status = RestExLibCreateChild (
+ Instance->Owner,
+ FixedPcdGetBool (PcdRedfishDiscoverAccessModeInBand)? EfiRestExServiceInBandAccess: EfiRestExServiceOutOfBandAccess,
+ EfiRestExConfigHttp,
+ EfiRestExServiceRedfish,
+ &Token->DiscoverList.RedfishInstances->Information.RedfishRestExHandle
+ );
+ return Status;
+}
+
+/**
+ This function gets EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+ by known owner handle.
+
+ @param[in] ImageHandle Image handle owns EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] TargetNetworkInterface Target network interface used by this EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] DiscoverFlags EFI_REDFISH_DISCOVER_FLAG
+
+ @retval NULL Instance not found.
+ @retval EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE The instance owned by this owner.
+
+**/
+EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *
+GetInstanceByOwner (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG DiscoverFlags
+ )
+{
+ EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *ThisInstance;
+
+ if (IsListEmpty (&mRedfishDiscoverList)) {
+ return NULL;
+ }
+ ThisInstance =
+ (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetFirstNode (&mRedfishDiscoverList);
+ while (TRUE) {
+ if ((ThisInstance->Owner == ImageHandle) &&
+ (ThisInstance->DiscoverFlags == DiscoverFlags) &&
+ (ThisInstance->NetworkInterface == TargetNetworkInterface)) {
+ return ThisInstance;
+ }
+ if (IsNodeAtEnd (&mRedfishDiscoverList, &ThisInstance->Entry)) {
+ break;
+ }
+ ThisInstance =
+ (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)GetNextNode (&mRedfishDiscoverList, &ThisInstance->Entry);
+ };
+ return NULL;
+}
+
+/**
+ This function gets the subnet information of this TCP4 instance.
+
+ @param[in] ImageHandle EFI handle with this image.
+ @param[in] Instance Instance of Network interface.
+ @retval EFI_STATUS Get subnet information successfully.
+ @retval Otherwise Fail to get subnet information.
+**/
+EFI_STATUS
+EFIAPI
+Tcp4GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+)
+{
+ EFI_STATUS Status;
+ EFI_TCP4_PROTOCOL *Tcp4;
+ EFI_TCP4_CONFIG_DATA Tcp4CfgData;
+ EFI_TCP4_OPTION Tcp4Option;
+ EFI_IP4_MODE_DATA IpModedata;
+ UINT8 SubnetMaskIndex;
+ UINT8 BitMask;
+ UINT8 PrefixLength;
+ BOOLEAN GotPrefixLength;
+
+ if (Instance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Tcp4 = (EFI_TCP4_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+
+ ZeroMem ((VOID *)&Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));
+ ZeroMem ((VOID *)&Tcp4Option, sizeof (EFI_TCP4_OPTION));
+ // Give a local host IP address just for getting subnet information.
+ Tcp4CfgData.AccessPoint.UseDefaultAddress = TRUE;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [0] = 127;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [1] = 0;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [2] = 0;
+ Tcp4CfgData.AccessPoint.RemoteAddress.Addr [3] = 1;
+ Tcp4CfgData.AccessPoint.RemotePort = 80;
+ Tcp4CfgData.AccessPoint.ActiveFlag = TRUE;
+
+ Tcp4CfgData.ControlOption = &Tcp4Option;
+ Tcp4Option.ReceiveBufferSize = 65535;
+ Tcp4Option.SendBufferSize = 65535;
+ Tcp4Option.MaxSynBackLog = 5;
+ Tcp4Option.ConnectionTimeout = 60;
+ Tcp4Option.DataRetries = 12;
+ Tcp4Option.FinTimeout = 2;
+ Tcp4Option.KeepAliveProbes = 6;
+ Tcp4Option.KeepAliveTime = 7200;
+ Tcp4Option.KeepAliveInterval = 30;
+ Tcp4Option.EnableNagle = TRUE;
+ Status = Tcp4->Configure (Tcp4, &Tcp4CfgData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get subnet information\n", __FUNCTION__));
+ return Status;
+ }
+ Status = Tcp4->GetModeData (Tcp4, NULL, NULL, &IpModedata, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n", __FUNCTION__));
+ return Status;
+ }
+ IP4_COPY_ADDRESS (&Instance->SubnetMask, &IpModedata.ConfigData.SubnetMask);
+ Instance->SubnetAddr.v4.Addr [0] = IpModedata.ConfigData.StationAddress.Addr [0] & Instance->SubnetMask.v4.Addr [0];
+ Instance->SubnetAddr.v4.Addr [1] = IpModedata.ConfigData.StationAddress.Addr [1] & Instance->SubnetMask.v4.Addr [1];
+ Instance->SubnetAddr.v4.Addr [2] = IpModedata.ConfigData.StationAddress.Addr [2] & Instance->SubnetMask.v4.Addr [2];
+ Instance->SubnetAddr.v4.Addr [3] = IpModedata.ConfigData.StationAddress.Addr [3] & Instance->SubnetMask.v4.Addr [3];
+ //
+ // Calculate the subnet mask prefix.
+ //
+ GotPrefixLength = FALSE;
+ PrefixLength = 0;
+ SubnetMaskIndex = 0;
+ while (GotPrefixLength == FALSE && SubnetMaskIndex < 4) {
+ BitMask = 0x80;
+ while (BitMask != 0) {
+ if ((Instance->SubnetMask.v4.Addr [SubnetMaskIndex] & BitMask) != 0) {
+ PrefixLength ++;
+ } else {
+ GotPrefixLength = TRUE;
+ break;
+ }
+ BitMask = BitMask >> 1;
+ };
+ SubnetMaskIndex ++;
+ };
+ Instance->SubnetPrefixLength = PrefixLength;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets the subnet information of this TCP6 instance.
+
+ @param[in] ImageHandle EFI handle with this image.
+ @param[in] Instance Instance of Network interface.
+ @retval EFI_STATUS Get subnet information successfully.
+ @retval Otherwise Fail to get subnet information.
+**/
+EFI_STATUS
+EFIAPI
+Tcp6GetSubnetInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+)
+{
+ EFI_STATUS Status;
+ EFI_TCP6_PROTOCOL *Tcp6;
+ EFI_IP6_MODE_DATA IpModedata;
+
+ if (Instance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Tcp6 = (EFI_TCP6_PROTOCOL *)Instance->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+
+ Status = Tcp6->GetModeData (Tcp6, NULL, NULL, &IpModedata, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Can't get IP mode data information\n"));
+ return Status;
+ }
+ if (IpModedata.AddressCount == 0) {
+ DEBUG ((DEBUG_INFO, "%a: No IPv6 address configured.\n"));
+ }
+ if (Instance->SubnetAddrInfoIPv6 != NULL) {
+ FreePool (Instance->SubnetAddrInfoIPv6);
+ }
+ Instance->SubnetAddrInfoIPv6 = AllocateZeroPool (IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO));
+ if (Instance->SubnetAddrInfoIPv6 == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to allocate memory fir IPv6 subnet address information\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Instance->SubnetAddrInfoIPv6Number = IpModedata.AddressCount;
+ CopyMem (
+ (VOID *)Instance->SubnetAddrInfoIPv6,
+ (VOID *)&IpModedata.AddressList,
+ IpModedata.AddressCount * sizeof (EFI_IP6_ADDRESS_INFO)
+ );
+ FreePool (IpModedata.AddressList);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function searches EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ instance with the given EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+
+ @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+ NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
+
+ @retval Non-NULL EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL is returned.
+ @retval NULL Non of EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance is returned.
+**/
+EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *
+GetTargetNetworkInterfaceInternal (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface
+ )
+{
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
+ return ThisNetworkInterface;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ return NULL;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ return NULL;
+}
+
+/**
+ This function validate if target network interface is ready for discovering
+ Redfish service.
+
+ @param[in] TargetNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE.
+ NULL for all EFI_REDFISH_DISCOVER_NETWORK_INTERFACEs.
+ @param[in] Flags EFI_REDFISH_DISCOVER_FLAG
+
+ @retval EFI_SUCCESS Target network interface is ready to use.
+ @retval EFI_UNSUPPORTED Target network interface is not ready to use.
+**/
+EFI_STATUS
+ValidateTargetNetworkInterface (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG Flags
+ )
+{
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface) && TargetNetworkInterface == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+ if (TargetNetworkInterface == NULL) {
+ return EFI_SUCCESS; // Return EFI_SUCCESS if no network interface is specified.
+ }
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode(&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (CompareMem((VOID *)&ThisNetworkInterface->MacAddress, &TargetNetworkInterface->MacAddress, ThisNetworkInterface->HwAddressSize) == 0) {
+ break;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ return EFI_UNSUPPORTED;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
+ // Validate if UDP4/6 is supported on the given network interface.
+ // SSDP is not supported.
+
+ return EFI_SUCCESS;
+ }
+ if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == NULL) {
+ return EFI_UNSUPPORTED; // The required protocol on this network interface is not found.
+ }
+ return EFI_SUCCESS;
+}
+/**
+ This function returns number of network interface instance.
+
+ @retval UINTN Number of network interface instances.
+**/
+UINTN
+NumberOfNetworkInterface (VOID)
+{
+ UINTN Num;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ return 0;
+ }
+
+ Num = 1;
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ Num ++;
+ };
+ return Num;
+}
+
+/**
+ This function checks the IP version supported on this
+ netwoek interface.
+
+ @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+
+ @retval TRUE Is IPv6, otherwise IPv4.
+
+**/
+BOOLEAN
+CheckIsIpVersion6 (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
+)
+{
+ if (ThisNetworkInterface->NetworkProtocolType == ProtocolTypeTcp6) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ This function discover Redfish service through SMBIOS host interface.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE
+
+ @retval EFI_SUCCESS Redfish service is discovered through SMBIOS Host interface.
+ @retval Others Fail to discover Redfish service throught SMBIOS host interface
+
+**/
+EFI_STATUS
+DiscoverRedfishHostInterface (IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance)
+{
+ EFI_STATUS Status;
+ REDFISH_OVER_IP_PROTOCOL_DATA *Data;
+ REDFISH_INTERFACE_DATA *DeviceDescriptor;
+ CHAR8 UuidStr[sizeof"00000000-0000-0000-0000-000000000000" + 1];
+ CHAR16 Ipv6Str [sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
+ CHAR8 RedfishServiceLocateStr [sizeof"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff" + 1];
+ UINTN StrSize;
+ UINTN MacCompareStstus;
+ BOOLEAN IsHttps;
+
+ Data = NULL;
+ DeviceDescriptor = NULL;
+
+ if (mSmbios == NULL) {
+ Status = gBS->LocateProtocol(&gEfiSmbiosProtocolGuid, NULL, (VOID **)&mSmbios);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ Status = RedfishGetHostInterfaceProtocolData (mSmbios, &DeviceDescriptor, &Data); // Search for SMBIOS type 42h
+ if (!EFI_ERROR (Status) && Data != NULL && DeviceDescriptor != NULL) {
+ //
+ // Chceck if we can reach out Redfish service using this network interface.
+ // Check with MAC address using Device Descroptor Data Device Type 04 and Type 05.
+ // Those two types of Redfish host interface device has MAC information.
+ //
+ if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.MacAddress, 6);
+ } else if (DeviceDescriptor->DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2){
+ MacCompareStstus = CompareMem(&Instance->NetworkInterface->MacAddress, &DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.MacAddress, 6);
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+ if (MacCompareStstus != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ if (Data->RedfishServiceIpAddressFormat == 1) {
+ IP4_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v4, (VOID *)Data->RedfishServiceIpAddress);
+ } else {
+ IP6_COPY_ADDRESS ((VOID *)&Instance->TargetIpAddress.v6, (VOID *)Data->RedfishServiceIpAddress);
+ }
+
+ if (Instance->HostIntfValidation) {
+ DEBUG ((DEBUG_ERROR,"%a:Send UPnP unicast SSDP to validate this Redfish Host Interface is not supported.\n", __FUNCTION__));
+ Status = EFI_UNSUPPORTED;
+ } else {
+ //
+ // Add this istance to list without detial information of Redfish
+ // service.
+ //
+ IsHttps = FALSE;
+ if (Data->RedfishServiceIpPort == 443) {
+ IsHttps = TRUE;
+ }
+ StrSize = sizeof(UuidStr);
+ AsciiSPrint(UuidStr, StrSize, "%g", &Data->ServiceUuid);
+ //
+ // Generate Redfish service location string.
+ //
+ if (Data->RedfishServiceIpAddressFormat == REDFISH_HOST_INTERFACE_HOST_IP_ADDRESS_FORMAT_IP6) {
+ NetLibIp6ToStr((IPv6_ADDRESS *)&Data->RedfishServiceIpAddress, Ipv6Str, sizeof (Ipv6Str));
+ if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) {
+ AsciiSPrintUnicodeFormat (
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ L"%s",
+ Ipv6Str
+ );
+ } else {
+ AsciiSPrintUnicodeFormat(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ L"[%s]:%d",
+ Ipv6Str,
+ Data->RedfishServiceIpPort
+ );
+ }
+ } else {
+ if (Data->RedfishServiceIpPort == 0 || IsHttps == TRUE) {
+ AsciiSPrint(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ "%d.%d.%d.%d",
+ Data->RedfishServiceIpAddress [0],
+ Data->RedfishServiceIpAddress [1],
+ Data->RedfishServiceIpAddress [2],
+ Data->RedfishServiceIpAddress [3]
+ );
+ } else {
+ AsciiSPrint(
+ RedfishServiceLocateStr,
+ sizeof (RedfishServiceLocateStr),
+ "%d.%d.%d.%d:%d",
+ Data->RedfishServiceIpAddress [0],
+ Data->RedfishServiceIpAddress [1],
+ Data->RedfishServiceIpAddress [2],
+ Data->RedfishServiceIpAddress [3],
+ Data->RedfishServiceIpPort
+ );
+ }
+ }
+ Status = AddAndSignalNewRedfishService (
+ Instance,
+ NULL,
+ RedfishServiceLocateStr,
+ UuidStr,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ IsHttps
+ );
+ }
+ }
+ return Status;
+}
+
+/**
+ The function adds a new found Redfish service to internal list and
+ notify client.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] RedfishVersion Redfish version.
+ @param[in] RedfishLocation Redfish location.
+ @param[in] Uuid Service UUID string.
+ @param[in] Os OS string.
+ @param[in] OsVer OS version string.
+ @param[in] Product Product string.
+ @param[in] ProductVer Product verison string.
+ @param[in] UseHttps Redfish service requires secured connection.
+ @retval EFI_SUCCESS Redfish service is added to list successfully.
+
+**/
+EFI_STATUS
+AddAndSignalNewRedfishService (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN UINTN *RedfishVersion OPTIONAL,
+ IN CHAR8 *RedfishLocation OPTIONAL,
+ IN CHAR8 *Uuid OPTIONAL,
+ IN CHAR8 *Os OPTIONAL,
+ IN CHAR8 *OsVer OPTIONAL,
+ IN CHAR8 *Product OPTIONAL,
+ IN CHAR8 *ProductVer OPTIONAL,
+ IN BOOLEAN UseHttps
+ )
+{
+ BOOLEAN NewFound;
+ BOOLEAN InfoRefresh;
+ BOOLEAN RestExOpened;
+ BOOLEAN DeleteRestEx;
+ EFI_STATUS Status;
+ EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredList;
+ EFI_REDFISH_DISCOVERED_INSTANCE *DiscoveredInstance;
+ CHAR16 *Char16Uuid;
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_REST_EX_HTTP_CONFIG_DATA *RestExHttpConfigData;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface;
+
+ NewFound = TRUE;
+ InfoRefresh = FALSE;
+ Char16Uuid = NULL;
+ RestExOpened = FALSE;
+ DeleteRestEx = FALSE;
+
+ DEBUG ((DEBUG_INFO,"%a:Add this instance to Redfish instance list.\n", __FUNCTION__));
+
+ if (Uuid != NULL) {
+ Char16Uuid = (CHAR16 *)AllocateZeroPool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, Char16Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ }
+ DiscoveredList = NULL;
+ DiscoveredInstance = NULL;
+ RestExHttpConfigData = NULL;
+
+ NetworkInterface = Instance->NetworkInterface;
+ if (!IsListEmpty (&mRedfishInstanceList)) {
+ //
+ // Is this a duplicate redfish service.
+ //
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode (&mRedfishInstanceList);
+ NewFound = FALSE;
+ do {
+ if (Char16Uuid == NULL || DiscoveredList->Instance->Information.Uuid == NULL) {
+ //
+ // Check if this Redfish instance already found using IP addrress.
+ //
+ if (!CheckIsIpVersion6(NetworkInterface)) {
+ if (CompareMem ((VOID *)&Instance->TargetIpAddress.v4,
+ (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v4,
+ sizeof (EFI_IPv4_ADDRESS)
+ ) == 0)
+ {
+ DiscoveredInstance = DiscoveredList->Instance;
+ if (DiscoveredList->Instance->Information.Uuid == NULL &&
+ Char16Uuid != NULL) {
+ InfoRefresh = TRUE;
+ DiscoveredInstance = DiscoveredList->Instance;
+ DEBUG((DEBUG_INFO,"*** This Redfish Service information refresh ***\n"));
+ }
+ break;
+ }
+ } else {
+ if (CompareMem ((VOID *)&Instance->TargetIpAddress.v6,
+ (VOID *)&DiscoveredList->Instance->Information.RedfishHostIpAddress.v6,
+ sizeof (EFI_IPv6_ADDRESS)
+ ) == 0)
+ {
+ DiscoveredInstance = DiscoveredList->Instance;
+ break;
+ }
+ }
+ } else {
+ //
+ // Check if this Redfish instance already found using UUID.
+ //
+ if (StrCmp((const CHAR16 *)Char16Uuid, (const CHAR16 *)DiscoveredList->Instance->Information.Uuid) == 0) {
+ DiscoveredInstance = DiscoveredList->Instance;
+ break;
+ }
+ }
+ if (IsNodeAtEnd (&mRedfishInstanceList, &DiscoveredList->NextInstance)) {
+ NewFound = TRUE;
+ break;
+ }
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode (&mRedfishInstanceList, &DiscoveredList->NextInstance);
+ } while (TRUE);
+ }
+ if (NewFound || InfoRefresh) {
+ if (!InfoRefresh) {
+ DiscoveredList = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_LIST));
+ if (DiscoveredList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead (&DiscoveredList->NextInstance);
+ DiscoveredInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INSTANCE));
+ if (DiscoveredInstance == NULL) {
+ FreePool ((VOID *)DiscoveredList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ DEBUG ((DEBUG_INFO,"*** Redfish Service Information ***\n"));
+
+ DiscoveredInstance->Information.UseHttps = UseHttps;
+ if (RedfishVersion != NULL) {
+ DiscoveredInstance->Information.RedfishVersion = *RedfishVersion;
+ DEBUG ((DEBUG_INFO,"Redfish service version: %d.\n", DiscoveredInstance->Information.RedfishVersion));
+ }
+ if (RedfishLocation != NULL) {
+ DiscoveredInstance->Information.Location = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)RedfishLocation, DiscoveredInstance->Information.Location, AsciiStrSize((const CHAR8 *)RedfishLocation) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service location: %s.\n", DiscoveredInstance->Information.Location));
+ }
+ if (Uuid != NULL) {
+ DiscoveredInstance->Information.Uuid = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Uuid, DiscoveredInstance->Information.Uuid, AsciiStrSize((const CHAR8 *)Uuid) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
+ }
+ if (Os != NULL) {
+ DiscoveredInstance->Information.Os = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Os, DiscoveredInstance->Information.Os, AsciiStrSize((const CHAR8 *)Os) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service OS: %s, Version:%s.\n", DiscoveredInstance->Information.Os, DiscoveredInstance->Information.OsVersion));
+ }
+ if (OsVer != NULL) {
+ DiscoveredInstance->Information.OsVersion = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)OsVer, DiscoveredInstance->Information.OsVersion, AsciiStrSize((const CHAR8 *)OsVer) * sizeof(CHAR16));
+ }
+ if (Product != NULL && ProductVer != NULL) {
+ DiscoveredInstance->Information.Product = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)Product, DiscoveredInstance->Information.Product, AsciiStrSize((const CHAR8 *)Product) * sizeof(CHAR16));
+ DiscoveredInstance->Information.ProductVer = (CHAR16 *)AllocatePool(AsciiStrSize((const CHAR8 *)ProductVer) * sizeof(CHAR16));
+ AsciiStrToUnicodeStrS ((const CHAR8 *)ProductVer, DiscoveredInstance->Information.ProductVer, AsciiStrSize((const CHAR8 *)ProductVer) * sizeof(CHAR16));
+ DEBUG ((DEBUG_INFO,"Redfish service product: %s, Version:%s.\n", DiscoveredInstance->Information.Product, DiscoveredInstance->Information.ProductVer));
+ }
+
+ if (RedfishLocation == NULL) {
+ // This is the Redfish reported from SMBIOS 42h
+ // without validation.
+
+ IP4_COPY_ADDRESS((VOID *)&DiscoveredInstance->Information.RedfishHostIpAddress.v4, (VOID *)&Instance->TargetIpAddress.v4);
+ }
+ if (!InfoRefresh) {
+ DiscoveredList->Instance = DiscoveredInstance;
+ InsertTailList(&mRedfishInstanceList, &DiscoveredList->NextInstance);
+ }
+ DiscoveredInstance->Status = EFI_SUCCESS;
+ } else {
+ if (DiscoveredList != NULL) {
+ DEBUG((DEBUG_INFO,"*** This Redfish Service was already found ***\n"));
+ if (DiscoveredInstance->Information.Uuid != NULL) {
+ DEBUG((DEBUG_INFO,"Service UUID: %s.\n", DiscoveredInstance->Information.Uuid));
+ } else {
+ DEBUG((DEBUG_INFO,"Service UUID: unknown.\n"));
+ }
+ }
+ }
+ if (Char16Uuid != NULL) {
+ FreePool((VOID *)Char16Uuid);
+ }
+
+ Status = EFI_SUCCESS;
+ if (NewFound || InfoRefresh) {
+ //
+ // Build up EFI_REDFISH_DISCOVERED_LIST in token.
+ //
+ Instance->DiscoverToken->DiscoverList.NumberOfServiceFound = 1;
+ Instance->DiscoverToken->DiscoverList.RedfishInstances = DiscoveredInstance;
+ DiscoveredInstance->Status = EFI_SUCCESS;
+ if (!InfoRefresh) {
+ Status = CreateRestExInstance (Instance, Instance->DiscoverToken); // Create REST EX child.
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a:Can't create REST EX child instance.\n",__FUNCTION__));
+ goto ON_EXIT;
+ }
+ Status = gBS->OpenProtocol ( // Configure local host information.
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **)&RestEx,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ DeleteRestEx = TRUE;
+ goto ERROR_EXIT;
+ }
+ RestExOpened = TRUE;
+ RestExHttpConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (RestExHttpConfigData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ DeleteRestEx = TRUE;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ RestExHttpConfigData->SendReceiveTimeout = 5000;
+ RestExHttpConfigData->HttpConfigData.HttpVersion = HttpVersion11;
+ RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6 = CheckIsIpVersion6(NetworkInterface);
+ if (RestExHttpConfigData->HttpConfigData.LocalAddressIsIPv6) {
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv6Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ } else {
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ if (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT_FREE_CONFIG_DATA;
+ }
+ RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node->UseDefaultAddress = TRUE;
+ }
+ Status = RestEx->Configure (
+ RestEx,
+ (EFI_REST_EX_CONFIG_DATA)(UINT8 *)RestExHttpConfigData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:REST EX configured..\n", __FUNCTION__));
+ DeleteRestEx = TRUE;
+ goto EXIT_FREE_ALL;
+ }
+ //
+ // Signal client, close REST EX before signaling client.
+ //
+ if (RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ RestExOpened = FALSE;
+ }
+ }
+ Status = gBS->SignalEvent(Instance->DiscoverToken->Event);
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:No event to signal!\n", __FUNCTION__));
+ }
+ }
+
+EXIT_FREE_ALL:;
+ if (RestExHttpConfigData != NULL && RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node != NULL) {
+ FreePool (RestExHttpConfigData->HttpConfigData.AccessPoint.IPv4Node);
+ }
+
+EXIT_FREE_CONFIG_DATA:;
+ if (RestExHttpConfigData != NULL) {
+ FreePool((VOID *)RestExHttpConfigData);
+ }
+ if (RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ }
+ERROR_EXIT:;
+ if (DeleteRestEx && RestExOpened) {
+ gBS->CloseProtocol(
+ Instance->DiscoverToken->DiscoverList.RedfishInstances->Information.RedfishRestExHandle,
+ &gEfiRestExProtocolGuid,
+ Instance->NetworkInterface->OpenDriverAgentHandle,
+ Instance->NetworkInterface->OpenDriverControllerHandle
+ );
+ }
+ON_EXIT:;
+ return Status;
+}
+
+/**
+ This function gets the subnet information of this network interface instance.
+ can discover Redfish service on it.
+
+ @param[in] Instance EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
+ @param[in] ImageHandle EFI Image handle request the network interface list.
+
+ @retval EFI_SUCCESS
+
+**/
+EFI_STATUS
+NetworkInterfaceGetSubnetInfo (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance,
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ProtocolType;
+ UINT32 IPv6InfoIndex;
+ EFI_IP6_ADDRESS_INFO *ThisSubnetAddrInfoIPv6;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface;
+
+ if (Instance->GotSubnetInfo) {
+ return EFI_SUCCESS;
+ }
+
+ ProtocolType = Instance->NetworkProtocolType;
+ if (gRequiredProtocol [ProtocolType].GetSubnetInfo != NULL && Instance->GotSubnetInfo == FALSE) {
+ Status = gRequiredProtocol [ProtocolType].GetSubnetInfo (
+ ImageHandle,
+ Instance
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR,"%a:Faile to get Subnet infomation.\n", __FUNCTION__));
+ return Status;
+ } else {
+ DEBUG ((DEBUG_INFO,"%a:MAC address: %s\n", __FUNCTION__, Instance->StrMacAddr));
+ if (CheckIsIpVersion6 (Instance)) {
+ if (Instance->SubnetAddrInfoIPv6Number == 0) {
+ DEBUG ((DEBUG_ERROR,"%a: There is no Subnet infomation for IPv6 network interface.\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ ThisSubnetAddrInfoIPv6 = Instance->SubnetAddrInfoIPv6; // First IPv6 address information.
+ IP6_COPY_ADDRESS (&Instance->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
+ Instance->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
+ DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n",
+ ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256,
+ ThisSubnetAddrInfoIPv6->PrefixLength)
+ );
+ //
+ // If this is IPv6, then we may have to propagate network interface for IPv6 network scopes
+ // according to the Ipv6 address information.
+ //
+ ThisSubnetAddrInfoIPv6 ++;
+ for (IPv6InfoIndex = 0; IPv6InfoIndex < Instance->SubnetAddrInfoIPv6Number - 1; IPv6InfoIndex++) {
+ //
+ // Build up addtional EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instances.
+ //
+ NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
+ if (NewNetworkInterface != NULL) {
+ CopyMem ((VOID *)NewNetworkInterface, (VOID *)Instance, sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL)); // Clone information of first instance.
+ IP6_COPY_ADDRESS (&NewNetworkInterface->SubnetAddr.v6, &ThisSubnetAddrInfoIPv6->Address);
+ NewNetworkInterface->SubnetPrefixLength = ThisSubnetAddrInfoIPv6->PrefixLength;
+ NewNetworkInterface->GotSubnetInfo = TRUE;
+ InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NewNetworkInterface->Entry);
+ ThisSubnetAddrInfoIPv6 ++;
+ mNumNetworkInterface ++;
+ DEBUG((DEBUG_INFO," IPv6 Subnet ID:%d, Prefix length: %d.\n",
+ ThisSubnetAddrInfoIPv6->Address.Addr [7] + (UINT16)ThisSubnetAddrInfoIPv6->Address.Addr [6] * 256,
+ ThisSubnetAddrInfoIPv6->PrefixLength)
+ );
+ } else {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ } else {
+ DEBUG ((DEBUG_INFO," IPv4 Subnet:%d.%d.%d.%d Subnet mask: %d.%d.%d.%d.\n",
+ Instance->SubnetAddr.v4.Addr [0],
+ Instance->SubnetAddr.v4.Addr [1],
+ Instance->SubnetAddr.v4.Addr [2],
+ Instance->SubnetAddr.v4.Addr [3],
+ Instance->SubnetMask.v4.Addr [0],
+ Instance->SubnetMask.v4.Addr [1],
+ Instance->SubnetMask.v4.Addr [2],
+ Instance->SubnetMask.v4.Addr [3]
+ ));
+ }
+ }
+ }
+ Instance->GotSubnetInfo = TRUE; // Only try to get Subnet Info once.
+ return EFI_SUCCESS;
+}
+
+/**
+ This function gets the network interface list which Redfish discover protocol
+ can discover Redfish service on it.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI Image handle request the network interface list,
+ @param[out] NumberOfNetworkIntfs Number of network interfaces can do Redfish service discovery.
+ @param[out] NetworkIntfInstances Network interface instances. It's an array of instance. The number of entries
+ in array is indicated by NumberOfNetworkIntfs.
+ Caller has to release the memory
+ allocated by Redfish discover protocol.
+
+ @retval EFI_SUCCESS The information of network interface is returned in NumberOfNetworkIntfs and
+ NetworkIntfInstances.
+ @retval Others Fail to return the information of network interface.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceGetNetworkInterface (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ OUT UINTN *NumberOfNetworkIntfs,
+ OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE **NetworkIntfInstances
+)
+{
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterfaceIntn;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *ThisNetworkInterface;
+
+ if (NetworkIntfInstances == NULL || NumberOfNetworkIntfs == NULL || ImageHandle == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *NumberOfNetworkIntfs = 0;
+ *NetworkIntfInstances = NULL;
+
+ if (IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) {
+ return EFI_NOT_FOUND;
+ }
+
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE) * mNumNetworkInterface);
+ if (ThisNetworkInterface == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ *NetworkIntfInstances = ThisNetworkInterface;
+ ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ ThisNetworkInterface->IsIpv6 = FALSE;
+ if (CheckIsIpVersion6 (ThisNetworkInterfaceIntn)) {
+ ThisNetworkInterface->IsIpv6 = TRUE;
+ }
+ CopyMem((VOID *)&ThisNetworkInterface->MacAddress, &ThisNetworkInterfaceIntn->MacAddress, ThisNetworkInterfaceIntn->HwAddressSize);
+ NetworkInterfaceGetSubnetInfo(ThisNetworkInterfaceIntn, ImageHandle); // Get subnet info.
+ if (!ThisNetworkInterface->IsIpv6) {
+ IP4_COPY_ADDRESS(&ThisNetworkInterface->SubnetId.v4, &ThisNetworkInterfaceIntn->SubnetAddr.v4); // IPv4 subnet information.
+ } else {
+ IP6_COPY_ADDRESS (&ThisNetworkInterface->SubnetId.v6, &ThisNetworkInterfaceIntn->SubnetAddr.v6); // IPv6 subnet information in IPv6 address information.
+ }
+ ThisNetworkInterface->SubnetPrefixLength = ThisNetworkInterfaceIntn->SubnetPrefixLength;
+ ThisNetworkInterface->VlanId = ThisNetworkInterfaceIntn->VlanId;
+ (*NumberOfNetworkIntfs) ++;
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry)) {
+ break;
+ }
+ ThisNetworkInterfaceIntn = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterfaceIntn->Entry);
+ ThisNetworkInterface ++;
+ };
+ return EFI_SUCCESS;
+}
+/**
+ This function acquires Redfish services by discovering static Redfish setting
+ according to Redfish Host Interface or through SSDP. Returns a list of EFI
+ handles in EFI_REDFISH_DISCOVERED_LIST. Each of EFI handle has cooresponding
+ EFI REST EX instance installed on it. Each REST EX isntance is a child instance which
+ created through EFI REST EX serivce protoocl for communicating with specific
+ Redfish service.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] ImageHandle EFI image owns these Redfish service instances.
+ @param[in] TargetNetworkInterface Target network interface to do the discovery.
+ NULL means discover Redfish service on all network interfaces on platform.
+ @param[in] Flags Redfish service discover flags.
+ @param[in] Token EFI_REDFISH_DISCOVERED_TOKEN instance.
+ The memory of EFI_REDFISH_DISCOVERED_LIST and the strings in
+ EFI_REDFISH_DISCOVERED_INFORMATION are all allocated by Acquire()
+ and must be freed when caller invoke Release().
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval EFI_INVALID_PARAMETERS ImageHandle == NULL, Flags == 0, Token == NULL, Token->Timeout > 5,
+ or Token->Event == NULL.
+ @retval Others Fail acquire Redfish services.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceAcquireService (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface,
+ IN EFI_REDFISH_DISCOVER_FLAG Flags,
+ IN EFI_REDFISH_DISCOVERED_TOKEN *Token
+ )
+{
+ EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance;
+ EFI_STATUS Status1;
+ EFI_STATUS Status2;
+ BOOLEAN NewInstance;
+ UINTN NumNetworkInterfaces;
+ UINTN NetworkInterfacesIndex;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *TargetNetworkInterfaceInternal;
+
+ DEBUG ((DEBUG_INFO,"%a:Entry.\n", __FUNCTION__));
+
+ //
+ // Validate parameters.
+ //
+ if (ImageHandle == NULL || Token == NULL || ((Flags & ~EFI_REDFISH_DISCOVER_VALIDATION) == 0)) {
+ DEBUG ((DEBUG_ERROR,"%a:Invalid parameters.\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Validate target network interface.
+ //
+ if (EFI_ERROR (ValidateTargetNetworkInterface (TargetNetworkInterface, Flags))) {
+ return EFI_UNSUPPORTED;
+ }
+ if (TargetNetworkInterface != NULL) {
+ TargetNetworkInterfaceInternal = GetTargetNetworkInterfaceInternal (TargetNetworkInterface);
+ NumNetworkInterfaces = 1;
+ } else {
+ TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ NumNetworkInterfaces = NumberOfNetworkInterface ();
+ if (NumNetworkInterfaces == 0) {
+ DEBUG ((DEBUG_ERROR,"%a:No network interface on platform.\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+ }
+ for (NetworkInterfacesIndex = 0; NetworkInterfacesIndex < NumNetworkInterfaces; NetworkInterfacesIndex ++) {
+ Status1 = EFI_SUCCESS;
+ Status2 = EFI_SUCCESS;
+ NewInstance = FALSE;
+ Instance = GetInstanceByOwner (ImageHandle, TargetNetworkInterfaceInternal, Flags & ~EFI_REDFISH_DISCOVER_VALIDATION); // Check if we can re-use previous instance.
+ if (Instance == NULL) {
+ DEBUG ((DEBUG_INFO,"%a:Create new EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.\n", __FUNCTION__));
+ Instance = (EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *)AllocateZeroPool(sizeof(EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE));
+ if (Instance == NULL) {
+ DEBUG ((DEBUG_ERROR,"%a:Memory allocation fail.\n", __FUNCTION__));
+ }
+ InitializeListHead (&Instance->Entry);
+ Instance->Owner = ImageHandle;
+ Instance->DiscoverFlags = Flags & ~EFI_REDFISH_DISCOVER_VALIDATION;
+ Instance->NetworkInterface = TargetNetworkInterfaceInternal;
+ //
+ // Get subnet information in case subnet information is not set because
+ // RedfishServiceGetNetworkInterfaces hasn't been called yet.
+ //
+ NetworkInterfaceGetSubnetInfo (TargetNetworkInterfaceInternal, ImageHandle);
+ NewInstance = TRUE;
+ }
+ if (TargetNetworkInterfaceInternal->StrMacAddr != NULL) {
+ DEBUG((DEBUG_INFO,"%a:Acquire Redfish service on network interface MAC address:%s.\n", __FUNCTION__, TargetNetworkInterfaceInternal->StrMacAddr));
+ } else {
+ DEBUG((DEBUG_INFO,"%a:WARNING: No MAC address on this network interface.\n", __FUNCTION__));
+ }
+
+ Instance->DiscoverToken = Token; // Always use the latest Token passed by caller.
+ if ((Flags & EFI_REDFISH_DISCOVER_HOST_INTERFACE) != 0) {
+ DEBUG ((DEBUG_INFO,"%a:Redfish HOST interface discovery.\n", __FUNCTION__));
+ Instance->HostIntfValidation = FALSE;
+ if ((Flags & EFI_REDFISH_DISCOVER_VALIDATION) != 0) {
+ Instance->HostIntfValidation = TRUE;
+ }
+ Status1 = DiscoverRedfishHostInterface (Instance); // Discover Redfish service through Redfish Host Interface.
+ }
+ if ((Flags & EFI_REDFISH_DISCOVER_SSDP) != 0) {
+ DEBUG ((DEBUG_ERROR,"%a:Redfish service discovery through SSDP is not supported\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ } else {
+ if (EFI_ERROR (Status1) && EFI_ERROR (Status2)) {
+ FreePool ((VOID *)Instance);
+ DEBUG ((DEBUG_ERROR,"%a:Something wrong on Redfish service discovery Status1=%x, Status2=%x.\n", __FUNCTION__, Status1, Status2));
+ } else {
+ if (NewInstance) {
+ InsertTailList(&mRedfishDiscoverList, &Instance->Entry);
+ }
+ }
+ }
+ if (TargetNetworkInterface == NULL) {
+ //
+ // Discover Redfish services on all of network interfaces.
+ //
+ TargetNetworkInterfaceInternal = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &TargetNetworkInterfaceInternal->Entry);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ This function aborts Redfish service discovery on the given network interface.
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] TargetNetworkInterface Target network interface to do the discovery.
+
+ @retval EFI_SUCCESS REST EX instance of discovered Redfish services are returned.
+ @retval Others Fail to abort Redfish service discovery.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceAbortAcquire (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE *TargetNetworkInterface OPTIONAL
+)
+{
+ // This function is used to abort Redfish service discovery through SSDP
+ // on the network interface. SSDP is optionally supprted by EFI_REDFISH_DISCOVER_PROTOCOL,
+ // we dont have implementation for SSDP now.
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function releases Redfish services found by RedfishServiceAcquire().
+
+ @param[in] This EFI_REDFISH_DISCOVER_PROTOCOL instance.
+ @param[in] InstanceList The Redfish service to release.
+
+ @retval EFI_SUCCESS REST EX instances of discovered Redfish are released.
+ @retval Others Fail to remove the entry
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishServiceReleaseService (
+ IN EFI_REDFISH_DISCOVER_PROTOCOL *This,
+ IN EFI_REDFISH_DISCOVERED_LIST *InstanceList
+ )
+{
+ UINTN NumService;
+ BOOLEAN AnyFailRelease;
+ EFI_REDFISH_DISCOVERED_INSTANCE *ThisRedfishInstance;
+ EFI_REDFISH_DISCOVERED_INTERNAL_LIST *DiscoveredRedfishInstance;
+
+ if (IsListEmpty (&mRedfishInstanceList)) {
+ DEBUG ((DEBUG_ERROR,"%a:No any discovered Redfish service.\n", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ AnyFailRelease = FALSE;
+ ThisRedfishInstance = InstanceList->RedfishInstances;
+ for (NumService = 0; NumService < InstanceList->NumberOfServiceFound; NumService ++) {
+ DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetFirstNode(&mRedfishInstanceList);
+ do {
+ if (DiscoveredRedfishInstance->Instance == ThisRedfishInstance) {
+ RemoveEntryList (&DiscoveredRedfishInstance->NextInstance);
+ if (ThisRedfishInstance->Information.Location != NULL) {
+ FreePool (ThisRedfishInstance->Information.Location);
+ }
+ if (ThisRedfishInstance->Information.Uuid != NULL) {
+ FreePool (ThisRedfishInstance->Information.Uuid);
+ }
+ if (ThisRedfishInstance->Information.Os != NULL) {
+ FreePool (ThisRedfishInstance->Information.Os);
+ }
+ if (ThisRedfishInstance->Information.OsVersion != NULL) {
+ FreePool (ThisRedfishInstance->Information.OsVersion);
+ }
+ if (ThisRedfishInstance->Information.Product != NULL) {
+ FreePool (ThisRedfishInstance->Information.Product);
+ }
+ if (ThisRedfishInstance->Information.ProductVer != NULL) {
+ FreePool (ThisRedfishInstance->Information.ProductVer);
+ }
+ FreePool((VOID *)ThisRedfishInstance);
+ goto ReleaseNext;
+ }
+
+ if (IsNodeAtEnd(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance)) {
+ break;
+ }
+ DiscoveredRedfishInstance = (EFI_REDFISH_DISCOVERED_INTERNAL_LIST *)GetNextNode(&mRedfishInstanceList, &DiscoveredRedfishInstance->NextInstance);
+ } while (TRUE);
+ AnyFailRelease = TRUE;
+ReleaseNext:;
+ //
+ // Release next discovered Redfish Service.
+ //
+ ThisRedfishInstance = (EFI_REDFISH_DISCOVERED_INSTANCE *)((UINT8 *)ThisRedfishInstance + sizeof (EFI_REDFISH_DISCOVERED_INSTANCE));
+ }
+ if (AnyFailRelease) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_SUCCESS;
+ }
+}
+
+EFI_REDFISH_DISCOVER_PROTOCOL mRedfishDiscover = {
+ RedfishServiceGetNetworkInterface,
+ RedfishServiceAcquireService,
+ RedfishServiceAbortAcquire,
+ RedfishServiceReleaseService
+};
+
+/**
+ This function create an EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL for the
+ given network interface.
+
+
+ @param[in] ControllerHandle MAC address of this network interface.
+ @param[in] NetworkProtocolType Network protocol type.
+ @param[out] IsNewInstance BOOLEAN means new instance or not.
+ @param[out] NetworkInterface Pointer to to EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL.
+
+ @retval EFI_STATUS
+**/
+EFI_STATUS
+CreateRedfishDiscoverNetworkInterface (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINT32 NetworkProtocolType,
+ OUT BOOLEAN *IsNewInstance,
+ OUT EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL **NetworkInterface
+ )
+{
+ EFI_MAC_ADDRESS MacAddress;
+ UINTN HwAddressSize;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NewNetworkInterface;
+
+ NetLibGetMacAddress (ControllerHandle, &MacAddress, &HwAddressSize);
+ NewNetworkInterface = NULL;
+ *IsNewInstance = TRUE;
+ if (!IsListEmpty ((const LIST_ENTRY*)&mEfiRedfishDiscoverNetworkInterface)) {
+ //
+ // Check if this instance already exist.
+ //
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ if (ThisNetworkInterface != NULL) {
+ while (TRUE) {
+ if ((CompareMem ((CONST VOID *)&ThisNetworkInterface->MacAddress.Addr, (CONST VOID *)&MacAddress.Addr, HwAddressSize) == 0) &&
+ (ThisNetworkInterface->NetworkProtocolType == NetworkProtocolType)){
+ NewNetworkInterface = ThisNetworkInterface;
+ *IsNewInstance = FALSE;
+ break;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ NewNetworkInterface = NULL;
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ }
+ }
+ if (NewNetworkInterface == NULL) {
+ //
+ // Create a new instance.
+ //
+ NewNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL));
+ if (NewNetworkInterface == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ NewNetworkInterface->HwAddressSize = HwAddressSize;
+ CopyMem (&NewNetworkInterface->MacAddress.Addr, &MacAddress.Addr, NewNetworkInterface->HwAddressSize);
+ NetLibGetMacString (ControllerHandle, NULL, &NewNetworkInterface->StrMacAddr);
+ NewNetworkInterface->VlanId = NetLibGetVlanId (ControllerHandle);
+ }
+ *NetworkInterface = NewNetworkInterface;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function destory network interface
+
+
+ @param[in] ThisNetworkInterface EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL instance.
+
+ @retval EFI_STATUS
+**/
+EFI_STATUS
+DestroyRedfishNetwrokInterface (
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->UninstallProtocolInterface(
+ ThisNetworkInterface->OpenDriverControllerHandle,
+ gRequiredProtocol [ThisNetworkInterface->NetworkProtocolType].DiscoveredProtocolGuid,
+ &ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId
+ );
+ RemoveEntryList (&ThisNetworkInterface->Entry);
+ mNumNetworkInterface --;
+ FreePool (ThisNetworkInterface);
+ return Status;
+}
+
+/**
+ Tests to see if the required protocols are provided on the given
+ controller handle.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval EFI_UNSUPPORTED None of required protocol is found.
+**/
+EFI_STATUS
+TestForRequiredProtocols (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ UINT32 Id;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: %s is found on this controller handle.\n", __FUNCTION__, gRequiredProtocol [Index].ProtocolName));
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Build up network interface and create corresponding service through the given
+ controller handle.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval EFI_UNSUPPORTED None of required protocol is found.
+ @retval EFI_UNSUPPORTED Failed to build up network interface.
+**/
+EFI_STATUS
+BuildupNetworkInterface (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ UINT32 Id;
+ UINT32 Index;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface;
+ BOOLEAN IsNew;
+ EFI_STATUS Status;
+ VOID *TempInterface;
+ VOID **Interface;
+ UINT32 *ProtocolDiscoverIdPtr;
+ EFI_HANDLE OpenDriverAgentHandle;
+ EFI_HANDLE OpenDriverControllerHandle;
+ EFI_HANDLE *HandleOfProtocolInterfacePtr;
+ EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance;
+ EFI_TPL OldTpl;
+ BOOLEAN NewNetworkInterfaceInstalled;
+
+ NewNetworkInterfaceInstalled = FALSE;
+ Index = 0;
+ do {
+ Status = gBS->OpenProtocol ( // Already in list?
+ ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ &TempInterface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) {
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ Status = CreateRedfishDiscoverNetworkInterface(ControllerHandle, gRequiredProtocol [Index].ProtocolType, &IsNew, &NetworkInterface);
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+ NetworkInterface->NetworkProtocolType = gRequiredProtocol [Index].ProtocolType;
+ NetworkInterface->OpenDriverAgentHandle = This->DriverBindingHandle;
+ NetworkInterface->OpenDriverControllerHandle = ControllerHandle;
+ NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolGuid = \
+ *gRequiredProtocol [Index].RequiredProtocolGuid;
+ NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolServiceGuid = \
+ *gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid;
+ ProtocolDiscoverIdPtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolDiscoverId;
+ OpenDriverAgentHandle = NetworkInterface->OpenDriverAgentHandle;
+ OpenDriverControllerHandle = NetworkInterface->OpenDriverControllerHandle;
+ HandleOfProtocolInterfacePtr = &NetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle;
+ Interface = &NetworkInterface->NetworkInterfaceProtocolInfo.NetworkProtocolInterface;
+ NewNetworkInterfaceInstalled = TRUE;
+ if (IsNew) {
+ InsertTailList (&mEfiRedfishDiscoverNetworkInterface, &NetworkInterface->Entry);
+ mNumNetworkInterface ++;
+ }
+ gBS->RestoreTPL (OldTpl);
+ } else {
+ // Record REST_EX instance. REST_EX is created when clinet asks for Redfish service discovery.
+ // Redfish Service Discover protocol will match REST EX to the corresponding EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ // when discovery.
+
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)AllocateZeroPool (sizeof (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL));
+ if (RestExInstance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ RestExInstance->OpenDriverAgentHandle = This->DriverBindingHandle;
+ RestExInstance->OpenDriverControllerHandle = ControllerHandle;
+ RestExInstance->RestExControllerHandle = ControllerHandle;
+ InitializeListHead (&RestExInstance->Entry);
+ InsertTailList (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
+ mNumRestExInstance ++;
+ ProtocolDiscoverIdPtr = &RestExInstance->RestExId;
+ OpenDriverAgentHandle = RestExInstance->OpenDriverAgentHandle;
+ OpenDriverControllerHandle = RestExInstance->OpenDriverControllerHandle;
+ HandleOfProtocolInterfacePtr = &RestExInstance->RestExChildHandle;
+ Interface = (VOID **)&RestExInstance->RestExProtocolInterface;
+ }
+ Status = gBS->InstallProtocolInterface (
+ &ControllerHandle,
+ gRequiredProtocol [Index].DiscoveredProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ ProtocolDiscoverIdPtr
+ );
+ if (EFI_ERROR (Status)) {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ //
+ // Create service binding child and open it BY_DRIVER.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->ImageHandle,
+ gRequiredProtocol [Index].RequiredServiceBindingProtocolGuid,
+ HandleOfProtocolInterfacePtr
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ *HandleOfProtocolInterfacePtr,
+ gRequiredProtocol [Index].RequiredProtocolGuid,
+ Interface,
+ OpenDriverAgentHandle,
+ OpenDriverControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (!EFI_ERROR (Status)) {
+ if (EfiRedfishDiscoverProtocolHandle == NULL &&
+ (gRequiredProtocol [Index].ProtocolType == ProtocolTypeRestEx) &&
+ !IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)
+ ) {
+ // Install the fisrt Redfish Discover Protocol when EFI REST EX protcol is discovered.
+ // This ensures EFI REST EX is ready while EFI_REDFISH_DISCOVER_PROTOCOL consumer acquires
+ // Redfish serivce over network interface.
+
+ Status = gBS->InstallProtocolInterface (
+ &EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mRedfishDiscover
+ );
+ } else if (EfiRedfishDiscoverProtocolHandle != NULL && NewNetworkInterfaceInstalled) {
+ Status = gBS->ReinstallProtocolInterface (
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover,
+ (VOID *)&mRedfishDiscover
+ );
+ NewNetworkInterfaceInstalled = FALSE;
+ }
+ }
+ return Status;
+ } else {
+ Index ++;
+ if (Index == (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL))) {
+ break;
+ }
+ continue;
+ }
+ } while (Index < (sizeof(gRequiredProtocol) / sizeof(REDFISH_DISCOVER_REQUIRED_PROTOCOL)));
+ return EFI_UNSUPPORTED;
+}
+/**
+ Close the protocol opened for Redfish discovery. This function also destories
+ the network services.
+
+ @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] ThisRequiredProtocol Pointer to the instance of REDFISH_DISCOVER_REQUIRED_PROTOCOL.
+ @param[in] DriverAgentHandle Driver agent handle which used to open protocol earlier.
+ @param[in] DriverControllerHandle Driver controller handle which used to open protocol earlier.
+
+ @retval EFI_SUCCESS Prorocol is closed successfully.
+ @retval Others Prorocol is closed unsuccessfully.
+
+**/
+EFI_STATUS
+CloseProtocolService (
+ IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol,
+ IN EFI_HANDLE ControllerHandle,
+ IN REDFISH_DISCOVER_REQUIRED_PROTOCOL *ThisRequiredProtocol,
+ IN EFI_HANDLE DriverAgentHandle,
+ IN EFI_HANDLE DriverControllerHandle
+)
+{
+ EFI_STATUS Status;
+
+ Status = gBS->CloseProtocol (
+ ControllerHandle,
+ ThisRequiredProtocol->RequiredProtocolGuid,
+ DriverAgentHandle,
+ DriverControllerHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ NetLibDestroyServiceChild(
+ ControllerHandle,
+ ThisBindingProtocol->ImageHandle,
+ ThisRequiredProtocol->RequiredServiceBindingProtocolGuid,
+ ControllerHandle
+ );
+ }
+ return Status;
+}
+/**
+ Stop the services on network interface.
+
+ @param[in] ThisBindingProtocol A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @retval EFI_SUCCESS One of required protocol is found.
+ @retval Others Faile to stop the services on network interface.
+**/
+EFI_STATUS
+StopServiceOnNetworkInterface (
+ IN EFI_DRIVER_BINDING_PROTOCOL *ThisBindingProtocol,
+ IN EFI_HANDLE ControllerHandle
+ )
+{
+ UINT32 Index;
+ EFI_STATUS Status;
+ VOID *Interface;
+ EFI_TPL OldTpl;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+ EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *RestExInstance;
+
+ for (Index = 0; Index < (sizeof (gRequiredProtocol) / sizeof (REDFISH_DISCOVER_REQUIRED_PROTOCOL)); Index ++) {
+ Status = gBS->HandleProtocol (
+ ControllerHandle,
+ gRequiredProtocol [Index].RequiredProtocolGuid,
+ (VOID **)&Interface
+ );
+ if (!EFI_ERROR (Status)) {
+ if (gRequiredProtocol [Index].ProtocolType != ProtocolTypeRestEx) {
+ if (IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ return EFI_NOT_FOUND;
+ }
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ while (TRUE) {
+ if (ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle == ControllerHandle) {
+
+ Status = CloseProtocolService ( // Close protocol and destroy service.
+ ThisBindingProtocol,
+ ControllerHandle,
+ &gRequiredProtocol [Index],
+ ThisNetworkInterface->OpenDriverAgentHandle,
+ ThisNetworkInterface->OpenDriverControllerHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = DestroyRedfishNetwrokInterface (ThisNetworkInterface);
+ }
+ gBS->RestoreTPL (OldTpl);
+ // Reinstall Redfish Discover protocol to notify network
+ // interface change.
+
+ Status = gBS->ReinstallProtocolInterface (
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover,
+ (VOID *)&mRedfishDiscover
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG((DEBUG_ERROR, "%a: Reinstall gEfiRedfishDiscoverProtocolGuid fail.", __FUNCTION__));
+ }
+ return Status;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry)) {
+ break;
+ }
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverNetworkInterface, &ThisNetworkInterface->Entry);
+ };
+ gBS->RestoreTPL (OldTpl);
+ } else {
+ if (IsListEmpty (&mEfiRedfishDiscoverRestExInstance)) {
+ return EFI_NOT_FOUND;
+ }
+ OldTpl = gBS->RaiseTPL (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL);
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverRestExInstance);
+ while (TRUE) {
+ if (RestExInstance->RestExChildHandle == ControllerHandle) {
+ Status = CloseProtocolService ( // Close REST_EX protocol.
+ ThisBindingProtocol,
+ ControllerHandle,
+ &gRequiredProtocol [Index],
+ RestExInstance->OpenDriverAgentHandle,
+ RestExInstance->OpenDriverControllerHandle
+ );
+ RemoveEntryList (&RestExInstance->Entry);
+ FreePool ((VOID *)RestExInstance);
+ mNumRestExInstance --;
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+ if (IsNodeAtEnd (&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry)) {
+ break;
+ }
+ RestExInstance = (EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL *)GetNextNode(&mEfiRedfishDiscoverRestExInstance, &RestExInstance->Entry);
+ };
+ gBS->RestoreTPL (OldTpl);
+ }
+ }
+ }
+ return EFI_NOT_FOUND;
+}
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ return TestForRequiredProtocols (This, ControllerHandle);
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ return BuildupNetworkInterface (This, ControllerHandle);
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ return StopServiceOnNetworkInterface (This, ControllerHandle);
+}
+
+EFI_DRIVER_BINDING_PROTOCOL gRedfishDiscoverDriverBinding = {
+ RedfishDiscoverDriverBindingSupported,
+ RedfishDiscoverDriverBindingStart,
+ RedfishDiscoverDriverBindingStop,
+ REDFISH_DISCOVER_VERSION,
+ NULL,
+ NULL
+};
+
+/**
+ This is the declaration of an EFI image entry point.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+ InitializeListHead (&mRedfishDiscoverList);
+ InitializeListHead (&mRedfishInstanceList);
+ InitializeListHead (&mEfiRedfishDiscoverNetworkInterface);
+ InitializeListHead (&mEfiRedfishDiscoverRestExInstance);
+ //
+ // Install binding protoocl to obtain UDP and REST EX protocol.
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gRedfishDiscoverDriverBinding,
+ ImageHandle,
+ &gRedfishDiscoverComponentName,
+ &gRedfishDiscoverComponentName2
+ );
+ return Status;
+}
+
+/**
+ This is the unload handle for Redfish discover module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishDiscoverUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *ThisNetworkInterface;
+
+ Status = EFI_SUCCESS;
+ // Destroy all network interfaces found by EFI Redfish Discover driver and
+ // stop services created for Redfish Discover.
+
+ while (!IsListEmpty (&mEfiRedfishDiscoverNetworkInterface)) {
+ ThisNetworkInterface = (EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *)GetFirstNode (&mEfiRedfishDiscoverNetworkInterface);
+ StopServiceOnNetworkInterface (&gRedfishDiscoverDriverBinding, ThisNetworkInterface->NetworkInterfaceProtocolInfo.ProtocolControllerHandle);
+ };
+ // Disconnect EFI Redfish discover driver controller to notify the
+ // clinet which uses .EFI Redfish discover protocol.
+
+ if (EfiRedfishDiscoverProtocolHandle != NULL) {
+ //
+ // Notify user EFI_REDFISH_DISCOVER_PROTOCOL is unloaded.
+ //
+ gBS->DisconnectController (EfiRedfishDiscoverProtocolHandle, NULL, NULL);
+ Status = gBS->UninstallProtocolInterface(
+ EfiRedfishDiscoverProtocolHandle,
+ &gEfiRedfishDiscoverProtocolGuid,
+ (VOID *)&mRedfishDiscover
+ );
+ }
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
new file mode 100644
index 00000000000..1f303fcba70
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverDxe.inf
@@ -0,0 +1,55 @@
+## @file
+# Implementation of EFI_REDFISH_DISCOVER_PROTOCOL interfaces.
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishDiscoverDxe
+ FILE_GUID = 28A76FE5-43D7-48A3-9714-C1B7BDD6DFB6
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishDiscoverEntryPoint
+ UNLOAD_IMAGE = RedfishDiscoverUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ ComponentName.c
+ RedfishDiscoverDxe.c
+ RedfishSmbiosHostInterface.c
+ RedfishDiscoverInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ RestExLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## Consuming
+ gEfiRestExProtocolGuid ## Consuming
+ gEfiTcp4ServiceBindingProtocolGuid ## Consuming
+ gEfiTcp4ProtocolGuid ## Consuming
+ gEfiTcp6ServiceBindingProtocolGuid ## Consuming
+ gEfiTcp6ProtocolGuid ## Consuming
+ gEfiRedfishDiscoverProtocolGuid ## Prodcuing
+ gEfiSmbiosProtocolGuid ## Consuming
+ gEfiDriverBindingProtocolGuid ## Consuming
+
+[Pcd]
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
new file mode 100644
index 00000000000..5407ee879d4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishDiscoverInternal.h
@@ -0,0 +1,234 @@
+/** @file
+ This file defines the EFI Redfish Discover Protocol interface.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_DISCOVER_INTERNAL_H_
+#define EFI_REDFISH_DISCOVER_INTERNAL_H_
+
+#include <Uefi.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RedfishDiscover.h>
+#include <Protocol/Smbios.h>
+#include <Protocol/Tcp4.h>
+#include <Protocol/Tcp6.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RestExLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+#include <IndustryStandard/RedfishHostInterface.h>
+
+#define REDFISH_DISCOVER_VERSION 0x00010000
+#define EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_TPL TPL_NOTIFY
+
+//
+//GUID definitions
+//
+
+#define EFI_REDFISH_DISCOVER_TCP4_INSTANCE_GUID \
+ { \
+ 0xfbab97a4, 0x4c6a, 0xf8e8, { 0xf2, 0x25, 0x42, 0x8a, 0x80, 0x3f, 0xb6, 0xaa } \
+ }
+
+#define EFI_REDFISH_DISCOVER_TCP6_INSTANCE_GUID \
+ { \
+ 0xbe513b6d, 0x41c1, 0x96Ed, { 0x8d, 0xaf, 0x3e, 0x89, 0xc5, 0xf5, 0x02, 0x25 } \
+ }
+
+#define EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_GUID \
+ { \
+ 0xc44a6076, 0xd42a, 0x4d54, { 0x85, 0x6d, 0x98, 0x8a, 0x85, 0x8f, 0xa1, 0x11 } \
+ }
+
+extern EFI_COMPONENT_NAME_PROTOCOL gRedfishDiscoverComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishDiscoverComponentName2;
+extern EFI_UNICODE_STRING_TABLE *gRedfishDiscoverControllerNameTable;
+
+//
+// Enumeration of network protocols
+// required for the Redfish service discovery.
+//
+typedef enum {
+ ProtocolTypeTcp4 = 0, ///< Network protocol TCPv4.
+ ProtocolTypeTcp6, ///< Network protocol TCCv6.
+ ProtocolTypeRestEx, ///< REST EX over network protocol.
+ MaxProtocolType
+} NETWORK_INTERFACE_PROTOCOL_TYPE;
+
+//
+// Network protocol information installed on
+// the network interface.
+//
+typedef struct {
+ EFI_GUID ProtocolGuid; ///< Network protocol GUID.
+ EFI_GUID ProtocolServiceGuid; ///< Network protocol service GUID.
+ UINT32 ProtocolDiscoverId; ///< The identifier installed on network protocol handle.
+ EFI_HANDLE ProtocolControllerHandle; ///< The controller handle on network protocol.
+ VOID *NetworkProtocolInterface; ///< The protocol interface of network protocol.
+} REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL;
+
+//
+// Internal structure used to maintain network
+// interface properties.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE OpenDriverAgentHandle; ///< The agent to open network protocol.
+ EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle to open network protocol.
+ UINTN HwAddressSize; ///< The size of network interface hardware address.
+ EFI_MAC_ADDRESS MacAddress; ///< MAC address of network interface.
+ CHAR16 *StrMacAddr; ///< String to MAC address of network interface.
+ BOOLEAN GotSubnetInfo; ///< Indicates sub net information is retrieved.
+ EFI_IP_ADDRESS SubnetAddr; ///< Subnet ID.
+ EFI_IP_ADDRESS SubnetMask; ///< Subnet mask (IPv4 only)
+ UINT8 SubnetPrefixLength; ///< Subnet prefix.
+ UINT16 VlanId; ///< VLAN ID
+ UINT32 SubnetAddrInfoIPv6Number; ///< IPv6 address info number.
+ EFI_IP6_ADDRESS_INFO *SubnetAddrInfoIPv6; ///< IPv6 address info.
+ //
+ // Network interface protocol and REST EX infor.
+ //
+ UINT32 NetworkProtocolType; ///< Network protocol type. Refer to
+ ///< NETWORK_INTERFACE_PROTOCOL_TYPE.
+ REDFISH_DISCOVER_NETWORK_INTERFACE_PROTOCOL NetworkInterfaceProtocolInfo; ///< Network interface protocol information.
+ EFI_HANDLE RestExHandle; ///< REST EX handle associated with this network interface.
+} EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL;
+
+//
+// Internal structure used to maintain REST EX properties.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE OpenDriverAgentHandle; ///< The agent to open network protocol.
+ EFI_HANDLE OpenDriverControllerHandle; ///< The controller handle to open network protocol.
+ EFI_HANDLE RestExChildHandle; ///< The child handle created throught REST EX Service Protocol.
+ EFI_HANDLE RestExControllerHandle; ///< The controller handle which provide REST EX protocol.
+ EFI_REST_EX_PROTOCOL *RestExProtocolInterface; ///< Pointer to EFI_REST_EX_PROTOCOL.
+ UINT32 RestExId; ///< The identifier installed on REST EX controller handle.
+} EFI_REDFISH_DISCOVER_REST_EX_INSTANCE_INTERNAL;
+
+/**
+ This function to get subnet information.
+
+ @param[in] ImageHandle EFI handle with this image.
+ @param[in] Instance Instance of Network interface.
+ @retval EFI_STATUS Get subnet information successfully.
+ @retval Otherwise Fail to get subnet information.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_REDFISH_DISCOVER_GET_SUBNET_INFO)(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *Instance
+);
+
+//
+// The require network protocol matrix.
+//
+typedef struct {
+ UINT32 ProtocolType; ///< Network protocol type,
+ ///< Refer to NETWORK_INTERFACE_PROTOCOL_TYPE.
+ CHAR16 *ProtocolName; ///< Protocol name.
+ EFI_GUID *RequiredProtocolGuid; ///< Network protocol interface GUID.
+ EFI_GUID *RequiredServiceBindingProtocolGuid; ///< Network protocol service GUID.
+ EFI_GUID *DiscoveredProtocolGuid; ///< Protocol interface GUID use to install identifier.
+ EFI_REDFISH_DISCOVER_GET_SUBNET_INFO GetSubnetInfo; ///< Function of getting subnet information.
+} REDFISH_DISCOVER_REQUIRED_PROTOCOL;
+
+//
+// Link list of Redfish discover instance.
+//
+typedef struct {
+ LIST_ENTRY NextInstance; ///< Next list.
+ EFI_REDFISH_DISCOVERED_INSTANCE *Instance; ///< Pointer to EFI_REDFISH_DISCOVERED_INSTANCE.
+} EFI_REDFISH_DISCOVERED_INTERNAL_LIST;
+
+//
+// Internal structure of Redfish discover instance.
+//
+typedef struct {
+ LIST_ENTRY Entry; ///< Link list entry.
+ EFI_HANDLE Owner; ///< The owner owns this Redfish service discovery.
+ ///< It's the EFI image handle of driver uses
+ ///< EFI Redfish Discover Protocol.
+ EFI_REDFISH_DISCOVER_FLAG DiscoverFlags; ///< EFI_REDFISH_DISCOVER_FLAG
+ EFI_REDFISH_DISCOVERED_TOKEN *DiscoverToken; ///< Token used to signal when Redfish service is discovered.
+ EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL *NetworkInterface; ///< EFI_REDFISH_DISCOVER_NETWORK_INTERFACE_INTERNAL
+ ///< instance used to discover Redfish service.
+ //
+ // Below for Host insterface discovery.
+ //
+ BOOLEAN HostIntfValidation; ///< Indicates whether to validate Redfish Host interface.
+ EFI_IP_ADDRESS TargetIpAddress; ///< Target IP address reported in Redfish Host interface.
+} EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE;
+
+/**
+ The function adds a new foudn Redfish service to internal list and
+ notify clinet.
+
+ It simply frees the packet.
+
+ @param[in] Instance EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE.
+ @param[in] RedfishVersion Redfish version.
+ @param[in] RedfishLocation Redfish location.
+ @param[in] Uuid Service UUID string.
+ @param[in] Os OS string.
+ @param[in] OsVer OS version string.
+ @param[in] Product Product string.
+ @param[in] ProductVer Product verison string.
+ @param[in] UseHttps Redfish service requires secured connection.
+ @retval EFI_SUCCESS Redfish service is added to list successfully.
+
+**/
+EFI_STATUS
+AddAndSignalNewRedfishService (
+ IN EFI_REDFISH_DISCOVERED_INTERNAL_INSTANCE *Instance,
+ IN UINTN *RedfishVersion OPTIONAL,
+ IN CHAR8 *RedfishLocation OPTIONAL,
+ IN CHAR8 *Uuid OPTIONAL,
+ IN CHAR8 *Os OPTIONAL,
+ IN CHAR8 *OsVer OPTIONAL,
+ IN CHAR8 *Product OPTIONAL,
+ IN CHAR8 *ProductVer OPTIONAL,
+ IN BOOLEAN UseHttps
+ );
+
+/**
+ The function gets information reported in Redfish Host Interface.
+
+ It simply frees the packet.
+
+ @param[in] Smbios SMBIOS protocol.
+ @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA.
+ @param[out] ProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA.
+
+ @retval EFI_SUCCESS Get host interface succesfully.
+ @retval Otherwise Fail to tet host interface.
+
+**/
+EFI_STATUS
+RedfishGetHostInterfaceProtocolData (
+ IN EFI_SMBIOS_PROTOCOL *Smbios,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor,
+ OUT REDFISH_OVER_IP_PROTOCOL_DATA **ProtocolData
+ );
+
+extern EFI_GUID gRedfishDiscoverTcp4Instance;
+extern EFI_GUID gRedfishDiscoverTcp6Instance;
+extern EFI_GUID gRedfishDiscoverRestEXInstance;
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c
new file mode 100644
index 00000000000..78d1447a086
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishDiscoverDxe/RedfishSmbiosHostInterface.c
@@ -0,0 +1,118 @@
+/** @file
+ RedfishSmbiosHostInterface.c
+
+ Discover Redfish SMBIOS Host Interface.
+
+ (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RedfishDiscoverInternal.h"
+
+SMBIOS_TABLE_TYPE42 *mType42Record;
+
+/**
+ The function gets information reported in Redfish Host Interface.
+
+ It simply frees the packet.
+
+ @param[in] Smbios SMBIOS protocol.
+ @param[out] DeviceDescriptor Pointer to REDFISH_INTERFACE_DATA.
+ @param[out] ProtocolData Pointer to REDFISH_OVER_IP_PROTOCOL_DATA.
+
+ @retval EFI_SUCCESS Get host interface succesfully.
+ @retval Otherwise Fail to tet host interface.
+
+**/
+EFI_STATUS
+RedfishGetHostInterfaceProtocolData (
+ IN EFI_SMBIOS_PROTOCOL *Smbios,
+ OUT REDFISH_INTERFACE_DATA **DeviceDescriptor,
+ OUT REDFISH_OVER_IP_PROTOCOL_DATA **ProtocolData
+ )
+{
+ EFI_STATUS Status;
+ EFI_SMBIOS_HANDLE SmbiosHandle;
+ EFI_SMBIOS_TABLE_HEADER *Record;
+ UINT16 Offset;
+ UINT8 *RecordTmp;
+ UINT8 ProtocolLength;
+ UINT8 SpecificDataLen;
+
+ if ((Smbios == NULL) || (ProtocolData == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
+ while (!EFI_ERROR (Status) && SmbiosHandle != SMBIOS_HANDLE_PI_RESERVED) {
+ if (Record->Type == SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE) {
+ //
+ // Check Interface Type, should be Network Host Interface = 40h
+ //
+ mType42Record = (SMBIOS_TABLE_TYPE42 *) Record;
+ if (mType42Record->InterfaceType == MCHostInterfaceTypeNetworkHostInterface) {
+ ASSERT (Record->Length >= 9);
+ Offset = 5;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Get interface specific data length.
+ //
+ SpecificDataLen = *RecordTmp;
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+
+ //
+ // Check Device Type, only PCI/PCIe Network Interface v2 is supported now.
+ //
+ if (*RecordTmp == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ ASSERT (SpecificDataLen == sizeof (PCI_OR_PCIE_INTERFACE_DEVICE_DESCRIPTOR_V2) + 1);
+ *DeviceDescriptor = (REDFISH_INTERFACE_DATA *)RecordTmp;
+ Offset = Offset + SpecificDataLen;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Check Protocol count. if > 1, only use the first protocol.
+ //
+ ASSERT (*RecordTmp == 1);
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+ //
+ // Check protocol identifier.
+ //
+ if (*RecordTmp == MCHostInterfaceProtocolTypeRedfishOverIP) {
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+ ProtocolLength = *RecordTmp;
+
+ Offset += 1;
+ RecordTmp = (UINT8 *) Record + Offset;
+
+ //
+ // This SMBIOS record is invalid, if the length of protocol specific data for
+ // Redfish Over IP protocol is wrong.
+ //
+ if ((*(RecordTmp + 90) + sizeof (REDFISH_OVER_IP_PROTOCOL_DATA) - 1) != ProtocolLength) {
+ return EFI_SECURITY_VIOLATION;
+ }
+
+ Offset += ProtocolLength;
+ //
+ // This SMBIOS record is invalid, if the length is smaller than the offset.
+ //
+ if (Offset > mType42Record->Hdr.Length) {
+ return EFI_SECURITY_VIOLATION;
+ }
+ *ProtocolData = (REDFISH_OVER_IP_PROTOCOL_DATA *)RecordTmp;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ }
+ Status = Smbios->GetNext (Smbios, &SmbiosHandle, NULL, &Record, NULL);
+ }
+
+ *ProtocolData = NULL;
+ return EFI_NOT_FOUND;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c
new file mode 100644
index 00000000000..d4ba24e45ad
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.c
@@ -0,0 +1,243 @@
+/** @file
+ RedfishHostInterfaceDxe builds up SMBIOS Type 42h host interface
+ record for Redfish service host interface using EFI MBIOS Protocol.
+ RedfishHostInterfacePlatformLib is the platform-level library which
+ provides the content of Redfish host interface type 42h record.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RedfishHostInterfaceLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+/**
+ Create SMBIOS type 42 record for Redfish host interface.
+
+ @retval EFI_SUCESS SMBIOS type 42 record is created.
+ @retval Others Fail to create SMBIOS 42 record.
+
+**/
+EFI_STATUS
+RedfishCreateSmbiosTable42 (
+ VOID
+ )
+{
+ REDFISH_INTERFACE_DATA *DeviceDescriptor;
+ UINT8 DeviceDataLength;
+ UINT8 DeviceType;
+ EFI_STATUS Status;
+ MC_HOST_INTERFACE_PROTOCOL_RECORD *ProtocolRecord;
+ VOID *ProtocolRecords;
+ VOID *NewProtocolRecords;
+ UINT8 ProtocolCount;
+ UINT8 CurrentProtocolsDataLength;
+ UINT8 NewProtocolsDataLength;
+ UINT8 ProtocolDataSize;
+ SMBIOS_TABLE_TYPE42 *Type42Record;
+ EFI_SMBIOS_PROTOCOL *Smbios;
+ EFI_SMBIOS_HANDLE MemArrayMappedAddrSmbiosHandle;
+
+ //
+ // Get platform Redfish host interface device type descriptor data.
+ //
+ Status = RedfishPlatformHostInterfaceDeviceDescriptor (&DeviceType, &DeviceDescriptor);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_NOT_FOUND) {
+ DEBUG ((DEBUG_ERROR, "%a: No Redfish host interface descriptor is provided on this platform.", __FUNCTION__));
+ return EFI_NOT_FOUND;
+ }
+ DEBUG((DEBUG_ERROR, "%a: Fail to get device descriptor, %r.", __FUNCTION__, Status));
+ return Status;
+ }
+ if (DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_USB_V2 &&
+ DeviceType != REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2
+ ) {
+ DEBUG ((DEBUG_ERROR, "%a: Only support either protocol type 04h or 05h as Redfish host interface.", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+ if (DeviceType == REDFISH_HOST_INTERFACE_DEVICE_TYPE_PCI_PCIE_V2) {
+ DeviceDataLength = DeviceDescriptor->DeviceDescriptor.PciPcieDeviceV2.Length;
+ } else {
+ DeviceDataLength = DeviceDescriptor->DeviceDescriptor.UsbDeviceV2.Length;
+ }
+ //
+ // Loop to get platform Redfish host interface protocol type data.
+ //
+ ProtocolRecord = NULL;
+ ProtocolRecords = NULL;
+ NewProtocolRecords = NULL;
+ Type42Record = NULL;
+ ProtocolCount = 0;
+ CurrentProtocolsDataLength = 0;
+ NewProtocolsDataLength = 0;
+ while (TRUE) {
+ Status = RedfishPlatformHostInterfaceProtocolData (&ProtocolRecord, ProtocolCount);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ if (EFI_ERROR(Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to get Redfish host interafce protocol type data.", __FUNCTION__));
+ if (ProtocolRecords != NULL) {
+ FreePool (ProtocolRecords);
+ }
+ if (ProtocolRecord != NULL) {
+ FreePool (ProtocolRecord);
+ }
+ return Status;
+ }
+ ProtocolDataSize = sizeof (MC_HOST_INTERFACE_PROTOCOL_RECORD) - sizeof(ProtocolRecord->ProtocolTypeData) + ProtocolRecord->ProtocolTypeDataLen;
+ NewProtocolsDataLength += ProtocolDataSize;
+ if (ProtocolRecords == NULL) {
+ ProtocolRecords = AllocateZeroPool (NewProtocolsDataLength);
+ if (ProtocolRecords == NULL) {
+ FreePool (ProtocolRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem ((VOID *)ProtocolRecords, (VOID *)ProtocolRecord, ProtocolDataSize);
+ NewProtocolRecords = ProtocolRecords;
+ } else {
+ NewProtocolRecords = ReallocatePool(CurrentProtocolsDataLength, NewProtocolsDataLength, (VOID *)ProtocolRecords);
+ if (NewProtocolRecords == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to allocate memory for Redfish host interface protocol data."));
+ FreePool (ProtocolRecords);
+ FreePool (ProtocolRecord);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem (
+ (VOID *)((UINT8 *)NewProtocolRecords + CurrentProtocolsDataLength),
+ (VOID *)ProtocolRecord,
+ ProtocolDataSize
+ );
+ }
+ FreePool (ProtocolRecord);
+ CurrentProtocolsDataLength = NewProtocolsDataLength;
+ ProtocolCount ++;
+ };
+ if (ProtocolCount == 0) {
+ goto ON_EXIT;
+ }
+ //
+ // Construct SMBIOS Type 42h for Redfish host inteface.
+ //
+ // SMBIOS type 42 Record for Redfish Interface
+ // 00h Type BYTE 42 Management Controller Host Interface structure indicator
+ // 01h Length BYTE Varies Length of the structure, a minimum of 09h
+ // 02h Handle WORD Varies
+ // 04h Interface Type BYTE Varies Management Controller Interface Type.
+ // 05h Interface Specific Data Length (n)
+ // 06h Interface Specific data
+ // 06h+n number of protocols defined for the host interface (typically 1)
+ // 07h+n Include a Protocol Record for each protocol supported.
+ //
+ Type42Record = (SMBIOS_TABLE_TYPE42 *) AllocateZeroPool (
+ sizeof (SMBIOS_TABLE_TYPE42) - 4
+ + DeviceDataLength
+ + 1 /// For Protocol Record Count
+ + CurrentProtocolsDataLength
+ + 2 /// Double NULL terminator/
+ );
+ if (Type42Record == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Type42Record->Hdr.Type = EFI_SMBIOS_TYPE_MANAGEMENT_CONTROLLER_HOST_INTERFACE;
+ Type42Record->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE42) - 4
+ + DeviceDataLength
+ + 1
+ + CurrentProtocolsDataLength;
+ Type42Record->Hdr.Handle = 0;
+ Type42Record->InterfaceType = MCHostInterfaceTypeNetworkHostInterface; // Network Host Interface
+
+ //
+ // Fill in InterfaceTypeSpecificDataLength field
+ //
+ Type42Record->InterfaceTypeSpecificDataLength = DeviceDataLength;
+
+ //
+ // Fill in InterfaceTypeSpecificData field
+ //
+ CopyMem (Type42Record->InterfaceTypeSpecificData, DeviceDescriptor, DeviceDataLength);
+ FreePool (DeviceDescriptor);
+ DeviceDescriptor = NULL;
+
+ //
+ // Fill in InterfaceTypeSpecificData Protocol Count field
+ //
+ *(Type42Record->InterfaceTypeSpecificData + DeviceDataLength) = ProtocolCount;
+
+ //
+ // Fill in Redfish Protocol Data
+ //
+ CopyMem (
+ Type42Record->InterfaceTypeSpecificData + DeviceDataLength + 1,
+ NewProtocolRecords,
+ CurrentProtocolsDataLength
+ );
+
+ //
+ // 5. Add Redfish interface data record to SMBIOS table 42
+ //
+ Status = gBS->LocateProtocol (&gEfiSmbiosProtocolGuid, NULL, (VOID**)&Smbios);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ MemArrayMappedAddrSmbiosHandle = SMBIOS_HANDLE_PI_RESERVED;
+ Status = Smbios->Add (
+ Smbios,
+ NULL,
+ &MemArrayMappedAddrSmbiosHandle,
+ (EFI_SMBIOS_TABLE_HEADER*) Type42Record
+ );
+ DEBUG ((DEBUG_INFO, "RedfishPlatformDxe: Smbios->Add() - %r\n", Status));
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ Status = EFI_SUCCESS;
+
+ON_EXIT:
+ if (DeviceDescriptor != NULL) {
+ FreePool (DeviceDescriptor);
+ }
+ if (NewProtocolRecords != NULL) {
+ FreePool (NewProtocolRecords);
+ }
+ if (Type42Record != NULL) {
+ FreePool (Type42Record);
+ }
+ return Status;
+}
+
+/**
+ Main entry for this driver.
+
+ @param ImageHandle Image handle this driver.
+ @param SystemTable Pointer to SystemTable.
+
+ @retval EFI_SUCESS This function always complete successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishHostInterfaceDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // Create SMBIOS type 42 record.
+ //
+ return RedfishCreateSmbiosTable42 ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
new file mode 100644
index 00000000000..a0d12e807b2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishHostInterfaceDxe/RedfishHostInterfaceDxe.inf
@@ -0,0 +1,50 @@
+## @file
+# RedfishHostInterfaceDxe builds up SMBIOS Type 42h host interface
+# record for Redfish service host interface using SMBIOS Protocol.
+# RedfishHostInterfacePlatformLib is the platform-level library which
+# provides the content of Redfish host interface type 42h record.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001000b
+ BASE_NAME = RedfishHostInterfaceDxe
+ FILE_GUID = 592626DA-4A1E-8B39-28BA-FEAD92C4A0A4
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishHostInterfaceDxeEntryPoint
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64 RISCV64
+#
+
+[Sources]
+ RedfishHostInterfaceDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ PrintLib
+ RedfishPlatformHostInterfaceLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiSmbiosProtocolGuid ## TO_START
+
+[Depex]
+ gEfiSmbiosProtocolGuid
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc
new file mode 100644
index 00000000000..0bcc32c32f0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishLibs.dsc.inc
@@ -0,0 +1,21 @@
+## @file
+# Redfish DSC include file for [LibraryClasses*] section of all Architectures.
+#
+# This file can be included to the [LibraryClasses*] section(s) of a platform DSC file
+# by using "!include RedfishPkg/RedfisLibs.dsc.inc" to specify the library instances
+# of EDKII network library classes.
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+!if $(REDFISH_ENABLE) == TRUE
+ RestExLib|RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
+ Ucs2Utf8Lib|RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
+ BaseSortLib|MdeModulePkg/Library/BaseSortLib/BaseSortLib.inf
+ RedfishCrtLib|RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
+ JsonLib|RedfishPkg/Library/JsonLib/JsonLib.inf
+ RedfishLib|RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
+!endif
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml
new file mode 100644
index 00000000000..bd3877a08f5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.ci.yaml
@@ -0,0 +1,105 @@
+## @file
+# CI configuration for NetworkPkg
+#
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ## Below are files incorporated with open source which are
+ ## not edk2 coding standard compliant.
+ ##
+ ## EDK2 CRT library which is not edk2 coding
+ ## standard compliant.
+ ## C runtime library for RedfishPkg modules
+ "PrivateInclude/Crt/sys",
+ "PrivateInclude/Crt/assert.h",
+ "PrivateInclude/Crt/errno.h",
+ "PrivateInclude/Crt/limits.h",
+ "PrivateInclude/Crt/math.h",
+ "PrivateInclude/Crt/stdarg.h",
+ "PrivateInclude/Crt/stddef.h",
+ "PrivateInclude/Crt/stdio.h",
+ "PrivateInclude/Crt/stdlib.h",
+ "PrivateInclude/Crt/string.h",
+ "PrivateInclude/Crt/time.h",
+ "PrivateInclude/Library/RedfishCrtLib.h",
+ "PrivateLibrary/RedfishCrtLib/RedfishCrtLib.c",
+ ##
+ ## For jansson library open source
+ ## load.c is overrided from open source.
+ "Library/JsonLib/load.c",
+ "Library/JsonLib/jansson_config.h",
+ "Library/JsonLib/jansson_private_config.h",
+ ##
+ ## For libredfish open source
+ ## The files under edk2libredfish are cloned
+ ## from DMTF open source
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redfish.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redfishPayload.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redfishService.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/include/redpath.h",
+ "PrivateLibrary/RedfishLib/edk2libredfish/src/payload.c",
+ "PrivateLibrary/RedfishLib/edk2libredfish/src/redpath.c",
+ "PrivateLibrary/RedfishLib/edk2libredfish/src/service.c"
+ ]
+ },
+ "CompilerPlugin": {
+ "DscPath": "RedfishPkg.dsc"
+ },
+ "CharEncodingCheck": {
+ "IgnoreFiles": []
+ },
+ "DependencyCheck": {
+ "AcceptableDependencies": [
+ "MdePkg/MdePkg.dec",
+ "MdeModulePkg/MdeModulePkg.dec",
+ "NetworkPkg/NetworkPkg.dec",
+ "RedfishPkg/RedfishPkg.dec"
+ ],
+ # For host based unit tests
+ "AcceptableDependencies-HOST_APPLICATION":[],
+ # For UEFI shell based apps
+ "AcceptableDependencies-UEFI_APPLICATION":[
+ "ShellPkg/ShellPkg.dec"
+ ],
+ "IgnoreInf": []
+ },
+ "DscCompleteCheck": {
+ "DscPath": "RedfishPkg.dsc",
+ "IgnoreInf": []
+ },
+ "GuidCheck": {
+ "IgnoreGuidName": [],
+ "IgnoreGuidValue": [],
+ "IgnoreFoldersAndFiles": []
+ },
+ "LibraryClassCheck": {
+ "IgnoreHeaderFile": []
+ },
+
+ ## options defined ci/Plugin/SpellCheck
+ "SpellCheck": {
+ "AuditOnly": True, # Fails test but run in AuditOnly mode to collect log
+ "IgnoreFiles": [], # use gitignore syntax to ignore errors in matching files
+ "ExtendWords": [], # words to extend to the dictionary for this package
+ "IgnoreStandardPaths": [], # Standard Plugin defined paths that should be ignore
+ "AdditionalIncludePaths": [] # Additional paths to spell check (wildcards supported)
+ },
+
+ "Defines": {
+ "BLD_*_CONTINUOUS_INTEGRATION": "TRUE",
+ "BLD_*_REDFISH_ENABLE": "TRUE"
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec
new file mode 100644
index 00000000000..972ea1b9017
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dec
@@ -0,0 +1,100 @@
+## @file
+# Redfish Package
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x0001001b
+ PACKAGE_NAME = RedfishPkg
+ PACKAGE_GUID = c432b76e-5232-11e7-9010-005056c00008
+ PACKAGE_VERSION = 1.0
+
+[Includes]
+ Include
+
+[Includes.Common.Private]
+ PrivateInclude # Private header files for C RTL.
+ PrivateInclude/Crt # Private header files for C RTL.
+ Library/JsonLib # Private header files for jansson
+ # configuration files.
+ # - jansson_config.h
+ # - jansson_private_config.h
+ # jansson.h refers to above two configuration
+ # files for building platform jansson library.
+ Library/JsonLib/jansson/src # For referring to jannson.h
+
+[LibraryClasses]
+ ## @libraryclass Platform Redfish Host Interface Library
+ # Platform implementation-specific Redfish Host Interface.
+ RedfishPlatformHostInterfaceLib|Include/Library/RedfishHostInterfaceLib.h
+
+ ## @libraryclass This library provides UCS2 to UTF8 manipulation
+ # functions.
+ #
+ Ucs2Utf8Lib|Include/Library/BaseUcs2Utf8Lib.h
+
+ ## @libraryclass Platform Redfish Credential Library
+ # Platform implementation-specific Redfish Credential Interface.
+ RedfishPlatformCredentialLib|Include/Library/RedfishCredentialLib.h
+
+ ## @libraryclass The helper routines to access REST EX service.
+ # This library is only intended to be used by UEFI network stack modules.
+ RestExLib|Include/Library/RestExLib.h
+
+ ## @libraryclass Provides the library functions based on third party
+ # jansson library to manipulate JSON data structure.
+ #
+ JsonLib|Include/Library/JsonLib.h
+
+ ## @libraryclass Provides the library functions to encode/decode
+ # Redfish packet.
+ #
+ RedfishContentCodingLib|Include/Library/RedfishContentCodingLib.h
+
+[LibraryClasses.Common.Private]
+ ## @libraryclass Provides the private C runtime library functions.
+ # CRT library is currently used by edk2 JsonLib (open source
+ # jansson project) and edk2 RedfishLib (libredfish open source
+ # project).
+ RedfishCrtLib|PrivateInclude/Library/RedfishCrtLib.h
+
+ ## @libraryclass Redfish Helper Library
+ # Library provides Redfish helper functions.
+ RedfishLib|PrivateInclude/Library/RedfishLib.h
+
+[Protocols]
+ ## Include/Protocol/EdkIIRedfishCredential.h
+ gEdkIIRedfishCredentialProtocolGuid = { 0x8804377, 0xaf7a, 0x4496, { 0x8a, 0x7b, 0x17, 0x59, 0x0, 0xe9, 0xab, 0x46 } }
+
+ ## Include/Protocol/Edk2RedfishConfigHandler.h
+ gEdkIIRedfishConfigHandlerProtocolGuid = { 0xbc0fe6bb, 0x2cc9, 0x463e, { 0x90, 0x82, 0xfa, 0x11, 0x76, 0xfc, 0x67, 0xde } }
+
+[Guids]
+ gEfiRedfishPkgTokenSpaceGuid = { 0x4fdbccb7, 0xe829, 0x4b4c, { 0x88, 0x87, 0xb2, 0x3f, 0xd7, 0x25, 0x4b, 0x85 }}
+
+[PcdsFixedAtBuild, PcdsPatchableInModule]
+ #
+ # This PCD is the UEFI device path which is used as the Redfish host interface.
+ #
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceDevicePath|{0x0}|REST_EX_SERVICE_DEVICE_PATH_DATA|0x00001000 {
+ <HeaderFiles>
+ Pcd/RestExServiceDevicePath.h
+ <Packages>
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+ }
+ #
+ # This PCD indicates the EFI REST EX access mode to Redfish service.
+ # Default is set to out of band access.
+ #
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand|FALSE|BOOLEAN|0x00001001
+ #
+ # This PCD indicates the access mode EFI Discover protocol uses to look for the proper EFI REST EX
+ # protocol instance.
+ #
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDiscoverAccessModeInBand|FALSE|BOOLEAN|0x00001002
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc
new file mode 100644
index 00000000000..b0d36e7f748
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishPkg.dsc
@@ -0,0 +1,62 @@
+## @file
+# Redfish Package
+#
+# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2021 Hewlett-Packard Enterprise Development LP.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = RedfishPkg
+ PLATFORM_GUID = c4352870-5232-11e7-9522-005056c00008
+ PLATFORM_VERSION = 1.0
+ DSC_SPECIFICATION = 0x0001001c
+ OUTPUT_DIRECTORY = Build/RedfishPkg
+ SUPPORTED_ARCHITECTURES = IA32|X64|ARM|AARCH64|RISCV64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include MdePkg/MdeLibs.dsc.inc
+
+[LibraryClasses]
+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ RedfishPlatformHostInterfaceLib|RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
+ HttpLib|NetworkPkg/Library/DxeHttpLib/DxeHttpLib.inf
+ HttpIoLib|NetworkPkg/Library/DxeHttpIoLib/DxeHttpIoLib.inf
+ NetLib|NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+ DpcLib|NetworkPkg/Library/DxeDpcLib/DxeDpcLib.inf
+ RedfishPlatformCredentialLib|RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
+ RedfishContentCodingLib|RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
+
+[LibraryClasses.ARM, LibraryClasses.AARCH64]
+ #
+ # This library provides the instrinsic functions generated by a given compiler.
+ #
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+ ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
+
+[Components]
+ RedfishPkg/Library/PlatformHostInterfaceLibNull/PlatformHostInterfaceLibNull.inf
+ RedfishPkg/Library/PlatformCredentialLibNull/PlatformCredentialLibNull.inf
+ RedfishPkg/Library/RedfishContentCodingLibNull/RedfishContentCodingLibNull.inf
+ RedfishPkg/Library/DxeRestExLib/DxeRestExLib.inf
+ RedfishPkg/Library/BaseUcs2Utf8Lib/BaseUcs2Utf8Lib.inf
+ RedfishPkg/PrivateLibrary/RedfishCrtLib/RedfishCrtLib.inf
+ RedfishPkg/Library/JsonLib/JsonLib.inf
+ RedfishPkg/PrivateLibrary/RedfishLib/RedfishLib.inf
+
+ !include RedfishPkg/Redfish.dsc.inc
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c
new file mode 100644
index 00000000000..1147d0701ea
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/ComponentName.c
@@ -0,0 +1,222 @@
+/** @file
+ Implementation of EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL
+ protocol.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+
+#include <Library/UefiLib.h>
+
+#include <Protocol/ComponentName.h>
+#include <Protocol/ComponentName2.h>
+
+//
+// EFI Component Name Functions
+//
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+///
+/// Component Name Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName = {
+ RedfishRestExComponentNameGetDriverName,
+ RedfishRestExComponentNameGetControllerName,
+ "eng"
+};
+
+///
+/// Component Name 2 Protocol instance
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2 = {
+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) RedfishRestExComponentNameGetDriverName,
+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) RedfishRestExComponentNameGetControllerName,
+ "en"
+};
+
+///
+/// Table of driver names
+///
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_UNICODE_STRING_TABLE mRedfishRestExDriverNameTable[] = {
+ { "eng;en", (CHAR16 *)L"Redfish RestEx Network Service Driver" },
+ { NULL, NULL }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable = NULL;
+
+/**
+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER DriverName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+{
+ return LookupUnicodeString2 (
+ Language,
+ This->SupportedLanguages,
+ mRedfishRestExDriverNameTable,
+ DriverName,
+ (BOOLEAN)(This == &gRedfishRestExComponentName)
+ );
+}
+
+/**
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ @param[in] ChildHandle The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ @param[in] Language A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language, from the point of view of the driver specified
+ by This.
+
+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ @retval EFI_INVALID_PARAMETER Language is NULL.
+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.
+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ @retval EFI_UNSUPPORTED The driver specified by This does not support the
+ language specified by Language.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
new file mode 100644
index 00000000000..1ecf444c584
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.c
@@ -0,0 +1,831 @@
+/** @file
+ The driver binding and service binding protocol for Redfish RestExDxe driver.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include "RedfishRestExDriver.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding = {
+ RedfishRestExDriverBindingSupported,
+ RedfishRestExDriverBindingStart,
+ RedfishRestExDriverBindingStop,
+ REDFISH_RESTEX_DRIVER_VERSION,
+ NULL,
+ NULL
+};
+
+EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding = {
+ RedfishRestExServiceBindingCreateChild,
+ RedfishRestExServiceBindingDestroyChild
+};
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ )
+{
+ RESTEX_INSTANCE *Instance;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+
+ if (Entry == NULL || Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = NET_LIST_USER_STRUCT_S (Entry, RESTEX_INSTANCE, Link, RESTEX_INSTANCE_SIGNATURE);
+ ServiceBinding = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
+ NumberOfChildren = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
+ ChildHandleBuffer = ((RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
+
+ if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
+ return EFI_SUCCESS;
+ }
+
+ return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
+}
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ )
+{
+ HttpIoDestroyIo (&(Instance->HttpIo));
+
+ FreePool (Instance);
+}
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ )
+{
+ RESTEX_INSTANCE *RestExIns;
+ EFI_STATUS Status;
+
+ *Instance = NULL;
+ Status = EFI_SUCCESS;
+
+ RestExIns = AllocateZeroPool (sizeof (RESTEX_INSTANCE));
+ if (RestExIns == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RestExIns->Signature = RESTEX_INSTANCE_SIGNATURE;
+ InitializeListHead (&RestExIns->Link);
+ RestExIns->InDestroy = FALSE;
+ RestExIns->Service = Service;
+
+ CopyMem (&RestExIns->RestEx, &mRedfishRestExProtocol, sizeof (RestExIns->RestEx));
+
+ //
+ // Create a HTTP_IO to access the HTTP service.
+ //
+ Status = HttpIoCreateIo (
+ RestExIns->Service->ImageHandle,
+ RestExIns->Service->ControllerHandle,
+ IP_VERSION_4,
+ NULL,
+ NULL,
+ NULL,
+ &(RestExIns->HttpIo)
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (RestExIns);
+ return Status;
+ }
+
+ *Instance = RestExIns;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param[in] RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ )
+{
+ if (RestExSb->HttpChildHandle != NULL) {
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ RestExSb->ImageHandle,
+ RestExSb->ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ RestExSb->ControllerHandle,
+ RestExSb->ImageHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ RestExSb->HttpChildHandle
+ );
+
+ RestExSb->HttpChildHandle = NULL;
+ }
+
+ gBS->UninstallProtocolInterface (
+ RestExSb->ControllerHandle,
+ &gEfiCallerIdGuid,
+ &RestExSb->Id
+ );
+
+ FreePool (RestExSb);
+}
+
+/**
+ Check the NIC controller handle represents an in-band or out-of-band Redfish host
+ interface device. If not in-band, treat it as out-of-band interface device.
+
+ @param[in] Controller The NIC controller handle needs to be checked.
+
+ @return EFI_REST_EX_SERVICE_ACCESS_MODE of the device.
+
+**/
+EFI_REST_EX_SERVICE_ACCESS_MODE
+RestExServiceAccessMode (
+ IN EFI_HANDLE Controller
+ )
+{
+ //
+ // This is EFI REST EX driver instance to connect
+ // to Redfish service using HTTP in out of band.
+ //
+ if (FixedPcdGetBool (PcdRedfishRestExServiceAccessModeInBand)) {
+ return EfiRestExServiceInBandAccess;
+ } else {
+ return EfiRestExServiceOutOfBandAccess;
+ }
+}
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ )
+{
+ EFI_STATUS Status;
+ RESTEX_SERVICE *RestExSb;
+
+ Status = EFI_SUCCESS;
+ RestExSb = NULL;
+
+ *Service = NULL;
+
+ RestExSb = AllocateZeroPool (sizeof (RESTEX_SERVICE));
+ if (RestExSb == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RestExSb->Signature = RESTEX_SERVICE_SIGNATURE;
+
+ RestExSb->ServiceBinding = mRedfishRestExServiceBinding;
+
+ RestExSb->RestExChildrenNum = 0;
+ InitializeListHead (&RestExSb->RestExChildrenList);
+
+ RestExSb->ControllerHandle = Controller;
+ RestExSb->ImageHandle = Image;
+
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.Length = sizeof (EFI_REST_EX_SERVICE_INFO);
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Major = 1;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.EfiRestExServiceInfoHeader.RestServiceInfoVer.Minor = 0;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceType = EfiRestExServiceRedfish;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestServiceAccessMode = RestExServiceAccessMode (Controller);
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigType = EfiRestExConfigHttp;
+ RestExSb->RestExServiceInfo.EfiRestExServiceInfoV10.RestExConfigDataLength = sizeof (EFI_REST_EX_HTTP_CONFIG_DATA);
+
+ Status = gBS->InstallProtocolInterface (
+ &Controller,
+ &gEfiCallerIdGuid,
+ EFI_NATIVE_INTERFACE,
+ &RestExSb->Id
+ );
+ if (EFI_ERROR (Status)) {
+ FreePool (RestExSb);
+ RestExSb = NULL;
+ }
+
+ *Service = RestExSb;
+ return Status;
+}
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Install the RestEx Driver Binding Protocol.
+ //
+ Status = EfiLibInstallDriverBindingComponentName2 (
+ ImageHandle,
+ SystemTable,
+ &gRedfishRestExDriverBinding,
+ ImageHandle,
+ &gRedfishRestExComponentName,
+ &gRedfishRestExComponentName2
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ return Status;
+}
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+
+ //
+ // Test for the HttpServiceBinding Protocol.
+ //
+ return gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+}
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ EFI_STATUS Status;
+ UINT32 *Id;
+ VOID *Interface;
+
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiCallerIdGuid,
+ (VOID **) &Id,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ Status = RestExCreateService (ControllerHandle, This->DriverBindingHandle, &RestExSb);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ ASSERT (RestExSb != NULL);
+
+ //
+ // Create a Http child instance, but do not configure it.
+ // This will establish the parent-child relationship.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ This->DriverBindingHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &RestExSb->HttpChildHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ &Interface,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Install the RestEx ServiceBinding Protocol onto ControllerHandle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ &RestExSb->ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ RestExDestroyService (RestExSb);
+
+ return Status;
+}
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ )
+{
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ RESTEX_SERVICE *RestExSb;
+ EFI_HANDLE NicHandle;
+ EFI_STATUS Status;
+ LIST_ENTRY *List;
+ RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+
+ //
+ // RestEx driver opens HTTP child, So, Controller is a HTTP
+ // child handle. Locate the Nic handle first. Then get the
+ // RestEx private data back.
+ //
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ (VOID **) &ServiceBinding,
+ This->DriverBindingHandle,
+ NicHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ RestExSb = RESTEX_SERVICE_FROM_THIS (ServiceBinding);
+
+ if (!IsListEmpty (&RestExSb->RestExChildrenList)) {
+ //
+ // Destroy the RestEx child instance in ChildHandleBuffer.
+ //
+ List = &RestExSb->RestExChildrenList;
+ Context.ServiceBinding = ServiceBinding;
+ Context.NumberOfChildren = NumberOfChildren;
+ Context.ChildHandleBuffer = ChildHandleBuffer;
+ Status = NetDestroyLinkList (
+ List,
+ RestExDestroyChildEntryInHandleBuffer,
+ &Context,
+ NULL
+ );
+ }
+
+ if (NumberOfChildren == 0 && IsListEmpty (&RestExSb->RestExChildrenList)) {
+ gBS->UninstallProtocolInterface (
+ NicHandle,
+ &gEfiRestExServiceBindingProtocolGuid,
+ ServiceBinding
+ );
+
+ RestExDestroyService (RestExSb);
+
+ if (gRedfishRestExControllerNameTable != NULL) {
+ FreeUnicodeStringTable (gRedfishRestExControllerNameTable);
+ gRedfishRestExControllerNameTable = NULL;
+ }
+
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ RESTEX_INSTANCE *Instance;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ VOID *Http;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ RestExSb = RESTEX_SERVICE_FROM_THIS (This);
+
+ Status = RestExCreateInstance (RestExSb, &Instance);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ ASSERT (Instance != NULL);
+
+ //
+ // Install the RestEx protocol onto ChildHandle
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Instance->ChildHandle = *ChildHandle;
+
+ //
+ // Open the Http protocol BY_CHILD.
+ //
+ Status = gBS->OpenProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ Instance->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+
+ goto ON_ERROR;
+ }
+
+ //
+ // Open the Http protocol by child.
+ //
+ Status = gBS->OpenProtocol (
+ Instance->HttpIo.Handle,
+ &gEfiHttpProtocolGuid,
+ (VOID **) &Http,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ Instance->ChildHandle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // Close the Http protocol.
+ //
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->ChildHandle,
+ &gEfiRestExProtocolGuid,
+ &Instance->RestEx,
+ NULL
+ );
+
+ goto ON_ERROR;
+ }
+
+ //
+ // Add it to the parent's child list.
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ InsertTailList (&RestExSb->RestExChildrenList, &Instance->Link);
+ RestExSb->RestExChildrenNum++;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ RestExDestroyInstance (Instance);
+ return Status;
+}
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ RESTEX_SERVICE *RestExSb;
+ RESTEX_INSTANCE *Instance;
+
+ EFI_REST_EX_PROTOCOL *RestEx;
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Retrieve the private context data structures
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ (VOID **) &RestEx,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (RestEx);
+ RestExSb = RESTEX_SERVICE_FROM_THIS (This);
+
+ if (Instance->Service != RestExSb) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Instance->InDestroy) {
+ return EFI_SUCCESS;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance->InDestroy = TRUE;
+
+ //
+ // Close the Http protocol.
+ //
+ gBS->CloseProtocol (
+ RestExSb->HttpChildHandle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ gBS->CloseProtocol (
+ Instance->HttpIo.Handle,
+ &gEfiHttpProtocolGuid,
+ gRedfishRestExDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+
+ gBS->RestoreTPL (OldTpl);
+
+ //
+ // Uninstall the RestEx protocol first to enable a top down destruction.
+ //
+ Status = gBS->UninstallProtocolInterface (
+ ChildHandle,
+ &gEfiRestExProtocolGuid,
+ RestEx
+ );
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if (EFI_ERROR (Status)) {
+ Instance->InDestroy = FALSE;
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+
+ RemoveEntryList (&Instance->Link);
+ RestExSb->RestExChildrenNum--;
+
+ gBS->RestoreTPL (OldTpl);
+
+ RestExDestroyInstance (Instance);
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
new file mode 100644
index 00000000000..0b9ba701bdd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDriver.h
@@ -0,0 +1,650 @@
+/** @file
+ RedfishRestExDxe support functions definitions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_RESTEX_DRIVER_H_
+#define EFI_REDFISH_RESTEX_DRIVER_H_
+
+///
+/// Libraries classes
+///
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+///
+/// UEFI Driver Model Protocols
+///
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RestEx.h>
+#include <Protocol/ServiceBinding.h>
+
+///
+/// Protocol instances
+///
+extern EFI_COMPONENT_NAME_PROTOCOL gRedfishRestExComponentName;
+extern EFI_COMPONENT_NAME2_PROTOCOL gRedfishRestExComponentName2;
+extern EFI_UNICODE_STRING_TABLE *gRedfishRestExControllerNameTable;
+
+extern EFI_DRIVER_BINDING_PROTOCOL gRedfishRestExDriverBinding;
+extern EFI_SERVICE_BINDING_PROTOCOL mRedfishRestExServiceBinding;
+extern EFI_REST_EX_PROTOCOL mRedfishRestExProtocol;
+///
+/// RestEx service block
+///
+typedef struct _RESTEX_SERVICE RESTEX_SERVICE;
+
+///
+/// RestEx instance block
+///
+typedef struct _RESTEX_INSTANCE RESTEX_INSTANCE;
+
+///
+/// Driver Version
+///
+#define REDFISH_RESTEX_DRIVER_VERSION 0x0100
+
+#define RESTEX_SERVICE_SIGNATURE SIGNATURE_32 ('R', 'E', 'S', 'S')
+#define RESTEX_INSTANCE_SIGNATURE SIGNATURE_32 ('R', 'E', 'I', 'S')
+
+#define RESTEX_SERVICE_FROM_THIS(a) \
+ CR (a, RESTEX_SERVICE, ServiceBinding, RESTEX_SERVICE_SIGNATURE)
+
+#define RESTEX_INSTANCE_FROM_THIS(a) \
+ CR (a, RESTEX_INSTANCE, RestEx, RESTEX_INSTANCE_SIGNATURE)
+
+
+#define RESTEX_STATE_UNCONFIGED 0
+#define RESTEX_STATE_CONFIGED 1
+
+struct _RESTEX_SERVICE {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ UINT16 RestExChildrenNum;
+ LIST_ENTRY RestExChildrenList;
+
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE ImageHandle;
+
+ //
+ // Use to establish the parent-child relationship.
+ //
+ EFI_HANDLE HttpChildHandle;
+
+ UINT32 Id;
+
+ EFI_REST_EX_SERVICE_INFO RestExServiceInfo;
+};
+
+#define RESTEX_INSTANCE_FLAGS_TLS_RETRY 0x00000001
+#define RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY 0x00000002
+
+struct _RESTEX_INSTANCE {
+ UINT32 Signature;
+ LIST_ENTRY Link;
+
+ EFI_REST_EX_PROTOCOL RestEx;
+
+ INTN State;
+ BOOLEAN InDestroy;
+
+ RESTEX_SERVICE *Service;
+ EFI_HANDLE ChildHandle;
+
+ EFI_REST_EX_CONFIG_DATA ConfigData;
+
+ //
+ // HTTP_IO to access the HTTP service
+ //
+ HTTP_IO HttpIo;
+
+ UINT32 Flags;
+};
+
+typedef struct {
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+} RESTEX_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT;
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ );
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI Errors Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+);
+
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ );
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ );
+
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ );
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ );
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
new file mode 100644
index 00000000000..de5411bf997
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.inf
@@ -0,0 +1,63 @@
+## @file
+# Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001b
+ BASE_NAME = RedfishRestExDxe
+ FILE_GUID = B64702DA-E6B5-43c8-8CE8-D253071E9D6C
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RedfishRestExDriverEntryPoint
+ UNLOAD_IMAGE = NetLibDefaultUnload
+ MODULE_UNI_FILE = RedfishRestExDxe.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ ComponentName.c
+ RedfishRestExDriver.c
+ RedfishRestExDriver.h
+ RedfishRestExImpl.c
+ RedfishRestExProtocol.c
+ RedfishRestExInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ DpcLib
+ HttpLib
+ HttpIoLib
+ PrintLib
+ MemoryAllocationLib
+ NetLib
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiRestExServiceBindingProtocolGuid ## BY_START
+ gEfiRestExProtocolGuid ## BY_START
+ gEfiHttpServiceBindingProtocolGuid ## TO_START
+ gEfiHttpProtocolGuid ## TO_START
+ gEfiDevicePathProtocolGuid ## TO_START
+
+[Pcd]
+ gEfiRedfishPkgTokenSpaceGuid.PcdRedfishRestExServiceAccessModeInBand ## CONSUMES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ RedfishRestExDxeExtra.uni
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
new file mode 100644
index 00000000000..afa0c142a9f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxe.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Redfish UEFI RESTEX DXE Driver.
+//
+// This driver provides Redfish UEFI RESTEX protocols.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "UEFI Redfish RESTEX service"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This driver provides Redfish EFI RESTEX Protocol and Redfish EFI RESREX Service Binding Protocol."
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
new file mode 100644
index 00000000000..a8ecf8aedee
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExDxeExtra.uni
@@ -0,0 +1,15 @@
+// /** @file
+// RestExDxe Localized Strings and Content
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Redfish UEFI RESTEX DXE"
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
new file mode 100644
index 00000000000..e09a7117374
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExImpl.c
@@ -0,0 +1,157 @@
+/** @file
+ RestExDxe support functions implementation.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include "RedfishRestExInternal.h"
+
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_ERROR Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+)
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a: TCP connection is finished. Could be TSL session closure, reset HTTP instance for the new TLS session.\n", __FUNCTION__));
+
+ Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Error to reset HTTP instance.\n", __FUNCTION__));
+ return Status;
+ }
+ Status = Instance->HttpIo.Http->Configure(Instance->HttpIo.Http, &((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Error to re-initiate HTTP instance.\n", __FUNCTION__));
+ }
+ return Status;
+}
+/**
+ This function check
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] HttpIoReceiveStatus This is the status return from HttpIoRecvResponse
+
+ @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
+ @retval EFI_NOT_READY May need to resend the HTTP request.
+ @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishCheckHttpReceiveStatus (
+ IN RESTEX_INSTANCE *Instance,
+ IN EFI_STATUS HttpIoReceiveStatus
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+
+ if (!EFI_ERROR (HttpIoReceiveStatus)){
+ ReturnStatus = EFI_SUCCESS;
+ } else if (EFI_ERROR (HttpIoReceiveStatus) && HttpIoReceiveStatus != EFI_CONNECTION_FIN) {
+ if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY) == 0) {
+ DEBUG ((DEBUG_ERROR, "%a: TCP error, reset HTTP session.\n", __FUNCTION__));
+ Instance->Flags |= RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY;
+ gBS->Stall (500);
+ Status = ResetHttpTslSession (Instance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ } else {
+ return EFI_NOT_READY;
+ }
+ } else {
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ } else {
+ if (HttpIoReceiveStatus == EFI_CONNECTION_FIN) {
+ if ((Instance->Flags & RESTEX_INSTANCE_FLAGS_TLS_RETRY) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: REST_EX Send and receive fail even with a new TLS session.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ Instance->Flags |= RESTEX_INSTANCE_FLAGS_TLS_RETRY;
+ Status = ResetHttpTslSession (Instance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Reset HTTP instance fail.\n", __FUNCTION__));
+ ReturnStatus = EFI_DEVICE_ERROR;
+ }
+ return EFI_NOT_READY;
+ }
+ }
+ //
+ // Clean TLS new session retry and error try flags.
+ //
+ Instance->Flags &= ~ (RESTEX_INSTANCE_FLAGS_TLS_RETRY | RESTEX_INSTANCE_FLAGS_TCP_ERROR_RETRY);
+ return ReturnStatus;
+}
+
+/**
+ This function send the HTTP request without body to see
+ if the write to URL is permitted by Redfish service. This function
+ checks if the HTTP request has Content-length in HTTP header. If yes,
+ set HTTP body to NULL and then send to service. Check the HTTP status
+ for the firther actions.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[in] PreservedRequestHeaders The pointer to save the request headers
+ @param[in] ItsWrite This is write method to URL.
+
+ @retval EFI_INVALID_PARAMETER Improper given parameters.
+ @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
+ @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
+ @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
+
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishHttpAddExpectation (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ IN EFI_HTTP_HEADER **PreservedRequestHeaders,
+ IN BOOLEAN *ItsWrite
+ )
+{
+ EFI_HTTP_HEADER *NewHeaders;
+
+ if (This == NULL || RequestMessage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *ItsWrite = FALSE;
+ if (PreservedRequestHeaders != NULL) {
+ *PreservedRequestHeaders = RequestMessage->Headers;
+ }
+
+ if ((RequestMessage->Data.Request->Method != HttpMethodPut) && (RequestMessage->Data.Request->Method != HttpMethodPost) &&
+ (RequestMessage->Data.Request->Method != HttpMethodPatch)) {
+ return EFI_SUCCESS;
+ }
+ *ItsWrite = TRUE;
+
+ NewHeaders = AllocateZeroPool((RequestMessage->HeaderCount + 1) * sizeof(EFI_HTTP_HEADER));
+ CopyMem ((VOID*)NewHeaders, (VOID *)RequestMessage->Headers, RequestMessage->HeaderCount * sizeof (EFI_HTTP_HEADER));
+ HttpSetFieldNameAndValue (NewHeaders + RequestMessage->HeaderCount, HTTP_HEADER_EXPECT, HTTP_EXPECT_100_CONTINUE);
+ RequestMessage->HeaderCount ++;
+ RequestMessage->Headers = NewHeaders;
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
new file mode 100644
index 00000000000..5a397ade05c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExInternal.h
@@ -0,0 +1,611 @@
+/** @file
+ RedfishRestExDxe support functions definitions.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2019-2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REDFISH_RESTEX_INTERNAL_H_
+#define EFI_REDFISH_RESTEX_INTERNAL_H_
+
+///
+/// Libraries classes
+///
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HttpIoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+
+///
+/// UEFI Driver Model Protocols
+///
+#include <Protocol/DriverBinding.h>
+#include <Protocol/RestEx.h>
+#include <Protocol/ServiceBinding.h>
+
+#include "RedfishRestExDriver.h"
+
+/**
+ This function check
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] HttpReceiveEfiStatus This is the status return from HttpIoRecvResponse
+
+ @retval EFI_SUCCESS The payload receive from Redfish service in sucessfully.
+ @retval EFI_NOT_READY May need to resend the HTTP request.
+ @retval EFI_DEVICE_ERROR Something wrong and can't be resolved.
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishCheckHttpReceiveStatus (
+ IN RESTEX_INSTANCE *Instance,
+ IN EFI_STATUS HttpIoReceiveStatus
+ );
+
+/**
+ This function send the HTTP request without body to see
+ if the write to URL is permitted by Redfish service. This function
+ checks if the HTTP request has Content-length in HTTP header. If yes,
+ set HTTP body to NULL and then send to service. Check the HTTP status
+ for the firther actions.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[in] PreservedRequestHeaders The pointer to save the request headers
+ @param[in] ItsWrite This is write method to URL.
+
+ @retval EFI_INVALID_PARAMETER Improper given parameters.
+ @retval EFI_SUCCESS This HTTP request is free to send to Redfish service.
+ @retval EFI_OUT_OF_RESOURCES NOt enough memory to process.
+ @retval EFI_ACCESS_DENIED Not allowed to write to this URL.
+
+ @retval Others Other errors as indicated.
+
+**/
+EFI_STATUS
+RedfishHttpAddExpectation (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ IN EFI_HTTP_HEADER **PreservedRequestHeaders,
+ IN BOOLEAN *ItsWrite
+ );
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ );
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ );
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ );
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ );
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ );
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ );
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ );
+/**
+ Create a new TLS session becuase the previous on is closed.
+ status.
+
+ @param[in] Instance Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI Errors Other errors.
+
+**/
+EFI_STATUS
+ResetHttpTslSession (
+ IN RESTEX_INSTANCE *Instance
+);
+
+
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+EFIAPI
+RestExDestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+ );
+
+/**
+ Destroy the RestEx instance and recycle the resources.
+
+ @param[in] Instance The pointer to the RestEx instance.
+
+**/
+VOID
+RestExDestroyInstance (
+ IN RESTEX_INSTANCE *Instance
+ );
+
+/**
+ Create the RestEx instance and initialize it.
+
+ @param[in] Service The pointer to the RestEx service.
+ @param[out] Instance The pointer to the RestEx instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
+ @retval EFI_SUCCESS The RestEx instance is created.
+
+**/
+EFI_STATUS
+RestExCreateInstance (
+ IN RESTEX_SERVICE *Service,
+ OUT RESTEX_INSTANCE **Instance
+ );
+
+
+/**
+ Release all the resource used the RestEx service binding instance.
+
+ @param[in] RestExSb The RestEx service binding instance.
+
+**/
+VOID
+RestExDestroyService (
+ IN RESTEX_SERVICE *RestExSb
+ );
+
+/**
+ Create then initialize a RestEx service binding instance.
+
+ @param[in] Controller The controller to install the RestEx service
+ binding on.
+ @param[in] Image The driver binding image of the RestEx driver.
+ @param[out] Service The variable to receive the created service
+ binding instance.
+
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
+ @retval EFI_SUCCESS The service instance is created for the controller.
+
+**/
+EFI_STATUS
+RestExCreateService (
+ IN EFI_HANDLE Controller,
+ IN EFI_HANDLE Image,
+ OUT RESTEX_SERVICE **Service
+ );
+
+/**
+ This is the declaration of an EFI image entry point. This entry point is
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+ both device drivers and bus drivers.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Tests to see if this driver supports a given controller. If a child device is provided,
+ it further tests to see if this driver supports creating a handle for the specified child device.
+
+ This function checks to see if the driver specified by This supports the device specified by
+ ControllerHandle. Drivers will typically use the device path attached to
+ ControllerHandle and/or the services from the bus I/O abstraction attached to
+ ControllerHandle to determine if the driver supports ControllerHandle. This function
+ may be called many times during platform initialization. In order to reduce boot times, the tests
+ performed by this function must be very small, and take as little time as possible to execute. This
+ function must not change the state of any hardware devices, and this function must be aware that the
+ device specified by ControllerHandle may already be managed by the same driver or a
+ different driver. This function must match its calls to AllocatePages() with FreePages(),
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required
+ to guarantee the state of ControllerHandle is not modified by this function.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to test. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For bus drivers, if this parameter is not NULL, then
+ the bus driver must determine if the bus controller specified
+ by ControllerHandle and the child controller specified
+ by RemainingDevicePath are both supported by this
+ bus driver.
+
+ @retval EFI_SUCCESS The device specified by ControllerHandle and
+ RemainingDevicePath is supported by the driver specified by This.
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by the driver
+ specified by This.
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
+ RemainingDevicePath is already being managed by a different
+ driver or an application that requires exclusive access.
+ Currently not implemented.
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
+ RemainingDevicePath is not supported by the driver specified by This.
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Starts a device controller or a bus controller.
+
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().
+ As a result, much of the error checking on the parameters to Start() has been moved into this
+ common boot service. It is legal to call Start() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE.
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
+ EFI_DEVICE_PATH_PROTOCOL.
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle The handle of the controller to start. This handle
+ must support a protocol interface that supplies
+ an I/O abstraction to the driver.
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
+ parameter is ignored by device drivers, and is optional for bus
+ drivers. For a bus driver, if this parameter is NULL, then handles
+ for all the children of Controller are created by this driver.
+ If this parameter is not NULL and the first Device Path Node is
+ not the End of Device Path Node, then only the handle for the
+ child device specified by the first Device Path Node of
+ RemainingDevicePath is created by this driver.
+ If the first Device Path Node of RemainingDevicePath is
+ the End of Device Path Node, no child handle is created by this
+ driver.
+
+ @retval EFI_SUCCESS The device was started.
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ @retval Others The driver failded to start the device.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+/**
+ Stops a device controller or a bus controller.
+
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
+ As a result, much of the error checking on the parameters to Stop() has been moved
+ into this common boot service. It is legal to call Stop() from other locations,
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
+ same driver's Start() function.
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's
+ Start() function, and the Start() function must have called OpenProtocol() on
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
+
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must
+ support a bus specific I/O protocol for the driver
+ to use to stop the device.
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
+ if NumberOfChildren is 0.
+
+ @retval EFI_SUCCESS The device was stopped.
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
+ );
+
+/**
+ Creates a child handle and installs a protocol.
+
+ The CreateChild() function installs a protocol on ChildHandle.
+ If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+ If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+ then a new handle is created. If it is a pointer to an existing UEFI handle,
+ then the protocol is added to the existing UEFI handle.
+
+ @retval EFI_SUCCES The protocol was added to ChildHandle.
+ @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
+ the child
+ @retval other The child handle was not created
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+/**
+ Destroys a child handle with a protocol installed on it.
+
+ The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+ that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+ last protocol on ChildHandle, then ChildHandle is destroyed.
+
+ @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+ @param[in] ChildHandle Handle of the child to destroy
+
+ @retval EFI_SUCCES The protocol was removed from ChildHandle.
+ @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is NULL.
+ @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
+ because its services are being used.
+ @retval other The child handle was not destroyed
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
new file mode 100644
index 00000000000..418fac29259
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RedfishRestExDxe/RedfishRestExProtocol.c
@@ -0,0 +1,735 @@
+/** @file
+ Implementation of Redfish EFI_REST_EX_PROTOCOL interfaces.
+
+ Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Uefi.h>
+#include "RedfishRestExInternal.h"
+
+EFI_REST_EX_PROTOCOL mRedfishRestExProtocol = {
+ RedfishRestExSendReceive,
+ RedfishRestExGetServiceTime,
+ RedfishRestExGetService,
+ RedfishRestExGetModeData,
+ RedfishRestExConfigure,
+ RedfishRestExAyncSendReceive,
+ RedfishRestExEventService
+};
+
+/**
+ Provides a simple HTTP-like interface to send and receive resources from a REST service.
+
+ The SendReceive() function sends an HTTP request to this REST service, and returns a
+ response when the data is retrieved from the service. RequestMessage contains the HTTP
+ request to the REST resource identified by RequestMessage.Request.Url. The
+ ResponseMessage is the returned HTTP response for that request, including any HTTP
+ status.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[in] RequestMessage Pointer to the HTTP request data for this resource
+ @param[out] ResponseMessage Pointer to the HTTP response data obtained for this requested.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This, RequestMessage, or ResponseMessage are NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_ACCESS_DENIED HTTP method is not allowed on this URL.
+ @retval EFI_BAD_BUFFER_SIZE The payload is to large to be handled on server side.
+ @retval EFI_UNSUPPORTED Unsupported HTTP response.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage,
+ OUT EFI_HTTP_MESSAGE *ResponseMessage
+ )
+{
+ EFI_STATUS Status;
+ RESTEX_INSTANCE *Instance;
+ HTTP_IO_RESPONSE_DATA *ResponseData;
+ UINTN TotalReceivedSize;
+ UINTN Index;
+ LIST_ENTRY *ChunkListLink;
+ HTTP_IO_CHUNKS *ThisChunk;
+ BOOLEAN CopyChunkData;
+ BOOLEAN MediaPresent;
+ EFI_HTTP_HEADER *PreservedRequestHeaders;
+ BOOLEAN ItsWrite;
+ BOOLEAN IsGetChunkedTransfer;
+ HTTP_IO_SEND_CHUNK_PROCESS SendChunkProcess;
+ HTTP_IO_SEND_NON_CHUNK_PROCESS SendNonChunkProcess;
+ EFI_HTTP_MESSAGE ChunkTransferRequestMessage;
+
+ Status = EFI_SUCCESS;
+ ResponseData = NULL;
+ IsGetChunkedTransfer = FALSE;
+ SendChunkProcess = HttpIoSendChunkNone;
+ SendNonChunkProcess = HttpIoSendNonChunkNone;
+
+ //
+ // Validate the parameters
+ //
+ if ((This == NULL) || (RequestMessage == NULL) || ResponseMessage == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ //
+ // Check Media Status.
+ //
+ MediaPresent = TRUE;
+ NetLibDetectMedia (Instance->Service->ControllerHandle, &MediaPresent);
+ if (!MediaPresent) {
+ DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive(): No MediaPresent.\n"));
+ return EFI_NO_MEDIA;
+ }
+
+ DEBUG ((DEBUG_INFO, "\nRedfishRestExSendReceive():\n"));
+ DEBUG ((DEBUG_INFO, "*** Perform HTTP Request Method - %d, URL: %s\n", RequestMessage->Data.Request->Method, RequestMessage->Data.Request->Url));
+
+ //
+ // Add header "Expect" to server, only for URL write.
+ //
+ Status = RedfishHttpAddExpectation (This, RequestMessage, &PreservedRequestHeaders, &ItsWrite);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (ItsWrite == TRUE) {
+ if (RequestMessage->BodyLength > HTTP_IO_MAX_SEND_PAYLOAD) {
+ //
+ // Send chunked transfer.
+ //
+ SendChunkProcess ++;
+ CopyMem ((VOID *)&ChunkTransferRequestMessage, (VOID *)RequestMessage, sizeof (EFI_HTTP_MESSAGE));
+ } else {
+ SendNonChunkProcess ++;
+ }
+ }
+ReSendRequest:;
+ //
+ // Send out the request to REST service.
+ //
+ if (ItsWrite == TRUE) {
+ //
+ // This is write to URI
+ //
+ if (SendChunkProcess > HttpIoSendChunkNone) {
+ //
+ // This is chunk transfer for writing large payload.
+ // Send request header first and then handle the
+ // following request message body using chunk transfer.
+ //
+ do {
+ Status = HttpIoSendChunkedTransfer(
+ &(Instance->HttpIo),
+ &SendChunkProcess,
+ &ChunkTransferRequestMessage
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } while (SendChunkProcess == HttpIoSendChunkContent || SendChunkProcess == HttpIoSendChunkEndChunk);
+ } else {
+ //
+ // This is the non-chunk transfer, send request header first and then
+ // handle the following request message body using chunk transfer.
+ //
+ Status = HttpIoSendRequest(
+ &(Instance->HttpIo),
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL: RequestMessage->Data.Request,
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? 0: RequestMessage->HeaderCount,
+ (SendNonChunkProcess == HttpIoSendNonChunkContent)? NULL: RequestMessage->Headers,
+ (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)? 0: RequestMessage->BodyLength,
+ (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent)? NULL: RequestMessage->Body
+ );
+ }
+ } else {
+ //
+ // This is read from URI.
+ //
+ Status = HttpIoSendRequest(
+ &(Instance->HttpIo),
+ RequestMessage->Data.Request,
+ RequestMessage->HeaderCount,
+ RequestMessage->Headers,
+ RequestMessage->BodyLength,
+ RequestMessage->Body
+ );
+ }
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ //
+ // ResponseMessage->Data.Response is to indicate whether to receive the HTTP header or not.
+ // ResponseMessage->BodyLength/ResponseMessage->Body are to indicate whether to receive the response body or not.
+ // Clean the previous buffers and all of them will be allocated later according to the actual situation.
+ //
+ if (ResponseMessage->Data.Response != NULL) {
+ FreePool(ResponseMessage->Data.Response);
+ ResponseMessage->Data.Response = NULL;
+ }
+
+ ResponseMessage->BodyLength = 0;
+ if (ResponseMessage->Body != NULL) {
+ FreePool(ResponseMessage->Body);
+ ResponseMessage->Body = NULL;
+ }
+
+ //
+ // Use zero BodyLength to only receive the response headers.
+ //
+ ResponseData = AllocateZeroPool (sizeof(HTTP_IO_RESPONSE_DATA));
+ if (ResponseData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((DEBUG_INFO, "Receiving HTTP response and headers...\n"));
+ Status = RedfishCheckHttpReceiveStatus (
+ Instance,
+ HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ TRUE,
+ ResponseData
+ )
+ );
+ if (Status == EFI_NOT_READY) {
+ goto ReSendRequest;
+ } else if (Status == EFI_DEVICE_ERROR) {
+ goto ON_EXIT;
+ }
+ //
+ // Restore the headers if it ever changed in RedfishHttpAddExpectation().
+ //
+ if (RequestMessage->Headers != PreservedRequestHeaders) {
+ FreePool (RequestMessage->Headers);
+ RequestMessage->Headers = PreservedRequestHeaders; // Restore headers before we adding "Expect".
+ RequestMessage->HeaderCount --; // Minus one header count for "Expect".
+ }
+
+ DEBUG ((DEBUG_INFO, "HTTP Response StatusCode - %d:", ResponseData->Response.StatusCode));
+ if (ResponseData->Response.StatusCode == HTTP_STATUS_200_OK) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_200_OK\n"));
+
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "This is chunk transfer, start to send all chunks.", ResponseData->Response.StatusCode));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE\n"));
+
+ Status = EFI_BAD_BUFFER_SIZE;
+ goto ON_EXIT;
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_405_METHOD_NOT_ALLOWED){
+ DEBUG ((DEBUG_ERROR, "HTTP_STATUS_405_METHOD_NOT_ALLOWED\n"));
+
+ Status = EFI_ACCESS_DENIED;
+ goto ON_EXIT;
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_400_BAD_REQUEST) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_400_BAD_REQUEST\n"));
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "Bad request may caused by zero length chunk. Try to send all chunks...\n"));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ } else if (ResponseData->Response.StatusCode == HTTP_STATUS_100_CONTINUE) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE\n"));
+ if (SendChunkProcess == HttpIoSendChunkHeaderZeroContent) {
+ //
+ // We get HTTP_STATUS_100_CONTINUE to send the body using chunk transfer.
+ //
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for chunk transfer...\n"));
+ SendChunkProcess ++;
+ goto ReSendRequest;
+ }
+ if (SendNonChunkProcess == HttpIoSendNonChunkHeaderZeroContent) {
+ DEBUG ((DEBUG_INFO, "HTTP_STATUS_100_CONTINUE for non chunk transfer...\n"));
+ SendNonChunkProcess ++;
+ goto ReSendRequest;
+ }
+ //
+ // It's the REST protocol's responsibility to handle the interim HTTP response (e.g. 100 Continue Informational),
+ // and return the final response content to the caller.
+ //
+ if (ResponseData->Headers != NULL && ResponseData->HeaderCount != 0) {
+ FreePool (ResponseData->Headers);
+ }
+ ZeroMem (ResponseData, sizeof(HTTP_IO_RESPONSE_DATA));
+ Status = HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ TRUE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "This HTTP Status is not handled!\n"));
+ Status = EFI_UNSUPPORTED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Ready to return the StatusCode, Header info and BodyLength.
+ //
+ ResponseMessage->Data.Response = AllocateZeroPool (sizeof (EFI_HTTP_RESPONSE_DATA));
+ if (ResponseMessage->Data.Response == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ ResponseMessage->Data.Response->StatusCode = ResponseData->Response.StatusCode;
+ ResponseMessage->HeaderCount = ResponseData->HeaderCount;
+ ResponseMessage->Headers = ResponseData->Headers;
+
+ //
+ // Get response message body.
+ //
+ if (ResponseMessage->HeaderCount > 0) {
+ Status = HttpIoGetContentLength (ResponseMessage->HeaderCount, ResponseMessage->Headers, &ResponseMessage->BodyLength);
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ goto ON_EXIT;
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ ASSERT (ResponseMessage->BodyLength == 0);
+ }
+
+ if (ResponseMessage->BodyLength == 0) {
+ //
+ // Check if Chunked Transfer Coding.
+ //
+ Status = HttpIoGetChunkedTransferContent (
+ &(Instance->HttpIo),
+ ResponseMessage->HeaderCount,
+ ResponseMessage->Headers,
+ &ChunkListLink,
+ &ResponseMessage->BodyLength
+ );
+ if (EFI_ERROR (Status) && Status != EFI_NOT_FOUND) {
+ goto ON_EXIT;
+ }
+ if (Status == EFI_SUCCESS &&
+ ChunkListLink != NULL &&
+ !IsListEmpty(ChunkListLink) &&
+ ResponseMessage->BodyLength != 0) {
+ IsGetChunkedTransfer = TRUE;
+ //
+ // Copy data to Message body.
+ //
+ CopyChunkData = TRUE;
+ ResponseMessage->Body = AllocateZeroPool (ResponseMessage->BodyLength);
+ if (ResponseMessage->Body == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ CopyChunkData = FALSE;
+ }
+ Index = 0;
+ while (!IsListEmpty(ChunkListLink)) {
+ ThisChunk = (HTTP_IO_CHUNKS *)GetFirstNode (ChunkListLink);
+ if (CopyChunkData) {
+ CopyMem(((UINT8 *)ResponseMessage->Body + Index), (UINT8 *)ThisChunk->Data, ThisChunk->Length);
+ Index += ThisChunk->Length;
+ }
+ RemoveEntryList (&ThisChunk->NextChunk);
+ FreePool ((VOID *)ThisChunk->Data);
+ FreePool ((VOID *)ThisChunk);
+ };
+ FreePool ((VOID *)ChunkListLink);
+ }
+ }
+ Status = EFI_SUCCESS;
+ }
+
+ //
+ // Ready to return the Body from REST service if have any.
+ //
+ if (ResponseMessage->BodyLength > 0 && !IsGetChunkedTransfer) {
+ ResponseData->HeaderCount = 0;
+ ResponseData->Headers = NULL;
+
+ ResponseMessage->Body = AllocateZeroPool (ResponseMessage->BodyLength);
+ if (ResponseMessage->Body == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ //
+ // Only receive the Body.
+ //
+ TotalReceivedSize = 0;
+ while (TotalReceivedSize < ResponseMessage->BodyLength) {
+ ResponseData->BodyLength = ResponseMessage->BodyLength - TotalReceivedSize;
+ ResponseData->Body = (CHAR8 *) ResponseMessage->Body + TotalReceivedSize;
+ Status = HttpIoRecvResponse (
+ &(Instance->HttpIo),
+ FALSE,
+ ResponseData
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ TotalReceivedSize += ResponseData->BodyLength;
+ }
+ DEBUG ((DEBUG_INFO, "Total of lengh of Response :%d\n", TotalReceivedSize));
+ }
+ DEBUG ((DEBUG_INFO, "RedfishRestExSendReceive()- EFI_STATUS: %r\n", Status));
+
+ON_EXIT:
+
+ if (ResponseData != NULL) {
+ FreePool (ResponseData);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (ResponseMessage->Data.Response != NULL) {
+ FreePool (ResponseMessage->Data.Response);
+ ResponseMessage->Data.Response = NULL;
+ }
+
+ if (ResponseMessage->Body != NULL) {
+ FreePool (ResponseMessage->Body);
+ ResponseMessage->Body = NULL;
+ }
+ }
+ return Status;
+}
+
+/**
+ Obtain the current time from this REST service instance.
+
+ The GetServiceTime() function is an optional interface to obtain the current time from
+ this REST service instance. If this REST service does not support to retrieve the time,
+ this function returns EFI_UNSUPPORTED. This function must returns EFI_UNSUPPORTED if
+ EFI_REST_EX_SERVICE_TYPE returned in EFI_REST_EX_SERVICE_INFO from GetService() is
+ EFI_REST_EX_SERVICE_UNSPECIFIC.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] Time A pointer to storage to receive a snapshot of the current time of
+ the REST service.
+
+ @retval EFI_SUCCESS operation succeeded.
+ @retval EFI_INVALID_PARAMETER This or Time are NULL.
+ @retval EFI_UNSUPPORTED The RESTful service does not support returning the time.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must
+ be executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetServiceTime (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_TIME *Time
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function returns the information of REST service provided by this EFI REST EX driver instance.
+
+ The information such as the type of REST service and the access mode of REST EX driver instance
+ (In-band or Out-of-band) are described in EFI_REST_EX_SERVICE_INFO structure. For the vendor-specific
+ REST service, vendor-specific REST service information is returned in VendorSpecifcData.
+ REST EX driver designer is well know what REST service this REST EX driver instance intends to
+ communicate with. The designer also well know this driver instance is used to talk to BMC through
+ specific platform mechanism or talk to REST server through UEFI HTTP protocol. REST EX driver is
+ responsible to fill up the correct information in EFI_REST_EX_SERVICE_INFO. EFI_REST_EX_SERVICE_INFO
+ is referred by EFI REST clients to pickup the proper EFI REST EX driver instance to get and set resource.
+ GetService() is a basic and mandatory function which must be able to use even Configure() is not invoked
+ in previously.
+
+ @param[in] This Pointer to EFI_REST_EX_PROTOCOL instance for a particular
+ REST service.
+ @param[out] RestExServiceInfo Pointer to receive a pointer to EFI_REST_EX_SERVICE_INFO structure. The
+ format of EFI_REST_EX_SERVICE_INFO is version controlled for the future
+ extension. The version of EFI_REST_EX_SERVICE_INFO structure is returned
+ in the header within this structure. EFI REST client refers to the correct
+ format of structure according to the version number. The pointer to
+ EFI_REST_EX_SERVICE_INFO is a memory block allocated by EFI REST EX driver
+ instance. That is caller's responsibility to free this memory when this
+ structure is no longer needed. Refer to Related Definitions below for the
+ definitions of EFI_REST_EX_SERVICE_INFO structure.
+
+ @retval EFI_SUCCESS EFI_REST_EX_SERVICE_INFO is returned in RestExServiceInfo. This function
+ is not supported in this REST EX Protocol driver instance.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_SERVICE_INFO **RestExServiceInfo
+ )
+{
+ EFI_TPL OldTpl;
+ RESTEX_INSTANCE *Instance;
+ EFI_REST_EX_SERVICE_INFO *ServiceInfo;
+
+ ServiceInfo = NULL;
+
+ if (This == NULL || RestExServiceInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ ServiceInfo = AllocateZeroPool (sizeof (EFI_REST_EX_SERVICE_INFO));
+ if (ServiceInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ CopyMem (ServiceInfo, &(Instance->Service->RestExServiceInfo), sizeof (EFI_REST_EX_SERVICE_INFO));
+
+ *RestExServiceInfo = ServiceInfo;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function returns operational configuration of current EFI REST EX child instance.
+
+ This function returns the current configuration of EFI REST EX child instance. The format of
+ operational configuration depends on the implementation of EFI REST EX driver instance. For
+ example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol as the undying protocol
+ to communicate with REST service. In this case, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP returned from GetService(). EFI_HTTP_CONFIG_DATA is used as EFI REST
+ EX configuration format and returned to EFI REST client. User has to type cast RestExConfigData
+ to EFI_HTTP_CONFIG_DATA. For those non HTTP-aware REST EX driver instances, the type of configuration
+ is EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC returned from GetService(). In this case, the format of
+ returning data could be non industrial. Instead, the format of configuration data is system/platform
+ specific definition such as BMC mechanism used in EFI REST EX driver instance. EFI REST client and
+ EFI REST EX driver instance have to refer to the specific system /platform spec which is out of UEFI scope.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[out] RestExConfigData Pointer to receive a pointer to EFI_REST_EX_CONFIG_DATA.
+ The memory allocated for configuration data should be freed
+ by caller. See Related Definitions for the details.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is returned in successfully.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be
+ executed and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExGetModeData (
+ IN EFI_REST_EX_PROTOCOL *This,
+ OUT EFI_REST_EX_CONFIG_DATA *RestExConfigData
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is used to configure EFI REST EX child instance.
+
+ This function is used to configure the setting of underlying protocol of REST EX child
+ instance. The type of configuration is according to the implementation of EFI REST EX
+ driver instance. For example, HTTP-aware EFI REST EX driver instance uses EFI HTTP protocol
+ as the undying protocol to communicate with REST service. The type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_HTTP and RestExConfigData is the same format with EFI_HTTP_CONFIG_DATA.
+ Akin to HTTP configuration, REST EX child instance can be configure to use different HTTP
+ local access point for the data transmission. Multiple REST clients may use different
+ configuration of HTTP to distinguish themselves, such as to use the different TCP port.
+ For those non HTTP-aware REST EX driver instance, the type of configuration is
+ EFI_REST_EX_CONFIG_TYPE_UNSPECIFIC. RestExConfigData refers to the non industrial standard.
+ Instead, the format of configuration data is system/platform specific definition such as BMC.
+ In this case, EFI REST client and EFI REST EX driver instance have to refer to the specific
+ system/platform spec which is out of the UEFI scope. Besides GetService()function, no other
+ EFI REST EX functions can be executed by this instance until Configure()is executed and returns
+ successfully. All other functions must returns EFI_NOT_READY if this instance is not configured
+ yet. Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured
+ state.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RestExConfigData Pointer to EFI_REST_EX_CONFIG_DATA. See Related Definitions in
+ GetModeData() protocol interface.
+
+ @retval EFI_SUCCESS EFI_REST_EX_CONFIG_DATA is set in successfully.
+ @retval EFI_DEVICE_ERROR Configuration for this REST EX child instance is failed with the given
+ EFI_REST_EX_CONFIG_DATA.
+ @retval EFI_UNSUPPORTED This function is not supported in this REST EX Protocol driver instance.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExConfigure (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_REST_EX_CONFIG_DATA RestExConfigData
+ )
+{
+ EFI_STATUS Status;
+ EFI_TPL OldTpl;
+ RESTEX_INSTANCE *Instance;
+
+ EFI_HTTP_CONFIG_DATA *HttpConfigData;
+
+ Status = EFI_SUCCESS;
+ HttpConfigData = NULL;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = RESTEX_INSTANCE_FROM_THIS (This);
+
+ if (RestExConfigData == NULL) {
+ //
+ // Set RestExConfigData to NULL means to put EFI REST EX child instance into the unconfigured state.
+ //
+ HttpIoDestroyIo (&(Instance->HttpIo));
+
+ if (Instance->ConfigData != NULL) {
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node != NULL) {
+ FreePool(((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node);
+ }
+ FreePool(Instance->ConfigData);
+ Instance->ConfigData = NULL;
+ }
+
+ Instance->State = RESTEX_STATE_UNCONFIGED;
+ } else {
+ HttpConfigData = &((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)->HttpConfigData;
+ Status = Instance->HttpIo.Http->Configure (Instance->HttpIo.Http, HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ Instance->HttpIo.Timeout = ((EFI_REST_EX_HTTP_CONFIG_DATA *)RestExConfigData)->SendReceiveTimeout;
+
+ Instance->ConfigData = AllocateZeroPool (sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (Instance->ConfigData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (Instance->ConfigData, RestExConfigData, sizeof (EFI_REST_EX_HTTP_CONFIG_DATA));
+ if (HttpConfigData->LocalAddressIsIPv6 == TRUE) {
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv6Node,
+ HttpConfigData->AccessPoint.IPv6Node,
+ sizeof (EFI_HTTPv6_ACCESS_POINT)
+ );
+ } else {
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));
+ if (((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ CopyMem (
+ ((EFI_REST_EX_HTTP_CONFIG_DATA *)Instance->ConfigData)->HttpConfigData.AccessPoint.IPv4Node,
+ HttpConfigData->AccessPoint.IPv4Node,
+ sizeof (EFI_HTTPv4_ACCESS_POINT)
+ );
+ }
+ Instance->State = RESTEX_STATE_CONFIGED;
+ }
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ This function sends REST request to REST service and signal caller's event asynchronously when
+ the final response is received by REST EX Protocol driver instance.
+
+ The essential design of this function is to handle asynchronous send/receive implicitly according
+ to REST service asynchronous request mechanism. Caller will get the notification once the response
+ is returned from REST service.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous asynchronous request associated with the
+ corresponding RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol instance uses to notify REST client
+ the status of response of asynchronous REST request. See related definition
+ of EFI_REST_EX_TOKEN.
+ @param[in] TimeOutInMilliSeconds The pointer to the timeout in milliseconds which REST EX Protocol driver
+ instance refers as the duration to drop asynchronous REST request. NULL
+ pointer means no timeout for this REST request. REST EX Protocol driver
+ signals caller's event with EFI_STATUS set to EFI_TIMEOUT in RestExToken
+ if REST EX Protocol can't get the response from REST service within
+ TimeOutInMilliSeconds.
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_TIMEOUT Asynchronous REST request is not established and timeout is expired.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExAyncSendReceive (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken,
+ IN UINTN *TimeOutInMilliSeconds OPTIONAL
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function sends REST request to a REST Event service and signals caller's event
+ token asynchronously when the URI resource change event is received by REST EX
+ Protocol driver instance.
+
+ The essential design of this function is to monitor event implicitly according to
+ REST service event service mechanism. Caller will get the notification if certain
+ resource is changed.
+
+ @param[in] This This is the EFI_REST_EX_PROTOCOL instance.
+ @param[in] RequestMessage This is the HTTP request message sent to REST service. Set RequestMessage
+ to NULL to cancel the previous event service associated with the corresponding
+ RestExToken. See descriptions for the details.
+ @param[in] RestExToken REST EX token which REST EX Protocol driver instance uses to notify REST client
+ the URI resource which monitored by REST client has been changed. See the related
+ definition of EFI_REST_EX_TOKEN in EFI_REST_EX_PROTOCOL.AsyncSendReceive().
+
+ @retval EFI_SUCCESS Asynchronous REST request is established.
+ @retval EFI_UNSUPPORTED This REST EX Protocol driver instance doesn't support asynchronous request.
+ @retval EFI_ABORT Previous asynchronous REST request has been canceled or event subscription has been
+ delete from service.
+ @retval EFI_DEVICE_ERROR Otherwise, returns EFI_DEVICE_ERROR for other errors according to HTTP Status Code.
+ @retval EFI_NOT_READY The configuration of this instance is not set yet. Configure() must be executed
+ and returns successfully prior to invoke this function.
+
+**/
+EFI_STATUS
+EFIAPI
+RedfishRestExEventService (
+ IN EFI_REST_EX_PROTOCOL *This,
+ IN EFI_HTTP_MESSAGE *RequestMessage OPTIONAL,
+ IN EFI_REST_EX_TOKEN *RestExToken
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c
new file mode 100644
index 00000000000..527739d8ef1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.c
@@ -0,0 +1,586 @@
+/** @file
+
+ The implementation of EFI REST Resource JSON to C structure convertor
+ Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Protocol/RestJsonStructure.h>
+#include "RestJsonStructureInternal.h"
+
+LIST_ENTRY mRestJsonStructureList;
+EFI_HANDLE mProtocolHandle;
+
+/**
+ This function registers Restful resource interpreter for the
+ specific schema.
+
+ @param[in] This This is the EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] JsonStructureSupported The type and version of REST JSON resource which this converter
+ supports.
+ @param[in] ToStructure The function to convert REST JSON resource to structure.
+ @param[in] ToJson The function to convert REST JSON structure to JSON in text format.
+ @param[in] DestroyStructure Destroy REST JSON structure returned in ToStructure() function.
+
+ @retval EFI_SUCCESS Register successfully.
+ @retval Others Fail to register.
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureRegister (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_SUPPORTED *JsonStructureSupported,
+ IN EFI_REST_JSON_STRUCTURE_TO_STRUCTURE ToStructure,
+ IN EFI_REST_JSON_STRUCTURE_TO_JSON ToJson,
+ IN EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure
+)
+{
+ UINTN NumberOfNS;
+ UINTN Index;
+ LIST_ENTRY *ThisList;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *CloneSupportedInterpId;
+ EFI_REST_JSON_STRUCTURE_SUPPORTED *ThisSupportedInterp;
+
+ if (This == NULL ||
+ ToStructure == NULL ||
+ ToJson == NULL ||
+ DestroyStructure == NULL ||
+ JsonStructureSupported == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check how many name space interpreter can interpret.
+ //
+ ThisList = &JsonStructureSupported->NextSupportedRsrcInterp;
+ NumberOfNS = 1;
+ while (TRUE) {
+ if (ThisList->ForwardLink == &JsonStructureSupported->NextSupportedRsrcInterp) {
+ break;
+ } else {
+ ThisList = ThisList->ForwardLink;
+ NumberOfNS ++;
+ }
+ };
+
+ Instance =
+ (REST_JSON_STRUCTURE_INSTANCE *)AllocateZeroPool (sizeof (REST_JSON_STRUCTURE_INSTANCE) + NumberOfNS * sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));
+ if (Instance == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead (&Instance->NextRestJsonStructureInstance);
+ Instance->NumberOfNameSpaceToConvert = NumberOfNS;
+ Instance->SupportedRsrcIndentifier = (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *)((REST_JSON_STRUCTURE_INSTANCE *)Instance + 1);
+ //
+ // Copy supported resource identifer interpreter.
+ //
+ CloneSupportedInterpId = Instance->SupportedRsrcIndentifier;
+ ThisSupportedInterp = JsonStructureSupported;
+ for (Index = 0; Index < NumberOfNS; Index ++) {
+ CopyMem ((VOID *)CloneSupportedInterpId, (VOID *)&ThisSupportedInterp->RestResourceInterp, sizeof (EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER));
+ ThisSupportedInterp = (EFI_REST_JSON_STRUCTURE_SUPPORTED *)ThisSupportedInterp->NextSupportedRsrcInterp.ForwardLink;
+ CloneSupportedInterpId ++;
+ }
+ Instance->JsonToStructure = ToStructure;
+ Instance->StructureToJson = ToJson;
+ Instance->DestroyStructure = DestroyStructure;
+ InsertTailList (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function check if this interpreter instance support the given namesapce.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
+ @param[in] RsrcTypeIdentifier Resource type identifier.
+ @param[in] ResourceRaw Given Restful resource.
+ @param[out] RestJSonHeader Property interpreted from given ResourceRaw.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+InterpreterInstanceToStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,
+ IN CHAR8 *ResourceRaw,
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **RestJSonHeader
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
+
+ if (This == NULL ||
+ InterpreterInstance == NULL ||
+ ResourceRaw == NULL ||
+ RestJSonHeader == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RsrcTypeIdentifier == NULL) {
+ //
+ // No resource type identifier, send to intepreter anyway.
+ // Interpreter may recognize this resource.
+ //
+ Status = InterpreterInstance->JsonToStructure (
+ This,
+ NULL,
+ ResourceRaw,
+ RestJSonHeader
+ );
+ } else {
+ //
+ // Check if the namesapce and version is supported by this interpreter.
+ //
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
+ if (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName,
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){
+ if ((RsrcTypeIdentifier->NameSpace.MajorVersion == NULL) &&
+ (RsrcTypeIdentifier->NameSpace.MinorVersion == NULL) &&
+ (RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL)
+ ) {
+ //
+ // Don't check version of this resource type identifier.
+ //
+ Status = InterpreterInstance->JsonToStructure (
+ This,
+ RsrcTypeIdentifier,
+ ResourceRaw,
+ RestJSonHeader
+ );
+ break;
+ } else {
+ //
+ // Check version.
+ //
+ if ((AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MajorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MinorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ErrataVersion,
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
+ Status = InterpreterInstance->JsonToStructure (
+ This,
+ RsrcTypeIdentifier,
+ ResourceRaw,
+ RestJSonHeader
+ );
+ break;
+ }
+ }
+ }
+ ThisSupportedRsrcTypeId ++;
+ }
+ }
+ return Status;
+}
+/**
+ This function converts JSON C structure to JSON property.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
+ @param[in] RestJSonHeader Resource type identifier.
+ @param[out] ResourceRaw Output in JSON text format.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+InterpreterEfiStructToInstance (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,
+ OUT CHAR8 **ResourceRaw
+)
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier;
+
+ if (This == NULL ||
+ InterpreterInstance == NULL ||
+ RestJSonHeader == NULL ||
+ ResourceRaw == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+ RsrcTypeIdentifier = &RestJSonHeader->JsonRsrcIdentifier;
+ if (RsrcTypeIdentifier == NULL ||
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName == NULL ||
+ RsrcTypeIdentifier->NameSpace.MajorVersion == NULL ||
+ RsrcTypeIdentifier->NameSpace.MinorVersion == NULL ||
+ RsrcTypeIdentifier->NameSpace.ErrataVersion == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check if the namesapce and version is supported by this interpreter.
+ //
+ Status = EFI_UNSUPPORTED;
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
+ if (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ResourceTypeName,
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0){
+ //
+ // Check version.
+ //
+ if ((AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MajorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.MinorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
+ (AsciiStrCmp (
+ RsrcTypeIdentifier->NameSpace.ErrataVersion,
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
+ Status = InterpreterInstance->StructureToJson (
+ This,
+ RestJSonHeader,
+ ResourceRaw
+ );
+ break;
+ }
+ }
+ ThisSupportedRsrcTypeId ++;
+ }
+ return Status;
+}
+
+/**
+ This function destory REST property structure.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] InterpreterInstance REST_JSON_STRUCTURE_INSTANCE
+ @param[in] RestJSonHeader Property interpreted from given ResourceRaw.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+InterpreterInstanceDestoryJsonStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN REST_JSON_STRUCTURE_INSTANCE *InterpreterInstance,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *ThisSupportedRsrcTypeId;
+
+ if (This == NULL ||
+ InterpreterInstance == NULL ||
+ RestJSonHeader == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ //
+ // Check if the namesapce and version is supported by this interpreter.
+ //
+ ThisSupportedRsrcTypeId = InterpreterInstance->SupportedRsrcIndentifier;
+ for (Index = 0; Index < InterpreterInstance->NumberOfNameSpaceToConvert; Index ++){
+ if (AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.ResourceTypeName,
+ ThisSupportedRsrcTypeId->NameSpace.ResourceTypeName) == 0) {
+ if ((RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion == NULL) &&
+ (RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion == NULL) &&
+ (RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion == NULL)
+ ) {
+ //
+ // Don't check version of this resource type identifier.
+ //
+ Status = InterpreterInstance->DestroyStructure (
+ This,
+ RestJSonHeader
+ );
+ break;
+ } else {
+ //
+ // Check version.
+ //
+ if ((AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.MajorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MajorVersion) == 0) &&
+ (AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.MinorVersion,
+ ThisSupportedRsrcTypeId->NameSpace.MinorVersion) == 0) &&
+ (AsciiStrCmp (
+ RestJSonHeader->JsonRsrcIdentifier.NameSpace.ErrataVersion,
+ ThisSupportedRsrcTypeId->NameSpace.ErrataVersion) == 0)) {
+ Status = InterpreterInstance->DestroyStructure (
+ This,
+ RestJSonHeader
+ );
+ break;
+ }
+ }
+ }
+ ThisSupportedRsrcTypeId ++;
+ }
+ return Status;
+}
+
+/**
+ This function translates the given JSON text to JSON C Structure.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] RsrcTypeIdentifier Resource type identifier.
+ @param[in] ResourceJsonText Given Restful resource.
+ @param[out] JsonStructure Property interpreted from given ResourceRaw.
+
+ @retval EFI_SUCCESS
+ @retval Others.
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureToStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *RsrcTypeIdentifier OPTIONAL,
+ IN CHAR8 *ResourceJsonText,
+ OUT EFI_REST_JSON_STRUCTURE_HEADER **JsonStructure
+)
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+
+ if (This == NULL ||
+ ResourceJsonText == NULL ||
+ JsonStructure == NULL
+ ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = EFI_SUCCESS;
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ while (TRUE) {
+ Status = InterpreterInstanceToStruct (
+ This,
+ Instance,
+ RsrcTypeIdentifier,
+ ResourceJsonText,
+ JsonStructure
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ };
+ return Status;
+}
+
+/**
+ This function destory REST property EFI structure which returned in
+ JsonToStructure().
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] RestJSonHeader Property to destory.
+
+ @retval EFI_SUCCESS
+ @retval Others
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureDestroyStruct (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader
+)
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+
+ if (This == NULL || RestJSonHeader == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = EFI_SUCCESS;
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ while (TRUE) {
+ Status = InterpreterInstanceDestoryJsonStruct (
+ This,
+ Instance,
+ RestJSonHeader
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ };
+ return Status;
+}
+
+/**
+ This function translates the given JSON C Structure to JSON text.
+
+ @param[in] This EFI_REST_JSON_STRUCTURE_PROTOCOL instance.
+ @param[in] RestJSonHeader Given Restful resource.
+ @param[out] ResourceRaw Resource in RESTfuls service oriented.
+
+ @retval EFI_SUCCESS
+ @retval Others Fail to remove the entry
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureToJson (
+ IN EFI_REST_JSON_STRUCTURE_PROTOCOL *This,
+ IN EFI_REST_JSON_STRUCTURE_HEADER *RestJSonHeader,
+ OUT CHAR8 **ResourceRaw
+)
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+
+ if (This == NULL || RestJSonHeader == NULL || ResourceRaw == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return EFI_UNSUPPORTED;
+ }
+ Status = EFI_SUCCESS;
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ while (TRUE) {
+ Status = InterpreterEfiStructToInstance (
+ This,
+ Instance,
+ RestJSonHeader,
+ ResourceRaw
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ if (IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ };
+ return Status;
+}
+
+EFI_REST_JSON_STRUCTURE_PROTOCOL mRestJsonStructureProtocol = {
+ RestJsonStructureRegister,
+ RestJsonStructureToStruct,
+ RestJsonStructureToJson,
+ RestJsonStructureDestroyStruct
+};
+
+/**
+ This is the declaration of an EFI image entry point.
+
+ @param ImageHandle The firmware allocated handle for the UEFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval Others An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeListHead (&mRestJsonStructureList);
+ //
+ // Install the Restful Resource Interpreter Protocol.
+ //
+ mProtocolHandle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &mProtocolHandle,
+ &gEfiRestJsonStructureProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID *)&mRestJsonStructureProtocol
+ );
+ return Status;
+}
+
+/**
+ This is the unload handle for Redfish discover module.
+
+ Disconnect the driver specified by ImageHandle from all the devices in the handle database.
+ Uninstall all the protocols installed in the driver entry point.
+
+ @param[in] ImageHandle The drivers' driver image.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+
+**/
+EFI_STATUS
+EFIAPI
+RestJsonStructureUnload (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ REST_JSON_STRUCTURE_INSTANCE *Instance;
+ REST_JSON_STRUCTURE_INSTANCE *NextInstance;
+
+ Status = gBS->UninstallProtocolInterface (
+ mProtocolHandle,
+ &gEfiRestJsonStructureProtocolGuid,
+ (VOID *)&mRestJsonStructureProtocol
+ );
+
+ if (IsListEmpty (&mRestJsonStructureList)) {
+ return Status;
+ }
+ //
+ // Free memory of REST_JSON_STRUCTURE_INSTANCE instance.
+ //
+ Instance = (REST_JSON_STRUCTURE_INSTANCE *)GetFirstNode (&mRestJsonStructureList);
+ do {
+ NextInstance = NULL;
+ if (!IsNodeAtEnd(&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance)) {
+ NextInstance = (REST_JSON_STRUCTURE_INSTANCE *)GetNextNode (&mRestJsonStructureList, &Instance->NextRestJsonStructureInstance);
+ }
+ FreePool ((VOID *)Instance);
+ Instance = NextInstance;
+ } while (Instance != NULL);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
new file mode 100644
index 00000000000..1d6a2bfc792
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureDxe.inf
@@ -0,0 +1,39 @@
+## @file
+# Implementation of EFI REST JSON Structure Protocol.
+#
+# (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = RestJsonStructureDxe
+ FILE_GUID = 83FAAFBF-FC4B-469F-892A-798E66A6F50A
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = RestJsonStructureEntryPoint
+ UNLOAD_IMAGE = RestJsonStructureUnload
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ RedfishPkg/RedfishPkg.dec
+
+[Sources]
+ RestJsonStructureDxe.c
+ RestJsonStructureInternal.h
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Protocols]
+ gEfiRestJsonStructureProtocolGuid ## Producing
+
+[Depex]
+ TRUE
+
diff --git a/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h
new file mode 100644
index 00000000000..e1394cfd36d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/RedfishPkg/RestJsonStructureDxe/RestJsonStructureInternal.h
@@ -0,0 +1,33 @@
+/** @file
+ The internal definitions of EFI REST Resource JSON to C structure convertor
+ Protocol.
+
+ (C) Copyright 2020 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef EFI_REST_JSON_STRUCTURE_INTERNAL_H_
+#define EFI_REST_JSON_STRUCTURE_INTERNAL_H_
+
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+///
+/// Internal structure to maintain the information of JSON to
+/// C structure convertor.
+///
+typedef struct _REST_JSON_STRUCTURE_INSTANCE {
+ LIST_ENTRY NextRestJsonStructureInstance; ///< Next convertor instance
+ UINTN NumberOfNameSpaceToConvert; ///< Number of resource type this convertor supports.
+ EFI_REST_JSON_RESOURCE_TYPE_IDENTIFIER *SupportedRsrcIndentifier; ///< The resource type linklist
+ EFI_REST_JSON_STRUCTURE_TO_STRUCTURE JsonToStructure; ///< JSON to C structure function
+ EFI_REST_JSON_STRUCTURE_TO_JSON StructureToJson; ///< C structure to JSON function
+ EFI_REST_JSON_STRUCTURE_DESTORY_STRUCTURE DestroyStructure; ///< Destory C struture function.
+} REST_JSON_STRUCTURE_INSTANCE;
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/FvReportPei/FvReportPei.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/FvReportPei/FvReportPei.c
index 102a792e4e6..3029fa74a6b 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/FvReportPei/FvReportPei.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/FvReportPei/FvReportPei.c
@@ -67,7 +67,7 @@ InstallPreHashFvPpi (
HASH_INFO *HashInfo;
PpiSize = sizeof (EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI)
- + sizeof (sizeof (HASH_INFO))
+ + sizeof (HASH_INFO)
+ HashSize;
PreHashedFvPpi = AllocatePool (PpiSize);
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.c
index 4123541b5f8..b6785cf2ed5 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.c
@@ -120,8 +120,6 @@ typedef struct {
} EFI_HASH_INFO;
EFI_HASH_INFO mHashInfo[] = {
- {&gEfiHashAlgorithmMD5Guid, sizeof(EFI_MD5_HASH2), Md5GetContextSize, Md5Init, Md5Update, Md5Final },
- {&gEfiHashAlgorithmSha1Guid, sizeof(EFI_SHA1_HASH2), Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
{&gEfiHashAlgorithmSha256Guid, sizeof(EFI_SHA256_HASH2), Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final },
{&gEfiHashAlgorithmSha384Guid, sizeof(EFI_SHA384_HASH2), Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final },
{&gEfiHashAlgorithmSha512Guid, sizeof(EFI_SHA512_HASH2), Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final },
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
index e5133a428d3..bc9ff5b4c3c 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
@@ -4,7 +4,7 @@
# This module will use EDKII crypto library to HASH2 protocol.
#
# (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
-# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -44,8 +44,6 @@
UefiLib
[Guids]
- gEfiHashAlgorithmMD5Guid ## CONSUMES ## GUID
- gEfiHashAlgorithmSha1Guid ## CONSUMES ## GUID
gEfiHashAlgorithmSha256Guid ## CONSUMES ## GUID
gEfiHashAlgorithmSha384Guid ## CONSUMES ## GUID
gEfiHashAlgorithmSha512Guid ## CONSUMES ## GUID
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Guid/TpmNvsMm.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Guid/TpmNvsMm.h
new file mode 100644
index 00000000000..51abd89a4da
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Guid/TpmNvsMm.h
@@ -0,0 +1,68 @@
+/** @file
+ TPM NVS MM guid, used for exchanging information, including SWI value and NVS region
+ information, for patching TPM ACPI table.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef TCG2_NVS_MM_H_
+#define TCG2_NVS_MM_H_
+
+#define MM_TPM_NVS_HOB_GUID \
+ { 0xc96c76eb, 0xbc78, 0x429c, { 0x9f, 0x4b, 0xda, 0x51, 0x78, 0xc2, 0x84, 0x57 }}
+
+extern EFI_GUID gTpmNvsMmGuid;
+
+#pragma pack(1)
+typedef struct {
+ UINT8 SoftwareSmi;
+ UINT32 Parameter;
+ UINT32 Response;
+ UINT32 Request;
+ UINT32 RequestParameter;
+ UINT32 LastRequest;
+ UINT32 ReturnCode;
+} PHYSICAL_PRESENCE_NVS;
+
+typedef struct {
+ UINT8 SoftwareSmi;
+ UINT32 Parameter;
+ UINT32 Request;
+ UINT32 ReturnCode;
+} MEMORY_CLEAR_NVS;
+
+typedef struct {
+ PHYSICAL_PRESENCE_NVS PhysicalPresence;
+ MEMORY_CLEAR_NVS MemoryClear;
+ UINT32 PPRequestUserConfirm;
+ UINT32 TpmIrqNum;
+ BOOLEAN IsShortFormPkgLength;
+} TCG_NVS;
+
+typedef struct {
+ UINT8 OpRegionOp;
+ UINT32 NameString;
+ UINT8 RegionSpace;
+ UINT8 DWordPrefix;
+ UINT32 RegionOffset;
+ UINT8 BytePrefix;
+ UINT8 RegionLen;
+} AML_OP_REGION_32_8;
+
+typedef struct {
+ UINT64 Function;
+ UINT64 ReturnStatus;
+ EFI_PHYSICAL_ADDRESS TargetAddress;
+ UINT64 RegisteredPpSwiValue;
+ UINT64 RegisteredMcSwiValue;
+} TPM_NVS_MM_COMM_BUFFER;
+#pragma pack()
+
+typedef enum {
+ TpmNvsMmExchangeInfo,
+} TPM_NVS_MM_FUNCTION;
+
+#endif // TCG2_NVS_MM_H_
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/TcgEventLogRecordLib.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/TcgEventLogRecordLib.h
new file mode 100644
index 00000000000..8631b5b91bd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/TcgEventLogRecordLib.h
@@ -0,0 +1,97 @@
+/** @file
+ This library is used by other modules to measure Firmware to TPM.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _TCG_EVENTLOGRECORD_LIB_H_
+#define _TCG_EVENTLOGRECORD_LIB_H_
+
+#include <Uefi.h>
+
+#pragma pack (1)
+
+#define PLATFORM_FIRMWARE_BLOB_DESC "Fv(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)"
+typedef struct {
+ UINT8 BlobDescriptionSize;
+ UINT8 BlobDescription[sizeof(PLATFORM_FIRMWARE_BLOB_DESC)];
+ EFI_PHYSICAL_ADDRESS BlobBase;
+ UINT64 BlobLength;
+} PLATFORM_FIRMWARE_BLOB2_STRUCT;
+
+#define HANDOFF_TABLE_POINTER_DESC "1234567890ABCDEF"
+typedef struct {
+ UINT8 TableDescriptionSize;
+ UINT8 TableDescription[sizeof(HANDOFF_TABLE_POINTER_DESC)];
+ UINT64 NumberOfTables;
+ EFI_CONFIGURATION_TABLE TableEntry[1];
+} HANDOFF_TABLE_POINTERS2_STRUCT;
+
+#pragma pack ()
+
+/**
+ Get the FvName from the FV header.
+
+ Causion: The FV is untrusted input.
+
+ @param[in] FvBase Base address of FV image.
+ @param[in] FvLength Length of FV image.
+
+ @return FvName pointer
+ @retval NULL FvName is NOT found
+**/
+VOID *
+TpmMeasurementGetFvName (
+ IN EFI_PHYSICAL_ADDRESS FvBase,
+ IN UINT64 FvLength
+ );
+
+/**
+ Measure a FirmwareBlob.
+
+ @param[in] PcrIndex PCR Index.
+ @param[in] Description Description for this FirmwareBlob.
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+*/
+EFI_STATUS
+EFIAPI
+MeasureFirmwareBlob (
+ IN UINT32 PcrIndex,
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
+ IN UINT64 FirmwareBlobLength
+ );
+
+/**
+ Measure a HandoffTable.
+
+ @param[in] PcrIndex PcrIndex of the measurement.
+ @param[in] Description Description for this HandoffTable.
+ @param[in] TableGuid GUID of this HandoffTable.
+ @param[in] TableAddress Base address of this HandoffTable.
+ @param[in] TableLength Size in bytes of this HandoffTable.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+*/
+EFI_STATUS
+EFIAPI
+MeasureHandoffTable (
+ IN UINT32 PcrIndex,
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_GUID *TableGuid,
+ IN VOID *TableAddress,
+ IN UINTN TableLength
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/Tpm2CommandLib.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/Tpm2CommandLib.h
index 41cf10e963b..cccf3a68e72 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/Tpm2CommandLib.h
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Library/Tpm2CommandLib.h
@@ -791,6 +791,22 @@ Tpm2GetCapabilityAlgorithmSet (
);
/**
+ This function will query if the command is supported.
+
+ @param[In] Command TPM_CC command starts from TPM_CC_FIRST.
+ @param[out] IsCmdImpl The command is supported or not.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityIsCommandImplemented (
+ IN TPM_CC Command,
+ OUT BOOLEAN *IsCmdImpl
+ );
+
+/**
This command is used to check to see if specific combinations of algorithm parameters are supported.
@param[in] Parameters Algorithm parameters to be validated
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Ppi/Tcg.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Ppi/Tcg.h
new file mode 100644
index 00000000000..5ec971f1410
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Include/Ppi/Tcg.h
@@ -0,0 +1,65 @@
+/** @file
+ TCG PPI services.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _TCG_PPI_H_
+#define _TCG_PPI_H_
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+typedef struct _EDKII_TCG_PPI EDKII_TCG_PPI;
+
+//
+// This bit is shall be set when HashData is the pre-hash digest.
+//
+#define EDKII_TCG_PRE_HASH 0x0000000000000001
+
+//
+// This bit is shall be set when HashData is the pre-hash digest and log only.
+//
+#define EDKII_TCG_PRE_HASH_LOG_ONLY 0x0000000000000002
+
+/**
+ Tpm measure and log data, and extend the measurement result into a specific PCR.
+
+ @param[in] This Indicates the calling context
+ @param[in] Flags Bitmap providing additional information
+ @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
+ start of the data buffer to be hashed, extended, and logged.
+ If BIT0 of Flags is 1, it is physical address of the
+ start of the pre-hash data buffter to be extended, and logged.
+ The pre-hash data format is TPML_DIGEST_VALUES.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_TCG_HASH_LOG_EXTEND_EVENT)(
+ IN EDKII_TCG_PPI *This,
+ IN UINT64 Flags,
+ IN UINT8 *HashData,
+ IN UINTN HashDataLen,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ );
+
+///
+/// The EFI_TCG Protocol abstracts TCG activity.
+///
+struct _EDKII_TCG_PPI {
+ EDKII_TCG_HASH_LOG_EXTEND_EVENT HashLogExtendEvent;
+};
+
+extern EFI_GUID gEdkiiTcgPpiGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthService.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthService.c
index ac022fbdd35..b035a343fa0 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthService.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthService.c
@@ -19,12 +19,16 @@
to verify the signature.
Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "AuthServiceInternal.h"
+#include <Protocol/VariablePolicy.h>
+#include <Library/VariablePolicyLib.h>
+
//
// Public Exponent of RSA Key.
//
@@ -217,9 +221,12 @@ NeedPhysicallyPresent(
IN EFI_GUID *VendorGuid
)
{
- if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))
- || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {
- return TRUE;
+ // If the VariablePolicy engine is disabled, allow deletion of any authenticated variables.
+ if (IsVariablePolicyEnabled()) {
+ if ((CompareGuid (VendorGuid, &gEfiSecureBootEnableDisableGuid) && (StrCmp (VariableName, EFI_SECURE_BOOT_ENABLE_NAME) == 0))
+ || (CompareGuid (VendorGuid, &gEfiCustomModeEnableGuid) && (StrCmp (VariableName, EFI_CUSTOM_MODE_NAME) == 0))) {
+ return TRUE;
+ }
}
return FALSE;
@@ -842,7 +849,8 @@ ProcessVariable (
&OrgVariableInfo
);
- if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable (OrgVariableInfo.Attributes, Data, DataSize, Attributes) && UserPhysicalPresent()) {
+ // If the VariablePolicy engine is disabled, allow deletion of any authenticated variables.
+ if ((!EFI_ERROR (Status)) && IsDeleteAuthVariable (OrgVariableInfo.Attributes, Data, DataSize, Attributes) && (UserPhysicalPresent() || !IsVariablePolicyEnabled())) {
//
// Allow the delete operation of common authenticated variable(AT or AW) at user physical presence.
//
@@ -1920,6 +1928,12 @@ VerifyTimeBasedPayload (
PayloadPtr = SigData + SigDataSize;
PayloadSize = DataSize - OFFSET_OF_AUTHINFO2_CERT_DATA - (UINTN) SigDataSize;
+ // If the VariablePolicy engine is disabled, allow deletion of any authenticated variables.
+ if (PayloadSize == 0 && (Attributes & EFI_VARIABLE_APPEND_WRITE) == 0 && !IsVariablePolicyEnabled()) {
+ VerifyStatus = TRUE;
+ goto Exit;
+ }
+
//
// Construct a serialization buffer of the values of the VariableName, VendorGuid and Attributes
// parameters of the SetVariable() call and the TimeStamp component of the
@@ -2173,8 +2187,12 @@ VerifyTimeBasedPayload (
Exit:
if (AuthVarType == AuthVarTypePk || AuthVarType == AuthVarTypePriv) {
- Pkcs7FreeSigners (TopLevelCert);
- Pkcs7FreeSigners (SignerCerts);
+ if (TopLevelCert != NULL) {
+ Pkcs7FreeSigners (TopLevelCert);
+ }
+ if (SignerCerts != NULL) {
+ Pkcs7FreeSigners (SignerCerts);
+ }
}
if (!VerifyStatus) {
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
index a5be3e83ea9..6f94b63cebc 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
@@ -3,6 +3,7 @@
#
# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -41,6 +42,7 @@
MemoryAllocationLib
BaseCryptLib
PlatformSecureLib
+ VariablePolicyLib
[Guids]
## CONSUMES ## Variable:L"SetupMode"
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
index bf54f6525cc..275e86f6636 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c
@@ -59,7 +59,11 @@ UINT8 mHashOidValue[] = {
};
HASH_TABLE mHash[] = {
+#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
{ L"SHA1", 20, &mHashOidValue[0], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final },
+#else
+ { L"SHA1", 20, &mHashOidValue[0], 5, NULL, NULL, NULL, NULL },
+#endif
{ L"SHA224", 28, &mHashOidValue[5], 9, NULL, NULL, NULL, NULL },
{ L"SHA256", 32, &mHashOidValue[14], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final},
{ L"SHA384", 48, &mHashOidValue[23], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final},
@@ -315,10 +319,12 @@ HashPeImage (
ZeroMem (mImageDigest, MAX_DIGEST_SIZE);
switch (HashAlg) {
+#ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
case HASHALG_SHA1:
mImageDigestSize = SHA1_DIGEST_SIZE;
mCertType = gEfiCertSha1Guid;
break;
+#endif
case HASHALG_SHA256:
mImageDigestSize = SHA256_DIGEST_SIZE;
@@ -1465,7 +1471,7 @@ IsAllowedByDb (
//
// Fetch 'dbx' content. If 'dbx' doesn't exist, continue to check 'db'.
- // If any other errors occured, no need to check 'db' but just return
+ // If any other errors occurred, no need to check 'db' but just return
// not-allowed-by-db (FALSE) to avoid bypass.
//
DbxDataSize = 0;
@@ -1652,6 +1658,8 @@ DxeImageVerificationHandler (
UINT8 *AuthData;
UINTN AuthDataSize;
EFI_IMAGE_DATA_DIRECTORY *SecDataDir;
+ UINT32 SecDataDirEnd;
+ UINT32 SecDataDirLeft;
UINT32 OffSet;
CHAR16 *NameStr;
RETURN_STATUS PeCoffStatus;
@@ -1849,12 +1857,18 @@ DxeImageVerificationHandler (
// "Attribute Certificate Table".
// The first certificate starts at offset (SecDataDir->VirtualAddress) from the start of the file.
//
+ SecDataDirEnd = SecDataDir->VirtualAddress + SecDataDir->Size;
for (OffSet = SecDataDir->VirtualAddress;
- OffSet < (SecDataDir->VirtualAddress + SecDataDir->Size);
+ OffSet < SecDataDirEnd;
OffSet += (WinCertificate->dwLength + ALIGN_SIZE (WinCertificate->dwLength))) {
+ SecDataDirLeft = SecDataDirEnd - OffSet;
+ if (SecDataDirLeft <= sizeof (WIN_CERTIFICATE)) {
+ break;
+ }
WinCertificate = (WIN_CERTIFICATE *) (mImageBase + OffSet);
- if ((SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) <= sizeof (WIN_CERTIFICATE) ||
- (SecDataDir->VirtualAddress + SecDataDir->Size - OffSet) < WinCertificate->dwLength) {
+ if (SecDataDirLeft < WinCertificate->dwLength ||
+ (SecDataDirLeft - WinCertificate->dwLength <
+ ALIGN_SIZE (WinCertificate->dwLength))) {
break;
}
@@ -1948,7 +1962,7 @@ DxeImageVerificationHandler (
}
}
- if (OffSet != (SecDataDir->VirtualAddress + SecDataDir->Size)) {
+ if (OffSet != SecDataDirEnd) {
//
// The Size in Certificate Table or the attribute certificate table is corrupted.
//
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.c
new file mode 100644
index 00000000000..9636cbe8b57
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.c
@@ -0,0 +1,74 @@
+/** @file
+ This library is used by other modules to measure data to TPM.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/TpmMeasurementLib.h>
+
+#include <Ppi/Tcg.h>
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+/**
+ Tpm measure and log data, and extend the measurement result into a specific PCR.
+
+ @param[in] PcrIndex PCR Index.
+ @param[in] EventType Event type.
+ @param[in] EventLog Measurement event log.
+ @param[in] LogLen Event log length in bytes.
+ @param[in] HashData The start of the data buffer to be hashed, extended.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+TpmMeasureAndLogData (
+ IN UINT32 PcrIndex,
+ IN UINT32 EventType,
+ IN VOID *EventLog,
+ IN UINT32 LogLen,
+ IN VOID *HashData,
+ IN UINT64 HashDataLen
+ )
+{
+ EFI_STATUS Status;
+ EDKII_TCG_PPI *TcgPpi;
+ TCG_PCR_EVENT_HDR TcgEventHdr;
+
+ Status = PeiServicesLocatePpi (
+ &gEdkiiTcgPpiGuid,
+ 0,
+ NULL,
+ (VOID**)&TcgPpi
+ );
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ TcgEventHdr.PCRIndex = PcrIndex;
+ TcgEventHdr.EventType = EventType;
+ TcgEventHdr.EventSize = LogLen;
+
+ Status = TcgPpi->HashLogExtendEvent (
+ TcgPpi,
+ 0,
+ HashData,
+ (UINTN)HashDataLen,
+ &TcgEventHdr,
+ EventLog
+ );
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf
new file mode 100644
index 00000000000..e83c737fb1b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf
@@ -0,0 +1,49 @@
+## @file
+# Provides TPM measurement functions for TPM1.2 and TPM 2.0
+#
+# This library provides TpmMeasureAndLogData() to measure and log data, and
+# extend the measurement result into a specific PCR.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiTpmMeasurementLib
+ FILE_GUID = 9A62C49D-C45A-4322-9F3C-45958DF0056B
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = TpmMeasurementLib|PEIM
+ MODULE_UNI_FILE = PeiTpmMeasurementLib.uni
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ PeiTpmMeasurementLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ HobLib
+ DebugLib
+ PcdLib
+ PrintLib
+ PeiServicesLib
+ PeiServicesTablePointerLib
+
+[Ppis]
+ gEdkiiTcgPpiGuid ## CONSUMES
+
+[Depex]
+ gEfiPeiMasterBootModePpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.uni b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.uni
new file mode 100644
index 00000000000..7b4341b449f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Provides TPM measurement functions for TPM1.2 and TPM 2.0
+//
+// This library provides TpmMeasureAndLogData() to to measure and log data, and
+// extend the measurement result into a specific PCR.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Provides TPM measurement functions for TPM1.2 and TPM 2.0"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This library provides TpmMeasureAndLogData() to to measure and log data, and extend the measurement result into a specific PCR."
+
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.c
new file mode 100644
index 00000000000..12334b2c96c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.c
@@ -0,0 +1,398 @@
+/** @file
+ Handle TPM 2.0 physical presence requests from OS.
+
+ This library will handle TPM 2.0 physical presence request from OS.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable.
+ This external input must be validated carefully to avoid security issue.
+
+ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction()
+ will receive untrusted input and do validation.
+
+Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Guid/Tcg2PhysicalPresenceData.h>
+
+#include <Protocol/SmmVariable.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/Tcg2PpVendorLib.h>
+#include <Library/MmServicesTableLib.h>
+
+#define PP_INF_VERSION_1_2 "1.2"
+
+EFI_SMM_VARIABLE_PROTOCOL *mTcg2PpSmmVariable;
+BOOLEAN mIsTcg2PPVerLowerThan_1_3 = FALSE;
+UINT32 mTcg2PhysicalPresenceFlags;
+
+/**
+ The handler for TPM physical presence function:
+ Return TPM Operation Response to OS Environment.
+
+ This API should be invoked in OS runtime phase to interface with ACPI method.
+
+ @param[out] MostRecentRequest Most recent operation request.
+ @param[out] Response Response to the most recent operation request.
+
+ @return Return Code for Return TPM Operation Response to OS Environment.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
+ OUT UINT32 *MostRecentRequest,
+ OUT UINT32 *Response
+ )
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ EFI_TCG2_PHYSICAL_PRESENCE PpData;
+
+ DEBUG ((DEBUG_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
+
+ //
+ // Get the Physical Presence variable
+ //
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ Status = mTcg2PpSmmVariable->SmmGetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &PpData
+ );
+ if (EFI_ERROR (Status)) {
+ *MostRecentRequest = 0;
+ *Response = 0;
+ DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+ return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
+ }
+
+ *MostRecentRequest = PpData.LastPPRequest;
+ *Response = PpData.PPResponse;
+
+ return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
+}
+
+/**
+ The handler for TPM physical presence function:
+ Submit TPM Operation Request to Pre-OS Environment and
+ Submit TPM Operation Request to Pre-OS Environment 2.
+
+ This API should be invoked in OS runtime phase to interface with ACPI method.
+
+ Caution: This function may receive untrusted input.
+
+ @param[in, out] Pointer to OperationRequest TPM physical presence operation request.
+ @param[in, out] Pointer to RequestParameter TPM physical presence operation request parameter.
+
+ @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
+ Submit TPM Operation Request to Pre-OS Environment 2.
+ **/
+UINT32
+Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
+ IN OUT UINT32 *OperationRequest,
+ IN OUT UINT32 *RequestParameter
+ )
+{
+ EFI_STATUS Status;
+ UINT32 ReturnCode;
+ UINTN DataSize;
+ EFI_TCG2_PHYSICAL_PRESENCE PpData;
+ EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
+
+ DEBUG ((DEBUG_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", *OperationRequest, *RequestParameter));
+ ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
+
+ //
+ // Get the Physical Presence variable
+ //
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ Status = mTcg2PpSmmVariable->SmmGetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &PpData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+ ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
+ goto EXIT;
+ }
+
+ if ((*OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
+ (*OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
+ ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
+ goto EXIT;
+ }
+
+ if ((PpData.PPRequest != *OperationRequest) ||
+ (PpData.PPRequestParameter != *RequestParameter)) {
+ PpData.PPRequest = (UINT8)*OperationRequest;
+ PpData.PPRequestParameter = *RequestParameter;
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ Status = mTcg2PpSmmVariable->SmmSetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ DataSize,
+ &PpData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
+ ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
+ goto EXIT;
+ }
+ }
+
+ if (*OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+ Status = mTcg2PpSmmVariable->SmmGetVariable (
+ TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ Flags.PPFlags = mTcg2PhysicalPresenceFlags;
+ }
+ ReturnCode = Tcg2PpVendorLibSubmitRequestToPreOSFunction (*OperationRequest, Flags.PPFlags, *RequestParameter);
+ }
+
+EXIT:
+ //
+ // Sync PPRQ/PPRM from PP Variable if PP submission fails
+ //
+ if (ReturnCode != TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
+ DEBUG ((DEBUG_ERROR, "[TPM2] Submit PP Request failure! Sync PPRQ/PPRM with PP variable.\n", Status));
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ ZeroMem(&PpData, DataSize);
+ Status = mTcg2PpSmmVariable->SmmGetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &PpData
+ );
+ *OperationRequest = (UINT32)PpData.PPRequest;
+ *RequestParameter = PpData.PPRequestParameter;
+ }
+
+ return ReturnCode;
+}
+
+/**
+ The handler for TPM physical presence function:
+ Submit TPM Operation Request to Pre-OS Environment and
+ Submit TPM Operation Request to Pre-OS Environment 2.
+
+ This API should be invoked in OS runtime phase to interface with ACPI method.
+
+ Caution: This function may receive untrusted input.
+
+ @param[in] OperationRequest TPM physical presence operation request.
+ @param[in] RequestParameter TPM physical presence operation request parameter.
+
+ @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
+ Submit TPM Operation Request to Pre-OS Environment 2.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
+ IN UINT32 OperationRequest,
+ IN UINT32 RequestParameter
+ )
+{
+ UINT32 TempOperationRequest;
+ UINT32 TempRequestParameter;
+
+ TempOperationRequest = OperationRequest;
+ TempRequestParameter = RequestParameter;
+
+ return Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx(&TempOperationRequest, &TempRequestParameter);
+}
+
+/**
+ The handler for TPM physical presence function:
+ Get User Confirmation Status for Operation.
+
+ This API should be invoked in OS runtime phase to interface with ACPI method.
+
+ Caution: This function may receive untrusted input.
+
+ @param[in] OperationRequest TPM physical presence operation request.
+
+ @return Return Code for Get User Confirmation Status for Operation.
+**/
+UINT32
+EFIAPI
+Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
+ IN UINT32 OperationRequest
+ )
+{
+ EFI_STATUS Status;
+ UINTN DataSize;
+ EFI_TCG2_PHYSICAL_PRESENCE PpData;
+ EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
+ BOOLEAN RequestConfirmed;
+
+ DEBUG ((DEBUG_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest));
+
+ //
+ // Get the Physical Presence variable
+ //
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
+ Status = mTcg2PpSmmVariable->SmmGetVariable (
+ TCG2_PHYSICAL_PRESENCE_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &PpData
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
+ return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
+ }
+ //
+ // Get the Physical Presence flags
+ //
+ DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
+ Status = mTcg2PpSmmVariable->SmmGetVariable (
+ TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
+ &gEfiTcg2PhysicalPresenceGuid,
+ NULL,
+ &DataSize,
+ &Flags
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
+ return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
+ }
+
+ RequestConfirmed = FALSE;
+
+ switch (OperationRequest) {
+ case TCG2_PHYSICAL_PRESENCE_CLEAR:
+ case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
+ case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
+ case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
+ if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
+ case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
+ RequestConfirmed = TRUE;
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
+ if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
+ if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
+ RequestConfirmed = TRUE;
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
+ if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
+ if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
+ RequestConfirmed = TRUE;
+ }
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
+ case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
+ RequestConfirmed = TRUE;
+ break;
+
+ case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
+ case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
+ break;
+
+ default:
+ if (!mIsTcg2PPVerLowerThan_1_3) {
+ if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+ //
+ // TCG2 PP1.3 spec defined operations that are reserved or un-implemented
+ //
+ return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
+ }
+ } else {
+ //
+ // TCG PP lower than 1.3. (1.0, 1.1, 1.2)
+ //
+ if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
+ RequestConfirmed = TRUE;
+ } else if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+ return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
+ }
+ }
+ break;
+ }
+
+ if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
+ return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
+ }
+
+ if (RequestConfirmed) {
+ return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
+ } else {
+ return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
+ }
+}
+
+/**
+ The constructor function locates SmmVariable protocol.
+
+ It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor successfully added string package.
+ @retval Other value The constructor can't add string package.
+**/
+EFI_STATUS
+Tcg2PhysicalPresenceLibCommonConstructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ if (AsciiStrnCmp(PP_INF_VERSION_1_2, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer), sizeof(PP_INF_VERSION_1_2) - 1) >= 0) {
+ mIsTcg2PPVerLowerThan_1_3 = TRUE;
+ }
+
+ //
+ // Locate SmmVariableProtocol.
+ //
+ Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
+ ASSERT_EFI_ERROR (Status);
+
+ mTcg2PhysicalPresenceFlags = PcdGet32(PcdTcg2PhysicalPresenceFlags);
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.h
new file mode 100644
index 00000000000..5dabb4c2c7f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/MmTcg2PhysicalPresenceLibCommon.h
@@ -0,0 +1,34 @@
+/** @file
+ Handle TPM 2.0 physical presence requests from OS.
+
+ This library will handle TPM 2.0 physical presence request from OS.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable.
+ This external input must be validated carefully to avoid security issue.
+
+ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction()
+ will receive untrusted input and do validation.
+
+Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _MM_TCG2_PHYSICAL_PRESENCE_LIB_COMMON_H_
+#define _MM_TCG2_PHYSICAL_PRESENCE_LIB_COMMON_H_
+
+/**
+ The constructor function locates MmVariable protocol.
+
+ It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The constructor successfully added string package.
+ @retval Other value The constructor can't add string package.
+**/
+EFI_STATUS
+Tcg2PhysicalPresenceLibCommonConstructor (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c
index 84484bfad6f..d43f16111d6 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.c
@@ -17,355 +17,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <PiSmm.h>
-#include <Guid/Tcg2PhysicalPresenceData.h>
-
-#include <Protocol/SmmVariable.h>
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/Tcg2PpVendorLib.h>
-#include <Library/SmmServicesTableLib.h>
-
-#define PP_INF_VERSION_1_2 "1.2"
-
-EFI_SMM_VARIABLE_PROTOCOL *mTcg2PpSmmVariable;
-BOOLEAN mIsTcg2PPVerLowerThan_1_3 = FALSE;
-UINT32 mTcg2PhysicalPresenceFlags;
-
-/**
- The handler for TPM physical presence function:
- Return TPM Operation Response to OS Environment.
-
- This API should be invoked in OS runtime phase to interface with ACPI method.
-
- @param[out] MostRecentRequest Most recent operation request.
- @param[out] Response Response to the most recent operation request.
-
- @return Return Code for Return TPM Operation Response to OS Environment.
-**/
-UINT32
-EFIAPI
-Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (
- OUT UINT32 *MostRecentRequest,
- OUT UINT32 *Response
- )
-{
- EFI_STATUS Status;
- UINTN DataSize;
- EFI_TCG2_PHYSICAL_PRESENCE PpData;
-
- DEBUG ((EFI_D_INFO, "[TPM2] ReturnOperationResponseToOsFunction\n"));
-
- //
- // Get the Physical Presence variable
- //
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
- Status = mTcg2PpSmmVariable->SmmGetVariable (
- TCG2_PHYSICAL_PRESENCE_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- NULL,
- &DataSize,
- &PpData
- );
- if (EFI_ERROR (Status)) {
- *MostRecentRequest = 0;
- *Response = 0;
- DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
- return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_FAILURE;
- }
-
- *MostRecentRequest = PpData.LastPPRequest;
- *Response = PpData.PPResponse;
-
- return TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS;
-}
-
-/**
- The handler for TPM physical presence function:
- Submit TPM Operation Request to Pre-OS Environment and
- Submit TPM Operation Request to Pre-OS Environment 2.
-
- This API should be invoked in OS runtime phase to interface with ACPI method.
-
- Caution: This function may receive untrusted input.
-
- @param[in, out] Pointer to OperationRequest TPM physical presence operation request.
- @param[in, out] Pointer to RequestParameter TPM physical presence operation request parameter.
-
- @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
- Submit TPM Operation Request to Pre-OS Environment 2.
- **/
-UINT32
-Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx (
- IN OUT UINT32 *OperationRequest,
- IN OUT UINT32 *RequestParameter
- )
-{
- EFI_STATUS Status;
- UINT32 ReturnCode;
- UINTN DataSize;
- EFI_TCG2_PHYSICAL_PRESENCE PpData;
- EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
-
- DEBUG ((EFI_D_INFO, "[TPM2] SubmitRequestToPreOSFunction, Request = %x, %x\n", *OperationRequest, *RequestParameter));
- ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS;
-
- //
- // Get the Physical Presence variable
- //
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
- Status = mTcg2PpSmmVariable->SmmGetVariable (
- TCG2_PHYSICAL_PRESENCE_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- NULL,
- &DataSize,
- &PpData
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
- ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
- goto EXIT;
- }
-
- if ((*OperationRequest > TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) &&
- (*OperationRequest < TCG2_PHYSICAL_PRESENCE_STORAGE_MANAGEMENT_BEGIN) ) {
- ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_NOT_IMPLEMENTED;
- goto EXIT;
- }
-
- if ((PpData.PPRequest != *OperationRequest) ||
- (PpData.PPRequestParameter != *RequestParameter)) {
- PpData.PPRequest = (UINT8)*OperationRequest;
- PpData.PPRequestParameter = *RequestParameter;
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
- Status = mTcg2PpSmmVariable->SmmSetVariable (
- TCG2_PHYSICAL_PRESENCE_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- DataSize,
- &PpData
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "[TPM2] Set PP variable failure! Status = %r\n", Status));
- ReturnCode = TCG_PP_SUBMIT_REQUEST_TO_PREOS_GENERAL_FAILURE;
- goto EXIT;
- }
- }
-
- if (*OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
- Status = mTcg2PpSmmVariable->SmmGetVariable (
- TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- NULL,
- &DataSize,
- &Flags
- );
- if (EFI_ERROR (Status)) {
- Flags.PPFlags = mTcg2PhysicalPresenceFlags;
- }
- ReturnCode = Tcg2PpVendorLibSubmitRequestToPreOSFunction (*OperationRequest, Flags.PPFlags, *RequestParameter);
- }
-
-EXIT:
- //
- // Sync PPRQ/PPRM from PP Variable if PP submission fails
- //
- if (ReturnCode != TCG_PP_SUBMIT_REQUEST_TO_PREOS_SUCCESS) {
- DEBUG ((EFI_D_ERROR, "[TPM2] Submit PP Request failure! Sync PPRQ/PPRM with PP variable.\n", Status));
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
- ZeroMem(&PpData, DataSize);
- Status = mTcg2PpSmmVariable->SmmGetVariable (
- TCG2_PHYSICAL_PRESENCE_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- NULL,
- &DataSize,
- &PpData
- );
- *OperationRequest = (UINT32)PpData.PPRequest;
- *RequestParameter = PpData.PPRequestParameter;
- }
-
- return ReturnCode;
-}
-
-/**
- The handler for TPM physical presence function:
- Submit TPM Operation Request to Pre-OS Environment and
- Submit TPM Operation Request to Pre-OS Environment 2.
-
- This API should be invoked in OS runtime phase to interface with ACPI method.
-
- Caution: This function may receive untrusted input.
-
- @param[in] OperationRequest TPM physical presence operation request.
- @param[in] RequestParameter TPM physical presence operation request parameter.
-
- @return Return Code for Submit TPM Operation Request to Pre-OS Environment and
- Submit TPM Operation Request to Pre-OS Environment 2.
-**/
-UINT32
-EFIAPI
-Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction (
- IN UINT32 OperationRequest,
- IN UINT32 RequestParameter
- )
-{
- UINT32 TempOperationRequest;
- UINT32 TempRequestParameter;
-
- TempOperationRequest = OperationRequest;
- TempRequestParameter = RequestParameter;
-
- return Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunctionEx(&TempOperationRequest, &TempRequestParameter);
-}
-
-/**
- The handler for TPM physical presence function:
- Get User Confirmation Status for Operation.
-
- This API should be invoked in OS runtime phase to interface with ACPI method.
-
- Caution: This function may receive untrusted input.
-
- @param[in] OperationRequest TPM physical presence operation request.
-
- @return Return Code for Get User Confirmation Status for Operation.
-**/
-UINT32
-EFIAPI
-Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
- IN UINT32 OperationRequest
- )
-{
- EFI_STATUS Status;
- UINTN DataSize;
- EFI_TCG2_PHYSICAL_PRESENCE PpData;
- EFI_TCG2_PHYSICAL_PRESENCE_FLAGS Flags;
- BOOLEAN RequestConfirmed;
-
- DEBUG ((EFI_D_INFO, "[TPM2] GetUserConfirmationStatusFunction, Request = %x\n", OperationRequest));
-
- //
- // Get the Physical Presence variable
- //
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE);
- Status = mTcg2PpSmmVariable->SmmGetVariable (
- TCG2_PHYSICAL_PRESENCE_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- NULL,
- &DataSize,
- &PpData
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "[TPM2] Get PP variable failure! Status = %r\n", Status));
- return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
- }
- //
- // Get the Physical Presence flags
- //
- DataSize = sizeof (EFI_TCG2_PHYSICAL_PRESENCE_FLAGS);
- Status = mTcg2PpSmmVariable->SmmGetVariable (
- TCG2_PHYSICAL_PRESENCE_FLAGS_VARIABLE,
- &gEfiTcg2PhysicalPresenceGuid,
- NULL,
- &DataSize,
- &Flags
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((EFI_D_ERROR, "[TPM2] Get PP flags failure! Status = %r\n", Status));
- return TCG_PP_GET_USER_CONFIRMATION_BLOCKED_BY_BIOS_CONFIGURATION;
- }
-
- RequestConfirmed = FALSE;
-
- switch (OperationRequest) {
- case TCG2_PHYSICAL_PRESENCE_CLEAR:
- case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR:
- case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_2:
- case TCG2_PHYSICAL_PRESENCE_ENABLE_CLEAR_3:
- if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CLEAR) == 0) {
- RequestConfirmed = TRUE;
- }
- break;
-
- case TCG2_PHYSICAL_PRESENCE_NO_ACTION:
- case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_TRUE:
- RequestConfirmed = TRUE;
- break;
-
- case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_CLEAR_FALSE:
- break;
-
- case TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS:
- if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_PCRS) == 0) {
- RequestConfirmed = TRUE;
- }
- break;
-
- case TCG2_PHYSICAL_PRESENCE_CHANGE_EPS:
- if ((Flags.PPFlags & TCG2_BIOS_TPM_MANAGEMENT_FLAG_PP_REQUIRED_FOR_CHANGE_EPS) == 0) {
- RequestConfirmed = TRUE;
- }
- break;
-
- case TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS:
- RequestConfirmed = TRUE;
- break;
-
- case TCG2_PHYSICAL_PRESENCE_ENABLE_BLOCK_SID:
- if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_ENABLE_BLOCK_SID) == 0) {
- RequestConfirmed = TRUE;
- }
- break;
-
- case TCG2_PHYSICAL_PRESENCE_DISABLE_BLOCK_SID:
- if ((Flags.PPFlags & TCG2_BIOS_STORAGE_MANAGEMENT_FLAG_PP_REQUIRED_FOR_DISABLE_BLOCK_SID) == 0) {
- RequestConfirmed = TRUE;
- }
- break;
-
- case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_TRUE:
- case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_TRUE:
- RequestConfirmed = TRUE;
- break;
-
- case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_ENABLE_BLOCK_SID_FUNC_FALSE:
- case TCG2_PHYSICAL_PRESENCE_SET_PP_REQUIRED_FOR_DISABLE_BLOCK_SID_FUNC_FALSE:
- break;
-
- default:
- if (!mIsTcg2PPVerLowerThan_1_3) {
- if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
- //
- // TCG2 PP1.3 spec defined operations that are reserved or un-implemented
- //
- return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
- }
- } else {
- //
- // TCG PP lower than 1.3. (1.0, 1.1, 1.2)
- //
- if (OperationRequest <= TCG2_PHYSICAL_PRESENCE_NO_ACTION_MAX) {
- RequestConfirmed = TRUE;
- } else if (OperationRequest < TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
- return TCG_PP_GET_USER_CONFIRMATION_NOT_IMPLEMENTED;
- }
- }
- break;
- }
-
- if (OperationRequest >= TCG2_PHYSICAL_PRESENCE_VENDOR_SPECIFIC_OPERATION) {
- return Tcg2PpVendorLibGetUserConfirmationStatusFunction (OperationRequest, Flags.PPFlags);
- }
-
- if (RequestConfirmed) {
- return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_NOT_REQUIRED;
- } else {
- return TCG_PP_GET_USER_CONFIRMATION_ALLOWED_AND_PPUSER_REQUIRED;
- }
-}
+#include "MmTcg2PhysicalPresenceLibCommon.h"
/**
The constructor function locates SmmVariable protocol.
@@ -380,24 +32,10 @@ Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction (
**/
EFI_STATUS
EFIAPI
-Tcg2PhysicalPresenceLibConstructor (
+Tcg2PhysicalPresenceLibTraditionalConstructor (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
-
- if (AsciiStrnCmp(PP_INF_VERSION_1_2, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer), sizeof(PP_INF_VERSION_1_2) - 1) <= 0) {
- mIsTcg2PPVerLowerThan_1_3 = TRUE;
- }
-
- //
- // Locate SmmVariableProtocol.
- //
- Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mTcg2PpSmmVariable);
- ASSERT_EFI_ERROR (Status);
-
- mTcg2PhysicalPresenceFlags = PcdGet32(PcdTcg2PhysicalPresenceFlags);
-
- return EFI_SUCCESS;
+ return Tcg2PhysicalPresenceLibCommonConstructor ();
}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
index 9dd651f2d8e..b60073cc08c 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
@@ -20,7 +20,7 @@
MODULE_TYPE = DXE_SMM_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = Tcg2PhysicalPresenceLib|DXE_SMM_DRIVER
- CONSTRUCTOR = Tcg2PhysicalPresenceLibConstructor
+ CONSTRUCTOR = Tcg2PhysicalPresenceLibTraditionalConstructor
#
# The following information is for reference only and not required by the build tools.
@@ -30,6 +30,8 @@
[Sources]
SmmTcg2PhysicalPresenceLib.c
+ MmTcg2PhysicalPresenceLibCommon.c
+ MmTcg2PhysicalPresenceLibCommon.h
[Packages]
MdePkg/MdePkg.dec
@@ -39,7 +41,7 @@
[LibraryClasses]
DebugLib
Tcg2PpVendorLib
- SmmServicesTableLib
+ MmServicesTableLib
BaseMemoryLib
[Guids]
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.c
new file mode 100644
index 00000000000..87d9e634306
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.c
@@ -0,0 +1,42 @@
+/** @file
+ Handle TPM 2.0 physical presence requests from OS.
+
+ This library will handle TPM 2.0 physical presence request from OS.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable.
+ This external input must be validated carefully to avoid security issue.
+
+ Tcg2PhysicalPresenceLibSubmitRequestToPreOSFunction() and Tcg2PhysicalPresenceLibGetUserConfirmationStatusFunction()
+ will receive untrusted input and do validation.
+
+Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include "MmTcg2PhysicalPresenceLibCommon.h"
+
+/**
+ The constructor function locates SmmVariable protocol.
+
+ It will ASSERT() if that operation fails and it will always return EFI_SUCCESS.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The constructor successfully added string package.
+ @retval Other value The constructor can't add string package.
+**/
+EFI_STATUS
+EFIAPI
+Tcg2PhysicalPresenceLibStandaloneMmConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return Tcg2PhysicalPresenceLibCommonConstructor ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf
new file mode 100644
index 00000000000..1b69efe80b6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf
@@ -0,0 +1,62 @@
+## @file
+# Handle TPM 2.0 physical presence requests from OS.
+#
+# This library will handle TPM 2.0 physical presence request from OS.
+#
+# Caution: This module requires additional review when modified.
+# This driver will have external input - variable.
+# This external input must be validated carefully to avoid security issue.
+#
+# Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = StandaloneMmTcg2PhysicalPresenceLib
+ FILE_GUID = 75E3D07B-689C-4F42-A8A0-46AFAE868A6F
+ MODULE_TYPE = MM_STANDALONE
+ PI_SPECIFICATION_VERSION = 0x00010032
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Tcg2PhysicalPresenceLib|MM_STANDALONE
+ CONSTRUCTOR = Tcg2PhysicalPresenceLibStandaloneMmConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ StandaloneMmTcg2PhysicalPresenceLib.c
+ MmTcg2PhysicalPresenceLibCommon.c
+ MmTcg2PhysicalPresenceLibCommon.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ Tcg2PpVendorLib
+ MmServicesTableLib
+ BaseMemoryLib
+
+[Guids]
+ ## SOMETIMES_PRODUCES ## Variable:L"PhysicalPresence"
+ ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresence"
+ ## SOMETIMES_CONSUMES ## Variable:L"PhysicalPresenceFlags"
+ gEfiTcg2PhysicalPresenceGuid
+
+[Protocols]
+ gEfiSmmVariableProtocolGuid ## CONSUMES
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcg2PhysicalPresenceFlags ## SOMETIMES_CONSUMES
+
+[Depex]
+ gEfiSmmVariableProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
index a602d79c102..71ab08622c7 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
@@ -13,7 +13,7 @@
FILE_GUID = 51924AE9-BE81-4820-94BA-7C9546E702D0
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
- LIBRARY_CLASS = Tcg2PpVendorLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_DRIVER
+ LIBRARY_CLASS = Tcg2PpVendorLib|DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_DRIVER MM_STANDALONE
#
# The following information is for reference only and not required by the build tools.
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c
new file mode 100644
index 00000000000..02dbbeb976a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.c
@@ -0,0 +1,197 @@
+/** @file
+ This library is used by other modules to measure data to TPM.
+
+Copyright (c) 2020, Intel Corporation. All rights reserved. <BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Pi/PiFirmwareVolume.h>
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ReportStatusCodeLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TcgEventLogRecordLib.h>
+#include <Library/TpmMeasurementLib.h>
+
+#include <IndustryStandard/UefiTcgPlatform.h>
+
+/**
+ Get the FvName from the FV header.
+
+ Causion: The FV is untrusted input.
+
+ @param[in] FvBase Base address of FV image.
+ @param[in] FvLength Length of FV image.
+
+ @return FvName pointer
+ @retval NULL FvName is NOT found
+**/
+VOID *
+TpmMeasurementGetFvName (
+ IN EFI_PHYSICAL_ADDRESS FvBase,
+ IN UINT64 FvLength
+ )
+{
+ EFI_FIRMWARE_VOLUME_HEADER *FvHeader;
+ EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader;
+
+ if (FvBase >= MAX_ADDRESS) {
+ return NULL;
+ }
+ if (FvLength >= MAX_ADDRESS - FvBase) {
+ return NULL;
+ }
+ if (FvLength < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
+ return NULL;
+ }
+
+ FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)FvBase;
+ if (FvHeader->Signature != EFI_FVH_SIGNATURE) {
+ return NULL;
+ }
+ if (FvHeader->ExtHeaderOffset < sizeof(EFI_FIRMWARE_VOLUME_HEADER)) {
+ return NULL;
+ }
+ if (FvHeader->ExtHeaderOffset + sizeof(EFI_FIRMWARE_VOLUME_EXT_HEADER) > FvLength) {
+ return NULL;
+ }
+ FvExtHeader = (EFI_FIRMWARE_VOLUME_EXT_HEADER *)(UINTN)(FvBase + FvHeader->ExtHeaderOffset);
+
+ return &FvExtHeader->FvName;
+}
+
+/**
+ Measure a FirmwareBlob.
+
+ @param[in] PcrIndex PcrIndex of the measurement.
+ @param[in] Description Description for this FirmwareBlob.
+ @param[in] FirmwareBlobBase Base address of this FirmwareBlob.
+ @param[in] FirmwareBlobLength Size in bytes of this FirmwareBlob.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+MeasureFirmwareBlob (
+ IN UINT32 PcrIndex,
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_PHYSICAL_ADDRESS FirmwareBlobBase,
+ IN UINT64 FirmwareBlobLength
+ )
+{
+ EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
+ PLATFORM_FIRMWARE_BLOB2_STRUCT FvBlob2;
+ VOID *FvName;
+ UINT32 EventType;
+ VOID *EventLog;
+ UINT32 EventLogSize;
+ EFI_STATUS Status;
+
+ FvName = TpmMeasurementGetFvName (FirmwareBlobBase, FirmwareBlobLength);
+
+ if (((Description != NULL) || (FvName != NULL)) &&
+ (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) {
+ if (Description != NULL) {
+ AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "%a", Description);
+ } else {
+ AsciiSPrint((CHAR8*)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);
+ }
+
+ FvBlob2.BlobDescriptionSize = sizeof(FvBlob2.BlobDescription);
+ FvBlob2.BlobBase = FirmwareBlobBase;
+ FvBlob2.BlobLength = FirmwareBlobLength;
+
+ EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
+ EventLog = &FvBlob2;
+ EventLogSize = sizeof(FvBlob2);
+ } else {
+ FvBlob.BlobBase = FirmwareBlobBase;
+ FvBlob.BlobLength = FirmwareBlobLength;
+
+ EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
+ EventLog = &FvBlob;
+ EventLogSize = sizeof(FvBlob);
+ }
+
+ Status = TpmMeasureAndLogData (
+ PcrIndex,
+ EventType,
+ EventLog,
+ EventLogSize,
+ (VOID*)(UINTN)FirmwareBlobBase,
+ FirmwareBlobLength
+ );
+
+ return Status;
+}
+
+/**
+ Measure a HandoffTable.
+
+ @param[in] PcrIndex PcrIndex of the measurement.
+ @param[in] Description Description for this HandoffTable.
+ @param[in] TableGuid GUID of this HandoffTable.
+ @param[in] TableAddress Base address of this HandoffTable.
+ @param[in] TableLength Size in bytes of this HandoffTable.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_UNSUPPORTED TPM device not available.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR The operation was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+MeasureHandoffTable (
+ IN UINT32 PcrIndex,
+ IN CHAR8 *Description OPTIONAL,
+ IN EFI_GUID *TableGuid,
+ IN VOID *TableAddress,
+ IN UINTN TableLength
+ )
+{
+ EFI_HANDOFF_TABLE_POINTERS HandoffTables;
+ HANDOFF_TABLE_POINTERS2_STRUCT HandoffTables2;
+ UINT32 EventType;
+ VOID *EventLog;
+ UINT32 EventLogSize;
+ EFI_STATUS Status;
+
+ if ((Description != NULL) &&
+ (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105)) {
+ AsciiSPrint((CHAR8*)HandoffTables2.TableDescription, sizeof(HandoffTables2.TableDescription), "%a", Description);
+
+ HandoffTables2.TableDescriptionSize = sizeof(HandoffTables2.TableDescription);
+ HandoffTables2.NumberOfTables = 1;
+ CopyGuid (&(HandoffTables2.TableEntry[0].VendorGuid), TableGuid);
+ HandoffTables2.TableEntry[0].VendorTable = TableAddress;
+
+ EventType = EV_EFI_HANDOFF_TABLES2;
+ EventLog = &HandoffTables2;
+ EventLogSize = sizeof(HandoffTables2);
+ } else {
+ HandoffTables.NumberOfTables = 1;
+ CopyGuid (&(HandoffTables.TableEntry[0].VendorGuid), TableGuid);
+ HandoffTables.TableEntry[0].VendorTable = TableAddress;
+
+ EventType = EV_EFI_HANDOFF_TABLES;
+ EventLog = &HandoffTables;
+ EventLogSize = sizeof(HandoffTables);
+ }
+
+ Status = TpmMeasureAndLogData (
+ PcrIndex,
+ EventType,
+ EventLog,
+ EventLogSize,
+ TableAddress,
+ TableLength
+ );
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf
new file mode 100644
index 00000000000..567cb4366b6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf
@@ -0,0 +1,40 @@
+## @file
+# Provides interface for firmwware TPM measurement
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = TcgEventLogRecordLib
+ MODULE_UNI_FILE = TcgEventLogRecordLib.uni
+ FILE_GUID = F8125B2A-3922-4A22-A6F8-3B6159A25A3B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ TcgEventLogRecordLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PcdLib
+ TpmMeasurementLib
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni
new file mode 100644
index 00000000000..b1ca410074d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.uni
@@ -0,0 +1,17 @@
+// /** @file
+// Provides interface for firmwware TPM measurement
+//
+// This library provides MeasureFirmwareBlob() and MeasureHandoffTable()
+// to measure and log data, and extend the measurement result into a specific PCR.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Provides Firmware TPM measurement functions for TPM1.2 and TPM 2.0"
+
+#string STR_MODULE_DESCRIPTION #language en-US "This library provides MeasureFirmwareBlob() and MeasureHandoffTable() to measure and log data, and extend the measurement result into a specific PCR."
+
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
index 70d4a0f4fad..d33540fb304 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2CommandLib/Tpm2Capability.c
@@ -39,6 +39,8 @@ typedef struct {
#pragma pack()
+#define TPMA_CC_COMMANDINDEX_MASK 0x2000FFFF
+
/**
This command returns various information regarding the TPM and its current state.
@@ -629,6 +631,44 @@ Tpm2GetCapabilityAlgorithmSet (
}
/**
+ This function will query if the command is supported.
+
+ @param[In] Command TPM_CC command starts from TPM_CC_FIRST.
+ @param[out] IsCmdImpl The command is supported or not.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+**/
+EFI_STATUS
+EFIAPI
+Tpm2GetCapabilityIsCommandImplemented (
+ IN TPM_CC Command,
+ OUT BOOLEAN *IsCmdImpl
+ )
+{
+ TPMS_CAPABILITY_DATA TpmCap;
+ TPMI_YES_NO MoreData;
+ EFI_STATUS Status;
+ UINT32 Attribute;
+
+ Status = Tpm2GetCapability (
+ TPM_CAP_COMMANDS,
+ Command,
+ 1,
+ &MoreData,
+ &TpmCap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ CopyMem (&Attribute, &TpmCap.data.command.commandAttributes[0], sizeof (UINT32));
+ *IsCmdImpl = (Command == (SwapBytes32(Attribute) & TPMA_CC_COMMANDINDEX_MASK));
+
+ return EFI_SUCCESS;
+}
+
+/**
This command is used to check to see if specific combinations of algorithm parameters are supported.
@param[in] Parameters Algorithm parameters to be validated
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c
index c515cd341dc..e15cbd72b7d 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.c
@@ -13,29 +13,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/Tpm2DeviceLib.h>
#include <Library/PcdLib.h>
-/**
- Return PTP interface type.
-
- @param[in] Register Pointer to PTP register.
-
- @return PTP interface type.
-**/
-TPM2_PTP_INTERFACE_TYPE
-Tpm2GetPtpInterface (
- IN VOID *Register
- );
-
-/**
- Return PTP CRB interface IdleByPass state.
-
- @param[in] Register Pointer to PTP register.
-
- @return PTP CRB interface IdleByPass state.
-**/
-UINT8
-Tpm2GetIdleByPass (
- IN VOID *Register
- );
+#include "Tpm2DeviceLibDTpm.h"
/**
This service enables the sending of commands to the TPM2.
@@ -145,21 +123,5 @@ Tpm2DeviceLibConstructor (
VOID
)
{
- TPM2_PTP_INTERFACE_TYPE PtpInterface;
- UINT8 IdleByPass;
-
- //
- // Cache current active TpmInterfaceType only when needed
- //
- if (PcdGet8(PcdActiveTpmInterfaceType) == 0xFF) {
- PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
- PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
- }
-
- if (PcdGet8(PcdActiveTpmInterfaceType) == Tpm2PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
- IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
- PcdSet8S(PcdCRBIdleByPass, IdleByPass);
- }
-
- return EFI_SUCCESS;
+ return InternalTpm2DeviceLibDTpmCommonConstructor ();
}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.h
new file mode 100644
index 00000000000..bf62f3395e9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.h
@@ -0,0 +1,67 @@
+/** @file
+ This header file includes common internal fuction prototypes.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _TPM2_DEVICE_LIB_DTPM_H_
+#define _TPM2_DEVICE_LIB_DTPM_H_
+
+/**
+ Return PTP interface type.
+
+ @param[in] Register Pointer to PTP register.
+
+ @return PTP interface type.
+**/
+TPM2_PTP_INTERFACE_TYPE
+Tpm2GetPtpInterface (
+ IN VOID *Register
+ );
+
+/**
+ Return PTP CRB interface IdleByPass state.
+
+ @param[in] Register Pointer to PTP register.
+
+ @return PTP CRB interface IdleByPass state.
+**/
+UINT8
+Tpm2GetIdleByPass (
+ IN VOID *Register
+ );
+
+/**
+ Return cached PTP interface type.
+
+ @return Cached PTP interface type.
+**/
+TPM2_PTP_INTERFACE_TYPE
+GetCachedPtpInterface (
+ VOID
+ );
+
+/**
+ Return cached PTP CRB interface IdleByPass state.
+
+ @return Cached PTP CRB interface IdleByPass state.
+**/
+UINT8
+GetCachedIdleByPass (
+ VOID
+ );
+
+/**
+ The common function cache current active TpmInterfaceType when needed.
+
+ @retval EFI_SUCCESS DTPM2.0 instance is registered, or system does not support register DTPM2.0 instance
+**/
+EFI_STATUS
+InternalTpm2DeviceLibDTpmCommonConstructor (
+ VOID
+ );
+
+#endif // _TPM2_DEVICE_LIB_DTPM_H_
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
index a36767c9a56..e10d842fc87 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
@@ -11,6 +11,7 @@
# only uses TPM 2.0 DTPM device.
#
# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -34,6 +35,8 @@
Tpm2Tis.c
Tpm2Ptp.c
Tpm2DeviceLibDTpm.c
+ Tpm2DeviceLibDTpmBase.c
+ Tpm2DeviceLibDTpm.h
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmBase.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmBase.c
new file mode 100644
index 00000000000..43ac13eda57
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmBase.c
@@ -0,0 +1,68 @@
+/** @file
+ This file abstract internal interfaces of which implementation differs per library instance.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/PcdLib.h>
+
+#include "Tpm2DeviceLibDTpm.h"
+
+/**
+ Return cached PTP CRB interface IdleByPass state.
+
+ @return Cached PTP CRB interface IdleByPass state.
+**/
+UINT8
+GetCachedIdleByPass (
+ VOID
+ )
+{
+ return PcdGet8(PcdCRBIdleByPass);
+}
+
+/**
+ Return cached PTP interface type.
+
+ @return Cached PTP interface type.
+**/
+TPM2_PTP_INTERFACE_TYPE
+GetCachedPtpInterface (
+ VOID
+ )
+{
+ return PcdGet8(PcdActiveTpmInterfaceType);
+}
+
+/**
+ The common function cache current active TpmInterfaceType when needed.
+
+ @retval EFI_SUCCESS DTPM2.0 instance is registered, or system does not support register DTPM2.0 instance
+**/
+EFI_STATUS
+InternalTpm2DeviceLibDTpmCommonConstructor (
+ VOID
+ )
+{
+ TPM2_PTP_INTERFACE_TYPE PtpInterface;
+ UINT8 IdleByPass;
+
+ //
+ // Cache current active TpmInterfaceType only when needed
+ //
+ if (PcdGet8(PcdActiveTpmInterfaceType) == 0xFF) {
+ PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
+ PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
+ }
+
+ if (PcdGet8(PcdActiveTpmInterfaceType) == Tpm2PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
+ IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
+ PcdSet8S(PcdCRBIdleByPass, IdleByPass);
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.c
new file mode 100644
index 00000000000..4f1079b746e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.c
@@ -0,0 +1,66 @@
+/** @file
+ This file abstract internal interfaces of which implementation differs per library instance.
+
+Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved. <BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/Tpm2DeviceLib.h>
+
+#include "Tpm2DeviceLibDTpm.h"
+
+TPM2_PTP_INTERFACE_TYPE mActiveTpmInterfaceType;
+UINT8 mCRBIdleByPass;
+
+/**
+ Return cached PTP CRB interface IdleByPass state.
+
+ @return Cached PTP CRB interface IdleByPass state.
+**/
+UINT8
+GetCachedIdleByPass (
+ VOID
+ )
+{
+ return mCRBIdleByPass;
+}
+
+/**
+ Return cached PTP interface type.
+
+ @return Cached PTP interface type.
+**/
+TPM2_PTP_INTERFACE_TYPE
+GetCachedPtpInterface (
+ VOID
+ )
+{
+ return mActiveTpmInterfaceType;
+}
+
+/**
+ The common function cache current active TpmInterfaceType when needed.
+
+ @retval EFI_SUCCESS DTPM2.0 instance is registered, or system does not support register DTPM2.0 instance
+**/
+EFI_STATUS
+InternalTpm2DeviceLibDTpmCommonConstructor (
+ VOID
+ )
+{
+ mActiveTpmInterfaceType = 0xFF;
+ mCRBIdleByPass = 0xFF;
+
+ //
+ // Always cache current active TpmInterfaceType for StandaloneMm implementation
+ //
+ mActiveTpmInterfaceType = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
+
+ if (mActiveTpmInterfaceType == Tpm2PtpInterfaceCrb) {
+ mCRBIdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.inf
new file mode 100644
index 00000000000..6f4ae035805
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.inf
@@ -0,0 +1,54 @@
+## @file
+# Provides TPM 2.0 TIS/PTP functions for DTPM
+#
+# Spec Compliance Info:
+# "TCG PC Client Platform TPM Profile(PTP) Specification Family 2.0 Level 00 Revision 00.43"
+# "TCG PC Client Specific TPM Interface Specification(TIS) Version 1.3"
+#
+# This library implements TIS (TPM Interface Specification) and
+# PTP (Platform TPM Profile) functions which is
+# used for every TPM 2.0 command. Choosing this library means platform uses and
+# only uses TPM 2.0 DTPM device.
+#
+# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Tpm2DeviceLibDTpmStandaloneMm
+ FILE_GUID = 9A5DB21A-FF0B-46D0-8672-B4F83FEF1F0E
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = Tpm2DeviceLib|MM_STANDALONE
+ CONSTRUCTOR = Tpm2DeviceLibConstructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ Tpm2Tis.c
+ Tpm2Ptp.c
+ Tpm2DeviceLibDTpm.c
+ Tpm2DeviceLibDTpmStandaloneMm.c
+ Tpm2DeviceLibDTpm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ IoLib
+ TimerLib
+ DebugLib
+ PcdLib
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c
index 81b7d841dbb..028f823fcab 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.c
@@ -16,29 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Guid/TpmInstance.h>
-/**
- Return PTP interface type.
-
- @param[in] Register Pointer to PTP register.
-
- @return PTP interface type.
-**/
-TPM2_PTP_INTERFACE_TYPE
-Tpm2GetPtpInterface (
- IN VOID *Register
- );
-
-/**
- Return PTP CRB interface IdleByPass state.
-
- @param[in] Register Pointer to PTP register.
-
- @return PTP CRB interface IdleByPass state.
-**/
-UINT8
-Tpm2GetIdleByPass (
- IN VOID *Register
- );
+#include "Tpm2DeviceLibDTpm.h"
/**
Dump PTP register information.
@@ -102,8 +80,6 @@ Tpm2InstanceLibDTpmConstructor (
)
{
EFI_STATUS Status;
- TPM2_PTP_INTERFACE_TYPE PtpInterface;
- UINT8 IdleByPass;
Status = Tpm2RegisterTpm2DeviceLib (&mDTpm2InternalTpm2Device);
if ((Status == EFI_SUCCESS) || (Status == EFI_UNSUPPORTED)) {
@@ -111,19 +87,7 @@ Tpm2InstanceLibDTpmConstructor (
// Unsupported means platform policy does not need this instance enabled.
//
if (Status == EFI_SUCCESS) {
- //
- // Cache current active TpmInterfaceType only when needed
- //
- if (PcdGet8(PcdActiveTpmInterfaceType) == 0xFF) {
- PtpInterface = Tpm2GetPtpInterface ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
- PcdSet8S(PcdActiveTpmInterfaceType, PtpInterface);
- }
-
- if (PcdGet8(PcdActiveTpmInterfaceType) == Tpm2PtpInterfaceCrb && PcdGet8(PcdCRBIdleByPass) == 0xFF) {
- IdleByPass = Tpm2GetIdleByPass((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
- PcdSet8S(PcdCRBIdleByPass, IdleByPass);
- }
-
+ Status = InternalTpm2DeviceLibDTpmCommonConstructor ();
DumpPtpInfo ((VOID *) (UINTN) PcdGet64 (PcdTpmBaseAddress));
}
return EFI_SUCCESS;
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
index dd037d8746a..a0dc5b35e62 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
@@ -6,6 +6,7 @@
# and PTP (Platform TPM Profile) functions.
#
# Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -30,6 +31,8 @@
Tpm2Tis.c
Tpm2Ptp.c
Tpm2InstanceLibDTpm.c
+ Tpm2DeviceLibDTpmBase.c
+ Tpm2DeviceLibDTpm.h
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c
index 068a9043c2a..8fbc9a87065 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2Ptp.c
@@ -2,6 +2,7 @@
PTP (Platform TPM Profile) CRB (Command Response Buffer) interface used by dTPM2.0 library.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c), Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -19,6 +20,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <IndustryStandard/TpmPtp.h>
#include <IndustryStandard/TpmTis.h>
+#include "Tpm2DeviceLibDTpm.h"
+
//
// Execution of the command may take from several seconds to minutes for certain
// commands, such as key generation.
@@ -174,7 +177,7 @@ PtpCrbTpmCommand (
// STEP 0:
// if CapCRbIdelByPass == 0, enforce Idle state before sending command
//
- if (PcdGet8(PcdCRBIdleByPass) == 0 && (MmioRead32((UINTN)&CrbReg->CrbControlStatus) & PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE) == 0){
+ if (GetCachedIdleByPass () == 0 && (MmioRead32((UINTN)&CrbReg->CrbControlStatus) & PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE) == 0){
Status = PtpCrbWaitRegisterBits (
&CrbReg->CrbControlStatus,
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
@@ -330,7 +333,7 @@ GoReady_Exit:
// Goto Ready State if command is completed successfully and TPM support IdleBypass
// If not supported. flow down to GoIdle
//
- if (PcdGet8(PcdCRBIdleByPass) == 1) {
+ if (GetCachedIdleByPass () == 1) {
MmioWrite32((UINTN)&CrbReg->CrbControlRequest, PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY);
return Status;
}
@@ -350,7 +353,7 @@ GoIdle_Exit:
// Only enforce Idle state transition if execution fails when CRBIdleBypass==1
// Leave regular Idle delay at the beginning of next command execution
//
- if (PcdGet8(PcdCRBIdleByPass) == 1){
+ if (GetCachedIdleByPass () == 1){
Status = PtpCrbWaitRegisterBits (
&CrbReg->CrbControlStatus,
PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE,
@@ -519,7 +522,7 @@ DumpPtpInfo (
Vid = 0xFFFF;
Did = 0xFFFF;
Rid = 0xFF;
- PtpInterface = PcdGet8(PcdActiveTpmInterfaceType);
+ PtpInterface = GetCachedPtpInterface ();
DEBUG ((EFI_D_INFO, "PtpInterface - %x\n", PtpInterface));
switch (PtpInterface) {
case Tpm2PtpInterfaceCrb:
@@ -564,7 +567,7 @@ DTpm2SubmitCommand (
{
TPM2_PTP_INTERFACE_TYPE PtpInterface;
- PtpInterface = PcdGet8(PcdActiveTpmInterfaceType);
+ PtpInterface = GetCachedPtpInterface ();
switch (PtpInterface) {
case Tpm2PtpInterfaceCrb:
return PtpCrbTpmCommand (
@@ -603,7 +606,7 @@ DTpm2RequestUseTpm (
{
TPM2_PTP_INTERFACE_TYPE PtpInterface;
- PtpInterface = PcdGet8(PcdActiveTpmInterfaceType);
+ PtpInterface = GetCachedPtpInterface ();
switch (PtpInterface) {
case Tpm2PtpInterfaceCrb:
return PtpCrbRequestUseTpm ((PTP_CRB_REGISTERS_PTR) (UINTN) PcdGet64 (PcdTpmBaseAddress));
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
new file mode 100644
index 00000000000..fa77db7baa6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AArch64/RngDxe.c
@@ -0,0 +1,126 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the RNDR instruction to produce random numbers.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>
+
+#include "RngDxeInternals.h"
+
+/**
+ Produces and returns an RNG value using either the default or specified RNG algorithm.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL instance.
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG
+ algorithm to use. May be NULL in which case the function will
+ use its default RNG algorithm.
+ @param[in] RNGValueLength The length in bytes of the memory buffer pointed to by
+ RNGValue. The driver shall return exactly this numbers of bytes.
+ @param[out] RNGValue A caller-allocated memory buffer filled by the driver with the
+ resulting RNG value.
+
+ @retval EFI_SUCCESS The RNG value was returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by
+ this driver.
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or
+ firmware error.
+ @retval EFI_NOT_READY There is not enough random data available to satisfy the length
+ requested by RNGValueLength.
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+ }
+
+ if (CompareGuid (RNGAlgorithm, PcdGetPtr (PcdCpuRngSupportedAlgorithm))) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms are unsupported by this driver.
+ //
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList.
+ On output with a return code of EFI_SUCCESS, the size
+ in bytes of the data returned in RNGAlgorithmList. On output
+ with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of RNGAlgorithmList required to obtain the list.
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver
+ with one EFI_RNG_ALGORITHM element for each supported
+ RNG algorithm. The list must not change across multiple
+ calls to the same driver. The first algorithm in the list
+ is the default algorithm for the driver.
+
+ @retval EFI_SUCCESS The RNG algorithm list was returned successfully.
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
index 7587ed0a928..7587ed0a928 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.c
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
index 11a4d8d4a6c..11a4d8d4a6c 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/AesCore.h
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/AesCore.h
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
index 63900eab894..0f7b8295ae4 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.c
@@ -8,48 +8,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Library/RngLib.h>
-#include "RdRand.h"
#include "AesCore.h"
-
-/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- )
-{
- BOOLEAN IsRandom;
- UINT64 TempRand[2];
-
- while (Length > 0) {
- IsRandom = GetRandomNumber128 (TempRand);
- if (!IsRandom) {
- return EFI_NOT_READY;
- }
- if (Length >= sizeof (TempRand)) {
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
- RandBuffer += sizeof (UINT64);
- WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
- RandBuffer += sizeof (UINT64);
- Length -= sizeof (TempRand);
- } else {
- CopyMem (RandBuffer, TempRand, Length);
- Length = 0;
- }
- }
-
- return EFI_SUCCESS;
-}
+#include "RdRand.h"
+#include "RngDxeInternals.h"
/**
Creates a 128bit random value that is fully forward and backward prediction resistant,
@@ -92,7 +53,7 @@ RdRandGetSeed128 (
//
for (Index = 0; Index < 32; Index++) {
MicroSecondDelay (10);
- Status = RdRandGetBytes (16, RandByte);
+ Status = RngGetBytes (16, RandByte);
if (EFI_ERROR (Status)) {
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
index 796c0e3e25c..0639ffd2d2f 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RdRand.h
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RdRand.h
@@ -24,23 +24,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/Rng.h>
/**
- Calls RDRAND to fill a buffer of arbitrary size with random bytes.
-
- @param[in] Length Size of the buffer, in bytes, to fill with.
- @param[out] RandBuffer Pointer to the buffer to store the random result.
-
- @retval EFI_SUCCESS Random bytes generation succeeded.
- @retval EFI_NOT_READY Failed to request random bytes.
-
-**/
-EFI_STATUS
-EFIAPI
-RdRandGetBytes (
- IN UINTN Length,
- OUT UINT8 *RandBuffer
- );
-
-/**
Generate high-quality entropy source through RDRAND.
@param[in] Length Size of the buffer, in bytes, to fill with.
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
new file mode 100644
index 00000000000..800462a1160
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
@@ -0,0 +1,145 @@
+/** @file
+ RNG Driver to produce the UEFI Random Number Generator protocol.
+
+ The driver will use the new RDRAND instruction to produce high-quality, high-performance
+ entropy and random number.
+
+ RNG Algorithms defined in UEFI 2.4:
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
+ (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
+ - EFI_RNG_ALGORITHM_RAW - Supported
+ (Structuring RDRAND invocation can be guaranteed as high-quality entropy source)
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+
+ Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "RdRand.h"
+#include "RngDxeInternals.h"
+
+/**
+ Produces and returns an RNG value using either the default or specified RNG algorithm.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL instance.
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG
+ algorithm to use. May be NULL in which case the function will
+ use its default RNG algorithm.
+ @param[in] RNGValueLength The length in bytes of the memory buffer pointed to by
+ RNGValue. The driver shall return exactly this numbers of bytes.
+ @param[out] RNGValue A caller-allocated memory buffer filled by the driver with the
+ resulting RNG value.
+
+ @retval EFI_SUCCESS The RNG value was returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by
+ this driver.
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or
+ firmware error.
+ @retval EFI_NOT_READY There is not enough random data available to satisfy the length
+ requested by RNGValueLength.
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+{
+ EFI_STATUS Status;
+
+ if ((RNGValueLength == 0) || (RNGValue == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RNGAlgorithm == NULL) {
+ //
+ // Use the default RNG algorithm if RNGAlgorithm is NULL.
+ //
+ RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
+ }
+
+ //
+ // NIST SP800-90-AES-CTR-256 supported by RDRAND
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
+ Status = RngGetBytes (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // The "raw" algorithm is intended to provide entropy directly
+ //
+ if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
+ //
+ // When a DRBG is used on the output of a entropy source,
+ // its security level must be at least 256 bits according to UEFI Spec.
+ //
+ if (RNGValueLength < 32) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
+ return Status;
+ }
+
+ //
+ // Other algorithms were unsupported by this driver.
+ //
+ return Status;
+}
+
+/**
+ Returns information about the random number generation implementation.
+
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList.
+ On output with a return code of EFI_SUCCESS, the size
+ in bytes of the data returned in RNGAlgorithmList. On output
+ with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of RNGAlgorithmList required to obtain the list.
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver
+ with one EFI_RNG_ALGORITHM element for each supported
+ RNG algorithm. The list must not change across multiple
+ calls to the same driver. The first algorithm in the list
+ is the default algorithm for the driver.
+
+ @retval EFI_SUCCESS The RNG algorithm list was returned successfully.
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+{
+ UINTN RequiredSize;
+ EFI_RNG_ALGORITHM *CpuRngSupportedAlgorithm;
+
+ RequiredSize = 2 * sizeof (EFI_RNG_ALGORITHM);
+
+ if (*RNGAlgorithmListSize < RequiredSize) {
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ CpuRngSupportedAlgorithm = PcdGetPtr (PcdCpuRngSupportedAlgorithm);
+
+ CopyMem(&RNGAlgorithmList[0], CpuRngSupportedAlgorithm, sizeof (EFI_RNG_ALGORITHM));
+
+ // x86 platforms also support EFI_RNG_ALGORITHM_RAW via RDSEED
+ CopyMem(&RNGAlgorithmList[1], &gEfiRngAlgorithmRaw, sizeof (EFI_RNG_ALGORITHM));
+
+ *RNGAlgorithmListSize = RequiredSize;
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
index 9ce2ab77a1a..a7c7a10155e 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.c
@@ -1,34 +1,32 @@
/** @file
RNG Driver to produce the UEFI Random Number Generator protocol.
- The driver will use the new RDRAND instruction to produce high-quality, high-performance
- entropy and random number.
+ The driver uses CPU RNG instructions to produce high-quality,
+ high-performance entropy and random number.
RNG Algorithms defined in UEFI 2.4:
- - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID - Supported
- (RDRAND implements a hardware NIST SP800-90 AES-CTR-256 based DRBG)
- - EFI_RNG_ALGORITHM_RAW - Supported
- (Structuring RDRAND invocation can be guaranteed as high-quality entropy source)
- - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_3DES_GUID - Unsupported
- - EFI_RNG_ALGORITHM_X9_31_AES_GUID - Unsupported
+ - EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID
+ - EFI_RNG_ALGORITHM_RAW
+ - EFI_RNG_ALGORITHM_SP800_90_HMAC_256_GUID
+ - EFI_RNG_ALGORITHM_SP800_90_HASH_256_GUID
+ - EFI_RNG_ALGORITHM_X9_31_3DES_GUID
+ - EFI_RNG_ALGORITHM_X9_31_AES_GUID
Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "RdRand.h"
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/RngLib.h>
+#include <Library/TimerLib.h>
+#include <Protocol/Rng.h>
-//
-// Supported RNG Algorithms list by this driver.
-//
-EFI_RNG_ALGORITHM mSupportedRngAlgorithms[] = {
- EFI_RNG_ALGORITHM_SP800_90_CTR_256_GUID,
- EFI_RNG_ALGORITHM_RAW
-};
+#include "RngDxeInternals.h"
/**
Returns information about the random number generation implementation.
@@ -62,103 +60,20 @@ RngGetInfo (
)
{
EFI_STATUS Status;
- UINTN RequiredSize;
if ((This == NULL) || (RNGAlgorithmListSize == NULL)) {
return EFI_INVALID_PARAMETER;
}
- RequiredSize = sizeof (mSupportedRngAlgorithms);
- if (*RNGAlgorithmListSize < RequiredSize) {
- Status = EFI_BUFFER_TOO_SMALL;
- } else {
- //
- // Return algorithm list supported by driver.
- //
- if (RNGAlgorithmList != NULL) {
- CopyMem (RNGAlgorithmList, mSupportedRngAlgorithms, RequiredSize);
- Status = EFI_SUCCESS;
- } else {
- Status = EFI_INVALID_PARAMETER;
- }
- }
- *RNGAlgorithmListSize = RequiredSize;
-
- return Status;
-}
-
-/**
- Produces and returns an RNG value using either the default or specified RNG algorithm.
-
- @param[in] This A pointer to the EFI_RNG_PROTOCOL instance.
- @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG
- algorithm to use. May be NULL in which case the function will
- use its default RNG algorithm.
- @param[in] RNGValueLength The length in bytes of the memory buffer pointed to by
- RNGValue. The driver shall return exactly this numbers of bytes.
- @param[out] RNGValue A caller-allocated memory buffer filled by the driver with the
- resulting RNG value.
-
- @retval EFI_SUCCESS The RNG value was returned successfully.
- @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by
- this driver.
- @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or
- firmware error.
- @retval EFI_NOT_READY There is not enough random data available to satisfy the length
- requested by RNGValueLength.
- @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero.
-
-**/
-EFI_STATUS
-EFIAPI
-RngGetRNG (
- IN EFI_RNG_PROTOCOL *This,
- IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
- IN UINTN RNGValueLength,
- OUT UINT8 *RNGValue
- )
-{
- EFI_STATUS Status;
-
- if ((RNGValueLength == 0) || (RNGValue == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = EFI_UNSUPPORTED;
- if (RNGAlgorithm == NULL) {
- //
- // Use the default RNG algorithm if RNGAlgorithm is NULL.
- //
- RNGAlgorithm = &gEfiRngAlgorithmSp80090Ctr256Guid;
- }
-
//
- // NIST SP800-90-AES-CTR-256 supported by RDRAND
+ // Return algorithm list supported by driver.
//
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmSp80090Ctr256Guid)) {
- Status = RdRandGetBytes (RNGValueLength, RNGValue);
- return Status;
- }
-
- //
- // The "raw" algorithm is intended to provide entropy directly
- //
- if (CompareGuid (RNGAlgorithm, &gEfiRngAlgorithmRaw)) {
- //
- // When a DRBG is used on the output of a entropy source,
- // its security level must be at least 256 bits according to UEFI Spec.
- //
- if (RNGValueLength < 32) {
- return EFI_INVALID_PARAMETER;
- }
-
- Status = RdRandGenerateEntropy (RNGValueLength, RNGValue);
- return Status;
+ if (RNGAlgorithmList != NULL) {
+ Status = ArchGetSupportedRngAlgorithms (RNGAlgorithmListSize, RNGAlgorithmList);
+ } else {
+ Status = EFI_INVALID_PARAMETER;
}
- //
- // Other algorithms were unsupported by this driver.
- //
return Status;
}
@@ -204,3 +119,44 @@ RngDriverEntry (
return Status;
}
+
+
+/**
+ Calls RDRAND to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ )
+{
+ BOOLEAN IsRandom;
+ UINT64 TempRand[2];
+
+ while (Length > 0) {
+ IsRandom = GetRandomNumber128 (TempRand);
+ if (!IsRandom) {
+ return EFI_NOT_READY;
+ }
+ if (Length >= sizeof (TempRand)) {
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[0]);
+ RandBuffer += sizeof (UINT64);
+ WriteUnaligned64 ((UINT64*)RandBuffer, TempRand[1]);
+ RandBuffer += sizeof (UINT64);
+ Length -= sizeof (TempRand);
+ } else {
+ CopyMem (RandBuffer, TempRand, Length);
+ Length = 0;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
index 530b807490a..f0c396469ab 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
@@ -26,15 +26,22 @@
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources.common]
RngDxe.c
- RdRand.c
- RdRand.h
- AesCore.c
- AesCore.h
+ RngDxeInternals.h
+
+[Sources.IA32, Sources.X64]
+ Rand/RngDxe.c
+ Rand/RdRand.c
+ Rand/RdRand.h
+ Rand/AesCore.c
+ Rand/AesCore.h
+
+[Sources.AARCH64]
+ AArch64/RngDxe.c
[Packages]
MdePkg/MdePkg.dec
@@ -50,12 +57,19 @@
RngLib
[Guids]
+ gEfiRngAlgorithmSp80090Hash256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmSp80090Hmac256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmSp80090Ctr256Guid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX9313DesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
+ gEfiRngAlgorithmX931AesGuid ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
gEfiRngAlgorithmRaw ## SOMETIMES_PRODUCES ## GUID # Unique ID of the algorithm for RNG
[Protocols]
gEfiRngProtocolGuid ## PRODUCES
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm ## CONSUMES
+
[Depex]
TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
new file mode 100644
index 00000000000..61e2d90c133
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/RandomNumberGenerator/RngDxe/RngDxeInternals.h
@@ -0,0 +1,117 @@
+/** @file
+ Function prototypes for UEFI Random Number Generator protocol support.
+
+ Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef RNGDXE_INTERNALS_H_
+#define RNGDXE_INTERNALS_H_
+
+/**
+ Returns information about the random number generation implementation.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL instance.
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList.
+ On output with a return code of EFI_SUCCESS, the size
+ in bytes of the data returned in RNGAlgorithmList. On output
+ with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of RNGAlgorithmList required to obtain the list.
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver
+ with one EFI_RNG_ALGORITHM element for each supported
+ RNG algorithm. The list must not change across multiple
+ calls to the same driver. The first algorithm in the list
+ is the default algorithm for the driver.
+
+ @retval EFI_SUCCESS The RNG algorithm list was returned successfully.
+ @retval EFI_UNSUPPORTED The services is not supported by this driver.
+ @retval EFI_DEVICE_ERROR The list of algorithms could not be retrieved due to a
+ hardware or firmware error.
+ @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect.
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetInfo (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ Produces and returns an RNG value using either the default or specified RNG algorithm.
+
+ @param[in] This A pointer to the EFI_RNG_PROTOCOL instance.
+ @param[in] RNGAlgorithm A pointer to the EFI_RNG_ALGORITHM that identifies the RNG
+ algorithm to use. May be NULL in which case the function will
+ use its default RNG algorithm.
+ @param[in] RNGValueLength The length in bytes of the memory buffer pointed to by
+ RNGValue. The driver shall return exactly this numbers of bytes.
+ @param[out] RNGValue A caller-allocated memory buffer filled by the driver with the
+ resulting RNG value.
+
+ @retval EFI_SUCCESS The RNG value was returned successfully.
+ @retval EFI_UNSUPPORTED The algorithm specified by RNGAlgorithm is not supported by
+ this driver.
+ @retval EFI_DEVICE_ERROR An RNG value could not be retrieved due to a hardware or
+ firmware error.
+ @retval EFI_NOT_READY There is not enough random data available to satisfy the length
+ requested by RNGValueLength.
+ @retval EFI_INVALID_PARAMETER RNGValue is NULL or RNGValueLength is zero.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetRNG (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm, OPTIONAL
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ );
+
+/**
+ Returns information about the random number generation implementation.
+
+ @param[in,out] RNGAlgorithmListSize On input, the size in bytes of RNGAlgorithmList.
+ On output with a return code of EFI_SUCCESS, the size
+ in bytes of the data returned in RNGAlgorithmList. On output
+ with a return code of EFI_BUFFER_TOO_SMALL,
+ the size of RNGAlgorithmList required to obtain the list.
+ @param[out] RNGAlgorithmList A caller-allocated memory buffer filled by the driver
+ with one EFI_RNG_ALGORITHM element for each supported
+ RNG algorithm. The list must not change across multiple
+ calls to the same driver. The first algorithm in the list
+ is the default algorithm for the driver.
+
+ @retval EFI_SUCCESS The RNG algorithm list was returned successfully.
+ @retval EFI_BUFFER_TOO_SMALL The buffer RNGAlgorithmList is too small to hold the result.
+
+**/
+UINTN
+EFIAPI
+ArchGetSupportedRngAlgorithms (
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ );
+
+/**
+ Runs CPU RNG instruction to fill a buffer of arbitrary size with random bytes.
+
+ @param[in] Length Size of the buffer, in bytes, to fill with.
+ @param[out] RandBuffer Pointer to the buffer to store the random result.
+
+ @retval EFI_SUCCESS Random bytes generation succeeded.
+ @retval EFI_NOT_READY Failed to request random bytes.
+
+**/
+EFI_STATUS
+EFIAPI
+RngGetBytes (
+ IN UINTN Length,
+ OUT UINT8 *RandBuffer
+ );
+
+#endif // RNGDXE_INTERNALS_H_
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.ci.yaml
index 94600cf3f45..2b819e4c2c4 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.ci.yaml
@@ -2,9 +2,24 @@
# CI configuration for SecurityPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
"CompilerPlugin": {
"DscPath": "SecurityPkg.dsc"
},
@@ -16,6 +31,7 @@
"MdePkg/MdePkg.dec",
"MdeModulePkg/MdeModulePkg.dec",
"SecurityPkg/SecurityPkg.dec",
+ "StandaloneMmPkg/StandaloneMmPkg.dec",
"CryptoPkg/CryptoPkg.dec"
],
# For host based unit tests
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dec b/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dec
index 80e4961f060..e8993fbae0d 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dec
@@ -84,6 +84,9 @@
#
VariableKeyLib|Include/Library/VariableKeyLib.h
+ ## @libraryclass Provides interfaces about firmware TPM measurement.
+ #
+ TcgEventLogRecordLib|Include/Library/TcgEventLogRecordLib.h
[Guids]
## Security package token space guid.
# Include/Guid/SecurityPkgTokenSpace.h
@@ -180,6 +183,13 @@
## Include/OpalPasswordExtraInfoVariable.h
gOpalExtraInfoVariableGuid = {0x44a2ad5d, 0x612c, 0x47b3, {0xb0, 0x6e, 0xc8, 0xf5, 0x0b, 0xfb, 0xf0, 0x7d}}
+ ## GUID used to exchange registered SWI value and NVS region between Tcg2Acpi and Tcg2Smm.
+ ## Include/Guid/TpmNvsMm.h
+ gTpmNvsMmGuid = { 0xc96c76eb, 0xbc78, 0x429c, { 0x9f, 0x4b, 0xda, 0x51, 0x78, 0xc2, 0x84, 0x57 }}
+
+ ## GUID used to enforce loading order between Tcg2Acpi and Tcg2Smm
+ gTcg2MmSwSmiRegisteredGuid = { 0x9d4548b9, 0xa48d, 0x4db4, { 0x9a, 0x68, 0x32, 0xc5, 0x13, 0x9e, 0x20, 0x18 } }
+
[Ppis]
## The PPI GUID for that TPM physical presence should be locked.
@@ -203,6 +213,9 @@
## Include/Ppi/FirmwareVolumeInfoStoredHashFv.h
gEdkiiPeiFirmwareVolumeInfoStoredHashFvPpiGuid = {0x7f5e4e31, 0x81b1, 0x47e5, { 0x9e, 0x21, 0x1e, 0x4b, 0x5b, 0xc2, 0xf6, 0x1d } }
+ ## Include/Ppi/Tcg.h
+ gEdkiiTcgPpiGuid = {0x57a13b87, 0x133d, 0x4bf3, { 0xbf, 0xf1, 0x1b, 0xca, 0xc7, 0x17, 0x6c, 0xf1 } }
+
#
# [Error.gEfiSecurityPkgTokenSpaceGuid]
# 0x80000001 | Invalid value provided.
@@ -284,6 +297,8 @@
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationPass|0x0303100A|UINT32|0x00010030
gEfiSecurityPkgTokenSpaceGuid.PcdStatusCodeFvVerificationFail|0x0303100B|UINT32|0x00010031
+ gEfiSecurityPkgTokenSpaceGuid.PcdCpuRngSupportedAlgorithm|{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}|VOID*|0x00010032
+
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## Image verification policy for OptionRom. Only following values are valid:<BR><BR>
# NOTE: Do NOT use 0x5 and 0x2 since it violates the UEFI specification and has been removed.<BR>
@@ -370,6 +385,7 @@
gEfiSecurityPkgTokenSpaceGuid.PcdTpmScrtmPolicy|1|UINT8|0x0001000E
## Guid name to identify TPM instance.<BR><BR>
+ # NOTE: This Pcd must be FixedAtBuild if Standalone MM is used
# TPM_DEVICE_INTERFACE_NONE means disable.<BR>
# TPM_DEVICE_INTERFACE_TPM12 means TPM 1.2 DTPM.<BR>
# TPM_DEVICE_INTERFACE_DTPM2 means TPM 2.0 DTPM.<BR>
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dsc b/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dsc
index b852f6022b3..8fd30e4c617 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/SecurityPkg.dsc
@@ -1,7 +1,7 @@
## @file
# Security Module Package for All Architectures.
#
-# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -17,6 +17,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
@@ -66,6 +68,8 @@
ResetSystemLib|MdeModulePkg/Library/BaseResetSystemLibNull/BaseResetSystemLibNull.inf
VariableKeyLib|SecurityPkg/Library/VariableKeyLibNull/VariableKeyLibNull.inf
RpmcLib|SecurityPkg/Library/RpmcLibNull/RpmcLibNull.inf
+ TcgEventLogRecordLib|SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf
+ MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
[LibraryClasses.ARM]
#
@@ -96,6 +100,7 @@
Tpm12DeviceLib|SecurityPkg/Library/Tpm12DeviceLibDTpm/Tpm12DeviceLibDTpm.inf
Tpm2DeviceLib|SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
Tcg2PhysicalPresenceLib|SecurityPkg/Library/PeiTcg2PhysicalPresenceLib/PeiTcg2PhysicalPresenceLib.inf
+ TpmMeasurementLib|SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf
RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
[LibraryClasses.common.DXE_DRIVER]
@@ -148,6 +153,7 @@
[LibraryClasses.common.DXE_SMM_DRIVER]
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
ReportStatusCodeLib|MdeModulePkg/Library/SmmReportStatusCodeLib/SmmReportStatusCodeLib.inf
SmmMemLib|MdePkg/Library/SmmMemLib/SmmMemLib.inf
@@ -163,6 +169,14 @@
Tcg2PhysicalPresenceLib|SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
SmmIoLib|MdePkg/Library/SmmIoLib/SmmIoLib.inf
+[LibraryClasses.common.MM_STANDALONE]
+ StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
+ MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
+ Tcg2PhysicalPresenceLib|SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf
+ MemLib|StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
+ HobLib|StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf
+ MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
+
[PcdsDynamicDefault.common.DEFAULT]
gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid|{0xb6, 0xe5, 0x01, 0x8b, 0x19, 0x4f, 0xe8, 0x46, 0xab, 0x93, 0x1c, 0x53, 0x67, 0x1b, 0x90, 0xcc}
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2InitializationPolicy|1
@@ -208,6 +222,7 @@
SecurityPkg/Library/Tpm2DeviceLibTcg2/Tpm2DeviceLibTcg2.inf
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpm.inf
SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2InstanceLibDTpm.inf
+ SecurityPkg/Library/Tpm2DeviceLibDTpm/Tpm2DeviceLibDTpmStandaloneMm.inf
SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterDxe.inf
SecurityPkg/Library/Tpm2DeviceLibRouter/Tpm2DeviceLibRouterPei.inf
@@ -234,14 +249,22 @@
SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf
SecurityPkg/Library/FmpAuthenticationLibRsa2048Sha256/FmpAuthenticationLibRsa2048Sha256.inf
+ SecurityPkg/Library/PeiTpmMeasurementLib/PeiTpmMeasurementLib.inf
SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
SecurityPkg/Library/Tcg2PpVendorLibNull/Tcg2PpVendorLibNull.inf
SecurityPkg/Library/TcgPpVendorLibNull/TcgPpVendorLibNull.inf
+ SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf
[Components.IA32, Components.X64, Components.ARM, Components.AARCH64]
SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
+[Components.IA32, Components.X64, Components.AARCH64]
+ #
+ # Random Number Generator
+ #
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+
[Components.IA32, Components.X64]
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
@@ -311,12 +334,11 @@
SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf
SecurityPkg/Tcg/TcgSmm/TcgSmm.inf
SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
+ SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.inf
+ SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.inf
+ SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/SmmTcg2PhysicalPresenceLib.inf
-
- #
- # Random Number Generator
- #
- SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+ SecurityPkg/Library/SmmTcg2PhysicalPresenceLib/StandaloneMmTcg2PhysicalPresenceLib.inf
#
# Opal Password solution
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
index 92831f6bff6..50406a259df 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Opal/OpalPassword/OpalHii.c
@@ -548,7 +548,7 @@ HiiConfirmDataRemovalAction (
Unicode,
L" System should not be powered off until action completion ",
L" ",
- L" Press 'Y/y' to continue, press 'N/n' to cancal ",
+ L" Press 'Y/y' to continue, press 'N/n' to cancel ",
NULL
);
} while (
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c
new file mode 100644
index 00000000000..a0964aefdf9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.c
@@ -0,0 +1,902 @@
+/** @file
+ This driver implements TPM 2.0 definition block in ACPI table and
+ populates registered SMI callback functions for Tcg2 physical presence
+ and MemoryClear to handle the requests for ACPI method. It needs to be
+ used together with Tcg2 MM drivers to exchange information on registered
+ SwSmiValue and allocated NVS region address.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable and ACPINvs data in SMM mode.
+ This external input must be validated carefully to avoid security issue.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Tpm2Acpi.h>
+
+#include <Guid/TpmInstance.h>
+#include <Guid/TpmNvsMm.h>
+#include <Guid/PiSmmCommunicationRegionTable.h>
+
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Tcg2Protocol.h>
+#include <Protocol/MmCommunication.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DxeServicesLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/TpmMeasurementLib.h>
+#include <Library/Tpm2DeviceLib.h>
+#include <Library/Tpm2CommandLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MmUnblockMemoryLib.h>
+
+//
+// Physical Presence Interface Version supported by Platform
+//
+#define PHYSICAL_PRESENCE_VERSION_TAG "$PV"
+#define PHYSICAL_PRESENCE_VERSION_SIZE 4
+
+//
+// PNP _HID for TPM2 device
+//
+#define TPM_HID_TAG "NNNN0000"
+#define TPM_HID_PNP_SIZE 8
+#define TPM_HID_ACPI_SIZE 9
+
+#define TPM_PRS_RESL "RESL"
+#define TPM_PRS_RESS "RESS"
+#define TPM_PRS_RES_NAME_SIZE 4
+//
+// Minimum PRS resource template size
+// 1 byte for BufferOp
+// 1 byte for PkgLength
+// 2 bytes for BufferSize
+// 12 bytes for Memory32Fixed descriptor
+// 5 bytes for Interrupt descriptor
+// 2 bytes for END Tag
+//
+#define TPM_POS_RES_TEMPLATE_MIN_SIZE (1 + 1 + 2 + 12 + 5 + 2)
+
+//
+// Max Interrupt buffer size for PRS interrupt resource
+// Now support 15 interrupts in maxmum
+//
+#define MAX_PRS_INT_BUF_SIZE (15*4)
+
+#pragma pack(1)
+
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ // Flags field is replaced in version 4 and above
+ // BIT0~15: PlatformClass This field is only valid for version 4 and above
+ // BIT16~31: Reserved
+ UINT32 Flags;
+ UINT64 AddressOfControlArea;
+ UINT32 StartMethod;
+ UINT8 PlatformSpecificParameters[12]; // size up to 12
+ UINT32 Laml; // Optional
+ UINT64 Lasa; // Optional
+} EFI_TPM2_ACPI_TABLE_V4;
+
+#pragma pack()
+
+EFI_TPM2_ACPI_TABLE_V4 mTpm2AcpiTemplate = {
+ {
+ EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
+ sizeof (mTpm2AcpiTemplate),
+ EFI_TPM2_ACPI_TABLE_REVISION,
+ //
+ // Compiler initializes the remaining bytes to 0
+ // These fields should be filled in in production
+ //
+ },
+ 0, // BIT0~15: PlatformClass
+ // BIT16~31: Reserved
+ 0, // Control Area
+ EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
+};
+
+TCG_NVS *mTcgNvs;
+
+/**
+ Find the operation region in TCG ACPI table by given Name and Size,
+ and initialize it if the region is found.
+
+ @param[in, out] Table The TPM item in ACPI table.
+ @param[in] Name The name string to find in TPM table.
+ @param[in] Size The size of the region to find.
+
+ @return The allocated address for the found region.
+
+**/
+VOID *
+AssignOpRegion (
+ EFI_ACPI_DESCRIPTION_HEADER *Table,
+ UINT32 Name,
+ UINT16 Size
+ )
+{
+ EFI_STATUS Status;
+ AML_OP_REGION_32_8 *OpRegion;
+ EFI_PHYSICAL_ADDRESS MemoryAddress;
+
+ MemoryAddress = SIZE_4GB - 1;
+
+ //
+ // Patch some pointers for the ASL code before loading the SSDT.
+ //
+ for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);
+ OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);
+ OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {
+ if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) &&
+ (OpRegion->NameString == Name) &&
+ (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
+ (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {
+
+ Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
+ ASSERT_EFI_ERROR (Status);
+ ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
+ OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;
+ OpRegion->RegionLen = (UINT8) Size;
+ // Request to unblock this region from MM core
+ Status = MmUnblockMemoryRequest (MemoryAddress, EFI_SIZE_TO_PAGES (Size));
+ if (Status != EFI_UNSUPPORTED && EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+ break;
+ }
+ }
+
+ return (VOID *) (UINTN) MemoryAddress;
+}
+
+/**
+ Locate the MM communication buffer and protocol, then use it to exchange information with
+ Tcg2StandaloneMmm on NVS address and SMI value.
+
+ @param[in, out] TcgNvs The NVS subject to send to MM environment.
+
+ @return The status for locating MM common buffer, communicate to MM, etc.
+
+**/
+EFI_STATUS
+EFIAPI
+ExchangeCommonBuffer (
+ IN OUT TCG_NVS *TcgNvs
+)
+{
+ EFI_STATUS Status;
+ EFI_MM_COMMUNICATION_PROTOCOL *MmCommunication;
+ EDKII_PI_SMM_COMMUNICATION_REGION_TABLE *PiSmmCommunicationRegionTable;
+ EFI_MEMORY_DESCRIPTOR *MmCommMemRegion;
+ EFI_MM_COMMUNICATE_HEADER *CommHeader;
+ TPM_NVS_MM_COMM_BUFFER *CommBuffer;
+ UINTN CommBufferSize;
+ UINTN Index;
+
+ // Step 0: Sanity check for input argument
+ if (TcgNvs == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a - Input argument is NULL!\n", __FUNCTION__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Step 1: Grab the common buffer header
+ Status = EfiGetSystemConfigurationTable (&gEdkiiPiSmmCommunicationRegionTableGuid, (VOID**) &PiSmmCommunicationRegionTable);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a - Failed to locate SMM communciation common buffer - %r!\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ // Step 2: Grab one that is large enough to hold TPM_NVS_MM_COMM_BUFFER, the IPL one should be sufficient
+ CommBufferSize = 0;
+ MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR*) (PiSmmCommunicationRegionTable + 1);
+ for (Index = 0; Index < PiSmmCommunicationRegionTable->NumberOfEntries; Index++) {
+ if (MmCommMemRegion->Type == EfiConventionalMemory) {
+ CommBufferSize = EFI_PAGES_TO_SIZE ((UINTN)MmCommMemRegion->NumberOfPages);
+ if (CommBufferSize >= (sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data))) {
+ break;
+ }
+ }
+ MmCommMemRegion = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)MmCommMemRegion + PiSmmCommunicationRegionTable->DescriptorSize);
+ }
+
+ if (Index >= PiSmmCommunicationRegionTable->NumberOfEntries) {
+ // Could not find one that meets our goal...
+ DEBUG ((DEBUG_ERROR, "%a - Could not find a common buffer that is big enough for NVS!\n", __FUNCTION__));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Step 3: Start to populate contents
+ // Step 3.1: MM Communication common header
+ CommHeader = (EFI_MM_COMMUNICATE_HEADER *) (UINTN) MmCommMemRegion->PhysicalStart;
+ CommBufferSize = sizeof (TPM_NVS_MM_COMM_BUFFER) + OFFSET_OF (EFI_MM_COMMUNICATE_HEADER, Data);
+ ZeroMem (CommHeader, CommBufferSize);
+ CopyGuid (&CommHeader->HeaderGuid, &gTpmNvsMmGuid);
+ CommHeader->MessageLength = sizeof (TPM_NVS_MM_COMM_BUFFER);
+
+ // Step 3.2: TPM_NVS_MM_COMM_BUFFER content per our needs
+ CommBuffer = (TPM_NVS_MM_COMM_BUFFER *) (CommHeader->Data);
+ CommBuffer->Function = TpmNvsMmExchangeInfo;
+ CommBuffer->TargetAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TcgNvs;
+
+ // Step 4: Locate the protocol and signal Mmi.
+ Status = gBS->LocateProtocol (&gEfiMmCommunicationProtocolGuid, NULL, (VOID**) &MmCommunication);
+ if (!EFI_ERROR (Status)) {
+ Status = MmCommunication->Communicate (MmCommunication, CommHeader, &CommBufferSize);
+ DEBUG ((DEBUG_INFO, "%a - Communicate() = %r\n", __FUNCTION__, Status));
+ }
+ else {
+ DEBUG ((DEBUG_ERROR, "%a - Failed to locate MmCommunication protocol - %r\n", __FUNCTION__, Status));
+ return Status;
+ }
+
+ // Step 5: If everything goes well, populate the channel number
+ if (!EFI_ERROR (CommBuffer->ReturnStatus)) {
+ // Need to demote to UINT8 according to SMI value definition
+ TcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) CommBuffer->RegisteredPpSwiValue;
+ TcgNvs->MemoryClear.SoftwareSmi = (UINT8) CommBuffer->RegisteredMcSwiValue;
+ DEBUG ((
+ DEBUG_INFO,
+ "%a Communication returned software SMI value. PP: 0x%x; MC: 0x%x.\n",
+ __FUNCTION__,
+ TcgNvs->PhysicalPresence.SoftwareSmi,
+ TcgNvs->MemoryClear.SoftwareSmi
+ ));
+ }
+
+ return (EFI_STATUS) CommBuffer->ReturnStatus;
+}
+
+/**
+ Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
+ACPI table is "$PV".
+
+ @param[in, out] Table The TPM item in ACPI table.
+ @param[in] PPVer Version string of Physical Presence interface supported by platform.
+
+ @return The allocated address for the found region.
+
+**/
+EFI_STATUS
+UpdatePPVersion (
+ EFI_ACPI_DESCRIPTION_HEADER *Table,
+ CHAR8 *PPVer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *DataPtr;
+
+ //
+ // Patch some pointers for the ASL code before loading the SSDT.
+ //
+ for (DataPtr = (UINT8 *)(Table + 1);
+ DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);
+ DataPtr += 1) {
+ if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {
+ Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
+ DEBUG((DEBUG_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));
+ return Status;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input
+ interrupt buffer size. BufferSize, PkgLength and interrupt descriptor in ByteList need to be patched
+
+ @param[in, out] Table The TPM item in ACPI table.
+ @param[in] IrqBuffer Input new IRQ buffer.
+ @param[in] IrqBuffserSize Input new IRQ buffer size.
+ @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).
+
+ @return patch status.
+
+**/
+EFI_STATUS
+UpdatePossibleResource (
+ IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table,
+ IN UINT32 *IrqBuffer,
+ IN UINT32 IrqBuffserSize,
+ OUT BOOLEAN *IsShortFormPkgLength
+ )
+{
+ UINT8 *DataPtr;
+ UINT8 *DataEndPtr;
+ UINT32 NewPkgLength;
+ UINT32 OrignalPkgLength;
+
+ NewPkgLength = 0;
+ OrignalPkgLength = 0;
+ DataEndPtr = NULL;
+
+ //
+ // Follow ACPI spec
+ // 6.4.3 Extend Interrupt Descriptor.
+ // 19.3.3 ASL Resource Template
+ // 20 AML specification
+ // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
+ //
+ // AML data is organized by following rule.
+ // Code need to patch BufferSize and PkgLength and interrupt descriptor in ByteList
+ //
+ // ============= Buffer ====================
+ // DefBuffer := BufferOp PkgLength BufferSize ByteList
+ // BufferOp := 0x11
+ //
+ // ==============PkgLength==================
+ // PkgLength := PkgLeadByte |
+ // <PkgLeadByte ByteData> |
+ // <PkgLeadByte ByteData ByteData> |
+ // <PkgLeadByte ByteData ByteData ByteData>
+ //
+ // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
+ // <bit 5-4: Only used if PkgLength <= 63 >
+ // <bit 3-0: Least significant package length nybble>
+ //
+ //==============BufferSize==================
+ // BufferSize := Integer
+ // Integer := ByteConst|WordConst|DwordConst....
+ //
+ // ByteConst := BytePrefix ByteData
+ //
+ //==============ByteList===================
+ // ByteList := ByteData ByteList
+ //
+ //=========================================
+
+ //
+ // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
+ //
+ for (DataPtr = (UINT8 *)(Table + 1);
+ DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+ DataPtr += 1) {
+ if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {
+ //
+ // Jump over object name & BufferOp
+ //
+ DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+ if ((*DataPtr & (BIT7|BIT6)) == 0) {
+ OrignalPkgLength = (UINT32)*DataPtr;
+ DataEndPtr = DataPtr + OrignalPkgLength;
+
+ //
+ // Jump over PkgLength = PkgLeadByte only
+ //
+ NewPkgLength++;
+
+ //
+ // Jump over BufferSize
+ //
+ if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
+ NewPkgLength += 2;
+ } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
+ NewPkgLength += 3;
+ } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
+ NewPkgLength += 5;
+ } else {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
+ //
+ NewPkgLength += 19 + IrqBuffserSize;
+ if (NewPkgLength > 63) {
+ break;
+ }
+
+ if (NewPkgLength > OrignalPkgLength) {
+ ASSERT(FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // 1.1 Patch PkgLength
+ //
+ *DataPtr = (UINT8)NewPkgLength;
+
+ //
+ // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).
+ // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
+ //
+ *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
+
+ //
+ // Notify _PRS to report short formed ResourceTemplate
+ //
+ *IsShortFormPkgLength = TRUE;
+
+ break;
+ }
+ }
+
+ //
+ // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
+ //
+ if (NewPkgLength > 63) {
+ NewPkgLength = 0;
+ OrignalPkgLength = 0;
+ for (DataPtr = (UINT8 *)(Table + 1);
+ DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
+ DataPtr += 1) {
+ if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {
+ //
+ // Jump over object name & BufferOp
+ //
+ DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
+
+ if ((*DataPtr & (BIT7|BIT6)) != 0) {
+ OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);
+ DataEndPtr = DataPtr + OrignalPkgLength;
+ //
+ // Jump over PkgLength = PkgLeadByte + ByteData length
+ //
+ NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
+
+ //
+ // Jump over BufferSize
+ //
+ if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
+ NewPkgLength += 2;
+ } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
+ NewPkgLength += 3;
+ } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
+ NewPkgLength += 5;
+ } else {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ ASSERT(FALSE);
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
+ //
+ NewPkgLength += 19 + IrqBuffserSize;
+
+ if (NewPkgLength > OrignalPkgLength) {
+ ASSERT(FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
+ //
+ *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
+ *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
+
+ //
+ // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).
+ // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
+ //
+ *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);
+
+ //
+ // Notify _PRS to report long formed ResourceTemplate
+ //
+ *IsShortFormPkgLength = FALSE;
+ break;
+ }
+ }
+ }
+
+ if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
+ // 5 bytes for interrupt descriptor header, 2 bytes for End Tag
+ //
+ DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);
+ //
+ // 3.1 Patch Length bit[7:0] of Interrupt descriptor patch interrupt descriptor
+ //
+ *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
+ //
+ // 3.2 Patch Interrupt Table Length
+ //
+ *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));
+ //
+ // 3.3 Copy patched InterruptNumBuffer
+ //
+ CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);
+
+ //
+ // 4. Jump over Interrupt descriptor and Patch END Tag, set Checksum field to 0
+ //
+ DataPtr += 5 + IrqBuffserSize;
+ *DataPtr = ACPI_END_TAG_DESCRIPTOR;
+ *(DataPtr + 1) = 0;
+
+ //
+ // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
+ //
+ DataPtr += 2;
+ if (DataPtr < DataEndPtr) {
+ SetMem(DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".
+
+ @param[in, out] Table The TPM2 SSDT ACPI table.
+
+ @return HID Update status.
+
+**/
+EFI_STATUS
+UpdateHID (
+ EFI_ACPI_DESCRIPTION_HEADER *Table
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *DataPtr;
+ CHAR8 Hid[TPM_HID_ACPI_SIZE];
+ UINT32 ManufacturerID;
+ UINT32 FirmwareVersion1;
+ UINT32 FirmwareVersion2;
+ BOOLEAN PnpHID;
+
+ PnpHID = TRUE;
+
+ //
+ // Initialize HID with Default PNP string
+ //
+ ZeroMem(Hid, TPM_HID_ACPI_SIZE);
+
+ //
+ // Get Manufacturer ID
+ //
+ Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);
+ if (!EFI_ERROR(Status)) {
+ DEBUG((DEBUG_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));
+ //
+ // ManufacturerID defined in TCG Vendor ID Registry
+ // may tailed with 0x00 or 0x20
+ //
+ if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {
+ //
+ // HID containing PNP ID "NNN####"
+ // NNN is uppercase letter for Vendor ID specified by manufacturer
+ //
+ CopyMem(Hid, &ManufacturerID, 3);
+ } else {
+ //
+ // HID containing ACP ID "NNNN####"
+ // NNNN is uppercase letter for Vendor ID specified by manufacturer
+ //
+ CopyMem(Hid, &ManufacturerID, 4);
+ PnpHID = FALSE;
+ }
+ } else {
+ DEBUG ((DEBUG_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));
+ ASSERT(FALSE);
+ return Status;
+ }
+
+ Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);
+ if (!EFI_ERROR(Status)) {
+ DEBUG((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));
+ DEBUG((DEBUG_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));
+ //
+ // #### is Firmware Version 1
+ //
+ if (PnpHID) {
+ AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
+ } else {
+ AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
+ }
+
+ } else {
+ DEBUG ((DEBUG_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));
+ ASSERT(FALSE);
+ return Status;
+ }
+
+ //
+ // Patch HID in ASL code before loading the SSDT.
+ //
+ for (DataPtr = (UINT8 *)(Table + 1);
+ DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);
+ DataPtr += 1) {
+ if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {
+ if (PnpHID) {
+ CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);
+ //
+ // if HID is PNP ID, patch the last byte in HID TAG to Noop
+ //
+ *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;
+ } else {
+
+ CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);
+ }
+ DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));
+
+ return Status;
+ }
+ }
+
+ DEBUG((DEBUG_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Initialize and publish TPM items in ACPI table.
+
+ @retval EFI_SUCCESS The TCG ACPI table is published successfully.
+ @retval Others The TCG ACPI table is not published.
+
+**/
+EFI_STATUS
+PublishAcpiTable (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ UINTN TableKey;
+ EFI_ACPI_DESCRIPTION_HEADER *Table;
+ UINTN TableSize;
+ UINT32 *PossibleIrqNumBuf;
+ UINT32 PossibleIrqNumBufSize;
+ BOOLEAN IsShortFormPkgLength;
+
+ IsShortFormPkgLength = FALSE;
+
+ Status = GetSectionFromFv (
+ &gEfiCallerIdGuid,
+ EFI_SECTION_RAW,
+ 0,
+ (VOID **) &Table,
+ &TableSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
+ // The measurement has to be done before any update.
+ // Otherwise, the PCR record would be different after TPM FW update
+ // or the PCD configuration change.
+ //
+ TpmMeasureAndLogData(
+ 0,
+ EV_POST_CODE,
+ EV_POSTCODE_INFO_ACPI_DATA,
+ ACPI_DATA_LEN,
+ Table,
+ TableSize
+ );
+
+ //
+ // Update Table version before measuring it to PCR
+ //
+ Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "Current physical presence interface version - %a\n",
+ (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)
+ ));
+
+ //
+ // Update TPM2 HID after measuring it to PCR
+ //
+ Status = UpdateHID(Table);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+
+ if (PcdGet32(PcdTpm2CurrentIrqNum) != 0) {
+ //
+ // Patch _PRS interrupt resource only when TPM interrupt is supported
+ //
+ PossibleIrqNumBuf = (UINT32 *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);
+ PossibleIrqNumBufSize = (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);
+
+ if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE && (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
+ Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);
+ DEBUG ((
+ DEBUG_INFO,
+ "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",
+ Status
+ ));
+ } else {
+ DEBUG ((
+ DEBUG_INFO,
+ "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",
+ PossibleIrqNumBufSize
+ ));
+ }
+ }
+
+ ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
+ CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );
+ mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
+ ASSERT (mTcgNvs != NULL);
+ mTcgNvs->TpmIrqNum = PcdGet32(PcdTpm2CurrentIrqNum);
+ mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;
+
+ Status = ExchangeCommonBuffer (mTcgNvs);
+
+ //
+ // Publish the TPM ACPI table. Table is re-checksummed.
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+ ASSERT_EFI_ERROR (Status);
+
+ TableKey = 0;
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ Table,
+ TableSize,
+ &TableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Publish TPM2 ACPI table
+
+ @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
+ @retval Others The TPM2 ACPI table is not published.
+
+**/
+EFI_STATUS
+PublishTpm2 (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
+ UINTN TableKey;
+ UINT64 OemTableId;
+ EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;
+ TPM2_PTP_INTERFACE_TYPE InterfaceType;
+
+ //
+ // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
+ // The measurement has to be done before any update.
+ // Otherwise, the PCR record would be different after event log update
+ // or the PCD configuration change.
+ //
+ TpmMeasureAndLogData(
+ 0,
+ EV_POST_CODE,
+ EV_POSTCODE_INFO_ACPI_DATA,
+ ACPI_DATA_LEN,
+ &mTpm2AcpiTemplate,
+ mTpm2AcpiTemplate.Header.Length
+ );
+
+ mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);
+ DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));
+
+ //
+ // PlatformClass is only valid for version 4 and above
+ // BIT0~15: PlatformClass
+ // BIT16~31: Reserved
+ //
+ if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {
+ mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass);
+ DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));
+ }
+
+ mTpm2AcpiTemplate.Laml = PcdGet32(PcdTpm2AcpiTableLaml);
+ mTpm2AcpiTemplate.Lasa = PcdGet64(PcdTpm2AcpiTableLasa);
+ if ((mTpm2AcpiTemplate.Header.Revision < EFI_TPM2_ACPI_TABLE_REVISION_4) ||
+ (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0)) {
+ //
+ // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original Length.
+ //
+ mTpm2AcpiTemplate.Header.Length = sizeof(EFI_TPM2_ACPI_TABLE);
+ }
+
+ InterfaceType = PcdGet8(PcdActiveTpmInterfaceType);
+ switch (InterfaceType) {
+ case Tpm2PtpInterfaceCrb:
+ mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;
+ mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;
+ ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
+ ControlArea->CommandSize = 0xF80;
+ ControlArea->ResponseSize = 0xF80;
+ ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;
+ ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;
+ break;
+ case Tpm2PtpInterfaceFifo:
+ case Tpm2PtpInterfaceTis:
+ break;
+ default:
+ DEBUG((DEBUG_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));
+ break;
+ }
+
+ CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
+ OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
+ CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
+ mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
+ mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
+ mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
+
+ //
+ // Construct ACPI table
+ //
+ Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = AcpiTable->InstallAcpiTable (
+ AcpiTable,
+ &mTpm2AcpiTemplate,
+ mTpm2AcpiTemplate.Header.Length,
+ &TableKey
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ The driver's entry point.
+
+ It patches and installs ACPI tables used for handling TPM physical presence
+ and Memory Clear requests through ACPI method.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Others Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeTcgAcpi (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
+ DEBUG ((DEBUG_ERROR, "No TPM2 DTPM instance required!\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ Status = PublishAcpiTable ();
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Set TPM2 ACPI table
+ //
+ Status = PublishTpm2 ();
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
new file mode 100644
index 00000000000..7f7fe09878d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tcg2Acpi.inf
@@ -0,0 +1,94 @@
+## @file
+# Provides ACPI methods for TPM 2.0 support
+#
+# Spec Compliance Info:
+# "TCG ACPI Specification Version 1.2 Revision 8"
+# "Physical Presence Interface Specification Version 1.30 Revision 00.52"
+# along with
+# "Errata Version 0.4 for TCG PC Client Platform Physical Presence Interface Specification"
+# "Platform Reset Attack Mitigation Specification Version 1.00"
+# TPM2.0 ACPI device object
+# "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 1.03 v51"
+# along with
+# "Errata for PC Client Specific Platform Firmware Profile Specification Version 1.0 Revision 1.03"
+#
+# This driver implements TPM 2.0 definition block in ACPI table and
+# populates registered SMI callback functions for Tcg2 physical presence
+# and MemoryClear to handle the requests for ACPI method. It needs to be
+# used together with Tcg2 MM drivers to exchange information on registered
+# SwSmiValue and allocated NVS region address.
+#
+# Caution: This module requires additional review when modified.
+# This driver will have external input - variable and ACPINvs data in SMM mode.
+# This external input must be validated carefully to avoid security issue.
+#
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Tcg2Acpi
+ FILE_GUID = 0D4BBF18-C2CC-4C23-BD63-BFDAD4C710D0
+ MODULE_TYPE = DXE_DRIVER
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeTcgAcpi
+
+[Sources]
+ Tcg2Acpi.c
+ Tpm.asl
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ DebugLib
+ DxeServicesLib
+ TpmMeasurementLib
+ Tpm2CommandLib
+ Tcg2PhysicalPresenceLib
+ PcdLib
+ MmUnblockMemoryLib
+
+[Guids]
+ gEfiTpmDeviceInstanceTpm20DtpmGuid ## PRODUCES ## GUID # TPM device identifier
+ gTpmNvsMmGuid ## CONSUMES
+ gEdkiiPiSmmCommunicationRegionTableGuid ## CONSUMES
+
+[Protocols]
+ gEfiAcpiTableProtocolGuid ## CONSUMES
+ gEfiMmCommunicationProtocolGuid ## CONSUMES
+
+[FixedPcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdSmiCommandIoPort ## CONSUMES
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## CONSUMES
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## CONSUMES
+
+[Depex]
+ gEfiAcpiTableProtocolGuid AND
+ gTcg2MmSwSmiRegisteredGuid AND
+ gEfiTcg2ProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tpm.asl
index 7b24ae656f4..7b24ae656f4 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tpm.asl
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Acpi/Tpm.asl
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr
index 938cbefeea4..8ea8e9ce2a3 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2Config.vfr
@@ -144,7 +144,9 @@ formset
option text = STRING_TOKEN(STR_TCG2_DISABLE), value = TCG2_PHYSICAL_PRESENCE_DISABLE, flags = RESET_REQUIRED;
option text = STRING_TOKEN(STR_TCG2_CLEAR), value = TCG2_PHYSICAL_PRESENCE_CLEAR, flags = RESET_REQUIRED;
option text = STRING_TOKEN(STR_TCG2_SET_PCD_BANKS), value = TCG2_PHYSICAL_PRESENCE_SET_PCR_BANKS, flags = RESET_REQUIRED;
+ suppressif ideqval TCG2_CONFIGURATION_INFO.ChangeEPSSupported == 0;
option text = STRING_TOKEN(STR_TCG2_CHANGE_EPS), value = TCG2_PHYSICAL_PRESENCE_CHANGE_EPS, flags = RESET_REQUIRED;
+ endif
option text = STRING_TOKEN(STR_TCG2_LOG_ALL_DIGESTS), value = TCG2_PHYSICAL_PRESENCE_LOG_ALL_DIGESTS, flags = RESET_REQUIRED;
option text = STRING_TOKEN(STR_TCG2_DISABLE_ENDORSEMENT_ENABLE_STORAGE_HIERARCHY), value = TCG2_PHYSICAL_PRESENCE_DISABLE_ENDORSEMENT_ENABLE_STORAGE_HIERARCHY, flags = RESET_REQUIRED;
endoneof;
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c
index 68c969de59a..e7b51213e18 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigImpl.c
@@ -788,6 +788,7 @@ InstallTcg2ConfigForm (
CHAR16 TempBuffer[1024];
TCG2_CONFIGURATION_INFO Tcg2ConfigInfo;
TPM2_PTP_INTERFACE_TYPE TpmDeviceInterfaceDetected;
+ BOOLEAN IsCmdImp = FALSE;
DriverHandle = NULL;
ConfigAccess = &PrivateData->ConfigAccess;
@@ -870,6 +871,12 @@ InstallTcg2ConfigForm (
HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_TPM2_SUPPORTED_HASH_ALGO_CONTENT), TempBuffer, NULL);
}
+ Status = Tpm2GetCapabilityIsCommandImplemented (TPM_CC_ChangeEPS, &IsCmdImp);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Tpm2GetCapabilityIsCmdImpl fails %r\n", Status));
+ }
+ Tcg2ConfigInfo.ChangeEPSSupported = IsCmdImp;
+
FillBufferWithBootHashAlg (TempBuffer, sizeof(TempBuffer), PcdGet32 (PcdTcg2HashAlgorithmBitmap));
HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_BIOS_HASH_ALGO_CONTENT), TempBuffer, NULL);
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
index 54ced75e3d0..5460a7674e7 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Config/Tcg2ConfigNvData.h
@@ -70,6 +70,7 @@ typedef struct {
UINT8 TpmDeviceInterfaceAttempt;
BOOLEAN TpmDeviceInterfacePtpFifoSupported;
BOOLEAN TpmDeviceInterfacePtpCrbSupported;
+ BOOLEAN ChangeEPSSupported;
} TCG2_CONFIGURATION_INFO;
//
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
index 4fd64a0a644..9d4142ba1a1 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
@@ -1589,7 +1589,7 @@ SetupEventLog (
TcgEfiSpecIdEventStruct->platformClass = PcdGet8 (PcdTpmPlatformClass);
TcgEfiSpecIdEventStruct->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2;
TcgEfiSpecIdEventStruct->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2;
- TcgEfiSpecIdEventStruct->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2;
+ TcgEfiSpecIdEventStruct->specErrata = (UINT8)PcdGet32(PcdTcgPfpMeasurementRevision);
TcgEfiSpecIdEventStruct->uintnSize = sizeof(UINTN)/sizeof(UINT32);
NumberOfAlgorithms = 0;
DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *)((UINT8 *)TcgEfiSpecIdEventStruct + sizeof(*TcgEfiSpecIdEventStruct) + sizeof(NumberOfAlgorithms));
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
index 07f54d80d71..0b839ad2ff5 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf
@@ -106,6 +106,7 @@
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev ## CONSUMES
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## PRODUCES
gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## PRODUCES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdTcgPfpMeasurementRevision ## CONSUMES
[Depex]
# According to PcdTpm2AcpiTableRev definition in SecurityPkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
index d0ec1a77140..a54a0b2f318 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.c
@@ -1,7 +1,7 @@
/** @file
Initialize TPM2 device and measure FVs before handing off control to DXE.
-Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -17,10 +17,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Ppi/EndOfPeiPhase.h>
#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
#include <Ppi/FirmwareVolumeInfoPrehashedFV.h>
+#include <Ppi/Tcg.h>
#include <Guid/TcgEventHob.h>
#include <Guid/MeasuredFvHob.h>
#include <Guid/TpmInstance.h>
+#include <Guid/MigratedFvInfo.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
@@ -66,6 +68,48 @@ EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
NULL
};
+/**
+ Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
+ and build a GUIDed HOB recording the event which will be passed to the DXE phase and
+ added into the Event Log.
+
+ @param[in] This Indicates the calling context
+ @param[in] Flags Bitmap providing additional information.
+ @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
+ start of the data buffer to be hashed, extended, and logged.
+ If BIT0 of Flags is 1, it is physical address of the
+ start of the pre-hash data buffter to be extended, and logged.
+ The pre-hash data format is TPML_DIGEST_VALUES.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+HashLogExtendEvent (
+ IN EDKII_TCG_PPI *This,
+ IN UINT64 Flags,
+ IN UINT8 *HashData,
+ IN UINTN HashDataLen,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ );
+
+EDKII_TCG_PPI mEdkiiTcgPpi = {
+ HashLogExtendEvent
+};
+
+EFI_PEI_PPI_DESCRIPTOR mTcgPpiList = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEdkiiTcgPpiGuid,
+ &mEdkiiTcgPpi
+};
+
//
// Number of firmware blobs to grow by each time we run out of room
//
@@ -375,9 +419,13 @@ LogHashEvent (
and build a GUIDed HOB recording the event which will be passed to the DXE phase and
added into the Event Log.
+ @param[in] This Indicates the calling context
@param[in] Flags Bitmap providing additional information.
- @param[in] HashData Physical address of the start of the data buffer
- to be hashed, extended, and logged.
+ @param[in] HashData If BIT0 of Flags is 0, it is physical address of the
+ start of the data buffer to be hashed, extended, and logged.
+ If BIT0 of Flags is 1, it is physical address of the
+ start of the pre-hash data buffter to be extended, and logged.
+ The pre-hash data format is TPML_DIGEST_VALUES.
@param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
@param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
@param[in] NewEventData Pointer to the new event data.
@@ -388,7 +436,9 @@ LogHashEvent (
**/
EFI_STATUS
+EFIAPI
HashLogExtendEvent (
+ IN EDKII_TCG_PPI *This,
IN UINT64 Flags,
IN UINT8 *HashData,
IN UINTN HashDataLen,
@@ -403,16 +453,26 @@ HashLogExtendEvent (
return EFI_DEVICE_ERROR;
}
- Status = HashAndExtend (
- NewEventHdr->PCRIndex,
- HashData,
- HashDataLen,
- &DigestList
- );
- if (!EFI_ERROR (Status)) {
- if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) {
- Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
+ if ((Flags & EDKII_TCG_PRE_HASH) != 0 || (Flags & EDKII_TCG_PRE_HASH_LOG_ONLY) != 0) {
+ ZeroMem (&DigestList, sizeof(DigestList));
+ CopyMem (&DigestList, HashData, sizeof(DigestList));
+ Status = EFI_SUCCESS;
+ if ((Flags & EDKII_TCG_PRE_HASH) !=0 ) {
+ Status = Tpm2PcrExtend (
+ NewEventHdr->PCRIndex,
+ &DigestList
+ );
}
+ } else {
+ Status = HashAndExtend (
+ NewEventHdr->PCRIndex,
+ HashData,
+ HashDataLen,
+ &DigestList
+ );
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = LogHashEvent (&DigestList, NewEventHdr, NewEventData);
}
if (Status == EFI_DEVICE_ERROR) {
@@ -452,6 +512,7 @@ MeasureCRTMVersion (
TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
return HashLogExtendEvent (
+ &mEdkiiTcgPpi,
0,
(UINT8*)PcdGetPtr (PcdFirmwareVersionString),
TcgEventHdr.EventSize,
@@ -536,6 +597,10 @@ MeasureFvImage (
EDKII_PEI_FIRMWARE_VOLUME_INFO_PREHASHED_FV_PPI *PrehashedFvPpi;
HASH_INFO *PreHashInfo;
UINT32 HashAlgoMask;
+ EFI_PHYSICAL_ADDRESS FvOrgBase;
+ EFI_PHYSICAL_ADDRESS FvDataBase;
+ EFI_PEI_HOB_POINTERS Hob;
+ EDKII_MIGRATED_FV_INFO *MigratedFvInfo;
//
// Check Excluded FV list
@@ -622,6 +687,26 @@ MeasureFvImage (
} while (!EFI_ERROR(Status));
//
+ // Search the matched migration FV info
+ //
+ FvOrgBase = FvBase;
+ FvDataBase = FvBase;
+ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
+ while (Hob.Raw != NULL) {
+ MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
+ if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) {
+ //
+ // Found the migrated FV info
+ //
+ FvOrgBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase;
+ FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase;
+ break;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
+ }
+
+ //
// Init the log event for FV measurement
//
if (PcdGet32(PcdTcgPfpMeasurementRevision) >= TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2_REV_105) {
@@ -631,13 +716,14 @@ MeasureFvImage (
if (FvName != NULL) {
AsciiSPrint ((CHAR8 *)FvBlob2.BlobDescription, sizeof(FvBlob2.BlobDescription), "Fv(%g)", FvName);
}
- FvBlob2.BlobBase = FvBase;
+ FvBlob2.BlobBase = FvOrgBase;
FvBlob2.BlobLength = FvLength;
+ TcgEventHdr.PCRIndex = 0;
TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB2;
TcgEventHdr.EventSize = sizeof (FvBlob2);
EventData = &FvBlob2;
} else {
- FvBlob.BlobBase = FvBase;
+ FvBlob.BlobBase = FvOrgBase;
FvBlob.BlobLength = FvLength;
TcgEventHdr.PCRIndex = 0;
TcgEventHdr.EventType = EV_EFI_PLATFORM_FIRMWARE_BLOB;
@@ -650,29 +736,24 @@ MeasureFvImage (
// FV pre-hash algos comply with current TPM hash requirement
// Skip hashing step in measure, only extend DigestList to PCR and log event
//
- Status = Tpm2PcrExtend(
- 0,
- &DigestList
+ Status = HashLogExtendEvent (
+ &mEdkiiTcgPpi,
+ EDKII_TCG_PRE_HASH,
+ (UINT8*) &DigestList, // HashData
+ (UINTN) sizeof(DigestList), // HashDataLen
+ &TcgEventHdr, // EventHdr
+ EventData // EventData
);
-
- if (!EFI_ERROR(Status)) {
- Status = LogHashEvent (&DigestList, &TcgEventHdr, EventData);
- DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase));
- DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength));
- } else if (Status == EFI_DEVICE_ERROR) {
- BuildGuidHob (&gTpmErrorHobGuid,0);
- REPORT_STATUS_CODE (
- EFI_ERROR_CODE | EFI_ERROR_MINOR,
- (PcdGet32 (PcdStatusCodeSubClassTpmDevice) | EFI_P_EC_INTERFACE_ERROR)
- );
- }
+ DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei starts at: 0x%x\n", FvBase));
+ DEBUG ((DEBUG_INFO, "The pre-hashed FV which is extended & logged by Tcg2Pei has the size: 0x%x\n", FvLength));
} else {
//
// Hash the FV, extend digest to the TPM and log TCG event
//
Status = HashLogExtendEvent (
+ &mEdkiiTcgPpi,
0,
- (UINT8*) (UINTN) FvBase, // HashData
+ (UINT8*) (UINTN) FvDataBase, // HashData
(UINTN) FvLength, // HashDataLen
&TcgEventHdr, // EventHdr
EventData // EventData
@@ -848,6 +929,12 @@ PeimEntryMP (
{
EFI_STATUS Status;
+ //
+ // install Tcg Services
+ //
+ Status = PeiServicesInstallPpi (&mTcgPpiList);
+ ASSERT_EFI_ERROR (Status);
+
if (PcdGet8 (PcdTpm2ScrtmPolicy) == 1) {
Status = MeasureCRTMVersion ();
}
@@ -892,7 +979,7 @@ MeasureSeparatorEventWithError (
TcgEvent.PCRIndex = PCRIndex;
TcgEvent.EventType = EV_SEPARATOR;
TcgEvent.EventSize = (UINT32)sizeof (EventData);
- return HashLogExtendEvent(0,(UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
+ return HashLogExtendEvent(&mEdkiiTcgPpi, 0, (UINT8 *)&EventData, TcgEvent.EventSize, &TcgEvent,(UINT8 *)&EventData);
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
index e5831c0968c..dc2ce364e20 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
@@ -8,7 +8,7 @@
#
# This module will initialize TPM device, measure reported FVs and BIOS version.
#
-# Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, Microsoft Corporation. All rights reserved. <BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -63,6 +63,7 @@
gTcgEvent2EntryHobGuid ## PRODUCES ## HOB
gEfiTpmDeviceInstanceNoneGuid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier
gEfiTpmDeviceInstanceTpm12Guid ## SOMETIMES_PRODUCES ## GUID # TPM device identifier
+ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB
[Ppis]
gEfiPeiFirmwareVolumeInfoPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY
@@ -72,6 +73,7 @@
gPeiTpmInitializationDonePpiGuid ## PRODUCES
gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY
gEdkiiPeiFirmwareVolumeInfoPrehashedFvPpiGuid ## SOMETIMES_CONSUMES
+ gEdkiiTcgPpiGuid ## PRODUCES
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.c
new file mode 100644
index 00000000000..27143698d49
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.c
@@ -0,0 +1,48 @@
+/** @file
+ Runtime DXE part corresponding to StandaloneMM Tcg2 module.
+
+This module installs gTcg2MmSwSmiRegisteredGuid to notify readiness of
+StandaloneMM Tcg2 module.
+
+Copyright (c) 2019 - 2021, Arm Ltd. All rights reserved.
+Copyright (c) Microsoft Corporation.
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ The constructor function installs gTcg2MmSwSmiRegisteredGuid to notify
+ readiness of StandaloneMM Tcg2 module.
+
+ @param ImageHandle The firmware allocated handle for the EFI image.
+ @param SystemTable A pointer to the Management mode System Table.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+Tcg2MmDependencyDxeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gTcg2MmSwSmiRegisteredGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.inf
new file mode 100644
index 00000000000..e99b900fc12
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2MmDependencyDxe.inf
@@ -0,0 +1,43 @@
+## @file
+# Runtime DXE part corresponding to StandaloneMM Tcg2 module.
+#
+# This module installs gTcg2MmSwSmiRegisteredGuid to notify readiness of
+# StandaloneMM Tcg2 module.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = Tcg2MmDependencyDxe
+ FILE_GUID = 94C210EA-3113-4563-ADEB-76FE759C2F46
+ MODULE_TYPE = DXE_DRIVER
+ ENTRY_POINT = Tcg2MmDependencyDxeEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+#
+
+[Sources]
+ Tcg2MmDependencyDxe.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Guids]
+ gTcg2MmSwSmiRegisteredGuid ## PRODUCES ## GUID # Install protocol
+
+[Depex]
+ gEfiMmCommunication2ProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
index f1c72fe66a8..5d14d3a192d 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.c
@@ -10,47 +10,95 @@
PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "Tcg2Smm.h"
-#pragma pack(1)
-
-typedef struct {
- EFI_ACPI_DESCRIPTION_HEADER Header;
- // Flags field is replaced in version 4 and above
- // BIT0~15: PlatformClass This field is only valid for version 4 and above
- // BIT16~31: Reserved
- UINT32 Flags;
- UINT64 AddressOfControlArea;
- UINT32 StartMethod;
- UINT8 PlatformSpecificParameters[12]; // size up to 12
- UINT32 Laml; // Optional
- UINT64 Lasa; // Optional
-} EFI_TPM2_ACPI_TABLE_V4;
-
-#pragma pack()
-
-EFI_TPM2_ACPI_TABLE_V4 mTpm2AcpiTemplate = {
- {
- EFI_ACPI_5_0_TRUSTED_COMPUTING_PLATFORM_2_TABLE_SIGNATURE,
- sizeof (mTpm2AcpiTemplate),
- EFI_TPM2_ACPI_TABLE_REVISION,
- //
- // Compiler initializes the remaining bytes to 0
- // These fields should be filled in in production
- //
- },
- 0, // BIT0~15: PlatformClass
- // BIT16~31: Reserved
- 0, // Control Area
- EFI_TPM2_ACPI_TABLE_START_METHOD_TIS, // StartMethod
-};
-
-EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable;
-TCG_NVS *mTcgNvs;
+EFI_SMM_VARIABLE_PROTOCOL *mSmmVariable = NULL;
+TCG_NVS *mTcgNvs = NULL;
+UINTN mPpSoftwareSmi;
+UINTN mMcSoftwareSmi;
+EFI_HANDLE mReadyToLockHandle;
+
+/**
+ Communication service SMI Handler entry.
+
+ This handler takes requests to exchange Mmi channel and Nvs address between MM and DXE.
+
+ Caution: This function may receive untrusted input.
+ Communicate buffer and buffer size are external input, so this function will do basic validation.
+
+ @param[in] DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().
+ @param[in] RegisterContext Points to an optional handler context which was specified when the
+ handler was registered.
+ @param[in, out] CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-SMM environment into an SMM environment.
+ @param[in, out] CommBufferSize The size of the CommBuffer.
+
+ @retval EFI_SUCCESS The interrupt was handled and quiesced. No other handlers
+ should still be called.
+ @retval EFI_UNSUPPORTED An unknown test function was requested.
+ @retval EFI_ACCESS_DENIED Part of the communication buffer lies in an invalid region.
+
+**/
+EFI_STATUS
+EFIAPI
+TpmNvsCommunciate (
+ IN EFI_HANDLE DispatchHandle,
+ IN CONST VOID *RegisterContext,
+ IN OUT VOID *CommBuffer,
+ IN OUT UINTN *CommBufferSize
+ )
+{
+ EFI_STATUS Status;
+ UINTN TempCommBufferSize;
+ TPM_NVS_MM_COMM_BUFFER *CommParams;
+
+ DEBUG ((DEBUG_VERBOSE, "%a()\n", __FUNCTION__));
+
+ //
+ // If input is invalid, stop processing this SMI
+ //
+ if (CommBuffer == NULL || CommBufferSize == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ TempCommBufferSize = *CommBufferSize;
+
+ if(TempCommBufferSize != sizeof (TPM_NVS_MM_COMM_BUFFER)) {
+ DEBUG ((DEBUG_ERROR, "[%a] MM Communication buffer size is invalid for this handler!\n", __FUNCTION__));
+ return EFI_ACCESS_DENIED;
+ }
+ if (!IsBufferOutsideMmValid ((UINTN) CommBuffer, TempCommBufferSize)) {
+ DEBUG ((DEBUG_ERROR, "[%a] - MM Communication buffer in invalid location!\n", __FUNCTION__));
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Farm out the job to individual functions based on what was requested.
+ //
+ CommParams = (TPM_NVS_MM_COMM_BUFFER*) CommBuffer;
+ Status = EFI_SUCCESS;
+ switch (CommParams->Function) {
+ case TpmNvsMmExchangeInfo:
+ DEBUG ((DEBUG_VERBOSE, "[%a] - Function requested: MM_EXCHANGE_NVS_INFO\n", __FUNCTION__));
+ CommParams->RegisteredPpSwiValue = mPpSoftwareSmi;
+ CommParams->RegisteredMcSwiValue = mMcSoftwareSmi;
+ mTcgNvs = (TCG_NVS*) (UINTN) CommParams->TargetAddress;
+ break;
+
+ default:
+ DEBUG ((DEBUG_INFO, "[%a] - Unknown function %d!\n", __FUNCTION__, CommParams->Function));
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ CommParams->ReturnStatus = (UINT64) Status;
+ return EFI_SUCCESS;
+}
/**
Software SMI callback for TPM physical presence which is called from ACPI method.
@@ -186,721 +234,142 @@ MemoryClearCallback (
}
/**
- Find the operation region in TCG ACPI table by given Name and Size,
- and initialize it if the region is found.
-
- @param[in, out] Table The TPM item in ACPI table.
- @param[in] Name The name string to find in TPM table.
- @param[in] Size The size of the region to find.
-
- @return The allocated address for the found region.
-
-**/
-VOID *
-AssignOpRegion (
- EFI_ACPI_DESCRIPTION_HEADER *Table,
- UINT32 Name,
- UINT16 Size
- )
-{
- EFI_STATUS Status;
- AML_OP_REGION_32_8 *OpRegion;
- EFI_PHYSICAL_ADDRESS MemoryAddress;
-
- MemoryAddress = SIZE_4GB - 1;
-
- //
- // Patch some pointers for the ASL code before loading the SSDT.
- //
- for (OpRegion = (AML_OP_REGION_32_8 *) (Table + 1);
- OpRegion <= (AML_OP_REGION_32_8 *) ((UINT8 *) Table + Table->Length);
- OpRegion = (AML_OP_REGION_32_8 *) ((UINT8 *) OpRegion + 1)) {
- if ((OpRegion->OpRegionOp == AML_EXT_REGION_OP) &&
- (OpRegion->NameString == Name) &&
- (OpRegion->DWordPrefix == AML_DWORD_PREFIX) &&
- (OpRegion->BytePrefix == AML_BYTE_PREFIX)) {
-
- Status = gBS->AllocatePages(AllocateMaxAddress, EfiACPIMemoryNVS, EFI_SIZE_TO_PAGES (Size), &MemoryAddress);
- ASSERT_EFI_ERROR (Status);
- ZeroMem ((VOID *)(UINTN)MemoryAddress, Size);
- OpRegion->RegionOffset = (UINT32) (UINTN) MemoryAddress;
- OpRegion->RegionLen = (UINT8) Size;
- break;
- }
- }
-
- return (VOID *) (UINTN) MemoryAddress;
-}
-
-/**
- Patch version string of Physical Presence interface supported by platform. The initial string tag in TPM
-ACPI table is "$PV".
-
- @param[in, out] Table The TPM item in ACPI table.
- @param[in] PPVer Version string of Physical Presence interface supported by platform.
-
- @return The allocated address for the found region.
-
-**/
-EFI_STATUS
-UpdatePPVersion (
- EFI_ACPI_DESCRIPTION_HEADER *Table,
- CHAR8 *PPVer
- )
-{
- EFI_STATUS Status;
- UINT8 *DataPtr;
-
- //
- // Patch some pointers for the ASL code before loading the SSDT.
- //
- for (DataPtr = (UINT8 *)(Table + 1);
- DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - PHYSICAL_PRESENCE_VERSION_SIZE);
- DataPtr += 1) {
- if (AsciiStrCmp((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_TAG) == 0) {
- Status = AsciiStrCpyS((CHAR8 *)DataPtr, PHYSICAL_PRESENCE_VERSION_SIZE, PPVer);
- DEBUG((EFI_D_INFO, "TPM2 Physical Presence Interface Version update status 0x%x\n", Status));
- return Status;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Patch interrupt resources returned by TPM _PRS. ResourceTemplate to patch is determined by input
- interrupt buffer size. BufferSize, PkgLength and interrupt descriptor in ByteList need to be patched
-
- @param[in, out] Table The TPM item in ACPI table.
- @param[in] IrqBuffer Input new IRQ buffer.
- @param[in] IrqBuffserSize Input new IRQ buffer size.
- @param[out] IsShortFormPkgLength If _PRS returns Short length Package(ACPI spec 20.2.4).
-
- @return patch status.
-
-**/
-EFI_STATUS
-UpdatePossibleResource (
- IN OUT EFI_ACPI_DESCRIPTION_HEADER *Table,
- IN UINT32 *IrqBuffer,
- IN UINT32 IrqBuffserSize,
- OUT BOOLEAN *IsShortFormPkgLength
- )
-{
- UINT8 *DataPtr;
- UINT8 *DataEndPtr;
- UINT32 NewPkgLength;
- UINT32 OrignalPkgLength;
-
- NewPkgLength = 0;
- OrignalPkgLength = 0;
- DataEndPtr = NULL;
-
- //
- // Follow ACPI spec
- // 6.4.3 Extend Interrupt Descriptor.
- // 19.3.3 ASL Resource Template
- // 20 AML specification
- // to patch TPM ACPI object _PRS returned ResourceTemplate() containing 2 resource descriptors and an auto appended End Tag
- //
- // AML data is organized by following rule.
- // Code need to patch BufferSize and PkgLength and interrupt descriptor in ByteList
- //
- // ============= Buffer ====================
- // DefBuffer := BufferOp PkgLength BufferSize ByteList
- // BufferOp := 0x11
- //
- // ==============PkgLength==================
- // PkgLength := PkgLeadByte |
- // <PkgLeadByte ByteData> |
- // <PkgLeadByte ByteData ByteData> |
- // <PkgLeadByte ByteData ByteData ByteData>
- //
- // PkgLeadByte := <bit 7-6: ByteData count that follows (0-3)>
- // <bit 5-4: Only used if PkgLength <= 63 >
- // <bit 3-0: Least significant package length nybble>
- //
- //==============BufferSize==================
- // BufferSize := Integer
- // Integer := ByteConst|WordConst|DwordConst....
- //
- // ByteConst := BytePrefix ByteData
- //
- //==============ByteList===================
- // ByteList := ByteData ByteList
- //
- //=========================================
-
- //
- // 1. Check TPM_PRS_RESS with PkgLength <=63 can hold the input interrupt number buffer for patching
- //
- for (DataPtr = (UINT8 *)(Table + 1);
- DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
- DataPtr += 1) {
- if (CompareMem(DataPtr, TPM_PRS_RESS, TPM_PRS_RES_NAME_SIZE) == 0) {
- //
- // Jump over object name & BufferOp
- //
- DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
-
- if ((*DataPtr & (BIT7|BIT6)) == 0) {
- OrignalPkgLength = (UINT32)*DataPtr;
- DataEndPtr = DataPtr + OrignalPkgLength;
-
- //
- // Jump over PkgLength = PkgLeadByte only
- //
- NewPkgLength++;
-
- //
- // Jump over BufferSize
- //
- if (*(DataPtr + 1) == AML_BYTE_PREFIX) {
- NewPkgLength += 2;
- } else if (*(DataPtr + 1) == AML_WORD_PREFIX) {
- NewPkgLength += 3;
- } else if (*(DataPtr + 1) == AML_DWORD_PREFIX) {
- NewPkgLength += 5;
- } else {
- ASSERT(FALSE);
- return EFI_UNSUPPORTED;
- }
- } else {
- ASSERT(FALSE);
- return EFI_UNSUPPORTED;
- }
-
- //
- // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
- //
- NewPkgLength += 19 + IrqBuffserSize;
- if (NewPkgLength > 63) {
- break;
- }
-
- if (NewPkgLength > OrignalPkgLength) {
- ASSERT(FALSE);
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // 1.1 Patch PkgLength
- //
- *DataPtr = (UINT8)NewPkgLength;
-
- //
- // 1.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).
- // It is Little endian. So only patch lowest byte of BufferSize due to current interrupt number limit.
- //
- *(DataPtr + 2) = (UINT8)(IrqBuffserSize + 19);
-
- //
- // Notify _PRS to report short formed ResourceTemplate
- //
- *IsShortFormPkgLength = TRUE;
-
- break;
- }
- }
-
- //
- // 2. Use TPM_PRS_RESL with PkgLength > 63 to hold longer input interrupt number buffer for patching
- //
- if (NewPkgLength > 63) {
- NewPkgLength = 0;
- OrignalPkgLength = 0;
- for (DataPtr = (UINT8 *)(Table + 1);
- DataPtr < (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE));
- DataPtr += 1) {
- if (CompareMem(DataPtr, TPM_PRS_RESL, TPM_PRS_RES_NAME_SIZE) == 0) {
- //
- // Jump over object name & BufferOp
- //
- DataPtr += TPM_PRS_RES_NAME_SIZE + 1;
-
- if ((*DataPtr & (BIT7|BIT6)) != 0) {
- OrignalPkgLength = (UINT32)(*(DataPtr + 1) << 4) + (*DataPtr & 0x0F);
- DataEndPtr = DataPtr + OrignalPkgLength;
- //
- // Jump over PkgLength = PkgLeadByte + ByteData length
- //
- NewPkgLength += 1 + ((*DataPtr & (BIT7|BIT6)) >> 6);
-
- //
- // Jump over BufferSize
- //
- if (*(DataPtr + NewPkgLength) == AML_BYTE_PREFIX) {
- NewPkgLength += 2;
- } else if (*(DataPtr + NewPkgLength) == AML_WORD_PREFIX) {
- NewPkgLength += 3;
- } else if (*(DataPtr + NewPkgLength) == AML_DWORD_PREFIX) {
- NewPkgLength += 5;
- } else {
- ASSERT(FALSE);
- return EFI_UNSUPPORTED;
- }
- } else {
- ASSERT(FALSE);
- return EFI_UNSUPPORTED;
- }
-
- //
- // Include Memory32Fixed Descriptor (12 Bytes) + Interrupt Descriptor header(5 Bytes) + End Tag(2 Bytes)
- //
- NewPkgLength += 19 + IrqBuffserSize;
-
- if (NewPkgLength > OrignalPkgLength) {
- ASSERT(FALSE);
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // 2.1 Patch PkgLength. Only patch PkgLeadByte and first ByteData
- //
- *DataPtr = (UINT8)((*DataPtr) & 0xF0) | (NewPkgLength & 0x0F);
- *(DataPtr + 1) = (UINT8)((NewPkgLength & 0xFF0) >> 4);
-
- //
- // 2.2 Patch BufferSize = sizeof(Memory32Fixed Descriptor + Interrupt Descriptor + End Tag).
- // It is Little endian. Only patch lowest byte of BufferSize due to current interrupt number limit.
- //
- *(DataPtr + 2 + ((*DataPtr & (BIT7|BIT6)) >> 6)) = (UINT8)(IrqBuffserSize + 19);
-
- //
- // Notify _PRS to report long formed ResourceTemplate
- //
- *IsShortFormPkgLength = FALSE;
- break;
- }
- }
- }
-
- if (DataPtr >= (UINT8 *) ((UINT8 *) Table + Table->Length - (TPM_PRS_RES_NAME_SIZE + TPM_POS_RES_TEMPLATE_MIN_SIZE))) {
- return EFI_NOT_FOUND;
- }
-
- //
- // 3. Move DataPtr to Interrupt descriptor header and patch interrupt descriptor.
- // 5 bytes for interrupt descriptor header, 2 bytes for End Tag
- //
- DataPtr += NewPkgLength - (5 + IrqBuffserSize + 2);
- //
- // 3.1 Patch Length bit[7:0] of Interrupt descriptor patch interrupt descriptor
- //
- *(DataPtr + 1) = (UINT8)(2 + IrqBuffserSize);
- //
- // 3.2 Patch Interrupt Table Length
- //
- *(DataPtr + 4) = (UINT8)(IrqBuffserSize / sizeof(UINT32));
- //
- // 3.3 Copy patched InterruptNumBuffer
- //
- CopyMem(DataPtr + 5, IrqBuffer, IrqBuffserSize);
-
- //
- // 4. Jump over Interrupt descriptor and Patch END Tag, set Checksum field to 0
- //
- DataPtr += 5 + IrqBuffserSize;
- *DataPtr = ACPI_END_TAG_DESCRIPTOR;
- *(DataPtr + 1) = 0;
-
- //
- // 5. Jump over new ResourceTemplate. Stuff rest bytes to NOOP
- //
- DataPtr += 2;
- if (DataPtr < DataEndPtr) {
- SetMem(DataPtr, (UINTN)DataEndPtr - (UINTN)DataPtr, AML_NOOP_OP);
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Patch TPM2 device HID string. The initial string tag in TPM2 ACPI table is "NNN0000".
-
- @param[in, out] Table The TPM2 SSDT ACPI table.
-
- @return HID Update status.
-
-**/
-EFI_STATUS
-UpdateHID (
- EFI_ACPI_DESCRIPTION_HEADER *Table
- )
-{
- EFI_STATUS Status;
- UINT8 *DataPtr;
- CHAR8 Hid[TPM_HID_ACPI_SIZE];
- UINT32 ManufacturerID;
- UINT32 FirmwareVersion1;
- UINT32 FirmwareVersion2;
- BOOLEAN PnpHID;
-
- PnpHID = TRUE;
-
- //
- // Initialize HID with Default PNP string
- //
- ZeroMem(Hid, TPM_HID_ACPI_SIZE);
-
- //
- // Get Manufacturer ID
- //
- Status = Tpm2GetCapabilityManufactureID(&ManufacturerID);
- if (!EFI_ERROR(Status)) {
- DEBUG((EFI_D_INFO, "TPM_PT_MANUFACTURER 0x%08x\n", ManufacturerID));
- //
- // ManufacturerID defined in TCG Vendor ID Registry
- // may tailed with 0x00 or 0x20
- //
- if ((ManufacturerID >> 24) == 0x00 || ((ManufacturerID >> 24) == 0x20)) {
- //
- // HID containing PNP ID "NNN####"
- // NNN is uppercase letter for Vendor ID specified by manufacturer
- //
- CopyMem(Hid, &ManufacturerID, 3);
- } else {
- //
- // HID containing ACP ID "NNNN####"
- // NNNN is uppercase letter for Vendor ID specified by manufacturer
- //
- CopyMem(Hid, &ManufacturerID, 4);
- PnpHID = FALSE;
- }
- } else {
- DEBUG ((EFI_D_ERROR, "Get TPM_PT_MANUFACTURER failed %x!\n", Status));
- ASSERT(FALSE);
- return Status;
- }
-
- Status = Tpm2GetCapabilityFirmwareVersion(&FirmwareVersion1, &FirmwareVersion2);
- if (!EFI_ERROR(Status)) {
- DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_1 0x%x\n", FirmwareVersion1));
- DEBUG((EFI_D_INFO, "TPM_PT_FIRMWARE_VERSION_2 0x%x\n", FirmwareVersion2));
- //
- // #### is Firmware Version 1
- //
- if (PnpHID) {
- AsciiSPrint(Hid + 3, TPM_HID_PNP_SIZE - 3, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
- } else {
- AsciiSPrint(Hid + 4, TPM_HID_ACPI_SIZE - 4, "%02d%02d", ((FirmwareVersion1 & 0xFFFF0000) >> 16), (FirmwareVersion1 & 0x0000FFFF));
- }
-
- } else {
- DEBUG ((EFI_D_ERROR, "Get TPM_PT_FIRMWARE_VERSION_X failed %x!\n", Status));
- ASSERT(FALSE);
- return Status;
- }
-
- //
- // Patch HID in ASL code before loading the SSDT.
- //
- for (DataPtr = (UINT8 *)(Table + 1);
- DataPtr <= (UINT8 *) ((UINT8 *) Table + Table->Length - TPM_HID_PNP_SIZE);
- DataPtr += 1) {
- if (AsciiStrCmp((CHAR8 *)DataPtr, TPM_HID_TAG) == 0) {
- if (PnpHID) {
- CopyMem(DataPtr, Hid, TPM_HID_PNP_SIZE);
- //
- // if HID is PNP ID, patch the last byte in HID TAG to Noop
- //
- *(DataPtr + TPM_HID_PNP_SIZE) = AML_NOOP_OP;
- } else {
-
- CopyMem(DataPtr, Hid, TPM_HID_ACPI_SIZE);
- }
- DEBUG((DEBUG_INFO, "TPM2 ACPI _HID is patched to %a\n", DataPtr));
-
- return Status;
- }
- }
-
- DEBUG((EFI_D_ERROR, "TPM2 ACPI HID TAG for patch not found!\n"));
- return EFI_NOT_FOUND;
-}
+ Notification for SMM ReadyToLock protocol.
-/**
- Initialize and publish TPM items in ACPI table.
+ @param[in] Protocol Points to the protocol's unique identifier.
+ @param[in] Interface Points to the interface instance.
+ @param[in] Handle The handle on which the interface was installed.
- @retval EFI_SUCCESS The TCG ACPI table is published successfully.
- @retval Others The TCG ACPI table is not published.
+ @retval EFI_SUCCESS Notification runs successfully.
**/
EFI_STATUS
-PublishAcpiTable (
- VOID
- )
-{
- EFI_STATUS Status;
- EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
- UINTN TableKey;
- EFI_ACPI_DESCRIPTION_HEADER *Table;
- UINTN TableSize;
- UINT32 *PossibleIrqNumBuf;
- UINT32 PossibleIrqNumBufSize;
- BOOLEAN IsShortFormPkgLength;
-
- IsShortFormPkgLength = FALSE;
-
- Status = GetSectionFromFv (
- &gEfiCallerIdGuid,
- EFI_SECTION_RAW,
- 0,
- (VOID **) &Table,
- &TableSize
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
- // The measurement has to be done before any update.
- // Otherwise, the PCR record would be different after TPM FW update
- // or the PCD configuration change.
- //
- TpmMeasureAndLogData(
- 0,
- EV_POST_CODE,
- EV_POSTCODE_INFO_ACPI_DATA,
- ACPI_DATA_LEN,
- Table,
- TableSize
- );
-
- //
- // Update Table version before measuring it to PCR
- //
- Status = UpdatePPVersion(Table, (CHAR8 *)PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer));
- ASSERT_EFI_ERROR (Status);
-
- DEBUG ((
- DEBUG_INFO,
- "Current physical presence interface version - %a\n",
- (CHAR8 *) PcdGetPtr(PcdTcgPhysicalPresenceInterfaceVer)
- ));
-
- //
- // Update TPM2 HID after measuring it to PCR
- //
- Status = UpdateHID(Table);
- if (EFI_ERROR(Status)) {
- return Status;
- }
-
- if (PcdGet32(PcdTpm2CurrentIrqNum) != 0) {
- //
- // Patch _PRS interrupt resource only when TPM interrupt is supported
- //
- PossibleIrqNumBuf = (UINT32 *)PcdGetPtr(PcdTpm2PossibleIrqNumBuf);
- PossibleIrqNumBufSize = (UINT32)PcdGetSize(PcdTpm2PossibleIrqNumBuf);
-
- if (PossibleIrqNumBufSize <= MAX_PRS_INT_BUF_SIZE && (PossibleIrqNumBufSize % sizeof(UINT32)) == 0) {
- Status = UpdatePossibleResource(Table, PossibleIrqNumBuf, PossibleIrqNumBufSize, &IsShortFormPkgLength);
- DEBUG ((
- DEBUG_INFO,
- "UpdatePossibleResource status - %x. TPM2 service may not ready in OS.\n",
- Status
- ));
- } else {
- DEBUG ((
- DEBUG_INFO,
- "PcdTpm2PossibleIrqNumBuf size %x is not correct. TPM2 service may not ready in OS.\n",
- PossibleIrqNumBufSize
- ));
- }
- }
-
- ASSERT (Table->OemTableId == SIGNATURE_64 ('T', 'p', 'm', '2', 'T', 'a', 'b', 'l'));
- CopyMem (Table->OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (Table->OemId) );
- mTcgNvs = AssignOpRegion (Table, SIGNATURE_32 ('T', 'N', 'V', 'S'), (UINT16) sizeof (TCG_NVS));
- ASSERT (mTcgNvs != NULL);
- mTcgNvs->TpmIrqNum = PcdGet32(PcdTpm2CurrentIrqNum);
- mTcgNvs->IsShortFormPkgLength = IsShortFormPkgLength;
-
- //
- // Publish the TPM ACPI table. Table is re-checksummed.
- //
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
- ASSERT_EFI_ERROR (Status);
-
- TableKey = 0;
- Status = AcpiTable->InstallAcpiTable (
- AcpiTable,
- Table,
- TableSize,
- &TableKey
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
-}
-
-/**
- Publish TPM2 ACPI table
-
- @retval EFI_SUCCESS The TPM2 ACPI table is published successfully.
- @retval Others The TPM2 ACPI table is not published.
-
-**/
-EFI_STATUS
-PublishTpm2 (
- VOID
- )
+EFIAPI
+TcgMmReadyToLock (
+ IN CONST EFI_GUID *Protocol,
+ IN VOID *Interface,
+ IN EFI_HANDLE Handle
+)
{
- EFI_STATUS Status;
- EFI_ACPI_TABLE_PROTOCOL *AcpiTable;
- UINTN TableKey;
- UINT64 OemTableId;
- EFI_TPM2_ACPI_CONTROL_AREA *ControlArea;
- TPM2_PTP_INTERFACE_TYPE InterfaceType;
-
- //
- // Measure to PCR[0] with event EV_POST_CODE ACPI DATA.
- // The measurement has to be done before any update.
- // Otherwise, the PCR record would be different after event log update
- // or the PCD configuration change.
- //
- TpmMeasureAndLogData(
- 0,
- EV_POST_CODE,
- EV_POSTCODE_INFO_ACPI_DATA,
- ACPI_DATA_LEN,
- &mTpm2AcpiTemplate,
- mTpm2AcpiTemplate.Header.Length
- );
-
- mTpm2AcpiTemplate.Header.Revision = PcdGet8(PcdTpm2AcpiTableRev);
- DEBUG((DEBUG_INFO, "Tpm2 ACPI table revision is %d\n", mTpm2AcpiTemplate.Header.Revision));
-
- //
- // PlatformClass is only valid for version 4 and above
- // BIT0~15: PlatformClass
- // BIT16~31: Reserved
- //
- if (mTpm2AcpiTemplate.Header.Revision >= EFI_TPM2_ACPI_TABLE_REVISION_4) {
- mTpm2AcpiTemplate.Flags = (mTpm2AcpiTemplate.Flags & 0xFFFF0000) | PcdGet8(PcdTpmPlatformClass);
- DEBUG((DEBUG_INFO, "Tpm2 ACPI table PlatformClass is %d\n", (mTpm2AcpiTemplate.Flags & 0x0000FFFF)));
- }
+ EFI_STATUS Status;
- mTpm2AcpiTemplate.Laml = PcdGet32(PcdTpm2AcpiTableLaml);
- mTpm2AcpiTemplate.Lasa = PcdGet64(PcdTpm2AcpiTableLasa);
- if ((mTpm2AcpiTemplate.Header.Revision < EFI_TPM2_ACPI_TABLE_REVISION_4) ||
- (mTpm2AcpiTemplate.Laml == 0) || (mTpm2AcpiTemplate.Lasa == 0)) {
- //
- // If version is smaller than 4 or Laml/Lasa is not valid, rollback to original Length.
- //
- mTpm2AcpiTemplate.Header.Length = sizeof(EFI_TPM2_ACPI_TABLE);
- }
+ Status = EFI_SUCCESS;
- InterfaceType = PcdGet8(PcdActiveTpmInterfaceType);
- switch (InterfaceType) {
- case Tpm2PtpInterfaceCrb:
- mTpm2AcpiTemplate.StartMethod = EFI_TPM2_ACPI_TABLE_START_METHOD_COMMAND_RESPONSE_BUFFER_INTERFACE;
- mTpm2AcpiTemplate.AddressOfControlArea = PcdGet64 (PcdTpmBaseAddress) + 0x40;
- ControlArea = (EFI_TPM2_ACPI_CONTROL_AREA *)(UINTN)mTpm2AcpiTemplate.AddressOfControlArea;
- ControlArea->CommandSize = 0xF80;
- ControlArea->ResponseSize = 0xF80;
- ControlArea->Command = PcdGet64 (PcdTpmBaseAddress) + 0x80;
- ControlArea->Response = PcdGet64 (PcdTpmBaseAddress) + 0x80;
- break;
- case Tpm2PtpInterfaceFifo:
- case Tpm2PtpInterfaceTis:
- break;
- default:
- DEBUG((EFI_D_ERROR, "TPM2 InterfaceType get error! %d\n", InterfaceType));
- break;
+ if (mReadyToLockHandle != NULL) {
+ Status = gMmst->MmiHandlerUnRegister (mReadyToLockHandle);
+ mReadyToLockHandle = NULL;
}
-
- CopyMem (mTpm2AcpiTemplate.Header.OemId, PcdGetPtr (PcdAcpiDefaultOemId), sizeof (mTpm2AcpiTemplate.Header.OemId));
- OemTableId = PcdGet64 (PcdAcpiDefaultOemTableId);
- CopyMem (&mTpm2AcpiTemplate.Header.OemTableId, &OemTableId, sizeof (UINT64));
- mTpm2AcpiTemplate.Header.OemRevision = PcdGet32 (PcdAcpiDefaultOemRevision);
- mTpm2AcpiTemplate.Header.CreatorId = PcdGet32 (PcdAcpiDefaultCreatorId);
- mTpm2AcpiTemplate.Header.CreatorRevision = PcdGet32 (PcdAcpiDefaultCreatorRevision);
-
- //
- // Construct ACPI table
- //
- Status = gBS->LocateProtocol (&gEfiAcpiTableProtocolGuid, NULL, (VOID **) &AcpiTable);
- ASSERT_EFI_ERROR (Status);
-
- Status = AcpiTable->InstallAcpiTable (
- AcpiTable,
- &mTpm2AcpiTemplate,
- mTpm2AcpiTemplate.Header.Length,
- &TableKey
- );
- ASSERT_EFI_ERROR (Status);
-
return Status;
}
/**
- The driver's entry point.
+ The driver's common initialization routine.
It install callbacks for TPM physical presence and MemoryClear, and locate
SMM variable to be used in the callback function.
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
@retval EFI_SUCCESS The entry point is executed successfully.
@retval Others Some error occurs when executing this entry point.
**/
EFI_STATUS
-EFIAPI
-InitializeTcgSmm (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
+InitializeTcgCommon (
+ VOID
)
{
EFI_STATUS Status;
EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
EFI_SMM_SW_REGISTER_CONTEXT SwContext;
- EFI_HANDLE SwHandle;
+ EFI_HANDLE PpSwHandle;
+ EFI_HANDLE McSwHandle;
+ EFI_HANDLE NotifyHandle;
if (!CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm20DtpmGuid)){
DEBUG ((EFI_D_ERROR, "No TPM2 DTPM instance required!\n"));
return EFI_UNSUPPORTED;
}
- Status = PublishAcpiTable ();
+ // Initialize variables first
+ mReadyToLockHandle = NULL;
+ SwDispatch = NULL;
+ PpSwHandle = NULL;
+ McSwHandle = NULL;
+ NotifyHandle = NULL;
+
+ // Register a root handler to communicate the NVS region and SMI channel between MM and DXE
+ Status = gMmst->MmiHandlerRegister (TpmNvsCommunciate, &gTpmNvsMmGuid, &mReadyToLockHandle);
ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register NVS communicate as root MM handler - %r!\n", __FUNCTION__, Status));
+ goto Cleanup;
+ }
//
// Get the Sw dispatch protocol and register SMI callback functions.
//
- Status = gSmst->SmmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);
+ Status = gMmst->MmLocateProtocol (&gEfiSmmSwDispatch2ProtocolGuid, NULL, (VOID**)&SwDispatch);
ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to locate Sw dispatch protocol - %r!\n", __FUNCTION__, Status));
+ goto Cleanup;
+ }
+
SwContext.SwSmiInputValue = (UINTN) -1;
- Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &SwHandle);
+ Status = SwDispatch->Register (SwDispatch, PhysicalPresenceCallback, &SwContext, &PpSwHandle);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
- return Status;
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register PP callback as SW MM handler - %r!\n", __FUNCTION__, Status));
+ goto Cleanup;
}
- mTcgNvs->PhysicalPresence.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
+ mPpSoftwareSmi = SwContext.SwSmiInputValue;
SwContext.SwSmiInputValue = (UINTN) -1;
- Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &SwHandle);
+ Status = SwDispatch->Register (SwDispatch, MemoryClearCallback, &SwContext, &McSwHandle);
ASSERT_EFI_ERROR (Status);
if (EFI_ERROR (Status)) {
- return Status;
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register MC callback as SW MM handler - %r!\n", __FUNCTION__, Status));
+ goto Cleanup;
}
- mTcgNvs->MemoryClear.SoftwareSmi = (UINT8) SwContext.SwSmiInputValue;
+ mMcSoftwareSmi = SwContext.SwSmiInputValue;
//
// Locate SmmVariableProtocol.
//
- Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
+ Status = gMmst->MmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&mSmmVariable);
ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ // Should not happen
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to locate SMM variable protocol - %r!\n", __FUNCTION__, Status));
+ goto Cleanup;
+ }
- //
- // Set TPM2 ACPI table
- //
- Status = PublishTpm2 ();
+ // Turn off the light before leaving the room... at least, take a remote...
+ Status = gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, TcgMmReadyToLock, &NotifyHandle);
ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "[%a] Failed to register ready to lock notification - %r!\n", __FUNCTION__, Status));
+ goto Cleanup;
+ }
+ Tcg2NotifyMmReady ();
- return EFI_SUCCESS;
+Cleanup:
+ if (EFI_ERROR (Status)) {
+ // Something is whacked, clean up the mess...
+ if (NotifyHandle != NULL) {
+ gMmst->MmRegisterProtocolNotify (&gEfiMmReadyToLockProtocolGuid, NULL, &NotifyHandle);
+ }
+ if (McSwHandle != NULL && SwDispatch != NULL) {
+ SwDispatch->UnRegister (SwDispatch, McSwHandle);
+ }
+ if (PpSwHandle != NULL && SwDispatch != NULL) {
+ SwDispatch->UnRegister (SwDispatch, PpSwHandle);
+ }
+ if (mReadyToLockHandle != NULL) {
+ gMmst->MmiHandlerUnRegister (mReadyToLockHandle);
+ }
+ }
+
+ return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
index 6eef6aa468c..8293bb49536 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.h
@@ -2,6 +2,7 @@
The header file for Tcg2 SMM driver.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -9,13 +10,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef __TCG2_SMM_H__
#define __TCG2_SMM_H__
-#include <PiDxe.h>
-#include <IndustryStandard/Acpi.h>
-#include <IndustryStandard/Tpm2Acpi.h>
+#include <PiMm.h>
#include <Guid/MemoryOverwriteControl.h>
#include <Guid/TpmInstance.h>
+#include <Guid/TpmNvsMm.h>
+#include <Protocol/MmReadyToLock.h>
#include <Protocol/SmmSwDispatch2.h>
#include <Protocol/AcpiTable.h>
#include <Protocol/SmmVariable.h>
@@ -24,57 +25,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
-#include <Library/SmmServicesTableLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/DxeServicesLib.h>
-#include <Library/TpmMeasurementLib.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/Tpm2CommandLib.h>
#include <Library/Tcg2PhysicalPresenceLib.h>
#include <Library/IoLib.h>
-#include <Library/PrintLib.h>
#include <Library/PcdLib.h>
#include <Library/Tpm2DeviceLib.h>
#include <IndustryStandard/TpmPtp.h>
-#pragma pack(1)
-typedef struct {
- UINT8 SoftwareSmi;
- UINT32 Parameter;
- UINT32 Response;
- UINT32 Request;
- UINT32 RequestParameter;
- UINT32 LastRequest;
- UINT32 ReturnCode;
-} PHYSICAL_PRESENCE_NVS;
-
-typedef struct {
- UINT8 SoftwareSmi;
- UINT32 Parameter;
- UINT32 Request;
- UINT32 ReturnCode;
-} MEMORY_CLEAR_NVS;
-
-typedef struct {
- PHYSICAL_PRESENCE_NVS PhysicalPresence;
- MEMORY_CLEAR_NVS MemoryClear;
- UINT32 PPRequestUserConfirm;
- UINT32 TpmIrqNum;
- BOOLEAN IsShortFormPkgLength;
-} TCG_NVS;
-
-typedef struct {
- UINT8 OpRegionOp;
- UINT32 NameString;
- UINT8 RegionSpace;
- UINT8 DWordPrefix;
- UINT32 RegionOffset;
- UINT8 BytePrefix;
- UINT8 RegionLen;
-} AML_OP_REGION_32_8;
-#pragma pack()
-
//
// The definition for TCG MOR
//
@@ -87,36 +46,42 @@ typedef struct {
#define MOR_REQUEST_SUCCESS 0
#define MOR_REQUEST_GENERAL_FAILURE 1
-//
-// Physical Presence Interface Version supported by Platform
-//
-#define PHYSICAL_PRESENCE_VERSION_TAG "$PV"
-#define PHYSICAL_PRESENCE_VERSION_SIZE 4
+/**
+ Notify the system that the SMM variable driver is ready.
+**/
+VOID
+Tcg2NotifyMmReady (
+ VOID
+ );
-//
-// PNP _HID for TPM2 device
-//
-#define TPM_HID_TAG "NNNN0000"
-#define TPM_HID_PNP_SIZE 8
-#define TPM_HID_ACPI_SIZE 9
+/**
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.
-#define TPM_PRS_RESL "RESL"
-#define TPM_PRS_RESS "RESS"
-#define TPM_PRS_RES_NAME_SIZE 4
-//
-// Minimum PRS resource template size
-// 1 byte for BufferOp
-// 1 byte for PkgLength
-// 2 bytes for BufferSize
-// 12 bytes for Memory32Fixed descriptor
-// 5 bytes for Interrupt descriptor
-// 2 bytes for END Tag
-//
-#define TPM_POS_RES_TEMPLATE_MIN_SIZE (1 + 1 + 2 + 12 + 5 + 2)
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+IsBufferOutsideMmValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ );
+
+/**
+ The driver's common initialization routine.
+
+ It install callbacks for TPM physical presence and MemoryClear, and locate
+ SMM variable to be used in the callback function.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Others Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+InitializeTcgCommon (
+ VOID
+ );
-//
-// Max Interrupt buffer size for PRS interrupt resource
-// Now support 15 interrupts in maxmum
-//
-#define MAX_PRS_INT_BUF_SIZE (15*4)
#endif // __TCG_SMM_H__
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
index d7a59fd9eed..e28701304f3 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2Smm.inf
@@ -39,7 +39,7 @@
[Sources]
Tcg2Smm.h
Tcg2Smm.c
- Tpm.asl
+ Tcg2TraditionalMm.c
[Packages]
MdePkg/MdePkg.dec
@@ -50,7 +50,7 @@
BaseLib
BaseMemoryLib
UefiDriverEntryPoint
- SmmServicesTableLib
+ MmServicesTableLib
UefiBootServicesTableLib
DebugLib
DxeServicesLib
@@ -58,6 +58,7 @@
Tpm2CommandLib
Tcg2PhysicalPresenceLib
PcdLib
+ SmmMemLib
[Guids]
## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
@@ -65,34 +66,18 @@
gEfiMemoryOverwriteControlDataGuid
gEfiTpmDeviceInstanceTpm20DtpmGuid ## PRODUCES ## GUID # TPM device identifier
+ gTcg2MmSwSmiRegisteredGuid ## PRODUCES
+ gTpmNvsMmGuid ## CONSUMES
[Protocols]
gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES
gEfiSmmVariableProtocolGuid ## CONSUMES
- gEfiAcpiTableProtocolGuid ## CONSUMES
-
-[FixedPcd]
- gEfiSecurityPkgTokenSpaceGuid.PcdSmiCommandIoPort ## CONSUMES
+ gEfiMmReadyToLockProtocolGuid ## CONSUMES
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemId ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemTableId ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultOemRevision ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorId ## SOMETIMES_CONSUMES
- gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiDefaultCreatorRevision ## SOMETIMES_CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTcgPhysicalPresenceInterfaceVer ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableRev ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpmPlatformClass ## SOMETIMES_CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2CurrentIrqNum ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2PossibleIrqNumBuf ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdActiveTpmInterfaceType ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLaml ## CONSUMES
- gEfiSecurityPkgTokenSpaceGuid.PcdTpm2AcpiTableLasa ## CONSUMES
[Depex]
- gEfiAcpiTableProtocolGuid AND
gEfiSmmSwDispatch2ProtocolGuid AND
gEfiSmmVariableProtocolGuid AND
gEfiTcg2ProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.c
new file mode 100644
index 00000000000..c194a13205e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.c
@@ -0,0 +1,71 @@
+/** @file
+ TCG2 Standalone MM driver that updates TPM2 items in ACPI table and registers
+ SMI2 callback functions for Tcg2 physical presence, ClearMemory, and
+ sample for dTPM StartMethod.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable and ACPINvs data in SMM mode.
+ This external input must be validated carefully to avoid security issue.
+
+ PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Tcg2Smm.h"
+#include <Library/StandaloneMmMemLib.h>
+
+/**
+ Notify the system that the SMM variable driver is ready.
+**/
+VOID
+Tcg2NotifyMmReady (
+ VOID
+ )
+{
+ // Do nothing
+}
+
+/**
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+IsBufferOutsideMmValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return MmIsBufferOutsideMmValid (Buffer, Length);
+}
+
+/**
+ The driver's entry point.
+
+ It install callbacks for TPM physical presence and MemoryClear, and locate
+ SMM variable to be used in the callback function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Others Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeTcgStandaloneMm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return InitializeTcgCommon ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.inf
new file mode 100644
index 00000000000..7dcfa88cab0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2StandaloneMm.inf
@@ -0,0 +1,77 @@
+## @file
+# Provides ACPI methods for TPM 2.0 support
+#
+# Spec Compliance Info:
+# "TCG ACPI Specification Version 1.2 Revision 8"
+# "Physical Presence Interface Specification Version 1.30 Revision 00.52"
+# along with
+# "Errata Version 0.4 for TCG PC Client Platform Physical Presence Interface Specification"
+# "Platform Reset Attack Mitigation Specification Version 1.00"
+# TPM2.0 ACPI device object
+# "TCG PC Client Platform Firmware Profile Specification for TPM Family 2.0 Level 00 Revision 1.03 v51"
+# along with
+# "Errata for PC Client Specific Platform Firmware Profile Specification Version 1.0 Revision 1.03"
+#
+# This driver implements TPM 2.0 definition block in ACPI table and
+# registers SMI callback functions for Tcg2 physical presence and
+# MemoryClear to handle the requests from ACPI method.
+#
+# Caution: This module requires additional review when modified.
+# This driver will have external input - variable and ACPINvs data in SMM mode.
+# This external input must be validated carefully to avoid security issue.
+#
+# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = Tcg2StandaloneMm
+ FILE_GUID = D40F321F-5349-4724-B667-131670587861
+ MODULE_TYPE = MM_STANDALONE
+ PI_SPECIFICATION_VERSION = 0x00010032
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializeTcgStandaloneMm
+
+[Sources]
+ Tcg2Smm.h
+ Tcg2Smm.c
+ Tcg2StandaloneMm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ SecurityPkg/SecurityPkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ StandaloneMmDriverEntryPoint
+ MmServicesTableLib
+ DebugLib
+ Tcg2PhysicalPresenceLib
+ PcdLib
+ MemLib
+
+[Guids]
+ ## SOMETIMES_PRODUCES ## Variable:L"MemoryOverwriteRequestControl"
+ ## SOMETIMES_CONSUMES ## Variable:L"MemoryOverwriteRequestControl"
+ gEfiMemoryOverwriteControlDataGuid
+
+ gEfiTpmDeviceInstanceTpm20DtpmGuid ## PRODUCES ## GUID # TPM device identifier
+ gTpmNvsMmGuid ## CONSUMES
+
+[Protocols]
+ gEfiSmmSwDispatch2ProtocolGuid ## CONSUMES
+ gEfiSmmVariableProtocolGuid ## CONSUMES
+ gEfiMmReadyToLockProtocolGuid ## CONSUMES
+
+[Pcd]
+ gEfiSecurityPkgTokenSpaceGuid.PcdTpmInstanceGuid ## CONSUMES
+
+[Depex]
+ gEfiSmmSwDispatch2ProtocolGuid AND
+ gEfiSmmVariableProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c
new file mode 100644
index 00000000000..f72f9c71268
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/Tcg2Smm/Tcg2TraditionalMm.c
@@ -0,0 +1,82 @@
+/** @file
+ TCG2 SMM driver that updates TPM2 items in ACPI table and registers
+ SMI2 callback functions for Tcg2 physical presence, ClearMemory, and
+ sample for dTPM StartMethod.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable and ACPINvs data in SMM mode.
+ This external input must be validated carefully to avoid security issue.
+
+ PhysicalPresenceCallback() and MemoryClearCallback() will receive untrusted input and do some check.
+
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "Tcg2Smm.h"
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/SmmMemLib.h>
+
+/**
+ Notify the system that the SMM variable driver is ready.
+**/
+VOID
+Tcg2NotifyMmReady (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+ Status = gBS->InstallProtocolInterface (
+ &Handle,
+ &gTcg2MmSwSmiRegisteredGuid,
+ EFI_NATIVE_INTERFACE,
+ NULL
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ This function is an abstraction layer for implementation specific Mm buffer validation routine.
+
+ @param Buffer The buffer start address to be checked.
+ @param Length The buffer length to be checked.
+
+ @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.
+ @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.
+**/
+BOOLEAN
+IsBufferOutsideMmValid (
+ IN EFI_PHYSICAL_ADDRESS Buffer,
+ IN UINT64 Length
+ )
+{
+ return SmmIsBufferOutsideSmmValid (Buffer, Length);
+}
+
+/**
+ The driver's entry point.
+
+ It install callbacks for TPM physical presence and MemoryClear, and locate
+ SMM variable to be used in the callback function.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Others Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+InitializeTcgSmm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return InitializeTcgCommon ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.c
index 9a47e5988a7..ad29affa9cc 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.c
@@ -1,7 +1,7 @@
/** @file
Initialize TPM device and measure FVs before handing off control to DXE.
-Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -17,10 +17,12 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Ppi/FirmwareVolume.h>
#include <Ppi/EndOfPeiPhase.h>
#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
+#include <Ppi/Tcg.h>
#include <Guid/TcgEventHob.h>
#include <Guid/MeasuredFvHob.h>
#include <Guid/TpmInstance.h>
+#include <Guid/MigratedFvInfo.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
@@ -51,6 +53,45 @@ EFI_PEI_PPI_DESCRIPTOR mTpmInitializationDonePpiList = {
NULL
};
+/**
+ Do a hash operation on a data buffer, extend a specific TPM PCR with the hash result,
+ and build a GUIDed HOB recording the event which will be passed to the DXE phase and
+ added into the Event Log.
+
+ @param[in] This Indicates the calling context
+ @param[in] Flags Bitmap providing additional information.
+ @param[in] HashData Physical address of the start of the data buffer
+ to be hashed, extended, and logged.
+ @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
+ @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
+ @param[in] NewEventData Pointer to the new event data.
+
+ @retval EFI_SUCCESS Operation completed successfully.
+ @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
+ @retval EFI_DEVICE_ERROR The command was unsuccessful.
+
+**/
+EFI_STATUS
+EFIAPI
+HashLogExtendEvent (
+ IN EDKII_TCG_PPI *This,
+ IN UINT64 Flags,
+ IN UINT8 *HashData,
+ IN UINTN HashDataLen,
+ IN TCG_PCR_EVENT_HDR *NewEventHdr,
+ IN UINT8 *NewEventData
+ );
+
+EDKII_TCG_PPI mEdkiiTcgPpi = {
+ HashLogExtendEvent
+};
+
+EFI_PEI_PPI_DESCRIPTOR mTcgPpiList = {
+ EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEdkiiTcgPpiGuid,
+ &mEdkiiTcgPpi
+};
+
//
// Number of firmware blobs to grow by each time we run out of room
//
@@ -243,7 +284,8 @@ TpmCommHashAll (
and build a GUIDed HOB recording the event which will be passed to the DXE phase and
added into the Event Log.
- @param[in] PeiServices Describes the list of possible PEI Services.
+ @param[in] This Indicates the calling context.
+ @param[in] Flags Bitmap providing additional information.
@param[in] HashData Physical address of the start of the data buffer
to be hashed, extended, and logged.
@param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData.
@@ -256,8 +298,10 @@ TpmCommHashAll (
**/
EFI_STATUS
+EFIAPI
HashLogExtendEvent (
- IN EFI_PEI_SERVICES **PeiServices,
+ IN EDKII_TCG_PPI *This,
+ IN UINT64 Flags,
IN UINT8 *HashData,
IN UINTN HashDataLen,
IN TCG_PCR_EVENT_HDR *NewEventHdr,
@@ -346,7 +390,8 @@ MeasureCRTMVersion (
TcgEventHdr.EventSize = (UINT32) StrSize((CHAR16*)PcdGetPtr (PcdFirmwareVersionString));
return HashLogExtendEvent (
- PeiServices,
+ &mEdkiiTcgPpi,
+ 0,
(UINT8*)PcdGetPtr (PcdFirmwareVersionString),
TcgEventHdr.EventSize,
&TcgEventHdr,
@@ -378,6 +423,10 @@ MeasureFvImage (
EFI_STATUS Status;
EFI_PLATFORM_FIRMWARE_BLOB FvBlob;
TCG_PCR_EVENT_HDR TcgEventHdr;
+ EFI_PHYSICAL_ADDRESS FvOrgBase;
+ EFI_PHYSICAL_ADDRESS FvDataBase;
+ EFI_PEI_HOB_POINTERS Hob;
+ EDKII_MIGRATED_FV_INFO *MigratedFvInfo;
//
// Check if it is in Excluded FV list
@@ -402,9 +451,29 @@ MeasureFvImage (
}
//
+ // Search the matched migration FV info
+ //
+ FvOrgBase = FvBase;
+ FvDataBase = FvBase;
+ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
+ while (Hob.Raw != NULL) {
+ MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
+ if ((MigratedFvInfo->FvNewBase == (UINT32) FvBase) && (MigratedFvInfo->FvLength == (UINT32) FvLength)) {
+ //
+ // Found the migrated FV info
+ //
+ FvOrgBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvOrgBase;
+ FvDataBase = (EFI_PHYSICAL_ADDRESS) (UINTN) MigratedFvInfo->FvDataBase;
+ break;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
+ }
+
+ //
// Measure and record the FV to the TPM
//
- FvBlob.BlobBase = FvBase;
+ FvBlob.BlobBase = FvOrgBase;
FvBlob.BlobLength = FvLength;
DEBUG ((DEBUG_INFO, "The FV which is measured by TcgPei starts at: 0x%x\n", FvBlob.BlobBase));
@@ -415,8 +484,9 @@ MeasureFvImage (
TcgEventHdr.EventSize = sizeof (FvBlob);
Status = HashLogExtendEvent (
- (EFI_PEI_SERVICES **) GetPeiServicesTablePointer(),
- (UINT8*) (UINTN) FvBlob.BlobBase,
+ &mEdkiiTcgPpi,
+ 0,
+ (UINT8*) (UINTN) FvDataBase,
(UINTN) FvBlob.BlobLength,
&TcgEventHdr,
(UINT8*) &FvBlob
@@ -744,6 +814,12 @@ PeimEntryMP (
Status = PeiServicesNotifyPpi (&mNotifyList[0]);
ASSERT_EFI_ERROR (Status);
+ //
+ // install Tcg Services
+ //
+ Status = PeiServicesInstallPpi (&mTcgPpiList);
+ ASSERT_EFI_ERROR (Status);
+
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.inf b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.inf
index 8e996d6d818..32c2c08c224 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Tcg/TcgPei/TcgPei.inf
@@ -4,7 +4,7 @@
# This module will initialize TPM device, measure reported FVs and BIOS version.
# This module may also lock TPM physical presence and physicalPresenceLifetimeLock.
#
-# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -58,6 +58,7 @@
gTpmErrorHobGuid ## SOMETIMES_PRODUCES ## HOB
gMeasuredFvHobGuid ## PRODUCES ## HOB
gEfiTpmDeviceInstanceTpm12Guid ## PRODUCES ## GUID # TPM device identifier
+ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB
[Ppis]
gPeiLockPhysicalPresencePpiGuid ## SOMETIMES_CONSUMES ## NOTIFY
@@ -67,6 +68,7 @@
gPeiTpmInitializedPpiGuid ## SOMETIMES_PRODUCES
gPeiTpmInitializationDonePpiGuid ## PRODUCES
gEfiEndOfPeiSignalPpiGuid ## SOMETIMES_CONSUMES ## NOTIFY
+ gEdkiiTcgPpiGuid ## PRODUCES
[Pcd]
gEfiSecurityPkgTokenSpaceGuid.PcdPhysicalPresenceLifetimeLock ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
index d17a6092e6a..ded5f3e9c21 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c
@@ -90,6 +90,22 @@ CHAR16* mDerEncodedSuffix[] = {
};
CHAR16* mSupportX509Suffix = L"*.cer/der/crt";
+//
+// Prompt strings during certificate enrollment.
+//
+CHAR16* mX509EnrollPromptTitle[] = {
+ L"",
+ L"ERROR: Unsupported file type!",
+ L"ERROR: Unsupported certificate!",
+ NULL
+};
+CHAR16* mX509EnrollPromptString[] = {
+ L"",
+ L"Only DER encoded certificate file (*.cer/der/crt) is supported.",
+ L"Public key length should be equal to or greater than 2048 bits.",
+ NULL
+};
+
SECUREBOOT_CONFIG_PRIVATE_DATA *gSecureBootPrivateData = NULL;
/**
@@ -384,6 +400,102 @@ SetSecureBootMode (
}
/**
+ This code checks if the encode type and key strength of X.509
+ certificate is qualified.
+
+ @param[in] X509FileContext FileContext of X.509 certificate storing
+ file.
+ @param[out] Error Error type checked in the certificate.
+
+ @return EFI_SUCCESS The certificate checked successfully.
+ @return EFI_INVALID_PARAMETER The parameter is invalid.
+ @return EFI_OUT_OF_RESOURCES Memory allocation failed.
+
+**/
+EFI_STATUS
+CheckX509Certificate (
+ IN SECUREBOOT_FILE_CONTEXT* X509FileContext,
+ OUT ENROLL_KEY_ERROR* Error
+)
+{
+ EFI_STATUS Status;
+ UINT16* FilePostFix;
+ UINTN NameLength;
+ UINT8* X509Data;
+ UINTN X509DataSize;
+ void* X509PubKey;
+ UINTN PubKeyModSize;
+
+ if (X509FileContext->FileName == NULL) {
+ *Error = Unsupported_Type;
+ return EFI_INVALID_PARAMETER;
+ }
+
+ X509Data = NULL;
+ X509DataSize = 0;
+ X509PubKey = NULL;
+ PubKeyModSize = 0;
+
+ //
+ // Parse the file's postfix. Only support DER encoded X.509 certificate files.
+ //
+ NameLength = StrLen (X509FileContext->FileName);
+ if (NameLength <= 4) {
+ DEBUG ((DEBUG_ERROR, "Wrong X509 NameLength\n"));
+ *Error = Unsupported_Type;
+ return EFI_INVALID_PARAMETER;
+ }
+ FilePostFix = X509FileContext->FileName + NameLength - 4;
+ if (!IsDerEncodeCertificate (FilePostFix)) {
+ DEBUG ((DEBUG_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix));
+ *Error = Unsupported_Type;
+ return EFI_INVALID_PARAMETER;
+ }
+ DEBUG ((DEBUG_INFO, "FileName= %s\n", X509FileContext->FileName));
+ DEBUG ((DEBUG_INFO, "FilePostFix = %s\n", FilePostFix));
+
+ //
+ // Read the certificate file content
+ //
+ Status = ReadFileContent (X509FileContext->FHandle, (VOID**) &X509Data, &X509DataSize, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Error occured while reading the file.\n"));
+ goto ON_EXIT;
+ }
+
+ //
+ // Parse the public key context.
+ //
+ if (RsaGetPublicKeyFromX509 (X509Data, X509DataSize, &X509PubKey) == FALSE) {
+ DEBUG ((DEBUG_ERROR, "Error occured while parsing the pubkey from certificate.\n"));
+ Status = EFI_INVALID_PARAMETER;
+ *Error = Unsupported_Type;
+ goto ON_EXIT;
+ }
+
+ //
+ // Parse Module size of public key using interface provided by CryptoPkg, which is
+ // actually the size of public key.
+ //
+ if (X509PubKey != NULL) {
+ RsaGetKey (X509PubKey, RsaKeyN, NULL, &PubKeyModSize);
+ if (PubKeyModSize < CER_PUBKEY_MIN_SIZE) {
+ DEBUG ((DEBUG_ERROR, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n"));
+ Status = EFI_INVALID_PARAMETER;
+ *Error = Unqualified_Key;
+ }
+ RsaFree (X509PubKey);
+ }
+
+ ON_EXIT:
+ if (X509Data != NULL) {
+ FreePool (X509Data);
+ }
+
+ return Status;
+}
+
+/**
Generate the PK signature list from the X509 Certificate storing file (.cer)
@param[in] X509File FileHandle of X509 Certificate storing file.
@@ -477,12 +589,6 @@ EnrollPlatformKey (
UINT32 Attr;
UINTN DataSize;
EFI_SIGNATURE_LIST *PkCert;
- UINT16* FilePostFix;
- UINTN NameLength;
-
- if (Private->FileContext->FileName == NULL) {
- return EFI_INVALID_PARAMETER;
- }
PkCert = NULL;
@@ -492,21 +598,6 @@ EnrollPlatformKey (
}
//
- // Parse the file's postfix. Only support DER encoded X.509 certificate files.
- //
- NameLength = StrLen (Private->FileContext->FileName);
- if (NameLength <= 4) {
- return EFI_INVALID_PARAMETER;
- }
- FilePostFix = Private->FileContext->FileName + NameLength - 4;
- if (!IsDerEncodeCertificate(FilePostFix)) {
- DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix));
- return EFI_INVALID_PARAMETER;
- }
- DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName));
- DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix));
-
- //
// Prase the selected PK file and generate PK certificate list.
//
Status = CreatePkX509SignatureList (
@@ -4300,12 +4391,14 @@ SecureBootCallback (
UINT16 *FilePostFix;
SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData;
BOOLEAN GetBrowserDataResult;
+ ENROLL_KEY_ERROR EnrollKeyErrorCode;
- Status = EFI_SUCCESS;
- SecureBootEnable = NULL;
- SecureBootMode = NULL;
- SetupMode = NULL;
- File = NULL;
+ Status = EFI_SUCCESS;
+ SecureBootEnable = NULL;
+ SecureBootMode = NULL;
+ SetupMode = NULL;
+ File = NULL;
+ EnrollKeyErrorCode = None_Error;
if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
return EFI_INVALID_PARAMETER;
@@ -4718,18 +4811,35 @@ SecureBootCallback (
}
break;
case KEY_VALUE_SAVE_AND_EXIT_PK:
- Status = EnrollPlatformKey (Private);
+ //
+ // Check the suffix, encode type and the key strength of PK certificate.
+ //
+ Status = CheckX509Certificate (Private->FileContext, &EnrollKeyErrorCode);
+ if (EFI_ERROR (Status)) {
+ if (EnrollKeyErrorCode != None_Error && EnrollKeyErrorCode < Enroll_Error_Max) {
+ CreatePopUp (
+ EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+ &Key,
+ mX509EnrollPromptTitle[EnrollKeyErrorCode],
+ mX509EnrollPromptString[EnrollKeyErrorCode],
+ NULL
+ );
+ break;
+ }
+ } else {
+ Status = EnrollPlatformKey (Private);
+ }
if (EFI_ERROR (Status)) {
UnicodeSPrint (
PromptString,
sizeof (PromptString),
- L"Only DER encoded certificate file (%s) is supported.",
- mSupportX509Suffix
+ L"Error status: %x.",
+ Status
);
CreatePopUp (
EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
&Key,
- L"ERROR: Unsupported file type!",
+ L"ERROR: Enrollment failed!",
PromptString,
NULL
);
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h b/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
index fe212ff4c8b..d021ec8f9a8 100644
--- a/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.h
@@ -93,6 +93,27 @@ extern EFI_IFR_GUID_LABEL *mEndLabel;
#define HASHALG_RAW 0x00000004
#define HASHALG_MAX 0x00000004
+//
+// Certificate public key minimum size (bytes)
+//
+#define CER_PUBKEY_MIN_SIZE 256
+
+//
+// Types of errors may occur during certificate enrollment.
+//
+typedef enum {
+ None_Error = 0,
+ //
+ // Unsupported_type indicates the certificate type is not supported.
+ //
+ Unsupported_Type,
+ //
+ // Unqualified_key indicates the key strength of certificate is not
+ // strong enough.
+ //
+ Unqualified_Key,
+ Enroll_Error_Max
+}ENROLL_KEY_ERROR;
typedef struct {
UINTN Signature;
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.c
new file mode 100644
index 00000000000..e4ade540ddc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.c
@@ -0,0 +1,40 @@
+/** @file
+ Main file for AcpiViewApp application
+
+ Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/ShellLib.h>
+#include <Library/AcpiViewCommandLib.h>
+
+#include <Protocol/ShellParameters.h>
+
+//
+// String token ID of help message text.
+// Shell supports to find help message in the resource section of an application image if
+// .MAN file is not found. This global variable is added to make build tool recognizes
+// that the help string is consumed by user and then build tool will add the string into
+// the resource section. Thus the application can use '-?' option to show help message in
+// Shell.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_GET_HELP_ACPIVIEW);
+
+/**
+ Application Entry Point wrapper around the shell command
+
+ @param[in] ImageHandle Handle to the Image (NULL if internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if internal).
+**/
+EFI_STATUS
+EFIAPI
+AcpiViewAppMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return ShellCommandRunAcpiView (gImageHandle, SystemTable);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.inf
new file mode 100644
index 00000000000..ab5f752da5d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.inf
@@ -0,0 +1,34 @@
+## @file
+# EFI application that displays and verifies ACPI tables
+#
+# Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = AcpiViewApp
+ FILE_GUID = 46361B5B-AF17-41FF-95F9-E1BCE08435B9
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = AcpiViewAppMain
+ UEFI_HII_RESOURCE_SECTION = TRUE
+
+[Sources.common]
+ AcpiViewApp.c
+ AcpiViewApp.uni
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ UefiLib
+ BaseLib
+ UefiApplicationEntryPoint
+ AcpiViewCommandLib
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.uni
new file mode 100644
index 00000000000..c56f2108435
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/AcpiViewApp/AcpiViewApp.uni
@@ -0,0 +1,122 @@
+// @file
+//
+// Standalone EFI application that displays and verifies ACPI tables
+//
+// Copyright (c) 2020, ARM Limited. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GET_HELP_ACPIVIEW #language en-US ""
+".TH acpiview 0 "Display ACPI information."\r\n"
+".SH NAME\r\n"
+"Display ACPI Table information.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"ACPIVIEWAPP.EFI [[-?] | [[[[-l] | [-s AcpiTable [-d]]] [-q] [-h]] [-r Spec]]]\r\n"
+" \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -l - Display list of installed ACPI Tables.\r\n"
+" -s - Display only the specified AcpiTable type and only support single\r\n"
+" invocation option.\r\n"
+" AcpiTable : The required ACPI Table type.\r\n"
+" -d - Generate a binary file dump of the specified AcpiTable.\r\n"
+" -q - Quiet. Suppress errors and warnings. Disables consistency checks.\r\n"
+" -h - Enable colour highlighting.\r\n"
+" -r - Validate that all required ACPI tables are installed\r\n"
+" Spec : Specification to validate against.\r\n"
+" For Arm, the possible values are:\r\n"
+" 0 - Server Base Boot Requirements v1.0\r\n"
+" 1 - Server Base Boot Requirements v1.1\r\n"
+" 2 - Server Base Boot Requirements v1.2\r\n"
+" -? - Show help.\r\n"
+" \r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+" This program is provided to allow examination of ACPI table values from the\r\n"
+" UEFI Shell. This can help with investigations, especially at that stage\r\n"
+" where the tables are not enabling an OS to boot.\r\n"
+" The program is not exhaustive, and only encapsulates detailed knowledge of a\r\n"
+" limited number of table types.\r\n"
+" \r\n"
+" Default behaviour is to display the content of all tables installed.\r\n"
+" 'Known' table types (listed in NOTES below) will be parsed and displayed\r\n"
+" with descriptions and field values. Where appropriate a degree of\r\n"
+" consistency checking is done and errors may be reported in the output.\r\n"
+" Other table types will be displayed as an array of Hexadecimal bytes.\r\n"
+" \r\n"
+" To facilitate debugging, the -s and -d options can be used to generate a\r\n"
+" binary file image of a table that can be copied elsewhere for investigation\r\n"
+" using tools such as those provided by acpica.org. This is especially\r\n"
+" relevant for AML type tables like DSDT and SSDT.\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The AcpiTable parameter can match any installed table type.\r\n"
+" Tables without specific handling will be displayed as a raw hex dump (or\r\n"
+" dumped to a file if -d is used).\r\n"
+" 2. -s option supports to display the specified AcpiTable type that is present\r\n"
+" in the system. For normal type AcpiTable, it would display the data of the\r\n"
+" AcpiTable and AcpiTable header. The following type may contain header type\r\n"
+" other than AcpiTable header. The actual header can refer to the ACPI spec\r\n"
+" 6.3\r\n"
+" Extra A. Particular types:\r\n"
+" APIC - Multiple APIC Description Table (MADT)\r\n"
+" BGRT - Boot Graphics Resource Table\r\n"
+" DBG2 - Debug Port Table 2\r\n"
+" DSDT - Differentiated System Description Table\r\n"
+" FACP - Fixed ACPI Description Table (FADT)\r\n"
+" GTDT - Generic Timer Description Table\r\n"
+" IORT - IO Remapping Table\r\n"
+" MCFG - Memory Mapped Config Space Base Address Description Table\r\n"
+" PPTT - Processor Properties Topology Table\r\n"
+" RSDP - Root System Description Pointer\r\n"
+" SLIT - System Locality Information Table\r\n"
+" SPCR - Serial Port Console Redirection Table\r\n"
+" SRAT - System Resource Affinity Table\r\n"
+" SSDT - Secondary SystemDescription Table\r\n"
+" XSDT - Extended System Description Table\r\n"
+" \r\n"
+".SH STANDARDS\r\n"
+" \r\n"
+" Table details correspond to those in 'Advanced Configuration and Power\r\n"
+" Interface Specification' Version 6.3 [January 2019]\r\n"
+" (https://uefi.org/specifications)\r\n"
+" \r\n"
+" NOTE: The nature of the ACPI standard means that almost all tables in 6.3\r\n"
+" will be 'backwards compatible' with prior version of the specification\r\n"
+" in terms of structure, so formatted output should be correct. The main\r\n"
+" exception will be that previously 'reserved' fields will be reported\r\n"
+" with new names, where they have been added in later versions of the\r\n"
+" specification.\r\n"
+" \r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display a list of the installed table types:\r\n"
+" fs0:\> acpiviewapp.efi -l\r\n"
+" \r\n"
+" * To parse and display a specific table type:\r\n"
+" fs0:\> acpiviewapp.efi -s GTDT\r\n"
+" \r\n"
+" * To save a binary dump of the contents of a table to a file\r\n"
+" in the current working directory:\r\n"
+" fs0:\> acpiviewapp.efi -s DSDT -d\r\n"
+" \r\n"
+" * To display contents of all ACPI tables:\r\n"
+" fs0:\> acpiviewapp.efi\r\n"
+" \r\n"
+" * To check if all Server Base Boot Requirements (SBBR) v1.2 mandatory\r\n"
+" ACPI tables are installed (Arm only):\r\n"
+" fs0:\> acpiviewapp.efi -r 2\r\n"
+" \r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS Data was displayed as requested.\r\n"
+" SHELL_INVALID_PARAMETER ACPI Table parsing failed.\r\n"
+" \r\n"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.c
index 58640ca15f6..ec6712c3474 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Application/Shell/ShellProtocol.c
@@ -1855,6 +1855,8 @@ EfiShellRemoveDupInFileList(
IN EFI_SHELL_FILE_INFO **FileList
)
{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *Duplicates;
EFI_SHELL_FILE_INFO *ShellFileListItem;
EFI_SHELL_FILE_INFO *ShellFileListItem2;
EFI_SHELL_FILE_INFO *TempNode;
@@ -1862,6 +1864,20 @@ EfiShellRemoveDupInFileList(
if (FileList == NULL || *FileList == NULL) {
return (EFI_INVALID_PARAMETER);
}
+
+ Status = ShellSortFileList (
+ FileList,
+ &Duplicates,
+ ShellSortFileListByFullName
+ );
+ if (!EFI_ERROR (Status)) {
+ EfiShellFreeFileList (&Duplicates);
+ return EFI_SUCCESS;
+ }
+ //
+ // Fall back to the slow method that needs no extra memory, and so cannot
+ // fail.
+ //
for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link)
; !IsNull(&(*FileList)->Link, &ShellFileListItem->Link)
; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link)
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
new file mode 100644
index 00000000000..5173ac1ea5a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.c
@@ -0,0 +1,1905 @@
+/** @file
+ The implementation for the 'http' Shell command.
+
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved. <BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ Copyright (c) 2020, Broadcom. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "Http.h"
+
+#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
+
+//
+// Constant strings and definitions related to the message
+// indicating the amount of progress in the dowloading of a HTTP file.
+//
+
+//
+// Number of steps in the progression slider.
+//
+#define HTTP_PROGRESS_SLIDER_STEPS \
+ ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 3)
+
+//
+// Size in number of characters plus one (final zero) of the message to
+// indicate the progress of an HTTP download. The format is "[(progress slider:
+// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
+// are thus the number of characters in HTTP_PROGR_FRAME[] plus 11 characters
+// (2 // spaces, "Kb" and seven characters for the number of KBytes).
+//
+#define HTTP_PROGRESS_MESSAGE_SIZE \
+ ((sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) + 12)
+
+//
+// Buffer size. Note that larger buffer does not mean better speed.
+//
+#define DEFAULT_BUF_SIZE SIZE_32KB
+#define MAX_BUF_SIZE SIZE_4MB
+
+#define MIN_PARAM_COUNT 2
+#define MAX_PARAM_COUNT 4
+#define NEED_REDIRECTION(Code) \
+ (((Code >= HTTP_STATUS_300_MULTIPLE_CHOICES) \
+ && (Code <= HTTP_STATUS_307_TEMPORARY_REDIRECT)) \
+ || (Code == HTTP_STATUS_308_PERMANENT_REDIRECT))
+
+#define CLOSE_HTTP_HANDLE(ControllerHandle,HttpChildHandle) \
+ do { \
+ if (HttpChildHandle) { \
+ CloseProtocolAndDestroyServiceChild ( \
+ ControllerHandle, \
+ &gEfiHttpServiceBindingProtocolGuid, \
+ &gEfiHttpProtocolGuid, \
+ HttpChildHandle \
+ ); \
+ HttpChildHandle = NULL; \
+ } \
+ } while (0)
+
+typedef enum {
+ HdrHost,
+ HdrConn,
+ HdrAgent,
+ HdrMax
+} HDR_TYPE;
+
+#define USER_AGENT_HDR "Mozilla/5.0 (EDK2; Linux) Gecko/20100101 Firefox/79.0"
+
+#define TIMER_MAX_TIMEOUT_S 10
+
+//
+// File name to use when Uri ends with "/".
+//
+#define DEFAULT_HTML_FILE L"index.html"
+#define DEFAULT_HTTP_PROTO L"http"
+
+//
+// String to delete the HTTP progress message to be able to update it :
+// (HTTP_PROGRESS_MESSAGE_SIZE-1) '\b'.
+//
+#define HTTP_PROGRESS_DEL \
+ L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\
+\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"
+
+#define HTTP_KB L"\b\b\b\b\b\b\b\b\b\b"
+//
+// Frame for the progression slider.
+//
+#define HTTP_PROGR_FRAME L"[ ]"
+
+//
+// Improve readability by using these macros.
+//
+#define PRINT_HII(token,...) \
+ ShellPrintHiiEx (\
+ -1, -1, NULL, token, mHttpHiiHandle, __VA_ARGS__)
+
+#define PRINT_HII_APP(token,value) \
+ PRINT_HII (token, HTTP_APP_NAME, value)
+
+//
+// TimeBaseLib.h constants.
+// These will be removed once the library gets fixed.
+//
+
+//
+// Define EPOCH (1970-JANUARY-01) in the Julian Date representation.
+//
+#define EPOCH_JULIAN_DATE 2440588
+
+//
+// Seconds per unit.
+//
+#define SEC_PER_MIN ((UINTN) 60)
+#define SEC_PER_HOUR ((UINTN) 3600)
+#define SEC_PER_DAY ((UINTN) 86400)
+
+//
+// String descriptions for server errors.
+//
+STATIC CONST CHAR16 *ErrStatusDesc[] =
+{
+ L"400 Bad Request",
+ L"401 Unauthorized",
+ L"402 Payment required",
+ L"403 Forbidden",
+ L"404 Not Found",
+ L"405 Method not allowed",
+ L"406 Not acceptable",
+ L"407 Proxy authentication required",
+ L"408 Request time out",
+ L"409 Conflict",
+ L"410 Gone",
+ L"411 Length required",
+ L"412 Precondition failed",
+ L"413 Request entity too large",
+ L"414 Request URI to large",
+ L"415 Unsupported media type",
+ L"416 Requested range not satisfied",
+ L"417 Expectation failed",
+ L"500 Internal server error",
+ L"501 Not implemented",
+ L"502 Bad gateway",
+ L"503 Service unavailable",
+ L"504 Gateway timeout",
+ L"505 HTTP version not supported"
+};
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-i", TypeValue},
+ {L"-k", TypeFlag},
+ {L"-l", TypeValue},
+ {L"-m", TypeFlag},
+ {L"-s", TypeValue},
+ {L"-t", TypeValue},
+ {NULL , TypeMax}
+};
+
+//
+// Local File Handle.
+//
+STATIC SHELL_FILE_HANDLE mFileHandle = NULL;
+
+//
+// Path of the local file, Unicode encoded.
+//
+STATIC CONST CHAR16 *mLocalFilePath;
+
+STATIC BOOLEAN gRequestCallbackComplete = FALSE;
+STATIC BOOLEAN gResponseCallbackComplete = FALSE;
+
+STATIC BOOLEAN gHttpError;
+
+EFI_HII_HANDLE mHttpHiiHandle;
+
+//
+// Functions declarations.
+//
+
+/**
+ Check and convert the UINT16 option values of the 'http' command.
+
+ @param[in] ValueStr Value as an Unicode encoded string.
+ @param[out] Value UINT16 value.
+
+ @retval TRUE The value was returned.
+ @retval FALSE A parsing error occured.
+**/
+STATIC
+BOOLEAN
+StringToUint16 (
+ IN CONST CHAR16 *ValueStr,
+ OUT UINT16 *Value
+ );
+
+/**
+ Get the name of the NIC.
+
+ @param[in] ControllerHandle The network physical device handle.
+ @param[in] NicNumber The network physical device number.
+ @param[out] NicName Address where to store the NIC name.
+ The memory area has to be at least
+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
+ double byte wide.
+
+ @retval EFI_SUCCESS The name of the NIC was returned.
+ @retval Others The creation of the child for the Managed
+ Network Service failed or the opening of
+ the Managed Network Protocol failed or
+ the operational parameters for the
+ Managed Network Protocol could not be
+ read.
+**/
+STATIC
+EFI_STATUS
+GetNicName (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NicNumber,
+ OUT CHAR16 *NicName
+ );
+
+/**
+ Create a child for the service identified by its service binding protocol GUID
+ and get from the child the interface of the protocol identified by its GUID.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be created.
+ @param[in] ProtocolGuid GUID of the protocol to be open.
+ @param[out] ChildHandle Address where the handler of the
+ created child is returned. NULL is
+ returned in case of error.
+ @param[out] Interface Address where a pointer to the
+ protocol interface is returned in
+ case of success.
+
+ @retval EFI_SUCCESS The child was created and the protocol opened.
+ @retval Others Either the creation of the child or the opening
+ of the protocol failed.
+**/
+STATIC
+EFI_STATUS
+CreateServiceChildAndOpenProtocol (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ OUT EFI_HANDLE *ChildHandle,
+ OUT VOID **Interface
+ );
+
+/**
+ Close the protocol identified by its GUID on the child handle of the service
+ identified by its service binding protocol GUID, then destroy the child
+ handle.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be destroyed.
+ @param[in] ProtocolGuid GUID of the protocol to be closed.
+ @param[in] ChildHandle Handle of the child to be destroyed.
+
+**/
+STATIC
+VOID
+CloseProtocolAndDestroyServiceChild (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_HANDLE ChildHandle
+ );
+
+/**
+ Worker function that download the data of a file from an HTTP server given
+ the path of the file and its size.
+
+ @param[in] Context A pointer to the download context.
+
+ @retval EFI_SUCCESS The file was downloaded.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval Others The downloading of the file
+ from the server failed.
+**/
+STATIC
+EFI_STATUS
+DownloadFile (
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN EFI_HANDLE ControllerHandle,
+ IN CHAR16 *NicName
+ );
+
+/**
+ Cleans off leading and trailing spaces and tabs.
+
+ @param[in] String pointer to the string to trim them off.
+
+ @retval EFI_SUCCESS No errors.
+ @retval EFI_INVALID_PARAMETER String pointer is NULL.
+**/
+STATIC
+EFI_STATUS
+TrimSpaces (
+ IN CHAR16 *String
+ )
+{
+ CHAR16 *Str;
+ UINTN Len;
+
+ ASSERT (String != NULL);
+
+ if (String == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Str = String;
+
+ //
+ // Remove any whitespace at the beginning of the Str.
+ //
+ while (*Str == L' ' || *Str == L'\t') {
+ Str++;
+ }
+
+ //
+ // Remove any whitespace at the end of the Str.
+ //
+ do {
+ Len = StrLen (Str);
+ if (!Len || (Str[Len - 1] != L' ' && Str[Len - 1] != '\t')) {
+ break;
+ }
+
+ Str[Len - 1] = CHAR_NULL;
+ } while (Len);
+
+ CopyMem (String, Str, StrSize (Str));
+
+ return EFI_SUCCESS;
+}
+
+//
+// Callbacks for request and response.
+// We just acknowledge that operation has completed here.
+//
+
+/**
+ Callback to set the request completion flag.
+
+ @param[in] Event: The event.
+ @param[in] Context: pointer to Notification Context.
+ **/
+STATIC
+VOID
+EFIAPI
+RequestCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gRequestCallbackComplete = TRUE;
+}
+
+/**
+ Callback to set the response completion flag.
+ @param[in] Event: The event.
+ @param[in] Context: pointer to Notification Context.
+ **/
+STATIC
+VOID
+EFIAPI
+ResponseCallback (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gResponseCallbackComplete = TRUE;
+}
+
+//
+// Set of functions from TimeBaseLib.
+// This will be removed once TimeBaseLib is enabled for ShellPkg.
+//
+
+/**
+ Calculate Epoch days.
+
+ @param[in] Time - a pointer to the EFI_TIME abstraction.
+
+ @retval Number of days elapsed since EPOCH_JULIAN_DAY.
+ **/
+STATIC
+UINTN
+EfiGetEpochDays (
+ IN EFI_TIME *Time
+ )
+{
+ UINTN a;
+ UINTN y;
+ UINTN m;
+ //
+ // Absolute Julian Date representation of the supplied Time.
+ //
+ UINTN JulianDate;
+ //
+ // Number of days elapsed since EPOCH_JULIAN_DAY.
+ //
+ UINTN EpochDays;
+
+ a = (14 - Time->Month) / 12 ;
+ y = Time->Year + 4800 - a;
+ m = Time->Month + (12 * a) - 3;
+
+ JulianDate = Time->Day + ((153 * m + 2) / 5) + (365 * y) + (y / 4) -
+ (y / 100) + (y / 400) - 32045;
+
+ ASSERT (JulianDate >= EPOCH_JULIAN_DATE);
+ EpochDays = JulianDate - EPOCH_JULIAN_DATE;
+
+ return EpochDays;
+}
+
+/**
+ Converts EFI_TIME to Epoch seconds
+ (elapsed since 1970 JANUARY 01, 00:00:00 UTC).
+
+ @param[in] Time: a pointer to EFI_TIME abstraction.
+ **/
+STATIC
+UINTN
+EFIAPI
+EfiTimeToEpoch (
+ IN EFI_TIME *Time
+ )
+{
+ //
+ // Number of days elapsed since EPOCH_JULIAN_DAY.
+ //
+ UINTN EpochDays;
+ UINTN EpochSeconds;
+
+ EpochDays = EfiGetEpochDays (Time);
+
+ EpochSeconds = (EpochDays * SEC_PER_DAY) +
+ ((UINTN)Time->Hour * SEC_PER_HOUR) +
+ (Time->Minute * SEC_PER_MIN) + Time->Second;
+
+ return EpochSeconds;
+}
+
+/**
+ Function for 'http' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The 'http' command completed successfully.
+ @retval SHELL_ABORTED The Shell Library initialization failed.
+ @retval SHELL_INVALID_PARAMETER At least one of the command's arguments is
+ not valid.
+ @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
+ @retval SHELL_NOT_FOUND Network Interface Card not found.
+ @retval SHELL_UNSUPPORTED Command was valid, but the server returned
+ a status code indicating some error.
+ Examine the file requested for error body.
+**/
+SHELL_STATUS
+RunHttp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *CheckPackage;
+ UINTN ParamCount;
+ UINTN HandleCount;
+ UINTN NicNumber;
+ UINTN InitialSize;
+ UINTN ParamOffset;
+ UINTN StartSize;
+ CHAR16 *ProblemParam;
+ CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
+ CHAR16 *Walker1;
+ CHAR16 *VStr;
+ CONST CHAR16 *UserNicName;
+ CONST CHAR16 *ValueStr;
+ CONST CHAR16 *RemoteFilePath;
+ CONST CHAR16 *Walker;
+ EFI_HTTPv4_ACCESS_POINT IPv4Node;
+ EFI_HANDLE *Handles;
+ EFI_HANDLE ControllerHandle;
+ HTTP_DOWNLOAD_CONTEXT Context;
+ BOOLEAN NicFound;
+
+ ProblemParam = NULL;
+ RemoteFilePath = NULL;
+ NicFound = FALSE;
+ Handles = NULL;
+
+ //
+ // Initialize the Shell library (we must be in non-auto-init...).
+ //
+ ParamOffset = 0;
+ gHttpError = FALSE;
+
+ Status = ShellInitialize ();
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return SHELL_ABORTED;
+ }
+
+ ZeroMem (&Context, sizeof (Context));
+
+ //
+ // Parse the command line.
+ //
+ Status = ShellCommandLineParse (
+ ParamList,
+ &CheckPackage,
+ &ProblemParam,
+ TRUE
+ );
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_VOLUME_CORRUPTED)
+ && (ProblemParam != NULL))
+ {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_PROBLEM), ProblemParam);
+ SHELL_FREE_NON_NULL (ProblemParam);
+ } else {
+ ASSERT (FALSE);
+ }
+
+ goto Error;
+ }
+
+ //
+ // Check the number of parameters.
+ //
+ Status = EFI_INVALID_PARAMETER;
+
+ ParamCount = ShellCommandLineGetCount (CheckPackage);
+ if (ParamCount > MAX_PARAM_COUNT) {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_TOO_MANY), NULL);
+ goto Error;
+ }
+
+ if (ParamCount < MIN_PARAM_COUNT) {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_TOO_FEW), NULL);
+ goto Error;
+ }
+
+ ZeroMem (&Context.HttpConfigData, sizeof (Context.HttpConfigData));
+ ZeroMem (&IPv4Node, sizeof (IPv4Node));
+ IPv4Node.UseDefaultAddress = TRUE;
+
+ Context.HttpConfigData.HttpVersion = HttpVersion11;
+ Context.HttpConfigData.AccessPoint.IPv4Node = &IPv4Node;
+
+ //
+ // Get the host address (not necessarily IPv4 format).
+ //
+ ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
+ if (!ValueStr) {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
+ goto Error;
+ } else {
+ StartSize = 0;
+ TrimSpaces ((CHAR16 *)ValueStr);
+ if (!StrStr (ValueStr, L"://")) {
+ Context.ServerAddrAndProto = StrnCatGrow (
+ &Context.ServerAddrAndProto,
+ &StartSize,
+ DEFAULT_HTTP_PROTO,
+ StrLen (DEFAULT_HTTP_PROTO)
+ );
+ Context.ServerAddrAndProto = StrnCatGrow (
+ &Context.ServerAddrAndProto,
+ &StartSize,
+ L"://",
+ StrLen (L"://")
+ );
+ VStr = (CHAR16 *)ValueStr;
+ } else {
+ VStr = StrStr (ValueStr, L"://") + StrLen (L"://");
+ }
+
+ for (Walker1 = VStr; *Walker1; Walker1++) {
+ if (*Walker1 == L'/') {
+ break;
+ }
+ }
+
+ if (*Walker1 == L'/') {
+ ParamOffset = 1;
+ RemoteFilePath = Walker1;
+ }
+
+ Context.ServerAddrAndProto = StrnCatGrow (
+ &Context.ServerAddrAndProto,
+ &StartSize,
+ ValueStr,
+ StrLen (ValueStr) - StrLen (Walker1)
+ );
+ if (!Context.ServerAddrAndProto) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ }
+
+ if (!RemoteFilePath) {
+ RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
+ if (!RemoteFilePath) {
+ //
+ // If no path given, assume just "/".
+ //
+ RemoteFilePath = L"/";
+ }
+ }
+
+ TrimSpaces ((CHAR16 *)RemoteFilePath);
+
+ if (ParamCount == MAX_PARAM_COUNT - ParamOffset) {
+ mLocalFilePath = ShellCommandLineGetRawValue (
+ CheckPackage,
+ MAX_PARAM_COUNT - 1 - ParamOffset
+ );
+ } else {
+ Walker = RemoteFilePath + StrLen (RemoteFilePath);
+ while ((--Walker) >= RemoteFilePath) {
+ if ((*Walker == L'\\') ||
+ (*Walker == L'/' ) ) {
+ break;
+ }
+ }
+
+ mLocalFilePath = Walker + 1;
+ }
+
+ if (!StrLen (mLocalFilePath)) {
+ mLocalFilePath = DEFAULT_HTML_FILE;
+ }
+
+ InitialSize = 0;
+ Context.Uri = StrnCatGrow (
+ &Context.Uri,
+ &InitialSize,
+ RemoteFilePath,
+ StrLen (RemoteFilePath)
+ );
+ if (!Context.Uri) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ //
+ // Get the name of the Network Interface Card to be used if any.
+ //
+ UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
+ if ((ValueStr != NULL)
+ && (!StringToUint16 (
+ ValueStr,
+ &Context.HttpConfigData.AccessPoint.IPv4Node->LocalPort
+ )
+ ))
+ {
+ goto Error;
+ }
+
+ Context.BufferSize = DEFAULT_BUF_SIZE;
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
+ if (ValueStr != NULL) {
+ Context.BufferSize = ShellStrToUintn (ValueStr);
+ if (!Context.BufferSize || Context.BufferSize > MAX_BUF_SIZE) {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
+ goto Error;
+ }
+ }
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
+ if (ValueStr != NULL) {
+ Context.HttpConfigData.TimeOutMillisec = (UINT32)ShellStrToUintn (ValueStr);
+ }
+
+ //
+ // Locate all HTTP Service Binding protocols.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ if (EFI_ERROR (Status) || (HandleCount == 0)) {
+ PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NO_NIC), NULL);
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_NOT_FOUND;
+ }
+
+ goto Error;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+ Context.Flags = 0;
+ if (ShellCommandLineGetFlag (CheckPackage, L"-m")) {
+ Context.Flags |= DL_FLAG_TIME;
+ }
+
+ if (ShellCommandLineGetFlag (CheckPackage, L"-k")) {
+ Context.Flags |= DL_FLAG_KEEP_BAD;
+ }
+
+ for (NicNumber = 0;
+ (NicNumber < HandleCount) && (Status != EFI_SUCCESS);
+ NicNumber++)
+ {
+ ControllerHandle = Handles[NicNumber];
+
+ Status = GetNicName (ControllerHandle, NicNumber, NicName);
+ if (EFI_ERROR (Status)) {
+ PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NAME), NicNumber, Status);
+ continue;
+ }
+
+ if (UserNicName != NULL) {
+ if (StrCmp (NicName, UserNicName) != 0) {
+ Status = EFI_NOT_FOUND;
+ continue;
+ }
+
+ NicFound = TRUE;
+ }
+
+ Status = DownloadFile (&Context, ControllerHandle, NicName);
+ PRINT_HII (STRING_TOKEN (STR_GEN_CRLF), NULL);
+
+ if (EFI_ERROR (Status)) {
+ PRINT_HII (
+ STRING_TOKEN (STR_HTTP_ERR_DOWNLOAD),
+ RemoteFilePath,
+ NicName,
+ Status
+ );
+ //
+ // If a user aborted the operation,
+ // do not try another controller.
+ //
+ if (Status == EFI_ABORTED) {
+ goto Error;
+ }
+ }
+
+ if (gHttpError) {
+ //
+ // This is not related to connection, so no need to repeat with
+ // another interface.
+ //
+ break;
+ }
+ }
+
+ if ((UserNicName != NULL) && (!NicFound)) {
+ PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_NIC_NOT_FOUND), UserNicName);
+ }
+
+Error:
+ ShellCommandLineFreeVarList (CheckPackage);
+ SHELL_FREE_NON_NULL (Handles);
+ SHELL_FREE_NON_NULL (Context.ServerAddrAndProto);
+ SHELL_FREE_NON_NULL (Context.Uri);
+
+ return Status & ~MAX_BIT;
+}
+
+/**
+ Check and convert the UINT16 option values of the 'http' command
+
+ @param[in] ValueStr Value as an Unicode encoded string
+ @param[out] Value UINT16 value
+
+ @retval TRUE The value was returned.
+ @retval FALSE A parsing error occured.
+**/
+STATIC
+BOOLEAN
+StringToUint16 (
+ IN CONST CHAR16 *ValueStr,
+ OUT UINT16 *Value
+ )
+{
+ UINTN Val;
+
+ Val = ShellStrToUintn (ValueStr);
+ if (Val > MAX_UINT16) {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_PARAM_INV), ValueStr);
+ return FALSE;
+ }
+
+ *Value = (UINT16)Val;
+ return TRUE;
+}
+
+/**
+ Get the name of the NIC.
+
+ @param[in] ControllerHandle The network physical device handle.
+ @param[in] NicNumber The network physical device number.
+ @param[out] NicName Address where to store the NIC name.
+ The memory area has to be at least
+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
+ double byte wide.
+
+ @retval EFI_SUCCESS The name of the NIC was returned.
+ @retval Others The creation of the child for the Managed
+ Network Service failed or the opening of
+ the Managed Network Protocol failed or
+ the operational parameters for the
+ Managed Network Protocol could not be
+ read.
+**/
+STATIC
+EFI_STATUS
+GetNicName (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NicNumber,
+ OUT CHAR16 *NicName
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE MnpHandle;
+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
+ EFI_SIMPLE_NETWORK_MODE SnpMode;
+
+ Status = CreateServiceChildAndOpenProtocol (
+ ControllerHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ &gEfiManagedNetworkProtocolGuid,
+ &MnpHandle,
+ (VOID**)&Mnp
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
+ goto Error;
+ }
+
+ UnicodeSPrint (
+ NicName,
+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,
+ SnpMode.IfType == NET_IFTYPE_ETHERNET ? L"eth%d" : L"unk%d",
+ NicNumber
+ );
+
+ Status = EFI_SUCCESS;
+
+Error:
+
+ if (MnpHandle != NULL) {
+ CloseProtocolAndDestroyServiceChild (
+ ControllerHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ &gEfiManagedNetworkProtocolGuid,
+ MnpHandle
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Create a child for the service identified by its service binding protocol GUID
+ and get from the child the interface of the protocol identified by its GUID.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be created.
+ @param[in] ProtocolGuid GUID of the protocol to be open.
+ @param[out] ChildHandle Address where the handler of the
+ created child is returned. NULL is
+ returned in case of error.
+ @param[out] Interface Address where a pointer to the
+ protocol interface is returned in
+ case of success.
+
+ @retval EFI_SUCCESS The child was created and the protocol opened.
+ @retval Others Either the creation of the child or the opening
+ of the protocol failed.
+**/
+STATIC
+EFI_STATUS
+CreateServiceChildAndOpenProtocol (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ OUT EFI_HANDLE *ChildHandle,
+ OUT VOID **Interface
+ )
+{
+ EFI_STATUS Status;
+
+ *ChildHandle = NULL;
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ gImageHandle,
+ ServiceBindingProtocolGuid,
+ ChildHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ *ChildHandle,
+ ProtocolGuid,
+ Interface,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ gImageHandle,
+ ServiceBindingProtocolGuid,
+ *ChildHandle
+ );
+ *ChildHandle = NULL;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Close the protocol identified by its GUID on the child handle of the service
+ identified by its service binding protocol GUID, then destroy the child
+ handle.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be destroyed.
+ @param[in] ProtocolGuid GUID of the protocol to be closed.
+ @param[in] ChildHandle Handle of the child to be destroyed.
+**/
+STATIC
+VOID
+CloseProtocolAndDestroyServiceChild (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ gBS->CloseProtocol (
+ ChildHandle,
+ ProtocolGuid,
+ gImageHandle,
+ ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ gImageHandle,
+ ServiceBindingProtocolGuid,
+ ChildHandle
+ );
+}
+
+/**
+ Wait until operation completes. Completion is indicated by
+ setting of an appropriate variable.
+
+ @param[in] Context A pointer to the HTTP download context.
+ @param[in, out] CallBackComplete A pointer to the callback completion
+ variable set by the callback.
+
+ @retval EFI_SUCCESS Callback signalled completion.
+ @retval EFI_TIMEOUT Timed out waiting for completion.
+ @retval Others Error waiting for completion.
+**/
+STATIC
+EFI_STATUS
+WaitForCompletion (
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN OUT BOOLEAN *CallBackComplete
+ )
+{
+ EFI_STATUS Status;
+ EFI_EVENT WaitEvt;
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Use a timer to measure timeout. Cannot use Stall here!
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &WaitEvt
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->SetTimer (
+ WaitEvt,
+ TimerRelative,
+ EFI_TIMER_PERIOD_SECONDS (TIMER_MAX_TIMEOUT_S)
+ );
+
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ while (! *CallBackComplete
+ && (!EFI_ERROR (Status))
+ && EFI_ERROR (gBS->CheckEvent (WaitEvt)))
+ {
+ Status = Context->Http->Poll (Context->Http);
+ if (!Context->ContentDownloaded
+ && CallBackComplete == &gResponseCallbackComplete)
+ {
+ //
+ // An HTTP server may just send a response redirection header.
+ // In this case, don't wait for the event as
+ // it might never happen and we waste 10s waiting.
+ // Note that at this point Response may not has been populated,
+ // so it needs to be checked first.
+ //
+ if (Context->ResponseToken.Message
+ && Context->ResponseToken.Message->Data.Response
+ && (NEED_REDIRECTION (
+ Context->ResponseToken.Message->Data.Response->StatusCode
+ )
+ ))
+ {
+ break;
+ }
+ }
+ }
+
+ gBS->SetTimer (WaitEvt, TimerCancel, 0);
+ gBS->CloseEvent (WaitEvt);
+
+ if (*CallBackComplete) {
+ return EFI_SUCCESS;
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = EFI_TIMEOUT;
+ }
+
+ return Status;
+}
+
+/**
+ Generate and send a request to the http server.
+
+ @param[in] Context HTTP download context.
+ @param[in] DownloadUrl Fully qualified URL to be downloaded.
+
+ @retval EFI_SUCCESS Request has been sent successfully.
+ @retval EFI_INVALID_PARAMETER Invalid URL.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval EFI_DEVICE_ERROR If HTTPS is used, this probably
+ means that TLS support either was not
+ installed or not configured.
+ @retval Others Error sending the request.
+**/
+STATIC
+EFI_STATUS
+SendRequest (
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN CHAR16 *DownloadUrl
+ )
+{
+ EFI_HTTP_REQUEST_DATA RequestData;
+ EFI_HTTP_HEADER RequestHeader[HdrMax];
+ EFI_HTTP_MESSAGE RequestMessage;
+ EFI_STATUS Status;
+ CHAR16 *Host;
+ UINTN StringSize;
+
+ ZeroMem (&RequestData, sizeof (RequestData));
+ ZeroMem (&RequestHeader, sizeof (RequestHeader));
+ ZeroMem (&RequestMessage, sizeof (RequestMessage));
+ ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
+
+ RequestHeader[HdrHost].FieldName = "Host";
+ RequestHeader[HdrConn].FieldName = "Connection";
+ RequestHeader[HdrAgent].FieldName = "User-Agent";
+
+ Host = (CHAR16 *)Context->ServerAddrAndProto;
+ while (*Host != CHAR_NULL && *Host != L'/') {
+ Host++;
+ }
+
+ if (*Host == CHAR_NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the next slash.
+ //
+ Host++;
+ //
+ // And now the host name.
+ //
+ Host++;
+
+ StringSize = StrLen (Host) + 1;
+ RequestHeader[HdrHost].FieldValue = AllocatePool (StringSize);
+ if (!RequestHeader[HdrHost].FieldValue) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ UnicodeStrToAsciiStrS (
+ Host,
+ RequestHeader[HdrHost].FieldValue,
+ StringSize
+ );
+
+ RequestHeader[HdrConn].FieldValue = "close";
+ RequestHeader[HdrAgent].FieldValue = USER_AGENT_HDR;
+ RequestMessage.HeaderCount = HdrMax;
+
+ RequestData.Method = HttpMethodGet;
+ RequestData.Url = DownloadUrl;
+
+ RequestMessage.Data.Request = &RequestData;
+ RequestMessage.Headers = RequestHeader;
+ RequestMessage.BodyLength = 0;
+ RequestMessage.Body = NULL;
+ Context->RequestToken.Event = NULL;
+
+ //
+ // Completion callback event to be set when Request completes.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ RequestCallback,
+ Context,
+ &Context->RequestToken.Event
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Context->RequestToken.Status = EFI_SUCCESS;
+ Context->RequestToken.Message = &RequestMessage;
+ gRequestCallbackComplete = FALSE;
+ Status = Context->Http->Request (Context->Http, &Context->RequestToken);
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = WaitForCompletion (Context, &gRequestCallbackComplete);
+ if (EFI_ERROR (Status)) {
+ Context->Http->Cancel (Context->Http, &Context->RequestToken);
+ }
+
+Error:
+ SHELL_FREE_NON_NULL (RequestHeader[HdrHost].FieldValue);
+ if (Context->RequestToken.Event) {
+ gBS->CloseEvent (Context->RequestToken.Event);
+ ZeroMem (&Context->RequestToken, sizeof (Context->RequestToken));
+ }
+
+ return Status;
+}
+
+/**
+ Update the progress of a file download
+ This procedure is called each time a new HTTP body portion is received.
+
+ @param[in] Context HTTP download context.
+ @param[in] DownloadLen Portion size, in bytes.
+ @param[in] Buffer The pointer to the parsed buffer.
+
+ @retval EFI_SUCCESS Portion saved.
+ @retval Other Error saving the portion.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+SavePortion (
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN UINTN DownloadLen,
+ IN CHAR8 *Buffer
+ )
+{
+ CHAR16 Progress[HTTP_PROGRESS_MESSAGE_SIZE];
+ UINTN NbOfKb;
+ UINTN Index;
+ UINTN LastStep;
+ UINTN Step;
+ EFI_STATUS Status;
+
+ LastStep = 0;
+ Step = 0;
+
+ ShellSetFilePosition (mFileHandle, Context->LastReportedNbOfBytes);
+ Status = ShellWriteFile (mFileHandle, &DownloadLen, Buffer);
+ if (EFI_ERROR (Status)) {
+ if (Context->ContentDownloaded > 0) {
+ PRINT_HII (STRING_TOKEN (STR_GEN_CRLF), NULL);
+ }
+
+ PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_WRITE), mLocalFilePath, Status);
+ return Status;
+ }
+
+ if (Context->ContentDownloaded == 0) {
+ ShellPrintEx (-1, -1, L"%s 0 Kb", HTTP_PROGR_FRAME);
+ }
+
+ Context->ContentDownloaded += DownloadLen;
+ NbOfKb = Context->ContentDownloaded >> 10;
+
+ Progress[0] = L'\0';
+ if (Context->ContentLength) {
+ LastStep = (Context->LastReportedNbOfBytes * HTTP_PROGRESS_SLIDER_STEPS) /
+ Context->ContentLength;
+ Step = (Context->ContentDownloaded * HTTP_PROGRESS_SLIDER_STEPS) /
+ Context->ContentLength;
+ }
+
+ Context->LastReportedNbOfBytes = Context->ContentDownloaded;
+
+ if (Step <= LastStep) {
+ if (!Context->ContentLength) {
+ //
+ // Update downloaded size, there is no length info available.
+ //
+ ShellPrintEx (-1, -1, L"%s", HTTP_KB);
+ ShellPrintEx (-1, -1, L"%7d Kb", NbOfKb);
+ }
+
+ return EFI_SUCCESS;
+ }
+
+ ShellPrintEx (-1, -1, L"%s", HTTP_PROGRESS_DEL);
+
+ Status = StrCpyS (Progress, HTTP_PROGRESS_MESSAGE_SIZE, HTTP_PROGR_FRAME);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 1; Index < Step; Index++) {
+ Progress[Index] = L'=';
+ }
+
+ if (Step) {
+ Progress[Step] = L'>';
+ }
+
+ UnicodeSPrint (
+ Progress + (sizeof (HTTP_PROGR_FRAME) / sizeof (CHAR16)) - 1,
+ sizeof (Progress) - sizeof (HTTP_PROGR_FRAME),
+ L" %7d Kb",
+ NbOfKb
+ );
+
+
+ ShellPrintEx (-1, -1, L"%s", Progress);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Replace the original Host and Uri with Host and Uri returned by the
+ HTTP server in 'Location' header (redirection).
+
+ @param[in] Location A pointer to the 'Location' string
+ provided by HTTP server.
+ @param[in] Context A pointer to HTTP download context.
+ @param[in] DownloadUrl Fully qualified HTTP URL.
+
+ @retval EFI_SUCCESS Host and Uri were successfully set.
+ @retval EFI_OUT_OF_RESOURCES Error setting Host or Uri.
+**/
+STATIC
+EFI_STATUS
+SetHostURI (
+ IN CHAR8 *Location,
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN CHAR16 *DownloadUrl
+ )
+{
+ EFI_STATUS Status;
+ UINTN StringSize;
+ UINTN FirstStep;
+ UINTN Idx;
+ UINTN Step;
+ CHAR8 *Walker;
+ CHAR16 *Temp;
+ CHAR8 *Tmp;
+ CHAR16 *Url;
+ BOOLEAN IsAbEmptyUrl;
+
+ Tmp = NULL;
+ Url = NULL;
+ IsAbEmptyUrl = FALSE;
+ FirstStep = 0;
+
+ StringSize = (AsciiStrSize (Location) * sizeof (CHAR16));
+ Url = AllocateZeroPool (StringSize);
+ if (!Url) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AsciiStrToUnicodeStrS (
+ (CONST CHAR8 *)Location,
+ Url,
+ StringSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ //
+ // If an HTTP server redirects to the same location more than once,
+ // then stop attempts and tell it is not reachable.
+ //
+ if (!StrCmp (Url, DownloadUrl)) {
+ Status = EFI_NO_MAPPING;
+ goto Error;
+ }
+
+ if (AsciiStrLen (Location) > 2) {
+ //
+ // Some servers return 'Location: //server/resource'
+ //
+ IsAbEmptyUrl = (Location[0] == '/') && (Location[1] == '/');
+ if (IsAbEmptyUrl) {
+ //
+ // Skip first "//"
+ //
+ Location += 2;
+ FirstStep = 1;
+ }
+ }
+
+ if (AsciiStrStr (Location, "://") || IsAbEmptyUrl) {
+ Idx = 0;
+ Walker = Location;
+
+ for (Step = FirstStep; Step < 2; Step++) {
+ for (; *Walker != '/' && *Walker != '\0'; Walker++) {
+ Idx++;
+ }
+
+ if (!Step) {
+ //
+ // Skip "//"
+ //
+ Idx += 2;
+ Walker += 2;
+ }
+ }
+
+ Tmp = AllocateZeroPool (Idx + 1);
+ if (!Tmp) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ CopyMem (Tmp, Location, Idx);
+
+ //
+ // Location now points to Uri
+ //
+ Location += Idx;
+ StringSize = (Idx + 1) * sizeof (CHAR16);
+
+ SHELL_FREE_NON_NULL (Context->ServerAddrAndProto);
+
+ Temp = AllocateZeroPool (StringSize);
+ if (!Temp) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ Status = AsciiStrToUnicodeStrS (
+ (CONST CHAR8 *)Tmp,
+ Temp,
+ StringSize
+ );
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (Temp);
+ goto Error;
+ }
+
+ Idx = 0;
+ if (IsAbEmptyUrl) {
+ Context->ServerAddrAndProto = StrnCatGrow (
+ &Context->ServerAddrAndProto,
+ &Idx,
+ L"http://",
+ StrLen (L"http://")
+ );
+ }
+
+ Context->ServerAddrAndProto = StrnCatGrow (
+ &Context->ServerAddrAndProto,
+ &Idx,
+ Temp,
+ StrLen (Temp)
+ );
+ SHELL_FREE_NON_NULL (Temp);
+ if (!Context->ServerAddrAndProto) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ }
+
+ SHELL_FREE_NON_NULL (Context->Uri);
+
+ StringSize = AsciiStrSize (Location) * sizeof (CHAR16);
+ Context->Uri = AllocateZeroPool (StringSize);
+ if (!Context->Uri) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ //
+ // Now make changes to the Uri part.
+ //
+ Status = AsciiStrToUnicodeStrS (
+ (CONST CHAR8 *)Location,
+ Context->Uri,
+ StringSize
+ );
+Error:
+ SHELL_FREE_NON_NULL (Tmp);
+ SHELL_FREE_NON_NULL (Url);
+
+ return Status;
+}
+
+/**
+ Message parser callback.
+ Save a portion of HTTP body.
+
+ @param[in] EventType Type of event. Can be either
+ OnComplete or OnData.
+ @param[in] Data A pointer to the buffer with data.
+ @param[in] Length Data length of this portion.
+ @param[in] Context A pointer to the HTTP download context.
+
+ @retval EFI_SUCCESS The portion was processed successfully.
+ @retval Other Error returned by SavePortion.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+ParseMsg (
+ IN HTTP_BODY_PARSE_EVENT EventType,
+ IN CHAR8 *Data,
+ IN UINTN Length,
+ IN VOID *Context
+ )
+{
+ if ((Data == NULL)
+ || (EventType == BodyParseEventOnComplete)
+ || (Context == NULL))
+ {
+ return EFI_SUCCESS;
+ }
+
+ return SavePortion (Context, Length, Data);
+}
+
+
+/**
+ Get HTTP server response and collect the whole body as a file.
+ Set appropriate status in Context (REQ_OK, REQ_REPEAT, REQ_ERROR).
+ Note that even if HTTP server returns an error code, it might send
+ the body as well. This body will be collected in the resultant file.
+
+ @param[in] Context A pointer to the HTTP download context.
+ @param[in] DownloadUrl A pointer to the fully qualified URL to download.
+
+ @retval EFI_SUCCESS Valid file. Body successfully collected.
+ @retval EFI_HTTP_ERROR Response is a valid HTTP response, but the
+ HTTP server
+ indicated an error (HTTP code >= 400).
+ Response body MAY contain full
+ HTTP server response.
+ @retval Others Error getting the reponse from the HTTP server.
+ Response body is not collected.
+**/
+STATIC
+EFI_STATUS
+GetResponse (
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN CHAR16 *DownloadUrl
+ )
+{
+ EFI_HTTP_RESPONSE_DATA ResponseData;
+ EFI_HTTP_MESSAGE ResponseMessage;
+ EFI_HTTP_HEADER *Header;
+ EFI_STATUS Status;
+ VOID *MsgParser;
+ EFI_TIME StartTime;
+ EFI_TIME EndTime;
+ CONST CHAR16 *Desc;
+ UINTN ElapsedSeconds;
+ BOOLEAN IsTrunked;
+ BOOLEAN CanMeasureTime;
+
+ ZeroMem (&ResponseData, sizeof (ResponseData));
+ ZeroMem (&ResponseMessage, sizeof (ResponseMessage));
+ ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken));
+ IsTrunked = FALSE;
+
+ ResponseMessage.Body = Context->Buffer;
+ Context->ResponseToken.Status = EFI_SUCCESS;
+ Context->ResponseToken.Message = &ResponseMessage;
+ Context->ContentLength = 0;
+ Context->Status = REQ_OK;
+ Status = EFI_SUCCESS;
+ MsgParser = NULL;
+ ResponseData.StatusCode = HTTP_STATUS_UNSUPPORTED_STATUS;
+ ResponseMessage.Data.Response = &ResponseData;
+ Context->ResponseToken.Event = NULL;
+ CanMeasureTime = FALSE;
+ if (Context->Flags & DL_FLAG_TIME) {
+ ZeroMem (&StartTime, sizeof (StartTime));
+ CanMeasureTime = !EFI_ERROR (gRT->GetTime (&StartTime, NULL));
+ }
+
+ do {
+ SHELL_FREE_NON_NULL (ResponseMessage.Headers);
+ ResponseMessage.HeaderCount = 0;
+ gResponseCallbackComplete = FALSE;
+ ResponseMessage.BodyLength = Context->BufferSize;
+
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+
+ if (!Context->ContentDownloaded && !Context->ResponseToken.Event) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ ResponseCallback,
+ Context,
+ &Context->ResponseToken.Event
+ );
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ ResponseMessage.Data.Response = NULL;
+ }
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = Context->Http->Response (Context->Http, &Context->ResponseToken);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ Status = WaitForCompletion (Context, &gResponseCallbackComplete);
+ if (EFI_ERROR (Status) && ResponseMessage.HeaderCount) {
+ Status = EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ Context->Http->Cancel (Context->Http, &Context->ResponseToken);
+ break;
+ }
+
+ if (!Context->ContentDownloaded) {
+ if (NEED_REDIRECTION (ResponseData.StatusCode)) {
+ //
+ // Need to repeat the request with new Location (server redirected).
+ //
+ Context->Status = REQ_NEED_REPEAT;
+
+ Header = HttpFindHeader (
+ ResponseMessage.HeaderCount,
+ ResponseMessage.Headers,
+ "Location"
+ );
+ if (Header) {
+ Status = SetHostURI (Header->FieldValue, Context, DownloadUrl);
+ if (Status == EFI_NO_MAPPING) {
+ PRINT_HII (
+ STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
+ Context->ServerAddrAndProto,
+ L"Recursive HTTP server relocation",
+ Context->Uri
+ );
+ }
+ } else {
+ //
+ // Bad reply from the server. Server must specify the location.
+ // Indicate that resource was not found, and no body collected.
+ //
+ Status = EFI_NOT_FOUND;
+ }
+
+ Context->Http->Cancel (Context->Http, &Context->ResponseToken);
+ break;
+ }
+
+ //
+ // Init message-body parser by header information.
+ //
+ if (!MsgParser) {
+ Status = HttpInitMsgParser (
+ ResponseMessage.Data.Request->Method,
+ ResponseData.StatusCode,
+ ResponseMessage.HeaderCount,
+ ResponseMessage.Headers,
+ ParseMsg,
+ Context,
+ &MsgParser
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ //
+ // If it is a trunked message, rely on the parser.
+ //
+ Header = HttpFindHeader (
+ ResponseMessage.HeaderCount,
+ ResponseMessage.Headers,
+ "Transfer-Encoding"
+ );
+ IsTrunked = (Header && !AsciiStrCmp (Header->FieldValue, "chunked"));
+
+ HttpGetEntityLength (MsgParser, &Context->ContentLength);
+
+ if (ResponseData.StatusCode >= HTTP_STATUS_400_BAD_REQUEST
+ && (ResponseData.StatusCode != HTTP_STATUS_308_PERMANENT_REDIRECT))
+ {
+ //
+ // Server reported an error via Response code.
+ // Collect the body if any.
+ //
+ if (!gHttpError) {
+ gHttpError = TRUE;
+
+ Desc = ErrStatusDesc[ResponseData.StatusCode -
+ HTTP_STATUS_400_BAD_REQUEST];
+ PRINT_HII (
+ STRING_TOKEN (STR_HTTP_ERR_STATUSCODE),
+ Context->ServerAddrAndProto,
+ Desc,
+ Context->Uri
+ );
+
+ //
+ // This gives an RFC HTTP error.
+ //
+ Context->Status = ShellStrToUintn (Desc);
+ Status = ENCODE_ERROR (Context->Status);
+ }
+ }
+ }
+
+ //
+ // Do NOT try to parse an empty body.
+ //
+ if (ResponseMessage.BodyLength || IsTrunked) {
+ Status = HttpParseMessageBody (
+ MsgParser,
+ ResponseMessage.BodyLength,
+ ResponseMessage.Body
+ );
+ }
+ } while (!HttpIsMessageComplete (MsgParser)
+ && !EFI_ERROR (Status)
+ && ResponseMessage.BodyLength);
+
+ if (Context->Status != REQ_NEED_REPEAT
+ && Status == EFI_SUCCESS
+ && CanMeasureTime)
+ {
+ if (!EFI_ERROR (gRT->GetTime (&EndTime, NULL))) {
+ ElapsedSeconds = EfiTimeToEpoch (&EndTime) - EfiTimeToEpoch (&StartTime);
+ Print (
+ L",%a%Lus\n",
+ ElapsedSeconds ? " " : " < ",
+ ElapsedSeconds > 1 ? (UINT64)ElapsedSeconds : 1
+ );
+ }
+ }
+
+ SHELL_FREE_NON_NULL (MsgParser);
+ if (Context->ResponseToken.Event) {
+ gBS->CloseEvent (Context->ResponseToken.Event);
+ ZeroMem (&Context->ResponseToken, sizeof (Context->ResponseToken));
+ }
+
+ return Status;
+}
+
+/**
+ Worker function that downloads the data of a file from an HTTP server given
+ the path of the file and its size.
+
+ @param[in] Context A pointer to the HTTP download context.
+ @param[in] ControllerHandle The handle of the network interface controller
+ @param[in] NicName NIC name
+
+ @retval EFI_SUCCESS The file was downloaded.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ #return EFI_HTTP_ERROR The server returned a valid HTTP error.
+ Examine the mLocalFilePath file
+ to get error body.
+ @retval Others The downloading of the file from the server
+ failed.
+**/
+STATIC
+EFI_STATUS
+DownloadFile (
+ IN HTTP_DOWNLOAD_CONTEXT *Context,
+ IN EFI_HANDLE ControllerHandle,
+ IN CHAR16 *NicName
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *DownloadUrl;
+ UINTN UrlSize;
+ EFI_HANDLE HttpChildHandle;
+
+ ASSERT (Context);
+ if (Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ DownloadUrl = NULL;
+ HttpChildHandle = NULL;
+
+ Context->Buffer = AllocatePool (Context->BufferSize);
+ if (Context->Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ //
+ // Open the file.
+ //
+ if (!EFI_ERROR (ShellFileExists (mLocalFilePath))) {
+ ShellDeleteFileByName (mLocalFilePath);
+ }
+
+ Status = ShellOpenFileByName (
+ mLocalFilePath,
+ &mFileHandle,
+ EFI_FILE_MODE_CREATE |
+ EFI_FILE_MODE_WRITE |
+ EFI_FILE_MODE_READ,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ PRINT_HII_APP (STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), mLocalFilePath);
+ goto ON_EXIT;
+ }
+
+ do {
+ SHELL_FREE_NON_NULL (DownloadUrl);
+
+ CLOSE_HTTP_HANDLE (ControllerHandle, HttpChildHandle);
+
+ Status = CreateServiceChildAndOpenProtocol (
+ ControllerHandle,
+ &gEfiHttpServiceBindingProtocolGuid,
+ &gEfiHttpProtocolGuid,
+ &HttpChildHandle,
+ (VOID**)&Context->Http
+ );
+
+ if (EFI_ERROR (Status)) {
+ PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_OPEN_PROTOCOL), NicName, Status);
+ goto ON_EXIT;
+ }
+
+ Status = Context->Http->Configure (Context->Http, &Context->HttpConfigData);
+ if (EFI_ERROR (Status)) {
+ PRINT_HII (STRING_TOKEN (STR_HTTP_ERR_CONFIGURE), NicName, Status);
+ goto ON_EXIT;
+ }
+
+ UrlSize = 0;
+ DownloadUrl = StrnCatGrow (
+ &DownloadUrl,
+ &UrlSize,
+ Context->ServerAddrAndProto,
+ StrLen (Context->ServerAddrAndProto)
+ );
+ if (Context->Uri[0] != L'/') {
+ DownloadUrl = StrnCatGrow (
+ &DownloadUrl,
+ &UrlSize,
+ L"/",
+ StrLen (Context->ServerAddrAndProto)
+ );
+ }
+
+ DownloadUrl = StrnCatGrow (
+ &DownloadUrl,
+ &UrlSize,
+ Context->Uri,
+ StrLen (Context->Uri));
+
+ PRINT_HII (STRING_TOKEN (STR_HTTP_DOWNLOADING), DownloadUrl);
+
+ Status = SendRequest (Context, DownloadUrl);
+ if (Status) {
+ goto ON_EXIT;
+ }
+
+ Status = GetResponse (Context, DownloadUrl);
+
+ if (Status) {
+ goto ON_EXIT;
+ }
+
+ } while (Context->Status == REQ_NEED_REPEAT);
+
+ if (Context->Status) {
+ Status = ENCODE_ERROR (Context->Status);
+ }
+
+ON_EXIT:
+ //
+ // Close the file.
+ //
+ if (mFileHandle != NULL) {
+ if (EFI_ERROR (Status) && !(Context->Flags & DL_FLAG_KEEP_BAD)) {
+ ShellDeleteFile (&mFileHandle);
+ } else {
+ ShellCloseFile (&mFileHandle);
+ }
+ }
+
+ SHELL_FREE_NON_NULL (DownloadUrl);
+ SHELL_FREE_NON_NULL (Context->Buffer);
+
+ CLOSE_HTTP_HANDLE (ControllerHandle, HttpChildHandle);
+
+ return Status;
+}
+
+/**
+ Retrive HII package list from ImageHandle and publish to HII database.
+
+ @param[in] ImageHandle The image handle of the process.
+
+ @retval HII handle.
+**/
+EFI_HII_HANDLE
+InitializeHiiPackage (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;
+ EFI_HII_HANDLE HiiHandle;
+
+ //
+ // Retrieve HII package list from ImageHandle.
+ //
+ Status = gBS->OpenProtocol (
+ ImageHandle,
+ &gEfiHiiPackageListProtocolGuid,
+ (VOID **)&PackageList,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Publish HII package list to HII Database.
+ //
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageList,
+ NULL,
+ &HiiHandle
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ return HiiHandle;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
new file mode 100644
index 00000000000..c09096afb12
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.h
@@ -0,0 +1,92 @@
+/** @file
+ Header file for 'http' command functions.
+
+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _HTTP_H_
+#define _HTTP_H_
+
+#include <Uefi.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HiiLib.h>
+#include <Library/HttpLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+
+#include <Protocol/HiiPackageList.h>
+#include <Protocol/HttpUtilities.h>
+#include <Protocol/ServiceBinding.h>
+
+#define HTTP_APP_NAME L"http"
+
+#define REQ_OK 0
+#define REQ_NEED_REPEAT 1
+
+//
+// Download Flags.
+//
+#define DL_FLAG_TIME BIT0 // Show elapsed time.
+#define DL_FLAG_KEEP_BAD BIT1 // Keep files even if download failed.
+
+extern EFI_HII_HANDLE mHttpHiiHandle;
+
+typedef struct {
+ UINTN ContentDownloaded;
+ UINTN ContentLength;
+ UINTN LastReportedNbOfBytes;
+ UINTN BufferSize;
+ UINTN Status;
+ UINTN Flags;
+ UINT8 *Buffer;
+ CHAR16 *ServerAddrAndProto;
+ CHAR16 *Uri;
+ EFI_HTTP_TOKEN ResponseToken;
+ EFI_HTTP_TOKEN RequestToken;
+ EFI_HTTP_PROTOCOL *Http;
+ EFI_HTTP_CONFIG_DATA HttpConfigData;
+} HTTP_DOWNLOAD_CONTEXT;
+
+/**
+ Function for 'http' command.
+
+ @param[in] ImageHandle The image handle.
+ @param[in] SystemTable The system table.
+
+ @retval SHELL_SUCCESS Command completed successfully.
+ @retval SHELL_INVALID_PARAMETER Command usage error.
+ @retval SHELL_ABORTED The user aborts the operation.
+ @retval value Unknown error.
+**/
+SHELL_STATUS
+RunHttp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Retrieve HII package list from ImageHandle and publish to HII database.
+
+ @param[in] ImageHandle The image handle of the process.
+
+ @retval HII handle.
+**/
+EFI_HII_HANDLE
+InitializeHiiPackage (
+ IN EFI_HANDLE ImageHandle
+ );
+#endif // _HTTP_H_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
new file mode 100644
index 00000000000..00cf05deeb5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/Http.uni
@@ -0,0 +1,117 @@
+// /**
+//
+// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+// Copyright (c) 2020, Broadcom. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+// Http.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell HTTP command
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments. Try help http.\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments. Try help http.\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'. Try help http.\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'. Try help http.\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_CRLF #language en-US "\r\n"
+
+#string STR_HTTP_ERR_NO_NIC #language en-US "No network interface card found.\r\n"
+#string STR_HTTP_ERR_NIC_NAME #language en-US "Failed to get the name of the network interface card number %d - %r\r\n"
+#string STR_HTTP_ERR_OPEN_PROTOCOL #language en-US "Unable to open HTTP protocol on '%H%s%N' - %r\r\n"
+#string STR_HTTP_ERR_CONFIGURE #language en-US "Unable to configure HTTP protocol on '%H%s%N' - %r\r\n"
+#string STR_HTTP_ERR_DOWNLOAD #language en-US "Unable to download the file '%H%s%N' on '%H%s%N' - %r\r\n"
+#string STR_HTTP_ERR_WRITE #language en-US "Unable to write into file '%H%s%N' - %r\r\n"
+#string STR_HTTP_ERR_NIC_NOT_FOUND #language en-US "Network Interface Card '%H%s%N' not found.\r\n"
+#string STR_HTTP_ERR_STATUSCODE #language en-US "\r'%H%s%N' reports '%s' for '%H%s%N' \r\n"
+#string STR_HTTP_DOWNLOADING #language en-US "Downloading '%H%s%N'\r\n"
+
+#string STR_GET_HELP_HTTP #language en-US ""
+".TH http 0 "Download a file from HTTP server."\r\n"
+".SH NAME\r\n"
+"Download a file from HTTP server.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"HTTP [-i interface] [-l port] [-t timeout] [-s size] [-m] [-k]\r\n"
+" <URL> [localfilepath]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -i interface - Specifies an adapter name, i.e., eth0.\r\n"
+" -k Keep the downloaded file even if there was an error.\r\n"
+" If this parameter is not used, the file will be deleted.\r\n"
+" -l port - Specifies the local port number. Default value is 0\r\n"
+" and the port number is automatically assigned.\r\n"
+" -m Measure and report download time (in seconds). \r\n"
+" -s size The size of the download buffer for a chunk, in bytes.\r\n"
+" Default is 32K. Note that larger buffer does not imply\r\n"
+" better speed.\r\n"
+" -t timeout - The number of seconds to wait for completion of\r\n"
+" requests and responses. Default is 0 which is 'automatic'.\r\n"
+" %HURL%N\r\n"
+" Two types of providing of URLs are supported:\r\n"
+" 1. tftp-like, where host and http_uri are separate parameters\r\n"
+" (example: host /host_uri), and\r\n\"
+" 2. wget-like, where host and host_uri is one parameter.\r\n"
+" (example: host/host_uri)\r\n"
+"\r\n"
+" host - Specifies HTTP Server address.\r\n
+ Can be either IPv4 address or 'http (or https)://addr'\r\n
+ Can use addresses resolvable by DNS as well. \r\n
+ Port can be specified after ':' if needed. \r\n
+ By default port 80 is used.\r\n"
+" http_uri - HTTP server URI to download the file.\r\n"
+"\r\n"
+" localfilepath - Local destination file path.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The HTTP command allows geting of the file specified by its 'http_uri'\r\n"
+" path from the HTTP server specified by its 'host' IPv4 address. If the\r\n"
+" optional 'localfilepath' parameter is provided, the downloaded file is\r\n"
+" stored locally using the provided file path. If the local file path is\r\n"
+" not specified, the file is stored in the current directory using the file\r\n"
+" server's name.\r\n"
+" 2. Before using the HTTP command, the network interface intended to be\r\n"
+" used to retrieve the file must be configured. This configuration may be\r\n"
+" done by means of the 'ifconfig' command.\r\n"
+" 3. If a network interface is defined with the '-i' option then only this\r\n"
+" interface will be used to retrieve the remote file. Otherwise, all network\r\n"
+" interfaces are tried in the order they have been discovered during the\r\n"
+" DXE phase.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To get the file "dir1/file1.dat" from the HTTP server 192.168.1.1, port 8080, and\r\n"
+" store it as file2.dat in the current directory (use tftp-like URL format) :\r\n"
+" fs0:\> http 192.168.1.1:8080 dir1/file1.dat file2.dat\r\n"
+" * To get the file /image.bin via HTTPS from server 192.168.1.1 at port 443 \r\n"
+" (default HTTPS port), and store it in the current directory: \r\n"
+" fs0:\> http https://192.168.1.1 image.bin\r\n"
+" To get an index file from http://google.com and place it into the \r\n"
+" current directory:\r\n"
+" fs0:\> http google.com index.html\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" HTTP_ERROR No EFI errors, but the server reported a status code\r\n"
+" which should be treated as an error. If an error body sent\r\n"
+" by the server, and -k parameter is on command line,
+" the file wil be saved either as localfilepath filename,\r\n"
+" or as an URI name in the current directory.\r\n"
+" If '/' is at the end of the URL, and no locafilepath filename\r\n"
+" is given on the command line, the file will be retrieved as\r\n"
+" index.html.\r\n"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
new file mode 100644
index 00000000000..b262e463670
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.c
@@ -0,0 +1,61 @@
+/** @file
+ Entrypoint of "http" shell standalone application.
+
+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "Http.h"
+
+/*
+ * String token ID of help message text.
+ * Shell supports to find help message in the resource section of an
+ * application image if * .MAN file is not found.
+ * This global variable is added to make build tool recognizes
+ * that the help string is consumed by user and then build tool will
+ * add the string into the resource section.
+ * Thus the application can use '-?' option to show help message in Shell.
+ */
+GLOBAL_REMOVE_IF_UNREFERENCED
+EFI_STRING_ID mStringHelpTokenId = STRING_TOKEN (STR_GET_HELP_HTTP);
+
+/**
+ Entry point of Http standalone application.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS Http command is executed sucessfully.
+ @retval EFI_ABORTED HII package was failed to initialize.
+ @retval others Other errors when executing http command.
+**/
+EFI_STATUS
+EFIAPI
+HttpAppInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+
+ mHttpHiiHandle = InitializeHiiPackage (ImageHandle);
+ if (mHttpHiiHandle == NULL) {
+ return EFI_ABORTED;
+ }
+
+ Status = EFI_SUCCESS;
+
+ ShellStatus = RunHttp (ImageHandle, SystemTable);
+
+ HiiRemovePackages (mHttpHiiHandle);
+
+ if (Status != SHELL_SUCCESS) {
+ Status = ENCODE_ERROR (ShellStatus);
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
new file mode 100644
index 00000000000..bdea1fc17e5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
@@ -0,0 +1,57 @@
+## @file
+# Provides Shell 'http' standalone application.
+#
+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved. <BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2020, Broadcom. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = http
+ FILE_GUID = 56B00FB7-91D2-869B-CE5C-26CD1A89C73C
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = HttpAppInitialize
+#
+# This flag specifies whether HII resource section is generated into PE image.
+#
+ UEFI_HII_RESOURCE_SECTION = TRUE
+
+[Sources.common]
+ Http.c
+ HttpApp.c
+ Http.h
+ Http.uni
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ HiiLib
+ HttpLib
+ MemoryAllocationLib
+ NetLib
+ ShellLib
+ UefiApplicationEntryPoint
+ UefiBootServicesTableLib
+ UefiHiiServicesLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiHiiPackageListProtocolGuid ## CONSUMES
+ gEfiHttpProtocolGuid ## CONSUMES
+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES
+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
new file mode 100644
index 00000000000..5245cba39b3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.c
@@ -0,0 +1,137 @@
+/** @file
+ Produce "http" shell dynamic command.
+
+ Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2020, Broadcom. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Protocol/ShellDynamicCommand.h>
+#include "Http.h"
+
+/**
+ This is the shell command handler function pointer callback type. This
+ function handles the command when it is invoked in the shell.
+
+ @param[in] This The instance of the
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+ @param[in] SystemTable The pointer to the system table.
+ @param[in] ShellParameters The parameters associated with the command.
+ @param[in] Shell The instance of the shell protocol used in
+ the context of processing this command.
+
+ @return EFI_SUCCESS the operation was sucessful
+ @return other the operation failed.
+**/
+SHELL_STATUS
+EFIAPI
+HttpCommandHandler (
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN EFI_SHELL_PROTOCOL *Shell
+ )
+{
+ gEfiShellParametersProtocol = ShellParameters;
+ gEfiShellProtocol = Shell;
+
+ return RunHttp (gImageHandle, SystemTable);
+}
+
+/**
+ This is the command help handler function pointer callback type. This
+ function is responsible for displaying help information for the associated
+ command.
+
+ @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+ @param[in] Language The pointer to the language string to use.
+
+ @return string Pool allocated help string, must be freed by caller
+**/
+CHAR16 *
+EFIAPI
+HttpCommandGetHelp (
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
+ IN CONST CHAR8 *Language
+ )
+{
+ return HiiGetString (
+ mHttpHiiHandle,
+ STRING_TOKEN (STR_GET_HELP_HTTP),
+ Language
+ );
+}
+
+EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL mHttpDynamicCommand = {
+ HTTP_APP_NAME,
+ HttpCommandHandler,
+ HttpCommandGetHelp
+};
+
+/**
+ Entry point of Http Dynamic Command.
+
+ Produce the DynamicCommand protocol to handle "http" command.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS Http command is executed sucessfully.
+ @retval EFI_ABORTED HII package was failed to initialize.
+ @retval others Other errors when executing http command.
+**/
+EFI_STATUS
+EFIAPI
+HttpCommandInitialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ mHttpHiiHandle = InitializeHiiPackage (ImageHandle);
+ if (mHttpHiiHandle == NULL) {
+ return EFI_ABORTED;
+ }
+
+ Status = gBS->InstallProtocolInterface (
+ &ImageHandle,
+ &gEfiShellDynamicCommandProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mHttpDynamicCommand
+ );
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+}
+
+/**
+ Http driver unload handler.
+
+ @param ImageHandle The image handle of the process.
+
+ @retval EFI_SUCCESS The image is unloaded.
+ @retval Others Failed to unload the image.
+**/
+EFI_STATUS
+EFIAPI
+HttpUnload (
+ IN EFI_HANDLE ImageHandle
+)
+{
+ EFI_STATUS Status;
+
+ Status = gBS->UninstallProtocolInterface (
+ ImageHandle,
+ &gEfiShellDynamicCommandProtocolGuid,
+ &mHttpDynamicCommand
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ HiiRemovePackages (mHttpHiiHandle);
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
new file mode 100644
index 00000000000..2621bcb78dc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf
@@ -0,0 +1,62 @@
+## @file
+# Provides Shell 'http' dynamic command.
+#
+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved. <BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2020, Broadcom. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = httpDynamicCommand
+ FILE_GUID = 19618BCE-55AE-09C6-37E9-4CE04084C7A1
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = HttpCommandInitialize
+ UNLOAD_IMAGE = HttpUnload
+#
+# This flag specifies whether HII resource section is generated into PE image.
+#
+ UEFI_HII_RESOURCE_SECTION = TRUE
+
+[Sources.common]
+ Http.c
+ HttpDynamicCommand.c
+ Http.h
+ Http.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ HiiLib
+ HttpLib
+ MemoryAllocationLib
+ NetLib
+ ShellLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiHiiServicesLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Protocols]
+ gEfiHiiPackageListProtocolGuid ## CONSUMES
+ gEfiHttpProtocolGuid ## CONSUMES
+ gEfiHttpServiceBindingProtocolGuid ## CONSUMES
+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
+ gEfiShellDynamicCommandProtocolGuid ## PRODUCES
+
+[DEPEX]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Guid/ShellLibHiiGuid.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Guid/ShellLibHiiGuid.h
index 249de12b332..eacd614de57 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Guid/ShellLibHiiGuid.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -59,6 +59,10 @@
0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4 } \
}
+#define SHELL_HTTP_HII_GUID \
+ { \
+ 0x390f84b3, 0x221c, 0x4d9e, { 0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e, 0x0a, 0x7e } \
+ }
#define SHELL_BCFG_HII_GUID \
{ \
@@ -75,6 +79,7 @@ extern EFI_GUID gShellLevel3HiiGuid;
extern EFI_GUID gShellNetwork1HiiGuid;
extern EFI_GUID gShellNetwork2HiiGuid;
extern EFI_GUID gShellTftpHiiGuid;
+extern EFI_GUID gShellHttpHiiGuid;
extern EFI_GUID gShellBcfgHiiGuid;
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/AcpiViewCommandLib.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/AcpiViewCommandLib.h
new file mode 100644
index 00000000000..0d2468e9dc1
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/AcpiViewCommandLib.h
@@ -0,0 +1,46 @@
+/** @file
+ Library providing 'acpiview' functionality to display and
+ validate installed ACPI tables.
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef ACPI_VIEW_COMMAND_LIB_H_
+#define ACPI_VIEW_COMMAND_LIB_H_
+
+/**
+ Dump a buffer to a file. Print error message if a file cannot be created.
+
+ @param[in] FileName The filename that shall be created to contain the buffer.
+ @param[in] Buffer Pointer to buffer that shall be dumped.
+ @param[in] BufferSize The size of buffer to be dumped in bytes.
+
+ @return The number of bytes that were written
+**/
+UINTN
+EFIAPI
+ShellDumpBufferToFile (
+ IN CONST CHAR16* FileNameBuffer,
+ IN CONST VOID* Buffer,
+ IN CONST UINTN BufferSize
+ );
+
+/**
+ Display and validate ACPI tables.
+
+ @param[in] ImageHandle Handle to the Image (NULL if internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if internal).
+
+ @retval SHELL_INVALID_PARAMETER The command line invocation could not be parsed.
+ @retval SHELL_NOT_FOUND The command failed.
+ @retval SHELL_SUCCESS The command was successful.
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAcpiView (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif // UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellCommandLib.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellCommandLib.h
index d26e22fedbc..61f7317b059 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellCommandLib.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellCommandLib.h
@@ -714,4 +714,85 @@ CatSDumpHex (
IN UINTN DataSize,
IN VOID *UserData
);
+
+//
+// Determines the ordering operation for ShellSortFileList().
+//
+typedef enum {
+ //
+ // Sort the EFI_SHELL_FILE_INFO objects by the FileName field, in increasing
+ // order, using gUnicodeCollation->StriColl().
+ //
+ ShellSortFileListByFileName,
+ //
+ // Sort the EFI_SHELL_FILE_INFO objects by the FullName field, in increasing
+ // order, using gUnicodeCollation->StriColl().
+ //
+ ShellSortFileListByFullName,
+ ShellSortFileListMax
+} SHELL_SORT_FILE_LIST;
+
+/**
+ Sort an EFI_SHELL_FILE_INFO list, optionally moving duplicates to a separate
+ list.
+
+ @param[in,out] FileList The list of EFI_SHELL_FILE_INFO objects to sort.
+
+ If FileList is NULL on input, then FileList is
+ considered an empty, hence already sorted, list.
+
+ Otherwise, if (*FileList) is NULL on input, then
+ EFI_INVALID_PARAMETER is returned.
+
+ Otherwise, the caller is responsible for having
+ initialized (*FileList)->Link with
+ InitializeListHead(). No other fields in the
+ (**FileList) head element are accessed by this
+ function.
+
+ On output, (*FileList) is sorted according to Order.
+ If Duplicates is NULL on input, then duplicate
+ elements are preserved, sorted stably, on
+ (*FileList). If Duplicates is not NULL on input,
+ then duplicates are moved (stably sorted) to the
+ new, dynamically allocated (*Duplicates) list.
+
+ @param[out] Duplicates If Duplicates is NULL on input, (*FileList) will be
+ a monotonically ordered list on output, with
+ duplicates stably sorted.
+
+ If Duplicates is not NULL on input, (*FileList) will
+ be a strictly monotonically oredered list on output,
+ with duplicates separated (stably sorted) to
+ (*Duplicates). All fields except Link will be
+ zero-initialized in the (**Duplicates) head element.
+ If no duplicates exist, then (*Duplicates) is set to
+ NULL on output.
+
+ @param[in] Order Determines the comparison operation between
+ EFI_SHELL_FILE_INFO objects.
+
+ @retval EFI_INVALID_PARAMETER (UINTN)Order is greater than or equal to
+ (UINTN)ShellSortFileListMax. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_INVALID_PARAMETER (*FileList) was NULL on input. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_SUCCESS Sorting successful, including the case when
+ FileList is NULL on input.
+**/
+EFI_STATUS
+EFIAPI
+ShellSortFileList (
+ IN OUT EFI_SHELL_FILE_INFO **FileList,
+ OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL,
+ IN SHELL_SORT_FILE_LIST Order
+ );
#endif //_SHELL_COMMAND_LIB_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellLib.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellLib.h
index 8e2e68d0593..94e4994d8ce 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellLib.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Include/Library/ShellLib.h
@@ -1034,7 +1034,7 @@ ShellIsFileInPath(
@param[in] String String representation of a number.
@return The unsigned integer result of the conversion.
- @retval (UINTN)(-1) An error occured.
+ @retval (UINTN)(-1) An error occurred.
**/
UINTN
EFIAPI
@@ -1051,7 +1051,7 @@ ShellStrToUintn(
@param[in] String String representation of a number.
@return The unsigned integer result of the conversion.
- @retval (UINTN)(-1) An error occured.
+ @retval (UINTN)(-1) An error occurred.
**/
UINTN
EFIAPI
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
index 6f518bb2cd3..239309543b1 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
@@ -3,7 +3,7 @@
Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
- (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2015-2021 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -2251,6 +2251,12 @@ STATIC CONST GUID_INFO_BLOCK mGuidStringList[] = {
{STRING_TOKEN(STR_HII_POPUP), &gEfiHiiPopupProtocolGuid, NULL},
//
+// UEFI 2.8
+//
+ {STRING_TOKEN(STR_REST_EX), &gEfiRestExProtocolGuid, NULL},
+ {STRING_TOKEN(STR_REDFISH_DISCOVER), &gEfiRedfishDiscoverProtocolGuid, NULL},
+
+//
// PI Spec ones
//
{STRING_TOKEN(STR_IDE_CONT_INIT), &gEfiIdeControllerInitProtocolGuid, NULL},
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
index fec3cc8ceb5..868e64840a0 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
@@ -2,7 +2,7 @@
# Provides interface to advanced shell functionality for parsing both handle and protocol database.
# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
# (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
-# (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+# (C) Copyright 2015-2021 Hewlett Packard Enterprise Development LP<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -269,6 +269,8 @@
gEfiHttpProtocolGuid ## UNDEFINED
gEfiHttpUtilitiesProtocolGuid ## UNDEFINED
gEfiRestProtocolGuid ## UNDEFINED
+ gEfiRestExProtocolGuid ## UNDEFINED
+ gEfiRedfishDiscoverProtocolGuid ## UNDEFINED
gEfiMmEndOfDxeProtocolGuid ## UNDEFINED
gEfiMmIoTrapDispatchProtocolGuid ## UNDEFINED
gEfiMmPowerButtonDispatchProtocolGuid ## UNDEFINED
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
index 9c8028d0d5c..aa3396cea94 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
@@ -2,7 +2,7 @@
//
// Copyright (c) 2010 - 2017, Intel Corporation. All rights reserved. <BR>
// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
-// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+// (C) Copyright 2015-2021 Hewlett Packard Enterprise Development LP<BR>
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Module Name:
@@ -308,6 +308,8 @@
#string STR_NET_HTTP #language en-US "Http"
#string STR_NET_HTTP_U #language en-US "HttpUtilities"
#string STR_REST #language en-US "Rest"
+#string STR_REST_EX #language en-US "RestEx"
+#string STR_REDFISH_DISCOVER #language en-US "RedfishDiscover"
#string STR_MM_EOD #language en-US "MmEndOfDxe"
#string STR_MM_ITD #language en-US "MmIoTrapDispatch"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
index 8f1a1c36983..f3c8e9d40ed 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
@@ -1,7 +1,7 @@
/** @file
ACPI parser
- Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -10,6 +10,7 @@
#include <Library/UefiBootServicesTableLib.h>
#include "AcpiParser.h"
#include "AcpiView.h"
+#include "AcpiViewConfig.h"
STATIC UINT32 gIndent;
STATIC UINT32 mTableErrorCount;
@@ -595,13 +596,12 @@ ParseAcpi (
Parser[Index].Length
);
} // switch
-
- // Validating only makes sense if we are tracing
- // the parsed table entries, to report by table name.
- if (GetConsistencyChecking () &&
- (Parser[Index].FieldValidator != NULL)) {
- Parser[Index].FieldValidator (Ptr, Parser[Index].Context);
- }
+ }
+ // Validating only makes sense if we are tracing
+ // the parsed table entries, to report by table name.
+ if (GetConsistencyChecking () &&
+ (Parser[Index].FieldValidator != NULL)) {
+ Parser[Index].FieldValidator (Ptr, Parser[Index].Context);
}
Print (L"\n");
} // if (Trace)
@@ -628,7 +628,7 @@ STATIC CONST ACPI_PARSER GasParser[] = {
{L"Address Space ID", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
{L"Register Bit Width", 1, 1, L"0x%x", NULL, NULL, NULL, NULL},
{L"Register Bit Offset", 1, 2, L"0x%x", NULL, NULL, NULL, NULL},
- {L"Address Size", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Access Size", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},
{L"Address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL}
};
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
index 295321ff33c..19d866d0d15 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.h
@@ -1,7 +1,7 @@
/** @file
Header file for ACPI parser
- Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
+ Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -462,6 +462,27 @@ ParseAcpiHeader (
);
/**
+ This function parses the ACPI AEST table.
+ When trace is enabled this function parses the AEST table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiAest (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ );
+
+/**
This function parses the ACPI BGRT table.
When trace is enabled this function parses the BGRT table and
traces the ACPI table fields.
@@ -592,6 +613,32 @@ ParseAcpiGtdt (
);
/**
+ This function parses the ACPI HMAT table.
+ When trace is enabled this function parses the HMAT table and
+ traces the ACPI table fields.
+
+ This function parses the following HMAT structures:
+ - Memory Proximity Domain Attributes Structure (Type 0)
+ - System Locality Latency and Bandwidth Info Structure (Type 1)
+ - Memory Side Cache Info structure (Type 2)
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiHmat (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ );
+
+/**
This function parses the ACPI IORT table.
When trace is enabled this function parses the IORT table and
traces the ACPI fields.
@@ -671,6 +718,28 @@ ParseAcpiMcfg (
);
/**
+ This function parses the ACPI PCCT table including its sub-structures
+ of type 0 through 4.
+ When trace is enabled this function parses the PCCT table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiPcct (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ );
+
+/**
This function parses the ACPI PPTT table.
When trace is enabled this function parses the PPTT table and
traces the ACPI table fields.
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c
index 93ba267845d..d081eb86749 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.c
@@ -17,6 +17,7 @@
#include "AcpiParser.h"
#include "AcpiTableParser.h"
#include "AcpiView.h"
+#include "AcpiViewConfig.h"
#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
#include "Arm/SbbrValidator.h"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h
index 41f67be2752..acf93f9f47c 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiTableParser.h
@@ -1,7 +1,7 @@
/** @file
Header file for ACPI table parser
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -11,7 +11,7 @@
/**
The maximum number of ACPI table parsers.
*/
-#define MAX_ACPI_TABLE_PARSERS 16
+#define MAX_ACPI_TABLE_PARSERS 32
/** An invalid/NULL signature value.
*/
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c
index 9cc533791e9..9d39d52e4bf 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.c
@@ -17,177 +17,18 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/AcpiViewCommandLib.h>
#include "AcpiParser.h"
#include "AcpiTableParser.h"
#include "AcpiView.h"
-#include "UefiShellAcpiViewCommandLib.h"
+#include "AcpiViewConfig.h"
#if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64)
#include "Arm/SbbrValidator.h"
#endif
-EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL;
-
-// Report variables
-STATIC UINT32 mSelectedAcpiTable;
-STATIC CONST CHAR16* mSelectedAcpiTableName;
-STATIC BOOLEAN mSelectedAcpiTableFound;
-STATIC EREPORT_OPTION mReportType;
STATIC UINT32 mTableCount;
STATIC UINT32 mBinTableCount;
-STATIC BOOLEAN mConsistencyCheck;
-STATIC BOOLEAN mColourHighlighting;
-STATIC BOOLEAN mMandatoryTableValidate;
-STATIC UINTN mMandatoryTableSpec;
-
-/**
- An array of acpiview command line parameters.
-**/
-STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
- {L"-q", TypeFlag},
- {L"-d", TypeFlag},
- {L"-h", TypeFlag},
- {L"-l", TypeFlag},
- {L"-s", TypeValue},
- {L"-r", TypeValue},
- {NULL, TypeMax}
-};
-
-/**
- This function returns the colour highlighting status.
-
- @retval TRUE if colour highlighting is enabled.
-**/
-BOOLEAN
-GetColourHighlighting (
- VOID
- )
-{
- return mColourHighlighting;
-}
-
-/**
- This function sets the colour highlighting status.
-
- @param Highlight The Highlight status.
-
-**/
-VOID
-SetColourHighlighting (
- BOOLEAN Highlight
- )
-{
- mColourHighlighting = Highlight;
-}
-
-/**
- This function returns the consistency checking status.
-
- @retval TRUE if consistency checking is enabled.
-**/
-BOOLEAN
-GetConsistencyChecking (
- VOID
- )
-{
- return mConsistencyCheck;
-}
-
-/**
- This function sets the consistency checking status.
-
- @param ConsistencyChecking The consistency checking status.
-
-**/
-VOID
-SetConsistencyChecking (
- BOOLEAN ConsistencyChecking
- )
-{
- mConsistencyCheck = ConsistencyChecking;
-}
-
-/**
- This function returns the ACPI table requirements validation flag.
-
- @retval TRUE if check for mandatory table presence should be performed.
-**/
-BOOLEAN
-GetMandatoryTableValidate (
- VOID
- )
-{
- return mMandatoryTableValidate;
-}
-
-/**
- This function sets the ACPI table requirements validation flag.
-
- @param Validate Enable/Disable ACPI table requirements validation.
-**/
-VOID
-SetMandatoryTableValidate (
- BOOLEAN Validate
- )
-{
- mMandatoryTableValidate = Validate;
-}
-
-/**
- This function returns the identifier of specification to validate ACPI table
- requirements against.
-
- @return ID of specification listing mandatory tables.
-**/
-UINTN
-GetMandatoryTableSpec (
- VOID
- )
-{
- return mMandatoryTableSpec;
-}
-
-/**
- This function sets the identifier of specification to validate ACPI table
- requirements against.
-
- @param Spec ID of specification listing mandatory tables.
-**/
-VOID
-SetMandatoryTableSpec (
- UINTN Spec
- )
-{
- mMandatoryTableSpec = Spec;
-}
-
-/**
- This function returns the report options.
-
- @retval Returns the report option.
-**/
-STATIC
-EREPORT_OPTION
-GetReportOption (
- VOID
- )
-{
- return mReportType;
-}
-
-/**
- This function returns the selected ACPI table.
-
- @retval Returns signature of the selected ACPI table.
-**/
-STATIC
-UINT32
-GetSelectedAcpiTable (
- VOID
- )
-{
- return mSelectedAcpiTable;
-}
/**
This function dumps the ACPI table to a file.
@@ -205,55 +46,23 @@ DumpAcpiTableToFile (
IN CONST UINTN Length
)
{
- EFI_STATUS Status;
- CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
- SHELL_FILE_HANDLE DumpFileHandle;
- UINTN TransferBytes;
+ CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
+ UINTN TransferBytes;
+ SELECTED_ACPI_TABLE *SelectedTable;
- DumpFileHandle = NULL;
- TransferBytes = Length;
+ GetSelectedAcpiTable (&SelectedTable);
UnicodeSPrint (
FileNameBuffer,
sizeof (FileNameBuffer),
L".\\%s%04d.bin",
- mSelectedAcpiTableName,
+ SelectedTable->Name,
mBinTableCount++
);
- Status = ShellOpenFileByName (
- FileNameBuffer,
- &DumpFileHandle,
- EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
- 0
- );
- if (EFI_ERROR (Status)) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_READONLY_MEDIA),
- gShellAcpiViewHiiHandle,
- L"acpiview"
- );
- return FALSE;
- }
-
Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer);
- Status = ShellWriteFile (
- DumpFileHandle,
- &TransferBytes,
- (VOID*)Ptr
- );
- if (EFI_ERROR (Status)) {
- Print (L"ERROR: Failed to dump table to binary file.\n");
- TransferBytes = 0;
- } else {
- Print (L"DONE.\n");
- }
-
- ShellCloseFile (&DumpFileHandle);
+ TransferBytes = ShellDumpBufferToFile (FileNameBuffer, Ptr, Length);
return (Length == TransferBytes);
}
@@ -273,10 +82,11 @@ ProcessTableReportOptions (
IN CONST UINT32 Length
)
{
- UINTN OriginalAttribute;
- UINT8* SignaturePtr;
- BOOLEAN Log;
- BOOLEAN HighLight;
+ UINTN OriginalAttribute;
+ UINT8 *SignaturePtr;
+ BOOLEAN Log;
+ BOOLEAN HighLight;
+ SELECTED_ACPI_TABLE *SelectedTable;
//
// set local variables to suppress incorrect compiler/analyzer warnings
@@ -285,15 +95,16 @@ ProcessTableReportOptions (
SignaturePtr = (UINT8*)(UINTN)&Signature;
Log = FALSE;
HighLight = GetColourHighlighting ();
+ GetSelectedAcpiTable (&SelectedTable);
switch (GetReportOption ()) {
case ReportAll:
Log = TRUE;
break;
case ReportSelected:
- if (Signature == GetSelectedAcpiTable ()) {
+ if (Signature == SelectedTable->Type) {
Log = TRUE;
- mSelectedAcpiTableFound = TRUE;
+ SelectedTable->Found = TRUE;
}
break;
case ReportTableList:
@@ -321,8 +132,8 @@ ProcessTableReportOptions (
);
break;
case ReportDumpBinFile:
- if (Signature == GetSelectedAcpiTable ()) {
- mSelectedAcpiTableFound = TRUE;
+ if (Signature == SelectedTable->Type) {
+ SelectedTable->Found = TRUE;
DumpAcpiTableToFile (TablePtr, Length);
}
break;
@@ -356,37 +167,7 @@ ProcessTableReportOptions (
return Log;
}
-/**
- This function converts a string to ACPI table signature.
- @param [in] Str Pointer to the string to be converted to the
- ACPI table signature.
-
- @retval The ACPI table signature.
-**/
-STATIC
-UINT32
-ConvertStrToAcpiSignature (
- IN CONST CHAR16* Str
- )
-{
- UINT8 Index;
- CHAR8 Ptr[4];
-
- ZeroMem (Ptr, sizeof (Ptr));
- Index = 0;
-
- // Convert to Upper case and convert to ASCII
- while ((Index < 4) && (Str[Index] != 0)) {
- if (Str[Index] >= L'a' && Str[Index] <= L'z') {
- Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A'));
- } else {
- Ptr[Index] = (CHAR8)Str[Index];
- }
- Index++;
- }
- return *(UINT32*)Ptr;
-}
/**
This function iterates the configuration table entries in the
@@ -398,7 +179,6 @@ ConvertStrToAcpiSignature (
Returns EFI_UNSUPPORTED if the RSDP version is less than 2.
Returns EFI_SUCCESS if successful.
**/
-STATIC
EFI_STATUS
EFIAPI
AcpiView (
@@ -417,6 +197,7 @@ AcpiView (
UINT8 RsdpRevision;
PARSE_ACPI_TABLE_PROC RsdpParserProc;
BOOLEAN Trace;
+ SELECTED_ACPI_TABLE *SelectedTable;
//
// set local variables to suppress incorrect compiler/analyzer warnings
@@ -424,6 +205,17 @@ AcpiView (
EfiConfigurationTable = NULL;
OriginalAttribute = 0;
+ // Reset Table counts
+ mTableCount = 0;
+ mBinTableCount = 0;
+
+ // Reset The error/warning counters
+ ResetErrorCount ();
+ ResetWarningCount ();
+
+ // Retrieve the user selection of ACPI table to process
+ GetSelectedAcpiTable (&SelectedTable);
+
// Search the table for an entry that matches the ACPI Table Guid
FoundAcpiTable = FALSE;
for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) {
@@ -492,7 +284,7 @@ AcpiView (
if (ReportTableList != ReportOption) {
if (((ReportSelected == ReportOption) ||
(ReportDumpBinFile == ReportOption)) &&
- (!mSelectedAcpiTableFound)) {
+ (!SelectedTable->Found)) {
Print (L"\nRequested ACPI Table not found.\n");
} else if (GetConsistencyChecking () &&
(ReportDumpBinFile != ReportOption)) {
@@ -530,207 +322,3 @@ AcpiView (
}
return EFI_SUCCESS;
}
-
-/**
- Function for 'acpiview' command.
-
- @param[in] ImageHandle Handle to the Image (NULL if Internal).
- @param[in] SystemTable Pointer to the System Table (NULL if Internal).
-**/
-SHELL_STATUS
-EFIAPI
-ShellCommandRunAcpiView (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE* SystemTable
- )
-{
- EFI_STATUS Status;
- SHELL_STATUS ShellStatus;
- LIST_ENTRY* Package;
- CHAR16* ProblemParam;
- SHELL_FILE_HANDLE TmpDumpFileHandle;
- CONST CHAR16* MandatoryTableSpecStr;
-
- // Set Defaults
- mReportType = ReportAll;
- mTableCount = 0;
- mBinTableCount = 0;
- mSelectedAcpiTable = 0;
- mSelectedAcpiTableName = NULL;
- mSelectedAcpiTableFound = FALSE;
- mConsistencyCheck = TRUE;
- mMandatoryTableValidate = FALSE;
- mMandatoryTableSpec = 0;
-
- ShellStatus = SHELL_SUCCESS;
- Package = NULL;
- TmpDumpFileHandle = NULL;
-
- // Reset The error/warning counters
- ResetErrorCount ();
- ResetWarningCount ();
-
- Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_PROBLEM),
- gShellAcpiViewHiiHandle,
- L"acpiview",
- ProblemParam
- );
- FreePool (ProblemParam);
- } else {
- Print (L"acpiview: Error processing input parameter(s)\n");
- }
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- if (ShellCommandLineGetCount (Package) > 1) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_TOO_MANY),
- gShellAcpiViewHiiHandle,
- L"acpiview"
- );
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (ShellCommandLineGetFlag (Package, L"-?")) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GET_HELP_ACPIVIEW),
- gShellAcpiViewHiiHandle,
- L"acpiview"
- );
- } else if (ShellCommandLineGetFlag (Package, L"-s") &&
- ShellCommandLineGetValue (Package, L"-s") == NULL) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_NO_VALUE),
- gShellAcpiViewHiiHandle,
- L"acpiview",
- L"-s"
- );
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (ShellCommandLineGetFlag (Package, L"-r") &&
- ShellCommandLineGetValue (Package, L"-r") == NULL) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_NO_VALUE),
- gShellAcpiViewHiiHandle,
- L"acpiview",
- L"-r"
- );
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if ((ShellCommandLineGetFlag (Package, L"-s") &&
- ShellCommandLineGetFlag (Package, L"-l"))) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_TOO_MANY),
- gShellAcpiViewHiiHandle,
- L"acpiview"
- );
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else if (ShellCommandLineGetFlag (Package, L"-d") &&
- !ShellCommandLineGetFlag (Package, L"-s")) {
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_MISSING_OPTION),
- gShellAcpiViewHiiHandle,
- L"acpiview",
- L"-s",
- L"-d"
- );
- ShellStatus = SHELL_INVALID_PARAMETER;
- } else {
- // Turn on colour highlighting if requested
- SetColourHighlighting (ShellCommandLineGetFlag (Package, L"-h"));
-
- // Surpress consistency checking if requested
- SetConsistencyChecking (!ShellCommandLineGetFlag (Package, L"-q"));
-
- // Evaluate the parameters for mandatory ACPI table presence checks
- SetMandatoryTableValidate (ShellCommandLineGetFlag (Package, L"-r"));
- MandatoryTableSpecStr = ShellCommandLineGetValue (Package, L"-r");
-
- if (MandatoryTableSpecStr != NULL) {
- SetMandatoryTableSpec (ShellHexStrToUintn (MandatoryTableSpecStr));
- }
-
- if (ShellCommandLineGetFlag (Package, L"-l")) {
- mReportType = ReportTableList;
- } else {
- mSelectedAcpiTableName = ShellCommandLineGetValue (Package, L"-s");
- if (mSelectedAcpiTableName != NULL) {
- mSelectedAcpiTable = (UINT32)ConvertStrToAcpiSignature (
- mSelectedAcpiTableName
- );
- mReportType = ReportSelected;
-
- if (ShellCommandLineGetFlag (Package, L"-d")) {
- // Create a temporary file to check if the media is writable.
- CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
- mReportType = ReportDumpBinFile;
-
- UnicodeSPrint (
- FileNameBuffer,
- sizeof (FileNameBuffer),
- L".\\%s%04d.tmp",
- mSelectedAcpiTableName,
- mBinTableCount
- );
-
- Status = ShellOpenFileByName (
- FileNameBuffer,
- &TmpDumpFileHandle,
- EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
- EFI_FILE_MODE_CREATE,
- 0
- );
-
- if (EFI_ERROR (Status)) {
- ShellStatus = SHELL_INVALID_PARAMETER;
- TmpDumpFileHandle = NULL;
- ShellPrintHiiEx (
- -1,
- -1,
- NULL,
- STRING_TOKEN (STR_GEN_READONLY_MEDIA),
- gShellAcpiViewHiiHandle,
- L"acpiview"
- );
- goto Done;
- }
- // Delete Temporary file.
- ShellDeleteFile (&TmpDumpFileHandle);
- } // -d
- } // -s
- }
-
- // Parse ACPI Table information
- Status = AcpiView (SystemTable);
- if (EFI_ERROR (Status)) {
- ShellStatus = SHELL_NOT_FOUND;
- }
- }
- }
-
-Done:
- if (Package != NULL) {
- ShellCommandLineFreeVarList (Package);
- }
- return ShellStatus;
-}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h
index 2263efca524..7905f179186 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiView.h
@@ -24,17 +24,6 @@
#define RSDP_LENGTH_OFFSET 20
/**
- The EREPORT_OPTION enum describes ACPI table Reporting options.
-**/
-typedef enum ReportOption {
- ReportAll, ///< Report All tables.
- ReportSelected, ///< Report Selected table.
- ReportTableList, ///< Report List of tables.
- ReportDumpBinFile, ///< Dump selected table to a file.
- ReportMax,
-} EREPORT_OPTION;
-
-/**
This function resets the ACPI table error counter to Zero.
**/
VOID
@@ -71,95 +60,11 @@ GetWarningCount (
);
/**
- This function returns the colour highlighting status.
-
- @retval TRUE if colour highlighting is enabled.
-**/
-BOOLEAN
-GetColourHighlighting (
- VOID
- );
-
-/**
- This function sets the colour highlighting status.
-
- @param Highlight The Highlight status.
-
-**/
-VOID
-SetColourHighlighting (
- BOOLEAN Highlight
- );
-
-/**
- This function returns the consistency checking status.
-
- @retval TRUE if consistency checking is enabled.
-**/
-BOOLEAN
-GetConsistencyChecking (
- VOID
- );
-
-/**
- This function sets the consistency checking status.
-
- @param ConsistencyChecking The consistency checking status.
-
-**/
-VOID
-SetConsistencyChecking (
- BOOLEAN ConsistencyChecking
- );
-
-/**
- This function returns the ACPI table requirements validation flag.
-
- @retval TRUE if check for mandatory table presence should be performed.
-**/
-BOOLEAN
-GetMandatoryTableValidate (
- VOID
- );
-
-/**
- This function sets the ACPI table requirements validation flag.
-
- @param Validate Enable/Disable ACPI table requirements validation.
-**/
-VOID
-SetMandatoryTableValidate (
- BOOLEAN Validate
- );
-
-/**
- This function returns the identifier of specification to validate ACPI table
- requirements against.
-
- @return ID of specification listing mandatory tables.
-**/
-UINTN
-GetMandatoryTableSpec (
- VOID
- );
-
-/**
- This function sets the identifier of specification to validate ACPI table
- requirements against.
-
- @param Spec ID of specification listing mandatory tables.
-**/
-VOID
-SetMandatoryTableSpec (
- UINTN Spec
- );
-
-/**
This function processes the table reporting options for the ACPI table.
@param [in] Signature The ACPI table Signature.
@param [in] TablePtr Pointer to the ACPI table data.
- @param [in] Length The length fo the ACPI table.
+ @param [in] Length The length of the ACPI table.
@retval Returns TRUE if the ACPI table should be traced.
**/
@@ -170,4 +75,20 @@ ProcessTableReportOptions (
IN CONST UINT32 Length
);
+/**
+ This function iterates the configuration table entries in the
+ system table, retrieves the RSDP pointer and starts parsing the ACPI tables.
+
+ @param [in] SystemTable Pointer to the EFI system table.
+
+ @retval EFI_NOT_FOUND The RSDP pointer was not found.
+ @retval EFI_UNSUPPORTED The RSDP version was less than 2.
+ @retval EFI_SUCCESS The command was successful.
+**/
+EFI_STATUS
+EFIAPI
+AcpiView (
+ IN EFI_SYSTEM_TABLE* SystemTable
+ );
+
#endif // ACPIVIEW_H_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.c
new file mode 100644
index 00000000000..cf02dc61fd8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.c
@@ -0,0 +1,246 @@
+/** @file
+ State and accessors for 'acpiview' configuration.
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+
+#include "AcpiViewConfig.h"
+
+// Report variables
+STATIC BOOLEAN mConsistencyCheck;
+STATIC BOOLEAN mColourHighlighting;
+STATIC EREPORT_OPTION mReportType;
+STATIC BOOLEAN mMandatoryTableValidate;
+STATIC UINTN mMandatoryTableSpec;
+
+// User selection of which ACPI table should be checked
+SELECTED_ACPI_TABLE mSelectedAcpiTable;
+
+/**
+ Reset the AcpiView user configuration to defaults
+**/
+VOID
+EFIAPI
+AcpiConfigSetDefaults (
+ VOID
+ )
+{
+ mReportType = ReportAll;
+ mSelectedAcpiTable.Type = 0;
+ mSelectedAcpiTable.Name = NULL;
+ mSelectedAcpiTable.Found = FALSE;
+ mConsistencyCheck = TRUE;
+ mMandatoryTableValidate = FALSE;
+ mMandatoryTableSpec = 0;
+}
+
+/**
+ This function converts a string to ACPI table signature.
+
+ @param [in] Str Pointer to the string to be converted to the
+ ACPI table signature.
+
+ @retval The ACPI table signature.
+**/
+STATIC
+UINT32
+ConvertStrToAcpiSignature (
+ IN CONST CHAR16 *Str
+ )
+{
+ UINT8 Index;
+ CHAR8 Ptr[4];
+
+ ZeroMem (Ptr, sizeof (Ptr));
+ Index = 0;
+
+ // Convert to Upper case and convert to ASCII
+ while ((Index < 4) && (Str[Index] != 0)) {
+ if (Str[Index] >= L'a' && Str[Index] <= L'z') {
+ Ptr[Index] = (CHAR8)(Str[Index] - (L'a' - L'A'));
+ } else {
+ Ptr[Index] = (CHAR8)Str[Index];
+ }
+ Index++;
+ }
+ return *(UINT32 *) Ptr;
+}
+
+/**
+ This function selects an ACPI table in current context.
+ The string name of the table is converted into UINT32
+ table signature.
+
+ @param [in] TableName The name of the ACPI table to select.
+**/
+VOID
+EFIAPI
+SelectAcpiTable (
+ IN CONST CHAR16 *TableName
+ )
+{
+ ASSERT (TableName != NULL);
+
+ mSelectedAcpiTable.Name = TableName;
+ mSelectedAcpiTable.Type = ConvertStrToAcpiSignature (mSelectedAcpiTable.Name);
+}
+
+/**
+ This function returns the selected ACPI table.
+
+ @param [out] SelectedAcpiTable Pointer that will contain the returned struct.
+**/
+VOID
+EFIAPI
+GetSelectedAcpiTable (
+ OUT SELECTED_ACPI_TABLE **SelectedAcpiTable
+ )
+{
+ *SelectedAcpiTable = &mSelectedAcpiTable;
+}
+
+/**
+ This function returns the colour highlighting status.
+
+ @retval TRUE Colour highlighting is enabled.
+**/
+BOOLEAN
+EFIAPI
+GetColourHighlighting (
+ VOID
+ )
+{
+ return mColourHighlighting;
+}
+
+/**
+ This function sets the colour highlighting status.
+
+ @param [in] Highlight The highlight status.
+**/
+VOID
+EFIAPI
+SetColourHighlighting (
+ BOOLEAN Highlight
+ )
+{
+ mColourHighlighting = Highlight;
+}
+
+/**
+ This function returns the consistency checking status.
+
+ @retval TRUE Consistency checking is enabled.
+**/
+BOOLEAN
+EFIAPI
+GetConsistencyChecking (
+ VOID
+ )
+{
+ return mConsistencyCheck;
+}
+
+/**
+ This function sets the consistency checking status.
+
+ @param [in] ConsistencyChecking The consistency checking status.
+**/
+VOID
+EFIAPI
+SetConsistencyChecking (
+ BOOLEAN ConsistencyChecking
+ )
+{
+ mConsistencyCheck = ConsistencyChecking;
+}
+
+/**
+ This function returns the report options.
+
+ @return The current report option.
+**/
+EREPORT_OPTION
+EFIAPI
+GetReportOption (
+ VOID
+ )
+{
+ return mReportType;
+}
+
+/**
+ This function sets the report options.
+
+ @param [in] ReportType The report option to set.
+**/
+VOID
+EFIAPI
+SetReportOption (
+ EREPORT_OPTION ReportType
+ )
+{
+ mReportType = ReportType;
+}
+
+/**
+ This function returns the ACPI table requirements validation flag.
+
+ @retval TRUE Check for mandatory table presence should be performed.
+**/
+BOOLEAN
+EFIAPI
+GetMandatoryTableValidate (
+ VOID
+ )
+{
+ return mMandatoryTableValidate;
+}
+
+/**
+ This function sets the ACPI table requirements validation flag.
+
+ @param [in] Validate Enable/Disable ACPI table requirements validation.
+**/
+VOID
+EFIAPI
+SetMandatoryTableValidate (
+ BOOLEAN Validate
+ )
+{
+ mMandatoryTableValidate = Validate;
+}
+
+/**
+ This function returns the identifier of specification to validate ACPI table
+ requirements against.
+
+ @return ID of specification listing mandatory tables.
+**/
+UINTN
+EFIAPI
+GetMandatoryTableSpec (
+ VOID
+ )
+{
+ return mMandatoryTableSpec;
+}
+
+/**
+ This function sets the identifier of specification to validate ACPI table
+ requirements against.
+
+ @param [in] Spec ID of specification listing mandatory tables.
+**/
+VOID
+EFIAPI
+SetMandatoryTableSpec (
+ UINTN Spec
+ )
+{
+ mMandatoryTableSpec = Spec;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.h
new file mode 100644
index 00000000000..d91738748d5
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiViewConfig.h
@@ -0,0 +1,177 @@
+/** @file
+ Header file for 'acpiview' configuration.
+
+ Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef ACPI_VIEW_CONFIG_H_
+#define ACPI_VIEW_CONFIG_H_
+
+/**
+ This function returns the colour highlighting status.
+
+ @retval TRUE Colour highlighting is enabled.
+**/
+BOOLEAN
+EFIAPI
+GetColourHighlighting (
+ VOID
+ );
+
+/**
+ This function sets the colour highlighting status.
+
+ @param [in] Highlight The highlight status.
+**/
+VOID
+EFIAPI
+SetColourHighlighting (
+ BOOLEAN Highlight
+ );
+
+/**
+ This function returns the consistency checking status.
+
+ @retval TRUE Consistency checking is enabled.
+**/
+BOOLEAN
+EFIAPI
+GetConsistencyChecking (
+ VOID
+ );
+
+/**
+ This function sets the consistency checking status.
+
+ @param [in] ConsistencyChecking The consistency checking status.
+**/
+VOID
+EFIAPI
+SetConsistencyChecking (
+ BOOLEAN ConsistencyChecking
+ );
+
+/**
+ This function returns the ACPI table requirements validation flag.
+
+ @retval TRUE Check for mandatory table presence should be performed.
+**/
+BOOLEAN
+EFIAPI
+GetMandatoryTableValidate (
+ VOID
+ );
+
+/**
+ This function sets the ACPI table requirements validation flag.
+
+ @param [in] Validate Enable/Disable ACPI table requirements validation.
+**/
+VOID
+EFIAPI
+SetMandatoryTableValidate (
+ BOOLEAN Validate
+ );
+
+/**
+ This function returns the identifier of specification to validate ACPI table
+ requirements against.
+
+ @return ID of specification listing mandatory tables.
+**/
+UINTN
+EFIAPI
+GetMandatoryTableSpec (
+ VOID
+ );
+
+/**
+ This function sets the identifier of specification to validate ACPI table
+ requirements against.
+
+ @param [in] Spec ID of specification listing mandatory tables.
+**/
+VOID
+EFIAPI
+SetMandatoryTableSpec (
+ UINTN Spec
+ );
+
+/**
+ The EREPORT_OPTION enum describes ACPI table Reporting options.
+**/
+typedef enum {
+ ReportAll, ///< Report All tables.
+ ReportSelected, ///< Report Selected table.
+ ReportTableList, ///< Report List of tables.
+ ReportDumpBinFile, ///< Dump selected table to a file.
+ ReportMax,
+} EREPORT_OPTION;
+
+/**
+ This function returns the report options.
+
+ @return The current report option.
+**/
+EREPORT_OPTION
+EFIAPI
+GetReportOption (
+ VOID
+ );
+
+/**
+ This function sets the report options.
+
+ @param [in] ReportType The report option to set.
+**/
+VOID
+EFIAPI
+SetReportOption (
+ EREPORT_OPTION ReportType
+ );
+
+/**
+ A structure holding the user selection detailing which
+ ACPI table is to be examined by the AcpiView code.
+**/
+typedef struct {
+ UINT32 Type; ///< 32bit signature of the selected ACPI table.
+ CONST CHAR16* Name; ///< User friendly name of the selected ACPI table.
+ BOOLEAN Found; ///< The selected table has been found in the system.
+} SELECTED_ACPI_TABLE;
+
+/**
+ This function returns the selected ACPI table.
+
+ @param [out] SelectedAcpiTable Pointer that will contain the returned struct.
+**/
+VOID
+EFIAPI
+GetSelectedAcpiTable (
+ OUT SELECTED_ACPI_TABLE** SelectedAcpiTable
+ );
+
+/**
+ This function selects an ACPI table in current context.
+ The string name of the table is converted into UINT32
+ table signature.
+
+ @param [in] TableName The name of the ACPI table to select.
+**/
+VOID
+EFIAPI
+SelectAcpiTable (
+ CONST CHAR16* TableName
+ );
+
+/**
+ Reset the AcpiView user configuration to defaults.
+**/
+VOID
+EFIAPI
+AcpiConfigSetDefaults (
+ VOID
+ );
+
+#endif // ACPI_VIEW_CONFIG_H_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c
new file mode 100644
index 00000000000..110412a258c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Aest/AestParser.c
@@ -0,0 +1,755 @@
+/** @file
+ AEST table parser
+
+ Copyright (c) 2020, Arm Limited.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document,
+ dated 28 September 2020.
+ (https://developer.arm.com/documentation/den0085/0101/)
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <IndustryStandard/ArmErrorSourceTable.h>
+#include "AcpiParser.h"
+#include "AcpiView.h"
+#include "AcpiViewConfig.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+STATIC UINT8* AestNodeType;
+STATIC UINT16* AestNodeLength;
+STATIC UINT32* NodeDataOffset;
+STATIC UINT32* NodeInterfaceOffset;
+STATIC UINT32* NodeInterruptArrayOffset;
+STATIC UINT32* NodeInterruptCount;
+STATIC UINT32* ProcessorId;
+STATIC UINT8* ProcessorFlags;
+STATIC UINT8* ProcessorResourceType;
+
+/**
+ Validate Processor Flags.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateProcessorFlags (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // If the global or shared node flag is set then the ACPI Processor ID
+ // field must be set to 0 and ignored.
+ if (((*Ptr & 0x3) != 0) && (*ProcessorId != 0)) {
+ IncrementErrorCount ();
+ Print (L"\nERROR: 'ACPI Processor ID' field must be set to 0 for global"
+ L" or shared nodes.");
+ }
+}
+
+/**
+ Validate GIC Interface Type.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateGicInterfaceType (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ UINT32 GicInterfaceType;
+
+ GicInterfaceType = *(UINT32*)Ptr;
+ if (GicInterfaceType > 3) {
+ IncrementErrorCount ();
+ Print (L"\nError: Invalid GIC Interface type %d", GicInterfaceType);
+ }
+}
+
+/**
+ Validate Interface Type.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInterfaceType (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*Ptr > 1) {
+ IncrementErrorCount ();
+ Print (L"\nError: Interface type should be 0 or 1");
+ }
+}
+
+/**
+ Validate Interrupt Type.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInterruptType (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*Ptr > 1) {
+ IncrementErrorCount ();
+ Print (L"\nError: Interrupt type should be 0 or 1");
+ }
+}
+
+/**
+ Validate interrupt flags.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateInterruptFlags (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if ((*Ptr & 0xfe) != 0) {
+ IncrementErrorCount ();
+ Print (L"\nError: Reserved Flag bits not set to 0");
+ }
+}
+
+/**
+ Dumps 16 bytes of data.
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+VOID
+EFIAPI
+DumpVendorSpecificData (
+ IN CONST CHAR16* Format OPTIONAL,
+ IN UINT8* Ptr
+ )
+{
+ Print (
+ L"%02X %02X %02X %02X %02X %02X %02X %02X\n",
+ Ptr[0],
+ Ptr[1],
+ Ptr[2],
+ Ptr[3],
+ Ptr[4],
+ Ptr[5],
+ Ptr[6],
+ Ptr[7]
+ );
+
+ Print (
+ L"%*a %02X %02X %02X %02X %02X %02X %02X %02X",
+ OUTPUT_FIELD_COLUMN_WIDTH,
+ "",
+ Ptr[8],
+ Ptr[9],
+ Ptr[10],
+ Ptr[11],
+ Ptr[12],
+ Ptr[13],
+ Ptr[14],
+ Ptr[15]
+ );
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI AEST Table.
+**/
+STATIC CONST ACPI_PARSER AestParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo)
+};
+
+/**
+ An ACPI_PARSER array describing the AEST Node Header.
+**/
+STATIC CONST ACPI_PARSER AestNodeHeaderParser[] = {
+ {L"Type", 1, 0, L"%d", NULL, (VOID**)&AestNodeType, NULL, NULL},
+ {L"Length", 2, 1, L"%d", NULL, (VOID**)&AestNodeLength, NULL, NULL},
+ {L"Reserved", 1, 3, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Node Data Offset", 4, 4, L"%d", NULL, (VOID**)&NodeDataOffset, NULL, NULL},
+ {L"Node Interface Offset", 4, 8, L"%d", NULL,
+ (VOID**)&NodeInterfaceOffset, NULL, NULL},
+ {L"Node Interrupt Array Offset", 4, 12, L"%d", NULL,
+ (VOID**)&NodeInterruptArrayOffset, NULL, NULL},
+ {L"Node Interrupt Count", 4, 16, L"%d", NULL,
+ (VOID**)&NodeInterruptCount, NULL, NULL},
+ {L"Timestamp Rate", 8, 20, L"%ld", NULL, NULL, NULL, NULL},
+ {L"Reserved1", 8, 28, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Error Injection Countdown Rate", 8, 36, L"%ld", NULL, NULL, NULL, NULL}
+ // Node specific data...
+ // Node interface...
+ // Node interrupt array...
+};
+
+/**
+ An ACPI_PARSER array describing the Processor error node specific data.
+**/
+STATIC CONST ACPI_PARSER AestProcessorStructure[] = {
+ {L"ACPI Processor ID", 4, 0, L"0x%x", NULL, (VOID**)&ProcessorId, NULL, NULL},
+ {L"Resource Type", 1, 4, L"%d", NULL, (VOID**)&ProcessorResourceType, NULL,
+ NULL},
+ {L"Reserved", 1, 5, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Flags", 1, 6, L"0x%x", NULL, (VOID**)&ProcessorFlags,
+ ValidateProcessorFlags, NULL},
+ {L"Revision", 1, 7, L"%d", NULL, NULL, NULL, NULL},
+ {L"Processor Affinity Level Indicator", 8, 8, L"0x%lx", NULL, NULL, NULL,
+ NULL},
+ // Resource specific data...
+};
+
+/**
+ An ACPI_PARSER array describing the processor cache resource substructure.
+**/
+STATIC CONST ACPI_PARSER AestProcessorCacheResourceSubstructure[] = {
+ {L"Cache reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the processor TLB resource substructure.
+**/
+STATIC CONST ACPI_PARSER AestProcessorTlbResourceSubstructure[] = {
+ {L"TLB reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 4, L"%d", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the processor generic resource substructure.
+**/
+STATIC CONST ACPI_PARSER AestProcessorGenericResourceSubstructure[] = {
+ {L"Vendor-defined data", 4, 0, L"%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the memory controller structure.
+**/
+STATIC CONST ACPI_PARSER AestMemoryControllerStructure[] = {
+ {L"Proximity Domain", 4, 0, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the SMMU structure.
+**/
+STATIC CONST ACPI_PARSER AestSmmuStructure[] = {
+ {L"IORT Node reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SubComponent reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the vendor-defined structure.
+**/
+STATIC CONST ACPI_PARSER AestVendorDefinedStructure[] = {
+ {L"Hardware ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Unique ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Vendor-specific data", 16, 8, NULL, DumpVendorSpecificData, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the GIC structure.
+**/
+STATIC CONST ACPI_PARSER AestGicStructure[] = {
+ {L"GIC Interface Type", 4, 0, L"0x%x", NULL, NULL, ValidateGicInterfaceType,
+ NULL},
+ {L"GIC Interface reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the node interface.
+**/
+STATIC CONST ACPI_PARSER AestNodeInterface[] = {
+ {L"Interface Type", 1, 0, L"%d", NULL, NULL, ValidateInterfaceType, NULL},
+ {L"Reserved", 3, 1, L"%x %x %x", Dump3Chars, NULL, NULL, NULL},
+ {L"Flags", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Start Error Record Index", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Number of Error Records", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Error Records Implemented", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Error Records Support", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Addressing mode", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the node interrupts.
+**/
+STATIC CONST ACPI_PARSER AestNodeInterrupt[] = {
+ {L"Interrupt Type", 1, 0, L"%d", NULL, NULL, ValidateInterruptType, NULL},
+ {L"Reserved", 2, 1, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Interrupt Flags", 1, 3, L"0x%x", NULL, NULL, ValidateInterruptFlags, NULL},
+ {L"Interrupt GSIV", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"ID", 1, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved1", 3, 9, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
+};
+
+/**
+ Parses the Processor Error Node structure along with its resource
+ specific data.
+
+ @param [in] Ptr Pointer to the start of the Processor node.
+ @param [in] Length Maximum length of the Processor node.
+**/
+STATIC
+VOID
+DumpProcessorNode (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ UINT32 Offset;
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "Processor",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestProcessorStructure)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((ProcessorId == NULL) ||
+ (ProcessorResourceType == NULL) ||
+ (ProcessorFlags == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient Processor Error Node length. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ switch (*ProcessorResourceType) {
+ case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_CACHE:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Cache Resource",
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (AestProcessorCacheResourceSubstructure)
+ );
+ break;
+ case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_TLB:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "TLB Resource",
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (AestProcessorTlbResourceSubstructure)
+ );
+ break;
+ case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_GENERIC:
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Generic Resource",
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (AestProcessorGenericResourceSubstructure)
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (L"ERROR: Invalid Processor Resource Type.");
+ return;
+ } // switch
+}
+
+/**
+ Parses the Memory Controller node.
+
+ @param [in] Ptr Pointer to the start of the Memory Controller node.
+ @param [in] Length Maximum length of the Memory Controller node.
+**/
+STATIC
+VOID
+DumpMemoryControllerNode (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Memory Controller",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestMemoryControllerStructure)
+ );
+}
+
+/**
+ Parses the SMMU node.
+
+ @param [in] Ptr Pointer to the start of the SMMU node.
+ @param [in] Length Maximum length of the SMMU node.
+**/
+STATIC
+VOID
+DumpSmmuNode (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "SMMU",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestSmmuStructure)
+ );
+}
+
+/**
+ Parses the Vendor-defined structure.
+
+ @param [in] Ptr Pointer to the start of the Vendor-defined node.
+ @param [in] Length Maximum length of the Vendor-defined node.
+**/
+STATIC
+VOID
+DumpVendorDefinedNode (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Vendor-defined",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestVendorDefinedStructure)
+ );
+}
+
+/**
+ Parses the GIC node.
+
+ @param [in] Ptr Pointer to the start of the GIC node.
+ @param [in] Length Maximum length of the GIC node.
+**/
+STATIC
+VOID
+DumpGicNode (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "GIC",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestGicStructure)
+ );
+}
+
+/**
+ Parses the Node Interface structure.
+
+ @param [in] Ptr Pointer to the start of the Node Interface Structure.
+ @param [in] Length Maximum length of the Node Interface Structure.
+**/
+STATIC
+VOID
+DumpNodeInterface (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Node Interface",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestNodeInterface)
+ );
+}
+
+/**
+ Parses the Node Interrupts Structure.
+
+ @param [in] Ptr Pointer to the start of the Node Interrupt array.
+ @param [in] Length Maximum length of the Node Interrupt array.
+ @param [in] InterruptCount Number if interrupts in the Node Interrupts array.
+**/
+STATIC
+VOID
+DumpNodeInterrupts (
+ IN UINT8* Ptr,
+ IN UINT32 Length,
+ IN UINT32 InterruptCount
+ )
+{
+ UINT32 Offset;
+ UINT32 Index;
+ CHAR8 Buffer[64];
+
+ if (Length < (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT))) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Node not long enough for Interrupt Array.\n"\
+ L" Length left = %d, Required = %d, Interrupt Count = %d\n",
+ Length,
+ (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT)),
+ InterruptCount
+ );
+ return;
+ }
+
+ Offset = 0;
+ for (Index = 0; Index < InterruptCount; Index++) {
+ AsciiSPrint (
+ Buffer,
+ sizeof (Buffer),
+ "Node Interrupt [%d]",
+ Index
+ );
+
+ Offset += ParseAcpi (
+ TRUE,
+ 4,
+ Buffer,
+ Ptr + Offset,
+ Length - Offset,
+ PARSER_PARAMS (AestNodeInterrupt)
+ );
+ } //for
+}
+
+/**
+ Parses a single AEST Node Structure.
+
+ @param [in] Ptr Pointer to the start of the Node.
+ @param [in] Length Maximum length of the Node.
+ @param [in] NodeType AEST node type.
+ @param [in] DataOffset Offset to the node data.
+ @param [in] InterfaceOffset Offset to the node interface data.
+ @param [in] InterruptArrayOffset Offset to the node interrupt array.
+ @param [in] InterruptCount Number of interrupts.
+**/
+STATIC
+VOID
+DumpAestNodeStructure (
+ IN UINT8* Ptr,
+ IN UINT32 Length,
+ IN UINT8 NodeType,
+ IN UINT32 DataOffset,
+ IN UINT32 InterfaceOffset,
+ IN UINT32 InterruptArrayOffset,
+ IN UINT32 InterruptCount
+ )
+{
+ UINT32 Offset;
+ UINT32 RemainingLength;
+ UINT8* NodeDataPtr;
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "Node Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (AestNodeHeaderParser)
+ );
+
+ if ((Offset > DataOffset) || (DataOffset > Length)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Node Data Offset: %d.\n"\
+ L" It should be between %d and %d.\n",
+ DataOffset,
+ Offset,
+ Length
+ );
+ }
+
+ if ((Offset > InterfaceOffset) || (InterfaceOffset > Length)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Node Interface Offset: %d.\n"\
+ L" It should be between %d and %d.\n",
+ InterfaceOffset,
+ Offset,
+ Length
+ );
+ }
+
+ if ((Offset > InterruptArrayOffset) || (InterruptArrayOffset > Length)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Node Interrupt Array Offset: %d.\n"\
+ L" It should be between %d and %d.\n",
+ InterruptArrayOffset,
+ Offset,
+ Length
+ );
+ }
+
+ // Parse Node Data Field.
+ NodeDataPtr = Ptr + DataOffset;
+ RemainingLength = Length - DataOffset;
+ switch (NodeType) {
+ case EFI_ACPI_AEST_NODE_TYPE_PROCESSOR:
+ DumpProcessorNode (NodeDataPtr, RemainingLength);
+ break;
+ case EFI_ACPI_AEST_NODE_TYPE_MEMORY:
+ DumpMemoryControllerNode (NodeDataPtr, RemainingLength);
+ break;
+ case EFI_ACPI_AEST_NODE_TYPE_SMMU:
+ DumpSmmuNode (NodeDataPtr, RemainingLength);
+ break;
+ case EFI_ACPI_AEST_NODE_TYPE_VENDOR_DEFINED:
+ DumpVendorDefinedNode (NodeDataPtr, RemainingLength);
+ break;
+ case EFI_ACPI_AEST_NODE_TYPE_GIC:
+ DumpGicNode (NodeDataPtr, RemainingLength);
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (L"ERROR: Invalid Error Node Type.\n");
+ return;
+ } // switch
+
+ // Parse the Interface Field.
+ DumpNodeInterface (
+ Ptr + InterfaceOffset,
+ Length - InterfaceOffset
+ );
+
+ // Parse the Node Interrupt Array.
+ DumpNodeInterrupts (
+ Ptr + InterruptArrayOffset,
+ Length - InterruptArrayOffset,
+ InterruptCount
+ );
+
+ return;
+}
+
+/**
+ This function parses the ACPI AEST table.
+ When trace is enabled this function parses the AEST table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiAest (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* NodePtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "AEST",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (AestParser)
+ );
+
+ while (Offset < AcpiTableLength) {
+ NodePtr = Ptr + Offset;
+
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ NodePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (AestNodeHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((AestNodeType == NULL) ||
+ (AestNodeLength == NULL) ||
+ (NodeDataOffset == NULL) ||
+ (NodeInterfaceOffset == NULL) ||
+ (NodeInterruptArrayOffset == NULL) ||
+ (NodeInterruptCount == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient length left for Node Structure.\n"\
+ L" Length left = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate AEST Node length
+ if ((*AestNodeLength == 0) ||
+ ((Offset + (*AestNodeLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid AEST Node length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *AestNodeLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ DumpAestNodeStructure (
+ NodePtr,
+ *AestNodeLength,
+ *AestNodeType,
+ *NodeDataOffset,
+ *NodeInterfaceOffset,
+ *NodeInterruptArrayOffset,
+ *NodeInterruptCount
+ );
+
+ Offset += *AestNodeLength;
+ } // while
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
index 933afcb4702..f490f07c2f5 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Gtdt/GtdtParser.c
@@ -12,6 +12,7 @@
#include <Library/UefiLib.h>
#include "AcpiParser.h"
#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
// "The number of GT Block Timers must be less than or equal to 8"
#define GT_BLOCK_TIMER_COUNT_MAX 8
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hmat/HmatParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hmat/HmatParser.c
new file mode 100644
index 00000000000..cbb9529dd1f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Hmat/HmatParser.c
@@ -0,0 +1,650 @@
+/** @file
+ HMAT table parser
+
+ Copyright (c) 2020, Arm Limited.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+
+ @par Glossary:
+ - MPDA - Memory Proximity Domain Attributes
+ - SLLBI - System Locality Latency and Bandwidth Information
+ - MSCI - Memory Side Cache Information
+ - Dom - Domain
+**/
+
+#include <Library/PrintLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiView.h"
+
+// Maximum Memory Domain matrix print size.
+#define MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX 10
+
+// Local variables
+STATIC CONST UINT16* HmatStructureType;
+STATIC CONST UINT32* HmatStructureLength;
+
+STATIC CONST UINT32* NumberInitiatorProximityDomain;
+STATIC CONST UINT32* NumberTargetProximityDomain;
+STATIC CONST
+EFI_ACPI_6_3_HMAT_STRUCTURE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO_FLAGS*
+SllbiFlags;
+
+STATIC CONST UINT8* SllbiDataType;
+STATIC CONST UINT16* NumberSMBIOSHandles;
+
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+/**
+ Names of System Locality Latency Bandwidth Information (SLLBI) data types
+**/
+STATIC CONST CHAR16* SllbiNames[] = {
+ L"Access %sLatency%s",
+ L"Read %sLatency%s",
+ L"Write %sLatency%s",
+ L"Access %sBandwidth%s",
+ L"Read %sBandwidth%s",
+ L"Write %sBandwidth%s"
+};
+
+/**
+ This function validates the Cache Attributes field.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateCacheAttributes (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES*
+ Attributes;
+
+ Attributes =
+ (EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES*)Ptr;
+
+ if (Attributes->TotalCacheLevels > 0x3) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Attributes bits [3:0] have invalid value: 0x%x",
+ Attributes->TotalCacheLevels
+ );
+ }
+ if (Attributes->CacheLevel > 0x3) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Attributes bits [7:4] have invalid value: 0x%x",
+ Attributes->CacheLevel
+ );
+ }
+ if (Attributes->CacheAssociativity > 0x2) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Attributes bits [11:8] have invalid value: 0x%x",
+ Attributes->CacheAssociativity
+ );
+ }
+ if (Attributes->WritePolicy > 0x2) {
+ IncrementErrorCount ();
+ Print (
+ L"\nERROR: Attributes bits [15:12] have invalid value: 0x%x",
+ Attributes->WritePolicy
+ );
+ }
+}
+
+/**
+ Dumps the cache attributes field
+
+ @param [in] Format Optional format string for tracing the data.
+ @param [in] Ptr Pointer to the start of the buffer.
+**/
+STATIC
+VOID
+EFIAPI
+DumpCacheAttributes (
+ IN CONST CHAR16* Format OPTIONAL,
+ IN UINT8* Ptr
+ )
+{
+ EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES*
+ Attributes;
+
+ Attributes =
+ (EFI_ACPI_6_3_HMAT_STRUCTURE_MEMORY_SIDE_CACHE_INFO_CACHE_ATTRIBUTES*)Ptr;
+
+ Print (L"\n");
+ PrintFieldName (4, L"Total Cache Levels");
+ Print (L"%d\n", Attributes->TotalCacheLevels);
+ PrintFieldName (4, L"Cache Level");
+ Print (L"%d\n", Attributes->CacheLevel);
+ PrintFieldName (4, L"Cache Associativity");
+ Print (L"%d\n", Attributes->CacheAssociativity);
+ PrintFieldName (4, L"Write Policy");
+ Print (L"%d\n", Attributes->WritePolicy);
+ PrintFieldName (4, L"Cache Line Size");
+ Print (L"%d\n", Attributes->CacheLineSize);
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI HMAT Table.
+*/
+STATIC CONST ACPI_PARSER HmatParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Reserved", 4, 36, NULL, NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the HMAT structure header.
+*/
+STATIC CONST ACPI_PARSER HmatStructureHeaderParser[] = {
+ {L"Type", 2, 0, NULL, NULL, (VOID**)&HmatStructureType, NULL, NULL},
+ {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL},
+ {L"Length", 4, 4, NULL, NULL, (VOID**)&HmatStructureLength, NULL, NULL}
+};
+
+/**
+ An ACPI PARSER array describing the Memory Proximity Domain Attributes
+ Structure - Type 0.
+*/
+STATIC CONST ACPI_PARSER MemProximityDomainAttributeParser[] = {
+ {L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL},
+ {L"Flags", 2, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 10, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Proximity Dom for initiator", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Proximity Dom for memory", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Reserved", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI PARSER array describing the System Locality Latency and Bandwidth
+ Information Structure - Type 1.
+*/
+STATIC CONST ACPI_PARSER SllbiParser[] = {
+ {L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL},
+ {L"Flags", 1, 8, L"0x%x", NULL, (VOID**)&SllbiFlags, NULL, NULL},
+ {L"Data type", 1, 9, L"0x%x", NULL, (VOID**)&SllbiDataType, NULL, NULL},
+ {L"Reserved", 2, 10, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Initiator Proximity Dom Count", 4, 12, L"%d", NULL,
+ (VOID**)&NumberInitiatorProximityDomain, NULL, NULL},
+ {L"Target Proximity Dom Count", 4, 16, L"%d", NULL,
+ (VOID**)&NumberTargetProximityDomain, NULL, NULL},
+ {L"Reserved", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Entry Base Unit", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL}
+ // initiator Proximity Domain list ...
+ // target Proximity Domain list ...
+ // Latency/Bandwidth matrix ...
+};
+
+/**
+ An ACPI PARSER array describing the Memory Side Cache Information
+ Structure - Type 2.
+*/
+STATIC CONST ACPI_PARSER MemSideCacheInfoParser[] = {
+ {L"Type", 2, 0, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Length", 4, 4, L"%d", NULL, NULL, NULL, NULL},
+ {L"Proximity Dom for memory", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Memory Side Cache Size", 8, 16, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Cache Attributes", 4, 24, NULL, DumpCacheAttributes, NULL,
+ ValidateCacheAttributes, NULL},
+ {L"Reserved", 2, 28, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"SMBIOS Handle Count", 2, 30, L"%d", NULL,
+ (VOID**)&NumberSMBIOSHandles, NULL, NULL}
+ // SMBIOS handles List ...
+};
+
+/**
+ This function parses the Memory Proximity Domain Attributes
+ Structure (Type 0).
+
+ @param [in] Ptr Pointer to the start of the Memory Proximity Domain
+ Attributes Structure data.
+ @param [in] Length Length of the Memory Proximity Domain Attributes
+ Structure.
+**/
+STATIC
+VOID
+DumpMpda (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Memory Proximity Domain Attributes Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (MemProximityDomainAttributeParser)
+ );
+}
+
+/**
+ This function parses the System Locality Latency and Bandwidth Information
+ Structure (Type 1).
+
+ @param [in] Ptr Pointer to the start of the System Locality Latency and
+ Bandwidth Information Structure data.
+ @param [in] Length Length of the System Locality Latency and Bandwidth
+ Information Structure.
+**/
+STATIC
+VOID
+DumpSllbi (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ CONST UINT32* InitiatorProximityDomainList;
+ CONST UINT32* TargetProximityDomainList;
+ CONST UINT16* LatencyBandwidthMatrix;
+ UINT32 Offset;
+ CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
+ CHAR16 SecondBuffer[OUTPUT_FIELD_COLUMN_WIDTH];
+ UINT32 RequiredTableSize;
+ UINT32 Index;
+ UINT32 IndexInitiator;
+ UINT32 IndexTarget;
+ UINT32 TargetStartOffset;
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "System Locality Latency and Bandwidth Information Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (SllbiParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((SllbiFlags == NULL) ||
+ (SllbiDataType == NULL) ||
+ (NumberInitiatorProximityDomain == NULL) ||
+ (NumberTargetProximityDomain == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"SLLBI structure header. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ RequiredTableSize = (*NumberInitiatorProximityDomain * sizeof (UINT32)) +
+ (*NumberTargetProximityDomain * sizeof (UINT32)) +
+ (*NumberInitiatorProximityDomain *
+ *NumberTargetProximityDomain * sizeof (UINT16)) +
+ Offset;
+
+ if (RequiredTableSize > Length) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient System Locality Latency and Bandwidth" \
+ L"Information Structure length. TableLength = %d. " \
+ L"RequiredTableLength = %d.\n",
+ Length,
+ RequiredTableSize
+ );
+ return;
+ }
+
+ InitiatorProximityDomainList = (UINT32*) (Ptr + Offset);
+ TargetProximityDomainList = InitiatorProximityDomainList +
+ *NumberInitiatorProximityDomain;
+ LatencyBandwidthMatrix = (UINT16*) (TargetProximityDomainList +
+ *NumberTargetProximityDomain);
+
+ // Display each element of the Initiator Proximity Domain list
+ for (Index = 0; Index < *NumberInitiatorProximityDomain; Index++) {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Initiator Proximity Dom [%d]",
+ Index
+ );
+
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ InitiatorProximityDomainList[Index]
+ );
+ }
+
+ // Display each element of the Target Proximity Domain list
+ for (Index = 0; Index < *NumberTargetProximityDomain; Index++) {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"Target Proximity Dom [%d]",
+ Index
+ );
+
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ TargetProximityDomainList[Index]
+ );
+ }
+
+ // Create base name depending on Data Type in this Structure
+ if (*SllbiDataType >= ARRAY_SIZE (SllbiNames)) {
+ IncrementErrorCount ();
+ Print (L"Error: Unkown Data Type. DataType = 0x%x.\n", *SllbiDataType);
+ return;
+ }
+ StrCpyS (Buffer, sizeof (Buffer), SllbiNames[*SllbiDataType]);
+
+ // Adjust base name depending on Memory Hierarchy in this Structure
+ switch (SllbiFlags->MemoryHierarchy) {
+ case 0:
+ UnicodeSPrint (
+ SecondBuffer,
+ sizeof (SecondBuffer),
+ Buffer,
+ L"",
+ L"%s"
+ );
+ break;
+ case 1:
+ case 2:
+ case 3:
+ UnicodeSPrint (
+ SecondBuffer,
+ sizeof (SecondBuffer),
+ Buffer,
+ L"Hit ",
+ L"%s"
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (
+ L"Error: Invalid Memory Hierarchy. MemoryHierarchy = %d.\n",
+ SllbiFlags->MemoryHierarchy
+ );
+ return;
+
+ } // switch
+
+ if (*NumberTargetProximityDomain <= MAX_MEMORY_DOMAIN_TARGET_PRINT_MATRIX) {
+ // Display the latency/bandwidth matrix as a matrix
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ SecondBuffer,
+ L""
+ );
+ PrintFieldName (4, Buffer);
+
+ Print (L"\n Target : X-axis (Horizontal)");
+ Print (L"\n Initiator : Y-axis (Vertical)");
+ Print (L"\n |");
+
+ for (IndexTarget = 0;
+ IndexTarget < *NumberTargetProximityDomain;
+ IndexTarget++) {
+ Print (L" %2d", IndexTarget);
+ }
+
+ Print (L"\n ---+");
+ for (IndexTarget = 0;
+ IndexTarget < *NumberTargetProximityDomain;
+ IndexTarget++) {
+ Print (L"------");
+ }
+ Print (L"\n");
+
+ TargetStartOffset = 0;
+ for (IndexInitiator = 0;
+ IndexInitiator < *NumberInitiatorProximityDomain;
+ IndexInitiator++) {
+ Print (L" %2d |", IndexInitiator);
+ for (IndexTarget = 0;
+ IndexTarget < *NumberTargetProximityDomain;
+ IndexTarget++) {
+ Print (
+ L" %5d",
+ LatencyBandwidthMatrix[TargetStartOffset + IndexTarget]
+ );
+ } // for Target
+ Print (L"\n");
+ TargetStartOffset += (*NumberTargetProximityDomain);
+ } // for Initiator
+ Print (L"\n");
+ } else {
+ // Display the latency/bandwidth matrix as a list
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ SecondBuffer,
+ L" [%d][%d]"
+ );
+
+ TargetStartOffset = 0;
+ for (IndexInitiator = 0;
+ IndexInitiator < *NumberInitiatorProximityDomain;
+ IndexInitiator++) {
+ for (IndexTarget = 0;
+ IndexTarget < *NumberTargetProximityDomain;
+ IndexTarget++) {
+ UnicodeSPrint (
+ SecondBuffer,
+ sizeof (SecondBuffer),
+ Buffer,
+ IndexInitiator,
+ IndexTarget
+ );
+
+ PrintFieldName (4, SecondBuffer);
+ Print (
+ L"%d\n",
+ LatencyBandwidthMatrix[TargetStartOffset + IndexTarget]
+ );
+ } // for Target
+ TargetStartOffset += (*NumberTargetProximityDomain);
+ } // for Initiator
+ }
+}
+
+/**
+ This function parses the Memory Side Cache Information Structure (Type 2).
+
+ @param [in] Ptr Pointer to the start of the Memory Side Cache Information
+ Structure data.
+ @param [in] Length Length of the Memory Side Cache Information Structure.
+**/
+STATIC
+VOID
+DumpMsci (
+ IN UINT8* Ptr,
+ IN UINT32 Length
+ )
+{
+ CONST UINT16* SMBIOSHandlesList;
+ CHAR16 Buffer[OUTPUT_FIELD_COLUMN_WIDTH];
+ UINT32 Offset;
+ UINT16 Index;
+
+ Offset = ParseAcpi (
+ TRUE,
+ 2,
+ "Memory Side Cache Information Structure",
+ Ptr,
+ Length,
+ PARSER_PARAMS (MemSideCacheInfoParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if (NumberSMBIOSHandles == NULL) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"MSCI structure header. Length = %d.\n",
+ Length
+ );
+ return;
+ }
+
+ if ((*NumberSMBIOSHandles * sizeof (UINT16)) > (Length - Offset)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Number of SMBIOS Handles. SMBIOSHandlesCount = %d." \
+ L"RemainingBufferLength = %d.\n",
+ *NumberSMBIOSHandles,
+ Length - Offset
+ );
+ return;
+ }
+
+ SMBIOSHandlesList = (UINT16*) (Ptr + Offset);
+
+ for (Index = 0; Index < *NumberSMBIOSHandles; Index++) {
+ UnicodeSPrint (
+ Buffer,
+ sizeof (Buffer),
+ L"SMBIOS Handles [%d]",
+ Index
+ );
+
+ PrintFieldName (4, Buffer);
+ Print (
+ L"0x%x\n",
+ SMBIOSHandlesList[Index]
+ );
+ }
+}
+
+/**
+ This function parses the ACPI HMAT table.
+ When trace is enabled this function parses the HMAT table and
+ traces the ACPI table fields.
+
+ This function parses the following HMAT structures:
+ - Memory Proximity Domain Attributes Structure (Type 0)
+ - System Locality Latency and Bandwidth Info Structure (Type 1)
+ - Memory Side Cache Info structure (Type 2)
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiHmat (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* HmatStructurePtr;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ Trace,
+ 0,
+ "HMAT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (HmatParser)
+ );
+
+ HmatStructurePtr = Ptr + Offset;
+
+ while (Offset < AcpiTableLength) {
+ // Parse HMAT Structure Header to obtain Type and Length.
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ HmatStructurePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (HmatStructureHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((HmatStructureType == NULL) ||
+ (HmatStructureLength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"HMAT structure header. Length = %d.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate HMAT Structure length.
+ if ((*HmatStructureLength == 0) ||
+ ((Offset + (*HmatStructureLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid HMAT Structure length. " \
+ L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
+ *HmatStructureLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ switch (*HmatStructureType) {
+ case EFI_ACPI_6_3_HMAT_TYPE_MEMORY_PROXIMITY_DOMAIN_ATTRIBUTES:
+ DumpMpda (
+ HmatStructurePtr,
+ *HmatStructureLength
+ );
+ break;
+ case EFI_ACPI_6_3_HMAT_TYPE_SYSTEM_LOCALITY_LATENCY_AND_BANDWIDTH_INFO:
+ DumpSllbi (
+ HmatStructurePtr,
+ *HmatStructureLength
+ );
+ break;
+ case EFI_ACPI_6_3_HMAT_TYPE_MEMORY_SIDE_CACHE_INFO:
+ DumpMsci (
+ HmatStructurePtr,
+ *HmatStructureLength
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Unknown HMAT structure:"
+ L" Type = %d, Length = %d\n",
+ *HmatStructureType,
+ *HmatStructureLength
+ );
+ break;
+ } // switch
+
+ HmatStructurePtr += *HmatStructureLength;
+ Offset += *HmatStructureLength;
+ } // while
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
index 43f99531531..1cd8b4f401c 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Iort/IortParser.c
@@ -13,6 +13,7 @@
#include <Library/UefiLib.h>
#include "AcpiParser.h"
#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
// Local variables
STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c
index a37a45f2a81..438826ce1b3 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Madt/MadtParser.c
@@ -15,6 +15,7 @@
#include <Library/UefiLib.h>
#include "AcpiParser.h"
#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
#include "MadtParser.h"
// Local Variables
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.c
new file mode 100644
index 00000000000..bf07a49e74b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.c
@@ -0,0 +1,615 @@
+/** @file
+ PCCT table parser
+
+ Copyright (c) 2020, Arm Limited.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Reference(s):
+ - ACPI 6.3 Specification - January 2019
+**/
+
+#include <Library/BaseMemoryLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include "AcpiParser.h"
+#include "AcpiView.h"
+#include "AcpiViewConfig.h"
+#include "PcctParser.h"
+
+// Local variables
+STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
+
+STATIC UINT32* PccGlobalFlags;
+STATIC UINT8* PccSubspaceLength;
+STATIC UINT8* PccSubspaceType;
+STATIC UINT8* ExtendedPccSubspaceInterruptFlags;
+
+/**
+ This function validates the length coded on 4 bytes of a shared memory range
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRangeLength4 (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT32*)Ptr < MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN) {
+ IncrementErrorCount ();
+ Print (
+ L"\nError: Shared memory range length is too short.\n"
+ L"Length is %u when it should be greater than or equal to %u",
+ *(UINT32*)Ptr,
+ MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN
+ );
+ }
+}
+
+/**
+ This function validates the length coded on 8 bytes of a shared memory range
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidateRangeLength8 (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ if (*(UINT64*)Ptr <= MIN_MEMORY_RANGE_LENGTH) {
+ IncrementErrorCount ();
+ Print (
+ L"\nError: Shared memory range length is too short.\n"
+ L"Length is %u when it should be greater than %u",
+ *(UINT64*)Ptr,
+ MIN_MEMORY_RANGE_LENGTH
+ );
+ }
+}
+
+/**
+ This function validates address space for type 0 structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePccType0Gas (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ switch (*(UINT8*)Ptr) {
+#if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
+ case EFI_ACPI_6_3_SYSTEM_IO:
+#endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
+ case EFI_ACPI_6_3_SYSTEM_MEMORY:
+ return;
+ default:
+ IncrementErrorCount ();
+ Print (L"\nError: Invalid address space");
+ }
+}
+
+/**
+ This function validates address space for structures of types other than 0.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePccGas (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ switch (*(UINT8*)Ptr) {
+#if !(defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
+ case EFI_ACPI_6_3_SYSTEM_IO:
+#endif //if not (defined (MDE_CPU_ARM) || defined (MDE_CPU_AARCH64))
+ case EFI_ACPI_6_3_FUNCTIONAL_FIXED_HARDWARE:
+ case EFI_ACPI_6_3_SYSTEM_MEMORY:
+ return;
+ default:
+ IncrementErrorCount ();
+ Print (L"\nError: Invalid address space");
+ }
+}
+
+/**
+ This function validates doorbell address space for type 4 structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePccDoorbellGas (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // For slave subspaces this field is optional, if not present the field
+ // should just contain zeros.
+ if (*PccSubspaceType == EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
+ if (IsZeroBuffer (
+ Ptr,
+ sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE)
+ )) {
+ return;
+ }
+ }
+
+ ValidatePccGas (Ptr, Context);
+}
+
+/**
+ This function validates interrupt acknowledge address space for
+ type 4 structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePccIntAckGas (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // If the subspace does not support interrupts or the interrupt is
+ // edge driven the register may be omitted. A value of 0x0 on all
+ // 12 bytes of the GAS structure indicates the register is not
+ // present.
+ if (((*PccGlobalFlags & EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT) !=
+ EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT) ||
+ ((*ExtendedPccSubspaceInterruptFlags &
+ EFI_ACPI_6_3_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE) ==
+ EFI_ACPI_6_3_PCCT_SUBSPACE_PLATFORM_INTERRUPT_FLAGS_MODE)) {
+ if (IsZeroBuffer (
+ Ptr,
+ sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE)
+ )) {
+ return;
+ }
+ }
+
+ ValidatePccGas (Ptr, Context);
+}
+
+/**
+ This function validates error status address space for type 4 structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePccErrStatusGas (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // This field is ignored by the OSPM on slave channels.
+ if (*PccSubspaceType == EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) {
+ return;
+ }
+
+ ValidatePccGas (Ptr, Context);
+}
+
+/**
+ This function validates platform interrupt flags for type 4 structure.
+
+ @param [in] Ptr Pointer to the start of the field data.
+ @param [in] Context Pointer to context specific information e.g. this
+ could be a pointer to the ACPI table header.
+**/
+STATIC
+VOID
+EFIAPI
+ValidatePlatInterrupt (
+ IN UINT8* Ptr,
+ IN VOID* Context
+ )
+{
+ // If a slave subspace is present in the PCCT, then the global Platform
+ // Interrupt flag must be set to 1.
+ if ((*PccSubspaceType == EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC) &&
+ ((*PccGlobalFlags & EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT) !=
+ EFI_ACPI_6_3_PCCT_FLAGS_PLATFORM_INTERRUPT)) {
+ IncrementErrorCount ();
+ Print (
+ L"\nError: Global Platform interrupt flag must be set to 1" \
+ L" if a PCC type 4 structure is present in PCCT."
+ );
+ }
+}
+
+/**
+ An ACPI_PARSER array describing the ACPI PCCT Table.
+*/
+STATIC CONST ACPI_PARSER PcctParser[] = {
+ PARSE_ACPI_HEADER (&AcpiHdrInfo),
+ {L"Flags", 4, 36, NULL, NULL, (VOID**)&PccGlobalFlags, NULL, NULL},
+ {L"Reserved", 8, 40, NULL, NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the platform communications channel subspace
+ structure header.
+*/
+STATIC CONST ACPI_PARSER PccSubspaceHeaderParser[] = {
+ PCC_SUBSPACE_HEADER ()
+ // ... Type Specific Fields ...
+};
+
+/**
+ An ACPI_PARSER array describing the Generic Communications Subspace - Type 0
+*/
+STATIC CONST ACPI_PARSER PccSubspaceType0Parser[] = {
+ PCC_SUBSPACE_HEADER (),
+ {L"Reserved", 6, 2, L"%x %x %x %x %x %x", Dump6Chars, NULL, NULL, NULL},
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Memory Range Length", 8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
+ NULL},
+ {L"Doorbell Register", 12, 24, NULL, DumpGas, NULL, ValidatePccType0Gas,
+ NULL},
+ {L"Doorbell Preserve", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL},
+ {L"Maximum Periodic Access Rate", 4, 56, L"%u", NULL, NULL, NULL, NULL},
+ {L"Minimum Request Turnaround Time", 2, 60, L"%u", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the HW-Reduced Communications Subspace
+ - Type 1
+*/
+STATIC CONST ACPI_PARSER PccSubspaceType1Parser[] = {
+ PCC_SUBSPACE_HEADER (),
+ {L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Memory Range Length", 8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
+ NULL},
+ {L"Doorbell Register", 12, 24, NULL, DumpGas, NULL,
+ ValidatePccGas, NULL},
+ {L"Doorbell Preserve", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL},
+ {L"Maximum Periodic Access Rate", 4, 56, L"%u", NULL, NULL, NULL, NULL},
+ {L"Minimum Request Turnaround Time", 2, 60, L"%u", NULL, NULL, NULL, NULL}
+};
+
+/**
+ An ACPI_PARSER array describing the HW-Reduced Communications Subspace
+ - Type 2
+*/
+STATIC CONST ACPI_PARSER PccSubspaceType2Parser[] = {
+ PCC_SUBSPACE_HEADER (),
+ {L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Memory Range Length", 8, 16, L"0x%lx", NULL, NULL, ValidateRangeLength8,
+ NULL},
+ {L"Doorbell Register", 12, 24, NULL, DumpGas, NULL,
+ ValidatePccGas, NULL},
+ {L"Doorbell Preserve", 8, 36, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Doorbell Write", 8, 44, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Nominal Latency", 4, 52, L"%u", NULL, NULL, NULL, NULL},
+ {L"Maximum Periodic Access Rate", 4, 56, L"%u", NULL, NULL, NULL, NULL},
+ {L"Minimum Request Turnaround Time", 2, 60, L"%u", NULL, NULL, NULL, NULL},
+ {L"Platform Interrupt Ack Register", 12, 62, NULL, DumpGas, NULL,
+ ValidatePccGas, NULL},
+ {L"Platform Interrupt Ack Preserve", 8, 74, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Platform Interrupt Ack Write", 8, 82, L"0x%lx", NULL, NULL,
+ NULL, NULL},
+};
+
+/**
+ An ACPI_PARSER array describing the Extended PCC Subspaces - Type 3/4
+*/
+STATIC CONST ACPI_PARSER PccSubspaceType3Parser[] = {
+ PCC_SUBSPACE_HEADER (),
+ {L"Platform Interrupt", 4, 2, L"0x%x", NULL, NULL,
+ ValidatePlatInterrupt, NULL},
+ {L"Platform Interrupt Flags", 1, 6, L"0x%x", NULL,
+ (VOID**)&ExtendedPccSubspaceInterruptFlags, NULL, NULL},
+ {L"Reserved", 1, 7, L"0x%x", NULL, NULL, NULL, NULL},
+ {L"Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Memory Range Length", 4, 16, L"0x%x", NULL, NULL, ValidateRangeLength4,
+ NULL},
+ {L"Doorbell Register", 12, 20, NULL, DumpGas, NULL,
+ ValidatePccDoorbellGas, NULL},
+ {L"Doorbell Preserve", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Doorbell Write", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Nominal Latency", 4, 48, L"%u", NULL, NULL, NULL, NULL},
+ {L"Maximum Periodic Access Rate", 4, 52, L"%u", NULL, NULL, NULL, NULL},
+ {L"Minimum Request Turnaround Time", 4, 56, L"%u", NULL, NULL, NULL, NULL},
+ {L"Platform Interrupt Ack Register", 12, 60, NULL, DumpGas, NULL,
+ ValidatePccIntAckGas, NULL},
+ {L"Platform Interrupt Ack Preserve", 8, 72, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Platform Interrupt Ack Set", 8, 80, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Reserved", 8, 88, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Cmd Complete Check Reg Addr", 12, 96, NULL, DumpGas, NULL,
+ ValidatePccGas, NULL},
+ {L"Cmd Complete Check Mask", 8, 108, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Cmd Update Reg Addr", 12, 116, NULL, DumpGas, NULL,
+ ValidatePccGas, NULL},
+ {L"Cmd Update Preserve mask", 8, 128, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Cmd Update Set mask", 8, 136, L"0x%lx", NULL, NULL, NULL, NULL},
+ {L"Error Status Register", 12, 144, NULL, DumpGas, NULL,
+ ValidatePccErrStatusGas, NULL},
+ {L"Error Status Mask", 8, 156, L"0x%lx", NULL, NULL, NULL, NULL},
+};
+
+/**
+ This function parses the PCC Subspace type 0.
+
+ @param [in] Ptr Pointer to the start of Subspace Structure.
+ @param [in] Length Length of the Subspace Structure.
+**/
+STATIC
+VOID
+DumpPccSubspaceType0 (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Subspace Type 0",
+ Ptr,
+ Length,
+ PARSER_PARAMS (PccSubspaceType0Parser)
+ );
+}
+
+/**
+ This function parses the PCC Subspace type 1.
+
+ @param [in] Ptr Pointer to the start of the Subspace Structure.
+ @param [in] Length Length of the Subspace Structure.
+**/
+STATIC
+VOID
+DumpPccSubspaceType1 (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Subspace Type 1",
+ Ptr,
+ Length,
+ PARSER_PARAMS (PccSubspaceType1Parser)
+ );
+}
+
+/**
+ This function parses the PCC Subspace type 2.
+
+ @param [in] Ptr Pointer to the start of the Subspace Structure.
+ @param [in] Length Length of the Subspace Structure.
+**/
+STATIC
+VOID
+DumpPccSubspaceType2 (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Subspace Type 2",
+ Ptr,
+ Length,
+ PARSER_PARAMS (PccSubspaceType2Parser)
+ );
+}
+
+/**
+ This function parses the PCC Subspace type 3.
+
+ @param [in] Ptr Pointer to the start of the Subspace Structure.
+ @param [in] Length Length of the Subspace Structure.
+**/
+STATIC
+VOID
+DumpPccSubspaceType3 (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Subspace Type 3",
+ Ptr,
+ Length,
+ PARSER_PARAMS (PccSubspaceType3Parser)
+ );
+}
+
+/**
+ This function parses the PCC Subspace type 4.
+
+ @param [in] Ptr Pointer to the start of the Subspace Structure.
+ @param [in] Length Length of the Subspace Structure.
+**/
+STATIC
+VOID
+DumpPccSubspaceType4 (
+ IN UINT8* Ptr,
+ IN UINT8 Length
+ )
+{
+ ParseAcpi (
+ TRUE,
+ 2,
+ "Subspace Type 4",
+ Ptr,
+ Length,
+ PARSER_PARAMS (PccSubspaceType3Parser)
+ );
+}
+
+/**
+ This function parses the ACPI PCCT table including its sub-structures
+ of type 0 through 4.
+ When trace is enabled this function parses the PCCT table and
+ traces the ACPI table fields.
+
+ This function also performs validation of the ACPI table fields.
+
+ @param [in] Trace If TRUE, trace the ACPI fields.
+ @param [in] Ptr Pointer to the start of the buffer.
+ @param [in] AcpiTableLength Length of the ACPI table.
+ @param [in] AcpiTableRevision Revision of the ACPI table.
+**/
+VOID
+EFIAPI
+ParseAcpiPcct (
+ IN BOOLEAN Trace,
+ IN UINT8* Ptr,
+ IN UINT32 AcpiTableLength,
+ IN UINT8 AcpiTableRevision
+ )
+{
+ UINT32 Offset;
+ UINT8* PccSubspacePtr;
+ UINTN SubspaceCount;
+
+ if (!Trace) {
+ return;
+ }
+
+ Offset = ParseAcpi (
+ TRUE,
+ 0,
+ "PCCT",
+ Ptr,
+ AcpiTableLength,
+ PARSER_PARAMS (PcctParser)
+ );
+
+ PccSubspacePtr = Ptr + Offset;
+
+ SubspaceCount = 0;
+ while (Offset < AcpiTableLength) {
+ // Parse common structure header to obtain Type and Length.
+ ParseAcpi (
+ FALSE,
+ 0,
+ NULL,
+ PccSubspacePtr,
+ AcpiTableLength - Offset,
+ PARSER_PARAMS (PccSubspaceHeaderParser)
+ );
+
+ // Check if the values used to control the parsing logic have been
+ // successfully read.
+ if ((PccSubspaceType == NULL) ||
+ (PccSubspaceLength == NULL)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Insufficient remaining table buffer length to read the " \
+ L"structure header. Length = %u.\n",
+ AcpiTableLength - Offset
+ );
+ return;
+ }
+
+ // Validate Structure length
+ if ((*PccSubspaceLength == 0) ||
+ ((Offset + (*PccSubspaceLength)) > AcpiTableLength)) {
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Invalid Structure length. " \
+ L"Length = %u. Offset = %u. AcpiTableLength = %u.\n",
+ *PccSubspaceLength,
+ Offset,
+ AcpiTableLength
+ );
+ return;
+ }
+
+ switch (*PccSubspaceType) {
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_GENERIC:
+ DumpPccSubspaceType0 (
+ PccSubspacePtr,
+ *PccSubspaceLength
+ );
+ break;
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_1_HW_REDUCED_COMMUNICATIONS:
+ DumpPccSubspaceType1 (
+ PccSubspacePtr,
+ *PccSubspaceLength
+ );
+ break;
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_2_HW_REDUCED_COMMUNICATIONS:
+ DumpPccSubspaceType2 (
+ PccSubspacePtr,
+ *PccSubspaceLength
+ );
+ break;
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_3_EXTENDED_PCC:
+ DumpPccSubspaceType3 (
+ PccSubspacePtr,
+ *PccSubspaceLength
+ );
+ break;
+ case EFI_ACPI_6_3_PCCT_SUBSPACE_TYPE_4_EXTENDED_PCC:
+ DumpPccSubspaceType4 (
+ PccSubspacePtr,
+ *PccSubspaceLength
+ );
+ break;
+ default:
+ IncrementErrorCount ();
+ Print (
+ L"ERROR: Unknown PCC subspace structure:"
+ L" Type = %u, Length = %u\n",
+ PccSubspaceType,
+ *PccSubspaceLength
+ );
+ }
+
+ PccSubspacePtr += *PccSubspaceLength;
+ Offset += *PccSubspaceLength;
+ SubspaceCount++;
+ } // while
+
+ if (SubspaceCount > MAX_PCC_SUBSPACES) {
+ IncrementErrorCount ();
+ Print (L"ERROR: Too many PCC subspaces.");
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.h
new file mode 100644
index 00000000000..c8e84c36ed4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pcct/PcctParser.h
@@ -0,0 +1,33 @@
+/** @file
+ Header file for PCCT parser
+
+ Copyright (c) 2020, Arm Limited.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef PCCT_PARSER_H_
+#define PCCT_PARSER_H_
+
+/**
+ Minimum value for the 'length' field in subspaces of types 0, 1 and 2.
+*/
+#define MIN_MEMORY_RANGE_LENGTH 8
+
+/**
+ Minimum value for the 'length' field in subspaces of types 3 and 4.
+*/
+#define MIN_EXT_PCC_SUBSPACE_MEM_RANGE_LEN 16
+
+/**
+ Maximum number of PCC subspaces.
+*/
+#define MAX_PCC_SUBSPACES 256
+
+/**
+ Parser for the header of any type of PCC subspace.
+*/
+#define PCC_SUBSPACE_HEADER() \
+ {L"Type", 1, 0, L"0x%x", NULL, (VOID**)&PccSubspaceType, NULL, NULL}, \
+ {L"Length", 1, 1, L"%u", NULL, (VOID**)&PccSubspaceLength, NULL, NULL}
+
+#endif // PCCT_PARSER_H_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
index f3d71245130..261fdee9ae0 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Pptt/PpttParser.c
@@ -13,6 +13,7 @@
#include <Library/UefiLib.h>
#include "AcpiParser.h"
#include "AcpiView.h"
+#include "AcpiViewConfig.h"
#include "PpttParser.h"
// Local variables
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c
index af0ed528649..e41500ab700 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/Parsers/Srat/SratParser.c
@@ -13,6 +13,7 @@
#include <Library/UefiLib.h>
#include "AcpiParser.h"
#include "AcpiTableParser.h"
+#include "AcpiViewConfig.h"
// Local Variables
STATIC CONST UINT8* SratRAType;
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
index 3ab4d07d5ba..a0b9def877a 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.c
@@ -1,23 +1,45 @@
/** @file
Main file for 'acpiview' Shell command function.
- Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Guid/ShellLibHiiGuid.h>
#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/ArmErrorSourceTable.h>
+
+#include <Library/BaseMemoryLib.h>
#include <Library/HiiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PrintLib.h>
#include <Library/ShellCommandLib.h>
-#include <Library/UefiLib.h>
+#include <Library/ShellLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/AcpiViewCommandLib.h>
#include <Uefi.h>
+
#include "AcpiParser.h"
#include "AcpiTableParser.h"
#include "AcpiView.h"
-#include "UefiShellAcpiViewCommandLib.h"
+#include "AcpiViewConfig.h"
CONST CHAR16 gShellAcpiViewFileName[] = L"ShellCommand";
+EFI_HII_HANDLE gShellAcpiViewHiiHandle = NULL;
+
+/**
+ An array of acpiview command line parameters.
+**/
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-q", TypeFlag},
+ {L"-d", TypeFlag},
+ {L"-h", TypeFlag},
+ {L"-l", TypeFlag},
+ {L"-s", TypeValue},
+ {L"-r", TypeValue},
+ {NULL, TypeMax}
+};
/**
A list of available table parsers.
@@ -25,6 +47,7 @@ CONST CHAR16 gShellAcpiViewFileName[] = L"ShellCommand";
STATIC
CONST
ACPI_TABLE_PARSER ParserList[] = {
+ {EFI_ACPI_6_3_ARM_ERROR_SOURCE_TABLE_SIGNATURE, ParseAcpiAest},
{EFI_ACPI_6_2_BOOT_GRAPHICS_RESOURCE_TABLE_SIGNATURE, ParseAcpiBgrt},
{EFI_ACPI_6_2_DEBUG_PORT_2_TABLE_SIGNATURE, ParseAcpiDbg2},
{EFI_ACPI_6_2_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE,
@@ -32,10 +55,13 @@ ACPI_TABLE_PARSER ParserList[] = {
{EFI_ACPI_6_3_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE, ParseAcpiFacs},
{EFI_ACPI_6_2_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiFadt},
{EFI_ACPI_6_2_GENERIC_TIMER_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiGtdt},
+ {EFI_ACPI_6_3_HETEROGENEOUS_MEMORY_ATTRIBUTE_TABLE_SIGNATURE, ParseAcpiHmat},
{EFI_ACPI_6_2_IO_REMAPPING_TABLE_SIGNATURE, ParseAcpiIort},
{EFI_ACPI_6_2_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE, ParseAcpiMadt},
{EFI_ACPI_6_2_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE,
ParseAcpiMcfg},
+ {EFI_ACPI_6_2_PLATFORM_COMMUNICATIONS_CHANNEL_TABLE_SIGNATURE,
+ ParseAcpiPcct},
{EFI_ACPI_6_2_PROCESSOR_PROPERTIES_TOPOLOGY_TABLE_STRUCTURE_SIGNATURE,
ParseAcpiPptt},
{RSDP_TABLE_INFO, ParseAcpiRsdp},
@@ -79,6 +105,64 @@ RegisterAllParsers (
}
/**
+ Dump a buffer to a file. Print error message if a file cannot be created.
+
+ @param[in] FileName The filename that shall be created to contain the buffer.
+ @param[in] Buffer Pointer to buffer that shall be dumped.
+ @param[in] BufferSize The size of buffer to be dumped in bytes.
+
+ @return The number of bytes that were written
+**/
+UINTN
+EFIAPI
+ShellDumpBufferToFile (
+ IN CONST CHAR16* FileNameBuffer,
+ IN CONST VOID* Buffer,
+ IN CONST UINTN BufferSize
+ )
+{
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE DumpFileHandle;
+ UINTN TransferBytes;
+
+ Status = ShellOpenFileByName (
+ FileNameBuffer,
+ &DumpFileHandle,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_READONLY_MEDIA),
+ gShellAcpiViewHiiHandle,
+ L"acpiview"
+ );
+ return 0;
+ }
+
+ TransferBytes = BufferSize;
+ Status = ShellWriteFile (
+ DumpFileHandle,
+ &TransferBytes,
+ (VOID *) Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ Print (L"ERROR: Failed to write binary file.\n");
+ TransferBytes = 0;
+ } else {
+ Print (L"DONE.\n");
+ }
+
+ ShellCloseFile (&DumpFileHandle);
+ return TransferBytes;
+}
+
+/**
Return the file name of the help text file if not using HII.
@return The string pointer to the file name.
@@ -93,6 +177,200 @@ ShellCommandGetManFileNameAcpiView (
}
/**
+ Function for 'acpiview' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if internal).
+
+ @retval SHELL_INVALID_PARAMETER The command line invocation could not be parsed
+ @retval SHELL_NOT_FOUND The command failed
+ @retval SHELL_SUCCESS The command was successful
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAcpiView (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE* SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY* Package;
+ CHAR16* ProblemParam;
+ SHELL_FILE_HANDLE TmpDumpFileHandle;
+ CONST CHAR16* MandatoryTableSpecStr;
+ CONST CHAR16* SelectedTableName;
+
+ // Set configuration defaults
+ AcpiConfigSetDefaults ();
+
+ ShellStatus = SHELL_SUCCESS;
+ Package = NULL;
+ TmpDumpFileHandle = NULL;
+
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM),
+ gShellAcpiViewHiiHandle,
+ L"acpiview",
+ ProblemParam
+ );
+ FreePool (ProblemParam);
+ } else {
+ Print (L"acpiview: Error processing input parameter(s)\n");
+ }
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandLineGetCount (Package) > 1) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_TOO_MANY),
+ gShellAcpiViewHiiHandle,
+ L"acpiview"
+ );
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag (Package, L"-?")) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GET_HELP_ACPIVIEW),
+ gShellAcpiViewHiiHandle,
+ L"acpiview"
+ );
+ } else if (ShellCommandLineGetFlag (Package, L"-s") &&
+ ShellCommandLineGetValue (Package, L"-s") == NULL) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_NO_VALUE),
+ gShellAcpiViewHiiHandle,
+ L"acpiview",
+ L"-s"
+ );
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag (Package, L"-r") &&
+ ShellCommandLineGetValue (Package, L"-r") == NULL) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_NO_VALUE),
+ gShellAcpiViewHiiHandle,
+ L"acpiview",
+ L"-r"
+ );
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if ((ShellCommandLineGetFlag (Package, L"-s") &&
+ ShellCommandLineGetFlag (Package, L"-l"))) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_TOO_MANY),
+ gShellAcpiViewHiiHandle,
+ L"acpiview"
+ );
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag (Package, L"-d") &&
+ !ShellCommandLineGetFlag (Package, L"-s")) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_MISSING_OPTION),
+ gShellAcpiViewHiiHandle,
+ L"acpiview",
+ L"-s",
+ L"-d"
+ );
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ // Turn on colour highlighting if requested
+ SetColourHighlighting (ShellCommandLineGetFlag (Package, L"-h"));
+
+ // Surpress consistency checking if requested
+ SetConsistencyChecking (!ShellCommandLineGetFlag (Package, L"-q"));
+
+ // Evaluate the parameters for mandatory ACPI table presence checks
+ SetMandatoryTableValidate (ShellCommandLineGetFlag (Package, L"-r"));
+ MandatoryTableSpecStr = ShellCommandLineGetValue (Package, L"-r");
+
+ if (MandatoryTableSpecStr != NULL) {
+ SetMandatoryTableSpec (ShellHexStrToUintn (MandatoryTableSpecStr));
+ }
+
+ if (ShellCommandLineGetFlag (Package, L"-l")) {
+ SetReportOption (ReportTableList);
+ } else {
+ SelectedTableName = ShellCommandLineGetValue (Package, L"-s");
+ if (SelectedTableName != NULL) {
+ SelectAcpiTable (SelectedTableName);
+ SetReportOption (ReportSelected);
+
+ if (ShellCommandLineGetFlag (Package, L"-d")) {
+ // Create a temporary file to check if the media is writable.
+ CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN];
+ SetReportOption (ReportDumpBinFile);
+
+ UnicodeSPrint (
+ FileNameBuffer,
+ sizeof (FileNameBuffer),
+ L".\\%s0000.tmp",
+ SelectedTableName
+ );
+
+ Status = ShellOpenFileByName (
+ FileNameBuffer,
+ &TmpDumpFileHandle,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE |
+ EFI_FILE_MODE_CREATE,
+ 0
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ TmpDumpFileHandle = NULL;
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_READONLY_MEDIA),
+ gShellAcpiViewHiiHandle,
+ L"acpiview"
+ );
+ goto Done;
+ }
+ // Delete Temporary file.
+ ShellDeleteFile (&TmpDumpFileHandle);
+ } // -d
+ } // -s
+ }
+
+ // Parse ACPI Table information
+ Status = AcpiView (SystemTable);
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ }
+
+Done:
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ return ShellStatus;
+}
+
+/**
Constructor for the Shell AcpiView Command library.
Install the handlers for acpiview UEFI Shell command.
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h
deleted file mode 100644
index dc2cec98190..00000000000
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @file
- Header file for 'acpiview' Shell command functions.
-
- Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#ifndef UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_
-#define UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_
-
-extern EFI_HII_HANDLE gShellAcpiViewHiiHandle;
-
-/**
- Function for 'acpiview' command.
-
- @param[in] ImageHandle Handle to the Image (NULL if Internal).
- @param[in] SystemTable Pointer to the System Table (NULL if Internal).
-**/
-SHELL_STATUS
-EFIAPI
-ShellCommandRunAcpiView (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- );
-
-#endif // UEFI_SHELL_ACPIVIEW_COMMAND_LIB_H_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
index ab02bf3403c..377d0935a6a 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
@@ -1,7 +1,7 @@
## @file
# Provides Shell 'acpiview' command functions
#
-# Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.<BR>
+# Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -14,62 +14,67 @@
FILE_GUID = FB5B305E-84F5-461F-940D-82D345757AFA
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 1.0
- LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ LIBRARY_CLASS = AcpiViewCommandLib|UEFI_APPLICATION UEFI_DRIVER
CONSTRUCTOR = UefiShellAcpiViewCommandLibConstructor
DESTRUCTOR = UefiShellAcpiViewCommandLibDestructor
[Sources.common]
- UefiShellAcpiViewCommandLib.uni
- UefiShellAcpiViewCommandLib.c
- UefiShellAcpiViewCommandLib.h
- AcpiParser.h
- AcpiTableParser.h
- AcpiView.h
AcpiParser.c
+ AcpiParser.h
AcpiTableParser.c
+ AcpiTableParser.h
AcpiView.c
+ AcpiView.h
+ AcpiViewConfig.c
+ AcpiViewConfig.h
+ Parsers/Aest/AestParser.c
Parsers/Bgrt/BgrtParser.c
Parsers/Dbg2/Dbg2Parser.c
Parsers/Dsdt/DsdtParser.c
Parsers/Facs/FacsParser.c
Parsers/Fadt/FadtParser.c
Parsers/Gtdt/GtdtParser.c
+ Parsers/Hmat/HmatParser.c
Parsers/Iort/IortParser.c
Parsers/Madt/MadtParser.c
+ Parsers/Madt/MadtParser.h
Parsers/Mcfg/McfgParser.c
+ Parsers/Pcct/PcctParser.c
+ Parsers/Pcct/PcctParser.h
Parsers/Pptt/PpttParser.c
+ Parsers/Pptt/PpttParser.h
Parsers/Rsdp/RsdpParser.c
Parsers/Slit/SlitParser.c
Parsers/Spcr/SpcrParser.c
Parsers/Srat/SratParser.c
Parsers/Ssdt/SsdtParser.c
Parsers/Xsdt/XsdtParser.c
- Parsers/Madt/MadtParser.h
- Parsers/Pptt/PpttParser.h
+ UefiShellAcpiViewCommandLib.c
+ UefiShellAcpiViewCommandLib.uni
[Sources.ARM, Sources.AARCH64]
Arm/SbbrValidator.h
Arm/SbbrValidator.c
[Packages]
+ MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
- MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
- MemoryAllocationLib
BaseLib
BaseMemoryLib
DebugLib
+ FileHandleLib
+ HiiLib
+ MemoryAllocationLib
+ PcdLib
+ PrintLib
ShellCommandLib
ShellLib
+ UefiBootServicesTableLib
UefiLib
UefiRuntimeServicesTableLib
- UefiBootServicesTableLib
- PcdLib
- HiiLib
- PrintLib
- FileHandleLib
[FixedPcd]
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni
index 7cd43d0518f..393110e0ee9 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.uni
@@ -1,6 +1,6 @@
// /**
//
-// Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.<BR>
+// Copyright (c) 2016 - 2020, Arm Limited. All rights reserved.<BR>
// SPDX-License-Identifier: BSD-2-Clause-Patent
//
// Module Name:
@@ -78,12 +78,14 @@
" other than AcpiTable header. The actual header can refer to the ACPI spec\r\n"
" 6.2\r\n"
" Extra A. Particular types:\r\n"
+" AEST - Arm Error Source Table\r\n"
" APIC - Multiple APIC Description Table (MADT)\r\n"
" BGRT - Boot Graphics Resource Table\r\n"
" DBG2 - Debug Port Table 2\r\n"
" DSDT - Differentiated System Description Table\r\n"
" FACP - Fixed ACPI Description Table (FADT)\r\n"
" GTDT - Generic Timer Description Table\r\n"
+" HMAT - Heterogeneous Memory Attributes Table\r\n"
" IORT - IO Remapping Table\r\n"
" MCFG - Memory Mapped Config Space Base Address Description Table\r\n"
" PPTT - Processor Properties Topology Table\r\n"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
index 1106d8c3854..a3b0224c279 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
@@ -84,7 +84,7 @@ typedef struct {
@param[in] Target The target of the operation.
@retval EFI_SUCCESS The data was sucessfully updated.
- @retval other A error occured.
+ @retval other A error occurred.
**/
EFI_STATUS
UpdateOptionalData(
@@ -170,7 +170,7 @@ UpdateOptionalData(
@param[in] BootIndex The boot option index to CRC.
@retval EFI_SUCCESS The CRC was sucessfully returned.
- @retval other A error occured.
+ @retval other A error occurred.
**/
EFI_STATUS
GetBootOptionCrc(
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
index 7d6836362b2..2a44d836b0f 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
@@ -1909,3 +1909,320 @@ CatSDumpHex (
return RetVal;
}
+
+/**
+ ORDERED_COLLECTION_USER_COMPARE function for SHELL_SORT_UNIQUE_NAME objects.
+
+ @param[in] Unique1AsVoid The first SHELL_SORT_UNIQUE_NAME object (Unique1),
+ passed in as a pointer-to-VOID.
+
+ @param[in] Unique2AsVoid The second SHELL_SORT_UNIQUE_NAME object (Unique2),
+ passed in as a pointer-to-VOID.
+
+ @retval <0 If Unique1 compares less than Unique2.
+
+ @retval 0 If Unique1 compares equal to Unique2.
+
+ @retval >0 If Unique1 compares greater than Unique2.
+**/
+STATIC
+INTN
+EFIAPI
+UniqueNameCompare (
+ IN CONST VOID *Unique1AsVoid,
+ IN CONST VOID *Unique2AsVoid
+ )
+{
+ CONST SHELL_SORT_UNIQUE_NAME *Unique1;
+ CONST SHELL_SORT_UNIQUE_NAME *Unique2;
+
+ Unique1 = Unique1AsVoid;
+ Unique2 = Unique2AsVoid;
+
+ //
+ // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
+ //
+ return gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)Unique1->Alias,
+ (CHAR16 *)Unique2->Alias
+ );
+}
+
+/**
+ ORDERED_COLLECTION_KEY_COMPARE function for SHELL_SORT_UNIQUE_NAME objects.
+
+ @param[in] UniqueAliasAsVoid The CHAR16 string UniqueAlias, passed in as a
+ pointer-to-VOID.
+
+ @param[in] UniqueAsVoid The SHELL_SORT_UNIQUE_NAME object (Unique),
+ passed in as a pointer-to-VOID.
+
+ @retval <0 If UniqueAlias compares less than Unique->Alias.
+
+ @retval 0 If UniqueAlias compares equal to Unique->Alias.
+
+ @retval >0 If UniqueAlias compares greater than Unique->Alias.
+**/
+STATIC
+INTN
+EFIAPI
+UniqueNameAliasCompare (
+ IN CONST VOID *UniqueAliasAsVoid,
+ IN CONST VOID *UniqueAsVoid
+ )
+{
+ CONST CHAR16 *UniqueAlias;
+ CONST SHELL_SORT_UNIQUE_NAME *Unique;
+
+ UniqueAlias = UniqueAliasAsVoid;
+ Unique = UniqueAsVoid;
+
+ //
+ // We need to cast away CONST for EFI_UNICODE_COLLATION_STRICOLL.
+ //
+ return gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)UniqueAlias,
+ (CHAR16 *)Unique->Alias
+ );
+}
+
+/**
+ Sort an EFI_SHELL_FILE_INFO list, optionally moving duplicates to a separate
+ list.
+
+ @param[in,out] FileList The list of EFI_SHELL_FILE_INFO objects to sort.
+
+ If FileList is NULL on input, then FileList is
+ considered an empty, hence already sorted, list.
+
+ Otherwise, if (*FileList) is NULL on input, then
+ EFI_INVALID_PARAMETER is returned.
+
+ Otherwise, the caller is responsible for having
+ initialized (*FileList)->Link with
+ InitializeListHead(). No other fields in the
+ (**FileList) head element are accessed by this
+ function.
+
+ On output, (*FileList) is sorted according to Order.
+ If Duplicates is NULL on input, then duplicate
+ elements are preserved, sorted stably, on
+ (*FileList). If Duplicates is not NULL on input,
+ then duplicates are moved (stably sorted) to the
+ new, dynamically allocated (*Duplicates) list.
+
+ @param[out] Duplicates If Duplicates is NULL on input, (*FileList) will be
+ a monotonically ordered list on output, with
+ duplicates stably sorted.
+
+ If Duplicates is not NULL on input, (*FileList) will
+ be a strictly monotonically oredered list on output,
+ with duplicates separated (stably sorted) to
+ (*Duplicates). All fields except Link will be
+ zero-initialized in the (**Duplicates) head element.
+ If no duplicates exist, then (*Duplicates) is set to
+ NULL on output.
+
+ @param[in] Order Determines the comparison operation between
+ EFI_SHELL_FILE_INFO objects.
+
+ @retval EFI_INVALID_PARAMETER (UINTN)Order is greater than or equal to
+ (UINTN)ShellSortFileListMax. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_INVALID_PARAMETER (*FileList) was NULL on input. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed. Neither the
+ (*FileList) nor the (*Duplicates) list has
+ been modified.
+
+ @retval EFI_SUCCESS Sorting successful, including the case when
+ FileList is NULL on input.
+**/
+EFI_STATUS
+EFIAPI
+ShellSortFileList (
+ IN OUT EFI_SHELL_FILE_INFO **FileList,
+ OUT EFI_SHELL_FILE_INFO **Duplicates OPTIONAL,
+ IN SHELL_SORT_FILE_LIST Order
+ )
+{
+ LIST_ENTRY *FilesHead;
+ ORDERED_COLLECTION *Sort;
+ LIST_ENTRY *FileEntry;
+ EFI_SHELL_FILE_INFO *FileInfo;
+ SHELL_SORT_UNIQUE_NAME *Unique;
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *Dupes;
+ LIST_ENTRY *NextFileEntry;
+ CONST CHAR16 *Alias;
+ ORDERED_COLLECTION_ENTRY *SortEntry;
+ LIST_ENTRY *TargetFileList;
+ ORDERED_COLLECTION_ENTRY *NextSortEntry;
+ VOID *UniqueAsVoid;
+
+ if ((UINTN)Order >= (UINTN)ShellSortFileListMax) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (FileList == NULL) {
+ //
+ // FileList is considered empty, hence already sorted, with no duplicates.
+ //
+ if (Duplicates != NULL) {
+ *Duplicates = NULL;
+ }
+ return EFI_SUCCESS;
+ }
+
+ if (*FileList == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ FilesHead = &(*FileList)->Link;
+
+ //
+ // Collect all the unique names.
+ //
+ Sort = OrderedCollectionInit (UniqueNameCompare, UniqueNameAliasCompare);
+ if (Sort == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ BASE_LIST_FOR_EACH (FileEntry, FilesHead) {
+ FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
+
+ //
+ // Try to record the name of this file as a unique name.
+ //
+ Unique = AllocatePool (sizeof (*Unique));
+ if (Unique == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UninitSort;
+ }
+ Unique->Alias = ((Order == ShellSortFileListByFileName) ?
+ FileInfo->FileName :
+ FileInfo->FullName);
+ InitializeListHead (&Unique->SameNameList);
+
+ Status = OrderedCollectionInsert (Sort, NULL, Unique);
+ if (EFI_ERROR (Status)) {
+ //
+ // Only two errors are possible: memory allocation failed, or this name
+ // has been encountered before. In either case, the
+ // SHELL_SORT_UNIQUE_NAME object being constructed has to be released.
+ //
+ FreePool (Unique);
+ //
+ // Memory allocation failure is fatal, while having seen the same name
+ // before is normal.
+ //
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ goto UninitSort;
+ }
+ ASSERT (Status == EFI_ALREADY_STARTED);
+ }
+ }
+
+ //
+ // Set Dupes to suppress incorrect compiler/analyzer warnings.
+ //
+ Dupes = NULL;
+
+ //
+ // If separation of duplicates has been requested, allocate the list for
+ // them.
+ //
+ if (Duplicates != NULL) {
+ Dupes = AllocateZeroPool (sizeof (*Dupes));
+ if (Dupes == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UninitSort;
+ }
+ InitializeListHead (&Dupes->Link);
+ }
+
+ //
+ // No memory allocation beyond this point; thus, no chance to fail. We can
+ // now migrate the EFI_SHELL_FILE_INFO objects from (*FileList) to Sort.
+ //
+ BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, FilesHead) {
+ FileInfo = (EFI_SHELL_FILE_INFO *)FileEntry;
+ //
+ // Look up the SHELL_SORT_UNIQUE_NAME that matches FileInfo's name.
+ //
+ Alias = ((Order == ShellSortFileListByFileName) ?
+ FileInfo->FileName :
+ FileInfo->FullName);
+ SortEntry = OrderedCollectionFind (Sort, Alias);
+ ASSERT (SortEntry != NULL);
+ Unique = OrderedCollectionUserStruct (SortEntry);
+ //
+ // Move FileInfo from (*FileList) to the end of the list of files whose
+ // names all compare identical to FileInfo's name.
+ //
+ RemoveEntryList (&FileInfo->Link);
+ InsertTailList (&Unique->SameNameList, &FileInfo->Link);
+ }
+
+ //
+ // All EFI_SHELL_FILE_INFO objects originally in (*FileList) have been
+ // distributed to Sort. Now migrate them back to (*FileList), advancing in
+ // unique name order.
+ //
+ for (SortEntry = OrderedCollectionMin (Sort);
+ SortEntry != NULL;
+ SortEntry = OrderedCollectionNext (SortEntry)) {
+ Unique = OrderedCollectionUserStruct (SortEntry);
+ //
+ // The first FileInfo encountered for each unique name goes back on
+ // (*FileList) unconditionally. Further FileInfo instances for the same
+ // unique name -- that is, duplicates -- are either returned to (*FileList)
+ // or separated, dependent on the caller's request.
+ //
+ TargetFileList = FilesHead;
+ BASE_LIST_FOR_EACH_SAFE (FileEntry, NextFileEntry, &Unique->SameNameList) {
+ RemoveEntryList (FileEntry);
+ InsertTailList (TargetFileList, FileEntry);
+ if (Duplicates != NULL) {
+ TargetFileList = &Dupes->Link;
+ }
+ }
+ }
+
+ //
+ // We're done. If separation of duplicates has been requested, output the
+ // list of duplicates -- and free that list at once, if it's empty (i.e., if
+ // no duplicates have been found).
+ //
+ if (Duplicates != NULL) {
+ if (IsListEmpty (&Dupes->Link)) {
+ FreePool (Dupes);
+ *Duplicates = NULL;
+ } else {
+ *Duplicates = Dupes;
+ }
+ }
+ Status = EFI_SUCCESS;
+
+ //
+ // Fall through.
+ //
+UninitSort:
+ for (SortEntry = OrderedCollectionMin (Sort);
+ SortEntry != NULL;
+ SortEntry = NextSortEntry) {
+ NextSortEntry = OrderedCollectionNext (SortEntry);
+ OrderedCollectionDelete (Sort, SortEntry, &UniqueAsVoid);
+ Unique = UniqueAsVoid;
+ ASSERT (IsListEmpty (&Unique->SameNameList));
+ FreePool (Unique);
+ }
+ OrderedCollectionUninit (Sort);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
index 916134afcba..b56aed7c87e 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
@@ -39,6 +39,7 @@
#include <Library/HiiLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Library/OrderedCollectionLib.h>
typedef struct{
LIST_ENTRY Link;
@@ -60,6 +61,24 @@ typedef struct {
CHAR16 *Path;
} SHELL_COMMAND_FILE_HANDLE;
+//
+// Collects multiple EFI_SHELL_FILE_INFO objects that share the same name.
+//
+typedef struct {
+ //
+ // A string that compares equal to either the FileName or the FullName fields
+ // of all EFI_SHELL_FILE_INFO objects on SameNameList, according to
+ // gUnicodeCollation->StriColl(). The string is not dynamically allocated;
+ // instead, it *aliases* the FileName or FullName field of the
+ // EFI_SHELL_FILE_INFO object that was first encountered with this name.
+ //
+ CONST CHAR16 *Alias;
+ //
+ // A list of EFI_SHELL_FILE_INFO objects whose FileName or FullName fields
+ // compare equal to Alias, according to gUnicodeCollation->StriColl().
+ //
+ LIST_ENTRY SameNameList;
+} SHELL_SORT_UNIQUE_NAME;
#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
index a87f4f6a5a8..f27eb4fa3d9 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
@@ -42,6 +42,7 @@
ShellLib
HiiLib
HandleParsingLib
+ OrderedCollectionLib
[Protocols]
gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c
index 768babb5080..a0d454ad83e 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c
@@ -21,6 +21,16 @@ typedef enum {
InPrevDiffPoint
} READ_STATUS;
+//
+// Buffer type, for reading both file operands in chunks.
+//
+typedef struct {
+ UINT8 *Data; // dynamically allocated buffer
+ UINTN Allocated; // the allocated size of Data
+ UINTN Next; // next position in Data to fetch a byte at
+ UINTN Left; // number of bytes left in Data for fetching at Next
+} FILE_BUFFER;
+
/**
Function to print differnt point data.
@@ -77,6 +87,106 @@ PrintDifferentPoint(
}
/**
+ Initialize a FILE_BUFFER.
+
+ @param[out] FileBuffer The FILE_BUFFER to initialize. On return, the caller
+ is responsible for checking FileBuffer->Data: if
+ FileBuffer->Data is NULL on output, then memory
+ allocation failed.
+**/
+STATIC
+VOID
+FileBufferInit (
+ OUT FILE_BUFFER *FileBuffer
+ )
+{
+ FileBuffer->Allocated = PcdGet32 (PcdShellFileOperationSize);
+ FileBuffer->Data = AllocatePool (FileBuffer->Allocated);
+ FileBuffer->Left = 0;
+}
+
+/**
+ Uninitialize a FILE_BUFFER.
+
+ @param[in,out] FileBuffer The FILE_BUFFER to uninitialize. The caller is
+ responsible for making sure FileBuffer was first
+ initialized with FileBufferInit(), successfully or
+ unsuccessfully.
+**/
+STATIC
+VOID
+FileBufferUninit (
+ IN OUT FILE_BUFFER *FileBuffer
+ )
+{
+ SHELL_FREE_NON_NULL (FileBuffer->Data);
+}
+
+/**
+ Read a byte from a SHELL_FILE_HANDLE, buffered with a FILE_BUFFER.
+
+ @param[in] FileHandle The SHELL_FILE_HANDLE to replenish FileBuffer
+ from, if needed.
+
+ @param[in,out] FileBuffer The FILE_BUFFER to read a byte from. If FileBuffer
+ is empty on entry, then FileBuffer is refilled
+ from FileHandle, before outputting a byte from
+ FileBuffer to Byte. The caller is responsible for
+ ensuring that FileBuffer was successfully
+ initialized with FileBufferInit().
+
+ @param[out] BytesRead On successful return, BytesRead is set to 1 if the
+ next byte from FileBuffer has been stored to Byte.
+ On successful return, BytesRead is set to 0 if
+ FileBuffer is empty, and FileHandle is at EOF.
+ When an error is returned, BytesRead is not set.
+
+ @param[out] Byte On output, the next byte from FileBuffer. Only set
+ if (a) EFI_SUCCESS is returned and (b) BytesRead
+ is set to 1 on output.
+
+ @retval EFI_SUCCESS BytesRead has been set to 0 or 1. In the latter case,
+ Byte has been set as well.
+
+ @return Error codes propagated from
+ gEfiShellProtocol->ReadFile().
+**/
+STATIC
+EFI_STATUS
+FileBufferReadByte (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT FILE_BUFFER *FileBuffer,
+ OUT UINTN *BytesRead,
+ OUT UINT8 *Byte
+ )
+{
+ UINTN ReadSize;
+ EFI_STATUS Status;
+
+ if (FileBuffer->Left == 0) {
+ ReadSize = FileBuffer->Allocated;
+ Status = gEfiShellProtocol->ReadFile (FileHandle, &ReadSize,
+ FileBuffer->Data);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (ReadSize == 0) {
+ *BytesRead = 0;
+ return EFI_SUCCESS;
+ }
+ FileBuffer->Next = 0;
+ FileBuffer->Left = ReadSize;
+ }
+
+ *BytesRead = 1;
+ *Byte = FileBuffer->Data[FileBuffer->Next];
+
+ FileBuffer->Next++;
+ FileBuffer->Left--;
+ return EFI_SUCCESS;
+}
+
+/**
Function for 'comp' command.
@param[in] ImageHandle Handle to the Image (NULL if Internal).
@@ -107,6 +217,8 @@ ShellCommandRunComp (
UINT8 OneByteFromFile2;
UINT8 *DataFromFile1;
UINT8 *DataFromFile2;
+ FILE_BUFFER FileBuffer1;
+ FILE_BUFFER FileBuffer2;
UINTN InsertPosition1;
UINTN InsertPosition2;
UINTN DataSizeFromFile1;
@@ -234,10 +346,15 @@ ShellCommandRunComp (
if (ShellStatus == SHELL_SUCCESS) {
DataFromFile1 = AllocateZeroPool ((UINTN)DifferentBytes);
DataFromFile2 = AllocateZeroPool ((UINTN)DifferentBytes);
- if (DataFromFile1 == NULL || DataFromFile2 == NULL) {
+ FileBufferInit (&FileBuffer1);
+ FileBufferInit (&FileBuffer2);
+ if (DataFromFile1 == NULL || DataFromFile2 == NULL ||
+ FileBuffer1.Data == NULL || FileBuffer2.Data == NULL) {
ShellStatus = SHELL_OUT_OF_RESOURCES;
SHELL_FREE_NON_NULL (DataFromFile1);
SHELL_FREE_NON_NULL (DataFromFile2);
+ FileBufferUninit (&FileBuffer1);
+ FileBufferUninit (&FileBuffer2);
}
}
@@ -247,9 +364,11 @@ ShellCommandRunComp (
DataSizeFromFile2 = 1;
OneByteFromFile1 = 0;
OneByteFromFile2 = 0;
- Status = gEfiShellProtocol->ReadFile (FileHandle1, &DataSizeFromFile1, &OneByteFromFile1);
+ Status = FileBufferReadByte (FileHandle1, &FileBuffer1,
+ &DataSizeFromFile1, &OneByteFromFile1);
ASSERT_EFI_ERROR (Status);
- Status = gEfiShellProtocol->ReadFile (FileHandle2, &DataSizeFromFile2, &OneByteFromFile2);
+ Status = FileBufferReadByte (FileHandle2, &FileBuffer2,
+ &DataSizeFromFile2, &OneByteFromFile2);
ASSERT_EFI_ERROR (Status);
TempAddress++;
@@ -346,6 +465,8 @@ ShellCommandRunComp (
SHELL_FREE_NON_NULL (DataFromFile1);
SHELL_FREE_NON_NULL (DataFromFile2);
+ FileBufferUninit (&FileBuffer1);
+ FileBufferUninit (&FileBuffer2);
if (DiffPointNumber == 0) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_PASS), gShellDebug1HiiHandle);
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
index 6f34abfc016..3c3f00fbf91 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
@@ -221,7 +221,7 @@ InternalEditorMiscLineRetreat (
>0 : advance
<0 : retreat
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return The line after advance/retreat.
**/
EFI_EDITOR_LINE *
@@ -2609,7 +2609,7 @@ RightCurrentScreen (
>0 : advance
<0: retreat
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return The line after advance/retreat.
**/
EFI_EDITOR_LINE *
@@ -2767,6 +2767,8 @@ FileBufferCutLine (
UINTN Row;
UINTN Col;
+ *CutLine = NULL;
+
if (FileBuffer.ReadOnly) {
StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
return EFI_SUCCESS;
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
index 234e49234ab..3c3c587da9d 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
@@ -40,7 +40,7 @@ EFI_EDITOR_GLOBAL_EDITOR MainEditor;
Load a file from disk to editor
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
@@ -74,7 +74,7 @@ MainCommandGotoLine (
@retval EFI_SUCCESS The file was saved correctly.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A file access error occured.
+ @retval EFI_LOAD_ERROR A file access error occurred.
**/
EFI_STATUS
MainCommandSaveFile (
@@ -96,7 +96,7 @@ MainCommandDisplayHelp (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandExit (
@@ -108,7 +108,7 @@ MainCommandExit (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandSearch (
@@ -120,7 +120,7 @@ MainCommandSearch (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandSearchReplace (
@@ -132,7 +132,7 @@ MainCommandSearchReplace (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandCutLine (
@@ -144,7 +144,7 @@ MainCommandCutLine (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandPasteLine (
@@ -277,7 +277,7 @@ EDITOR_MENU_ITEM MainMenuItems[] = {
Load a file from disk to editor
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
@@ -465,7 +465,7 @@ MainCommandSwitchFileType (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandCutLine (
@@ -503,7 +503,7 @@ MainCommandCutLine (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandPasteLine (
@@ -535,7 +535,7 @@ MainCommandPasteLine (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandSearch (
@@ -676,7 +676,7 @@ MainCommandSearch (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandSearchReplace (
@@ -979,7 +979,7 @@ MainCommandSearchReplace (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainCommandExit (
@@ -1133,7 +1133,7 @@ MainCommandGotoLine (
@retval EFI_SUCCESS The file was saved correctly.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A file access error occured.
+ @retval EFI_LOAD_ERROR A file access error occurred.
**/
EFI_STATUS
MainCommandSaveFile (
@@ -1439,7 +1439,7 @@ EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {
The initialization function for MainEditor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainEditorInit (
@@ -1585,7 +1585,7 @@ MainEditorInit (
The cleanup function for MainEditor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainEditorCleanup (
@@ -1823,7 +1823,7 @@ MainEditorHandleMouseInput (
Handle user key input. This routes to other functions for the actions.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
index 587d7e0ba61..8ee024c8bf2 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
@@ -15,7 +15,7 @@
The initialization function for MainEditor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainEditorInit (
@@ -26,7 +26,7 @@ MainEditorInit (
The cleanup function for MainEditor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
MainEditorCleanup (
@@ -45,7 +45,7 @@ MainEditorRefresh (
Handle user key input. This routes to other functions for the actions.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
index 915f9f438bc..70103cc6510 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
@@ -72,7 +72,7 @@ BOOLEAN HBufferImageMouseNeedRefresh;
Initialization function for HBufferImage
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HBufferImageInit (
@@ -730,7 +730,7 @@ HBufferImageRestorePosition (
Refresh function for HBufferImage.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A Load error occured.
+ @retval EFI_LOAD_ERROR A Load error occurred.
**/
EFI_STATUS
@@ -1314,7 +1314,7 @@ HBufferImageDoBackspace (
@param[in] Char The input char.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
@@ -2376,7 +2376,7 @@ HBufferImageAdjustMousePosition (
INS
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A Memory allocation failed.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
index ea15a7429f4..082a9cb29bc 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
@@ -16,7 +16,7 @@
Initialization function for HBufferImage
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HBufferImageInit (
@@ -37,7 +37,7 @@ HBufferImageCleanup (
Refresh function for HBufferImage.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A Load error occured.
+ @retval EFI_LOAD_ERROR A Load error occurred.
**/
EFI_STATUS
@@ -57,7 +57,7 @@ HBufferImageRefresh (
INS
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_OUT_OF_RESOURCES A Memory allocation failed.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
index 09bb2e8ad19..5de75a6ba0c 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
@@ -27,7 +27,7 @@ HEFI_EDITOR_CLIPBOARD HClipBoardConst = {
Initialization function for HDiskImage.
@param[in] EFI_SUCCESS The operation was successful.
- @param[in] EFI_LOAD_ERROR A load error occured.
+ @param[in] EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HClipBoardInit (
@@ -46,7 +46,7 @@ HClipBoardInit (
Initialization function for HDiskImage.
@param[in] EFI_SUCCESS The operation was successful.
- @param[in] EFI_LOAD_ERROR A load error occured.
+ @param[in] EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HClipBoardCleanup (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
index b9626830a9f..6408ae0efb2 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
@@ -16,7 +16,7 @@
Initialization function for HDiskImage
@param[in] EFI_SUCCESS The operation was successful.
- @param[in] EFI_LOAD_ERROR A load error occured.
+ @param[in] EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HClipBoardInit (
@@ -27,7 +27,7 @@ HClipBoardInit (
Initialization function for HDiskImage.
@param[in] EFI_SUCCESS The operation was successful.
- @param[in] EFI_LOAD_ERROR A load error occured.
+ @param[in] EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HClipBoardCleanup (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
index be771956b5b..80f614c6793 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
@@ -35,7 +35,7 @@ HEFI_EDITOR_DISK_IMAGE HDiskImageConst = {
Initialization function for HDiskImage.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HDiskImageInit (
@@ -147,7 +147,7 @@ HDiskImageSetDiskNameOffsetSize (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
**/
EFI_STATUS
@@ -319,7 +319,7 @@ HDiskImageRead (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
index 93371ab2a0c..dd1f4760d31 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
@@ -16,7 +16,7 @@
Initialization function for HDiskImage.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HDiskImageInit (
@@ -55,7 +55,7 @@ HDiskImageBackup (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
**/
EFI_STATUS
@@ -76,7 +76,7 @@ HDiskImageRead (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_INVALID_PARAMETER A parameter was invalid.
**/
EFI_STATUS
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
index 6404812da6a..01fb554d81c 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
@@ -131,7 +131,7 @@ HFileImageSetFileName (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HFileImageRead (
@@ -244,7 +244,7 @@ HFileImageRead (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HFileImageSave (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
index 68658b2fda2..9472b343807 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
@@ -52,7 +52,7 @@ HFileImageBackup (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HFileImageRead (
@@ -67,7 +67,7 @@ HFileImageRead (
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HFileImageSave (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
index 4987f17ae27..43e99ba3fa5 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
@@ -243,8 +243,8 @@ HMainCommandGoToOffset (
save to another file name.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandSaveBuffer (
@@ -540,8 +540,8 @@ HMainCommandSaveBuffer (
Load a disk buffer editor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandSelectStart (
@@ -578,8 +578,8 @@ HMainCommandSelectStart (
Load a disk buffer editor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandSelectEnd (
@@ -616,8 +616,8 @@ HMainCommandSelectEnd (
Cut current line to clipboard.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandCut (
@@ -688,8 +688,8 @@ HMainCommandCut (
Paste line to file buffer.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandPaste (
@@ -748,8 +748,8 @@ HMainCommandPaste (
Exit editor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandExit (
@@ -841,8 +841,8 @@ HMainCommandExit (
Load a file from disk to editor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainCommandOpenFile (
@@ -1074,8 +1074,8 @@ HMainCommandOpenFile (
Load a disk buffer editor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_NOT_FOUND The disk was not found.
**/
EFI_STATUS
@@ -1319,8 +1319,8 @@ HMainCommandOpenDisk (
Load memory content to editor
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_NOT_FOUND The disk was not found.
**/
EFI_STATUS
@@ -1623,7 +1623,7 @@ CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = {
Init function for MainEditor
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainEditorInit (
@@ -1780,7 +1780,7 @@ HMainEditorInit (
Cleanup function for MainEditor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainEditorCleanup (
@@ -1932,8 +1932,8 @@ HMainEditorRefresh (
@param[out] BeforeLeftButtonDown helps with selections.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_NOT_FOUND The disk was not found.
**/
EFI_STATUS
@@ -2091,8 +2091,8 @@ HMainEditorHandleMouseInput (
Handle user key input. will route it to other components handle function.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainEditorKeyInput (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
index dc2528b8167..8cce1991aaf 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
@@ -18,7 +18,7 @@
Init function for MainEditor
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainEditorInit (
@@ -29,7 +29,7 @@ HMainEditorInit (
Cleanup function for MainEditor.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainEditorCleanup (
@@ -50,8 +50,8 @@ HMainEditorRefresh (
Handle user key input. will route it to other components handle function.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occurred.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMainEditorKeyInput (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
index e0b220c3db6..ffafb90c06c 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
@@ -34,7 +34,7 @@ HEFI_EDITOR_MEM_IMAGE HMemImageConst = {
Initialization function for HDiskImage.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMemImageInit (
@@ -106,7 +106,7 @@ HMemImageSetMemOffsetSize (
@param[in] Size The size.
@param[in] Recover if is for recover, no information print.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
@@ -217,7 +217,7 @@ HMemImageRead (
@param[in] Offset The offset.
@param[in] Size The size.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
index cab5ce1cda9..5a398a946ac 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
@@ -16,7 +16,7 @@
Initialization function for HDiskImage.
@retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
**/
EFI_STATUS
HMemImageInit (
@@ -56,7 +56,7 @@ HMemImageSetMemOffsetSize (
@param[in] Size The size.
@param[in] Recover if is for recover, no information print.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
@@ -73,7 +73,7 @@ HMemImageRead (
@param[in] Offset The offset.
@param[in] Size The size.
- @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_LOAD_ERROR A load error occurred.
@retval EFI_SUCCESS The operation was successful.
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
index 8159d76df2e..31ce112ae69 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
@@ -33,7 +33,7 @@ HLineFree (
@param[in] Count The line number to advance.
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the line after advance.
**/
HEFI_EDITOR_LINE *
@@ -68,7 +68,7 @@ HLineAdvance (
@param[in] Count The line number to retreat.
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the line after retreat.
**/
HEFI_EDITOR_LINE *
@@ -105,7 +105,7 @@ HLineRetreat (
>0 : advance
<0: retreat
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the line after move.
**/
HEFI_EDITOR_LINE *
@@ -138,7 +138,7 @@ HMoveLine (
>0 : advance
<0: retreat
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the line after move.
**/
HEFI_EDITOR_LINE *
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
index d2316fc2f2e..4f941a60908 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
@@ -18,7 +18,7 @@
>0 : advance
<0: retreat
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the line after move.
**/
HEFI_EDITOR_LINE *
@@ -33,7 +33,7 @@ HMoveLine (
>0 : advance
<0: retreat
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the line after move.
**/
HEFI_EDITOR_LINE *
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
index 464ba7a0734..6cb5cf2382d 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
@@ -1,7 +1,7 @@
/** @file
Main file for Pci shell Debug1 function.
- Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2005 - 2021, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -2038,12 +2038,14 @@ LocatePciCapability (
@param[in] PciExpressCap PCI Express capability buffer.
@param[in] ExtendedConfigSpace PCI Express extended configuration space.
+ @param[in] ExtendedConfigSize PCI Express extended configuration size.
@param[in] ExtendedCapability PCI Express extended capability ID to explain.
**/
VOID
PciExplainPciExpress (
IN PCI_CAPABILITY_PCIEXP *PciExpressCap,
IN UINT8 *ExtendedConfigSpace,
+ IN UINTN ExtendedConfigSize,
IN CONST UINT16 ExtendedCapability
);
@@ -2921,6 +2923,7 @@ ShellCommandRunPci (
PciExplainPciExpress (
(PCI_CAPABILITY_PCIEXP *) ((UINT8 *) &ConfigSpace + PcieCapabilityPtr),
ExtendedConfigSpace,
+ ExtendedConfigSize,
ExtendedCapability
);
}
@@ -5534,8 +5537,8 @@ PrintInterpretedExtendedCompatibilityResizeableBar (
STRING_TOKEN (STR_PCI_EXT_CAP_RESIZE_BAR),
gShellDebug1HiiHandle,
ItemCount+1,
- Header->Capability[ItemCount].ResizableBarCapability,
- Header->Capability[ItemCount].ResizableBarControl
+ Header->Capability[ItemCount].ResizableBarCapability.Uint32,
+ Header->Capability[ItemCount].ResizableBarControl.Uint32
);
}
@@ -5698,12 +5701,14 @@ PrintPciExtendedCapabilityDetails(
@param[in] PciExpressCap PCI Express capability buffer.
@param[in] ExtendedConfigSpace PCI Express extended configuration space.
+ @param[in] ExtendedConfigSize PCI Express extended configuration size.
@param[in] ExtendedCapability PCI Express extended capability ID to explain.
**/
VOID
PciExplainPciExpress (
IN PCI_CAPABILITY_PCIEXP *PciExpressCap,
IN UINT8 *ExtendedConfigSpace,
+ IN UINTN ExtendedConfigSize,
IN CONST UINT16 ExtendedCapability
)
{
@@ -5786,7 +5791,7 @@ PciExplainPciExpress (
}
ExtHdr = (PCI_EXP_EXT_HDR*)ExtendedConfigSpace;
- while (ExtHdr->CapabilityId != 0 && ExtHdr->CapabilityVersion != 0) {
+ while (ExtHdr->CapabilityId != 0 && ExtHdr->CapabilityVersion != 0 && ExtHdr->CapabilityId != 0xFFFF) {
//
// Process this item
//
@@ -5800,7 +5805,8 @@ PciExplainPciExpress (
//
// Advance to the next item if it exists
//
- if (ExtHdr->NextCapabilityOffset != 0) {
+ if (ExtHdr->NextCapabilityOffset != 0 &&
+ (ExtHdr->NextCapabilityOffset <= (UINT32) (ExtendedConfigSize + EFI_PCIE_CAPABILITY_BASE_OFFSET - sizeof (PCI_EXP_EXT_HDR)))) {
ExtHdr = (PCI_EXP_EXT_HDR*)(ExtendedConfigSpace + ExtHdr->NextCapabilityOffset - EFI_PCIE_CAPABILITY_BASE_OFFSET);
} else {
break;
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
index 16ba63d53dd..a89688c841d 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
@@ -49,7 +49,7 @@
#define PRINT_STRUCT_VALUE(pStruct, type, element) \
do { \
ShellPrintEx(-1,-1,L"%a",#element); \
- ShellPrintEx(-1,-1,L": %d\n", (pStruct->type->element)); \
+ ShellPrintEx(-1,-1,L": %u\n", (pStruct->type->element)); \
} while (0);
#define PRINT_STRUCT_VALUE_H(pStruct, type, element) \
@@ -280,6 +280,7 @@ SmbiosPrintStructure (
)
{
UINT8 Index;
+ UINT8 Index2;
UINT8 *Buffer;
if (Struct == NULL) {
@@ -404,6 +405,21 @@ SmbiosPrintStructure (
if (Struct->Hdr->Length > 0x12) {
PRINT_STRUCT_VALUE (Struct, Type3, NumberofPowerCords);
}
+ if (Struct->Hdr->Length > 0x13) {
+ PRINT_STRUCT_VALUE (Struct, Type3, ContainedElementCount);
+ }
+ if (Struct->Hdr->Length > 0x14) {
+ PRINT_STRUCT_VALUE (Struct, Type3, ContainedElementRecordLength);
+ }
+ if (Struct->Hdr->Length > 0x15) {
+ for (Index = 0; Index < Struct->Type3->ContainedElementCount; Index++) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CONTAINED_ELEMENT), gShellDebug1HiiHandle, Index+1);
+ for (Index2 = 0; Index2< Struct->Type3->ContainedElementRecordLength; Index2++) {
+ Print (L"%02X ", Buffer[0x15 + (Index * Struct->Type3->ContainedElementRecordLength) + Index2]);
+ }
+ Print (L"\n");
+ }
+ }
}
if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x13)) {
if (Struct->Hdr->Length > (0x15 + (Struct->Type3->ContainedElementCount * Struct->Type3->ContainedElementRecordLength))) {
@@ -427,7 +443,7 @@ SmbiosPrintStructure (
} else {
DisplayProcessorFamily (Struct->Type4->ProcessorFamily, Option);
}
- PRINT_PENDING_STRING (Struct, Type4, ProcessorManufacture);
+ PRINT_PENDING_STRING (Struct, Type4, ProcessorManufacturer);
PRINT_BIT_FIELD (Struct, Type4, ProcessorId, 8);
PRINT_PENDING_STRING (Struct, Type4, ProcessorVersion);
DisplayProcessorVoltage (*(UINT8 *) &(Struct->Type4->Voltage), Option);
@@ -634,8 +650,8 @@ SmbiosPrintStructure (
NumOfItem = (Struct->Type14->Hdr.Length - 5) / 3;
PRINT_PENDING_STRING (Struct, Type14, GroupName);
for (Index = 0; Index < NumOfItem; Index++) {
- ShellPrintEx(-1,-1,L"ItemType %d: %d\n", Index + 1, Struct->Type14->Group[Index].ItemType);
- ShellPrintEx(-1,-1,L"ItemHandle %d: %d\n", Index + 1, Struct->Type14->Group[Index].ItemHandle);
+ ShellPrintEx(-1,-1,L"ItemType %u: %u\n", Index + 1, Struct->Type14->Group[Index].ItemType);
+ ShellPrintEx(-1,-1,L"ItemHandle %u: %u\n", Index + 1, Struct->Type14->Group[Index].ItemHandle);
}
}
break;
@@ -746,8 +762,8 @@ SmbiosPrintStructure (
case 17:
PRINT_STRUCT_VALUE_H (Struct, Type17, MemoryArrayHandle);
PRINT_STRUCT_VALUE_H (Struct, Type17, MemoryErrorInformationHandle);
- PRINT_STRUCT_VALUE (Struct, Type17, TotalWidth);
- PRINT_STRUCT_VALUE (Struct, Type17, DataWidth);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, TotalWidth);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, DataWidth);
PRINT_STRUCT_VALUE (Struct, Type17, Size);
DisplayMemoryDeviceFormFactor (Struct->Type17->FormFactor, Option);
PRINT_STRUCT_VALUE_H (Struct, Type17, DeviceSet);
@@ -765,7 +781,7 @@ SmbiosPrintStructure (
}
if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x1C)) {
PRINT_STRUCT_VALUE (Struct, Type17, ExtendedSize);
- PRINT_STRUCT_VALUE (Struct, Type17, ConfiguredMemoryClockSpeed);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, ConfiguredMemoryClockSpeed);
}
if (AE_SMBIOS_VERSION (0x2, 0x8) && (Struct->Hdr->Length > 0x22)) {
PRINT_STRUCT_VALUE (Struct, Type17, MinimumVoltage);
@@ -776,23 +792,23 @@ SmbiosPrintStructure (
if (Struct->Hdr->Length > 0x28) {
DisplayMemoryDeviceMemoryTechnology (Struct->Type17->MemoryTechnology, Option);
DisplayMemoryDeviceMemoryOperatingModeCapability (Struct->Type17->MemoryOperatingModeCapability.Uint16, Option);
- PRINT_PENDING_STRING (Struct, Type17, FirwareVersion);
+ PRINT_PENDING_STRING (Struct, Type17, FirmwareVersion);
PRINT_STRUCT_VALUE_H (Struct, Type17, ModuleManufacturerID);
PRINT_STRUCT_VALUE_H (Struct, Type17, ModuleProductID);
PRINT_STRUCT_VALUE_H (Struct, Type17, MemorySubsystemControllerManufacturerID);
PRINT_STRUCT_VALUE_H (Struct, Type17, MemorySubsystemControllerProductID);
}
if (Struct->Hdr->Length > 0x34) {
- PRINT_STRUCT_VALUE_H (Struct, Type17, NonVolatileSize);
+ PRINT_STRUCT_VALUE_LH (Struct, Type17, NonVolatileSize);
}
if (Struct->Hdr->Length > 0x3C) {
- PRINT_STRUCT_VALUE_H (Struct, Type17, VolatileSize);
+ PRINT_STRUCT_VALUE_LH (Struct, Type17, VolatileSize);
}
if (Struct->Hdr->Length > 0x44) {
- PRINT_STRUCT_VALUE_H (Struct, Type17, CacheSize);
+ PRINT_STRUCT_VALUE_LH (Struct, Type17, CacheSize);
}
if (Struct->Hdr->Length > 0x4C) {
- PRINT_STRUCT_VALUE_H (Struct, Type17, LogicalSize);
+ PRINT_STRUCT_VALUE_LH (Struct, Type17, LogicalSize);
}
}
break;
@@ -1284,7 +1300,7 @@ DisplayBiosCharacteristics (
}
if (BIT (Chara, 15) != 0) {
- ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_FORM_CD_SUPPORTED), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_CD_SUPPORTED), gShellDebug1HiiHandle);
}
if (BIT (Chara, 16) != 0) {
@@ -3025,7 +3041,7 @@ DisplaySystemResetCapabilities (
break;
case 3:
- ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT_BITS), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT), gShellDebug1HiiHandle);
break;
}
//
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c
index 2259a659b95..064bed3df6f 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c
@@ -188,19 +188,19 @@ TABLE_ITEM SystemEnclosureTypeTable[] = {
},
{
0x10,
- L" Main Server Chassis"
+ L" Lunch Box"
},
{
0x11,
- L" Expansion Chassis"
+ L" Main Server Chassis"
},
{
0x12,
- L" SubChassis"
+ L" Expansion Chassis"
},
{
0x13,
- L" Sub Notebook"
+ L" SubChassis"
},
{
0x14,
@@ -624,6 +624,10 @@ TABLE_ITEM ProcessorCharacteristicsTable[] = {
{
8,
L" 128-bit Capable"
+ },
+ {
+ 9,
+ L" ARM64 SoC ID"
}
};
@@ -2550,6 +2554,14 @@ TABLE_ITEM MemoryDeviceTypeTable[] = {
{
MemoryTypeHBM2,
L" HBM2 (High Bandwidth Memory Generation 2)"
+ },
+ {
+ MemoryTypeDdr5,
+ L" DDR5"
+ },
+ {
+ MemoryTypeLpddr5,
+ L" LPDDR5"
}
};
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni
index 7fbcc9a31af..9433e8a25f5 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni
@@ -93,6 +93,7 @@
#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_STATE #language en-US "Power Supply State "
#string STR_SMBIOSVIEW_PRINTINFO_THERMAL_STATE #language en-US "Thermal state "
#string STR_SMBIOSVIEW_PRINTINFO_SECURITY_STATUS #language en-US "Security Status "
+#string STR_SMBIOSVIEW_PRINTINFO_CONTAINED_ELEMENT #language en-US "Contained Element %d: "
#string STR_SMBIOSVIEW_PRINTINFO_SUPOPRT #language en-US "Support "
#string STR_SMBIOSVIEW_PRINTINFO_CURRENT #language en-US "Current "
#string STR_SMBIOSVIEW_PRINTINFO_INSTALLED #language en-US "Installed "
@@ -128,7 +129,7 @@
#string STR_SMBIOSVIEW_PRINTINFO_BIOS_SHADOWING #language en-US "BIOS shadowing is allowed\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_VESA_SUPPORTED #language en-US "VL-VESA is supported\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_ECSD_SUPPORT #language en-US "ESCD support is available\r\n"
-#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FORM_CD_SUPPORTED #language en-US "Boot form CD is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_CD_SUPPORTED #language en-US "Boot from CD is supported\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_SELECTED_BOOT_SUPPORTED #language en-US "Selectable Boot is supported\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_BIOS_ROM_SOCKETED #language en-US "BIOS ROM is socketed\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_PC_CARD #language en-US "Boot From PC Card(PCMCIA)is supported\r\n"
@@ -269,7 +270,7 @@
#string STR_SMBIOSVIEW_PRINTINFO_BIT15_NOT_ZERO #language en-US "Error, reserved BIT 15 must be zero\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_PROC_STATUS #language en-US "Processor Status:\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_POPULATED #language en-US "CPU Socket Populated\r\n"
-#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_UNPOPULATED #language en-US "CPU Socket Unpopulated Bits\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_UNPOPULATED #language en-US "CPU Socket Unpopulated\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_CPU_ENABLED #language en-US "CPU Enabled\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_CPU_DISABLED_BY_USER #language en-US "CPU Disabled by User via BIOS Setup\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_CPU_DIABLED_BY_BIOS #language en-US "CPU Disabled By BIOS (POST Error)\r\n"
@@ -333,7 +334,7 @@
#string STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION_LIMIT #language en-US "Boot Option on Limit: "
#string STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2 #language en-US "Operating system\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL #language en-US "System utilities\r\n"
-#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT_BITS #language en-US "Do not reboot Bits\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT #language en-US "Do not reboot\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION #language en-US "Boot Option :"
#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT #language en-US "Do not reboot\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_HARDWARE_SECURITY_SET #language en-US "Hardware Security Settings: \r\n"
@@ -373,7 +374,7 @@
#string STR_SMBIOSVIEW_PRINTINFO_NOT_APPLICABLE #language en-US " Not applicable\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_3 #language en-US " Reserved \r\n"
#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_UNPLUGGED #language en-US "Power supply is unplugged from the wall\r\n"
-#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PLUGGED #language en-US "Power supply is plugged from the wall\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PLUGGED #language en-US "Power supply is plugged into the wall\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PRESENT #language en-US "Power supply is present\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_PRESENT #language en-US "Power supply is not present\r\n"
#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_REPLACE #language en-US "Power supply is hot replaceable\r\n"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
index 44ec109ad53..9a4459e9fc9 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
@@ -113,6 +113,7 @@
BcfgCommandLib
[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## CONSUMES
gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
[Protocols]
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c
index 370e9df366b..cf8d3d32222 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c
@@ -22,7 +22,7 @@ STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
@param[in] TheHandle The handle to get the device path for.
- @retval NULL An error occured.
+ @retval NULL An error occurred.
@return A pointer to the driver path as a string. The callee must
free this memory.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
index 2ffd3dc8a90..f28d2728765 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
@@ -489,6 +489,20 @@ PrintLsOutput(
PrintSfoVolumeInfoTableEntry(ListHead);
}
+ if (!Sfo) {
+ //
+ // Sort the file list by FileName, stably.
+ //
+ // If the call below fails, then the EFI_SHELL_FILE_INFO list anchored to
+ // ListHead will not be changed in any way.
+ //
+ ShellSortFileList (
+ &ListHead,
+ NULL, // Duplicates
+ ShellSortFileListByFileName
+ );
+ }
+
for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link), LongestPath = 0
; !IsNull(&ListHead->Link, &Node->Link)
; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
index b70743b5713..40385346831 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
@@ -57,7 +57,7 @@ IsDirectoryEmpty (
@retval SHELL_SUCCESS The operation was successful.
@retval SHELL_ACCESS_DENIED A file was read only.
@retval SHELL_ABORTED The abort message was received.
- @retval SHELL_DEVICE_ERROR A device error occured reading this Node.
+ @retval SHELL_DEVICE_ERROR A device error occurred reading this Node.
**/
SHELL_STATUS
CascadeDelete(
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
index e1519f8e775..8f6b1cfdf16 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
@@ -351,7 +351,7 @@ CopySingleFile(
@retval SHELL_SUCCESS The operation was successful.
@retval SHELL_ACCESS_DENIED A file was read only.
@retval SHELL_ABORTED The abort message was received.
- @retval SHELL_DEVICE_ERROR A device error occured reading this Node.
+ @retval SHELL_DEVICE_ERROR A device error occurred reading this Node.
**/
SHELL_STATUS
CascadeDelete(
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
index f5344e9e7d1..8ce015746f7 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
@@ -101,24 +101,24 @@
#string STR_TIMEZONE_M6 #language en-US "UTC-06:00, Central America, Central Time(US & Canada)\r\n"
#string STR_TIMEZONE_M5 #language en-US "UTC-05:00, Bogota, Lima, Quito, Eastern Time(US & Canada)\r\n"
#string STR_TIMEZONE_M430 #language en-US "UTC-04:30, Caracas\r\n"
-#string STR_TIMEZONE_M4 #language en-US "UTC-04:00, Atlantic Time(Canada), Caracas, Santiago\r\n"
+#string STR_TIMEZONE_M4 #language en-US "UTC-04:00, Atlantic Time(Canada), Caracas, Santiago, Georgetown\r\n"
#string STR_TIMEZONE_M330 #language en-US "UTC-03:30, Newfoundland\r\n"
-#string STR_TIMEZONE_M3 #language en-US "UTC-03:00, Brasilia, Buenos Aires, Georgetown, Greenland\r\n"
+#string STR_TIMEZONE_M3 #language en-US "UTC-03:00, Brasilia, Buenos Aires, Greenland\r\n"
#string STR_TIMEZONE_M2 #language en-US "UTC-02:00, Mid-Atlantic\r\n"
#string STR_TIMEZONE_M1 #language en-US "UTC-01:00, Azores, Cape Verde Is.\r\n"
#string STR_TIMEZONE_0 #language en-US "UTC , Greenwich Mean Time, Casablanca, Monrovia, Dublin, London\r\n"
#string STR_TIMEZONE_P1 #language en-US "UTC+01:00, Amsterdam, Berlin, Bern, Rome, Paris, West Central Africa\r\n"
-#string STR_TIMEZONE_P2 #language en-US "UTC+02:00, Athens, Istanbul, Bucharest, Cairo, Jerusalem\r\n"
-#string STR_TIMEZONE_P3 #language en-US "UTC+03:00, Baghdad, Kuwait, Riyadh, Moscow, Nairobi\r\n"
+#string STR_TIMEZONE_P2 #language en-US "UTC+02:00, Athens, Bucharest, Cairo, Jerusalem\r\n"
+#string STR_TIMEZONE_P3 #language en-US "UTC+03:00, Baghdad, Kuwait, Riyadh, Moscow, Nairobi, Istanbul\r\n"
#string STR_TIMEZONE_P330 #language en-US "UTC+03:30, Tehran\r\n"
#string STR_TIMEZONE_P4 #language en-US "UTC+04:00, Abu Dhabi, Muscat, Baku, Tbilisi, Yerevan\r\n"
#string STR_TIMEZONE_P430 #language en-US "UTC+04:30, Kabul\r\n"
#string STR_TIMEZONE_P5 #language en-US "UTC+05:00, Ekaterinburg, Islamabad, Karachi, Tashkent\r\n"
#string STR_TIMEZONE_P530 #language en-US "UTC+05:30, Chennai, Kolkata, Mumbai, New Delhi\r\n"
#string STR_TIMEZONE_P545 #language en-US "UTC+05:45, Kathmandu\r\n"
-#string STR_TIMEZONE_P6 #language en-US "UTC+06:00, Almaty, Novosibirsk, Astana, Dhaka, Sri Jayawardenepura\r\n"
+#string STR_TIMEZONE_P6 #language en-US "UTC+06:00, Almaty, Astana, Dhaka, Sri Jayawardenepura\r\n"
#string STR_TIMEZONE_P630 #language en-US "UTC+06:30, Rangoon\r\n"
-#string STR_TIMEZONE_P7 #language en-US "UTC+07:00, Bangkok, Hanio, Jakarta, Krasnoyarsk\r\n"
+#string STR_TIMEZONE_P7 #language en-US "UTC+07:00, Bangkok, Hanio, Jakarta, Krasnoyarsk, Novosibirsk\r\n"
#string STR_TIMEZONE_P8 #language en-US "UTC+08:00, Beijing, Chongqing, Hong Kong, Urumqi, Taipei, Perth\r\n"
#string STR_TIMEZONE_P9 #language en-US "UTC+09:00, Osaka, Sapporo, Tokyo, Seoul, Yakutsk\r\n"
#string STR_TIMEZONE_P930 #language en-US "UTC+09:30, Adelaide, Darwin\r\n"
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLib/UefiShellLib.c b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLib/UefiShellLib.c
index 812ca49d2c0..b3af965f23f 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLib/UefiShellLib.c
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/Library/UefiShellLib/UefiShellLib.c
@@ -3181,7 +3181,7 @@ ShellIsFileInPath(
@param[in] String String representation of a number.
@return The unsigned integer result of the conversion.
- @retval (UINTN)(-1) An error occured.
+ @retval (UINTN)(-1) An error occurred.
**/
UINTN
EFIAPI
@@ -3810,7 +3810,7 @@ InternalShellHexCharToUintn (
@retval EFI_SUCCESS The conversion was successful.
@retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.
- @retval EFI_DEVICE_ERROR An overflow occured.
+ @retval EFI_DEVICE_ERROR An overflow occurred.
**/
EFI_STATUS
InternalShellStrHexToUint64 (
@@ -3911,7 +3911,7 @@ InternalShellStrHexToUint64 (
@retval EFI_SUCCESS The conversion was successful.
@retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.
- @retval EFI_DEVICE_ERROR An overflow occured.
+ @retval EFI_DEVICE_ERROR An overflow occurred.
**/
EFI_STATUS
InternalShellStrDecimalToUint64 (
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.ci.yaml
index 5c77db5c0bd..42d0f519566 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.ci.yaml
@@ -2,9 +2,24 @@
# CI configuration for ShellPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
"CompilerPlugin": {
"DscPath": "ShellPkg.dsc"
},
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dec b/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dec
index adaf81e00bb..bd64b961550 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dec
@@ -34,6 +34,9 @@
## @libraryclass provides BCFG command
BcfgCommandLib|Include/Library/BcfgCommandLib.h
+ ## @libraryclass provides the AcpiView command
+ AcpiViewCommandLib|Include/Library/AcpiViewCommandLib.h
+
[Guids]
gEfiShellEnvironment2ExtGuid = {0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87}}
gEfiShellPkgTokenSpaceGuid = {0x171e9188, 0x31d3, 0x40f5, {0xb1, 0x0c, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd}}
@@ -50,6 +53,7 @@
gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}}
gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, {0xaa, 0x60, 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37}}
gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}
+ gShellHttpHiiGuid = {0x390f84b3, 0x221c, 0x4d9e, {0xb5, 0x06, 0x6d, 0xb9, 0x42, 0x3e, 0x0a, 0x7e}}
gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}}
gShellAcpiViewHiiGuid = {0xda8ccdf4, 0xed8f, 0x4ffc, {0xb5, 0xef, 0x2e, 0xf5, 0x5e, 0x24, 0x93, 0x2a}}
# FILE_GUID as defined in ShellPkg/Application/Shell/Shell.inf
diff --git a/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dsc b/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dsc
index 5ccdd04a675..ad7d0be5da4 100644
--- a/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/ShellPkg/ShellPkg.dsc
@@ -1,8 +1,8 @@
## @file
# Shell Package
#
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
-# Copyright (c) 2018, Arm Limited. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018 - 2020, Arm Limited. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -19,6 +19,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses.common]
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
@@ -47,9 +49,11 @@
ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+ AcpiViewCommandLib|ShellPkg/Library/UefiShellAcpiViewCommandLib/UefiShellAcpiViewCommandLib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
@@ -138,11 +142,17 @@
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
ShellPkg/DynamicCommand/TftpDynamicCommand/TftpApp.inf
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpDynamicCommand.inf {
+ <PcdsFixedAtBuild>
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ }
+ ShellPkg/DynamicCommand/HttpDynamicCommand/HttpApp.inf
ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf {
<PcdsFixedAtBuild>
gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
}
ShellPkg/DynamicCommand/DpDynamicCommand/DpApp.inf
+ ShellPkg/Application/AcpiViewApp/AcpiViewApp.inf
[BuildOptions]
*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
diff --git a/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc b/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc
index 97f765c24c0..cbdaca2409e 100644
--- a/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/SourceLevelDebugPkg/SourceLevelDebugPkg.dsc
@@ -1,7 +1,8 @@
## @file
# Source Level Debug Package.
#
-# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -22,6 +23,8 @@
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
SKUID_IDENTIFIER = DEFAULT
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses.common]
DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
@@ -32,6 +35,7 @@
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
LocalApicLib|UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+ UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dependency.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dependency.c
index af80453f180..7c2c44cbeb5 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dependency.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dependency.c
@@ -3,10 +3,10 @@
This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine
if a driver can be scheduled for execution. The criteria for
- schedulability is that the dependency expression is satisfied.
+ scheduling is that the dependency expression is satisfied.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -193,7 +193,7 @@ MmIsSchedulable (
if (DriverEntry->Depex == NULL) {
//
// A NULL Depex means that the MM driver is not built correctly.
- // All MM drivers must have a valid depex expressiion.
+ // All MM drivers must have a valid depex expression.
//
DEBUG ((DEBUG_DISPATCH, " RESULT = FALSE (Depex is empty)\n"));
ASSERT (FALSE);
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dispatcher.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dispatcher.c
index 0db0e1f4df3..4888c13615e 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dispatcher.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Dispatcher.c
@@ -15,9 +15,10 @@
Step #3 - Adding to the mScheduledQueue requires that you process Before
and After dependencies. This is done recursively as the call to add
- to the mScheduledQueue checks for Before and recursively adds
- all Befores. It then addes the item that was passed in and then
- processess the After dependecies by recursively calling the routine.
+ to the mScheduledQueue checks for Before Depexes and recursively
+ adds all Before Depexes. It then adds the item that was passed in
+ and then processess the After dependencies by recursively calling
+ the routine.
Dispatcher Rules:
The rules for the dispatcher are similar to the DXE dispatcher.
@@ -29,7 +30,7 @@
Copyright (c) 2014, Hewlett-Packard Development Company, L.P.
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -60,8 +61,8 @@ MmCoreFfsFindMmDriver (
/**
Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
must add any driver with a before dependency on InsertedDriverEntry first.
- You do this by recursively calling this routine. After all the Befores are
- processed you can add InsertedDriverEntry to the mScheduledQueue.
+ You do this by recursively calling this routine. After all the Before Depexes
+ are processed you can add InsertedDriverEntry to the mScheduledQueue.
Then you can add any driver with an After dependency on InsertedDriverEntry
by recursively calling this routine.
@@ -92,7 +93,7 @@ LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue);
LIST_ENTRY mFwVolList = INITIALIZE_LIST_HEAD_VARIABLE (mFwVolList);
//
-// Flag for the MM Dispacher. TRUE if dispatcher is execuing.
+// Flag for the MM Dispacher. TRUE if dispatcher is executing.
//
BOOLEAN gDispatcherRunning = FALSE;
@@ -110,7 +111,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED UINT64 *mMmCodeMemoryRangeUsageB
/**
To check memory usage bit map array to figure out if the memory range in which the image will be loaded
- is available or not. If memory range is avaliable, the function will mark the correponding bits to 1
+ is available or not. If memory range is avaliable, the function will mark the corresponding bits to 1
which indicates the memory range is used. The function is only invoked when load modules at fixed address
feature is enabled.
@@ -163,7 +164,7 @@ CheckAndMarkFixLoadingMemoryUsageBitMap (
}
//
- // Test if the memory is avalaible or not.
+ // Test if the memory is available or not.
//
BaseOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES ((UINT32)(ImageBase - MmCodeBase));
TopOffsetPageNumber = (UINTN)EFI_SIZE_TO_PAGES ((UINT32)(ImageBase + ImageSize - MmCodeBase));
@@ -328,7 +329,7 @@ MmLoadImage (
ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)DstBuffer;
//
- // Align buffer on section boundry
+ // Align buffer on section boundary
//
ImageContext.ImageAddress += ImageContext.SectionAlignment - 1;
ImageContext.ImageAddress &= ~((EFI_PHYSICAL_ADDRESS)(ImageContext.SectionAlignment - 1));
@@ -604,7 +605,7 @@ MmDispatcher (
//
// Load the MM Driver image into memory. If the Driver was transitioned from
- // Untrused to Scheduled it would have already been loaded so we may need to
+ // Untrusted to Scheduled it would have already been loaded so we may need to
// skip the LoadImage
//
if (DriverEntry->ImageHandle == NULL) {
@@ -703,8 +704,8 @@ MmDispatcher (
/**
Insert InsertedDriverEntry onto the mScheduledQueue. To do this you
must add any driver with a before dependency on InsertedDriverEntry first.
- You do this by recursively calling this routine. After all the Befores are
- processed you can add InsertedDriverEntry to the mScheduledQueue.
+ You do this by recursively calling this routine. After all the Before Depexes
+ are processed you can add InsertedDriverEntry to the mScheduledQueue.
Then you can add any driver with an After dependency on InsertedDriverEntry
by recursively calling this routine.
@@ -816,7 +817,7 @@ FvIsBeingProcessed (
{
KNOWN_FWVOL *KnownFwVol;
- DEBUG ((DEBUG_INFO, "FvIsBeingProcessed - 0x%08x\n", KnownFwVol));
+ DEBUG ((DEBUG_INFO, "FvIsBeingProcessed - 0x%08x\n", FwVolHeader));
KnownFwVol = AllocatePool (sizeof (KNOWN_FWVOL));
ASSERT (KnownFwVol != NULL);
@@ -828,23 +829,19 @@ FvIsBeingProcessed (
/**
Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry,
- and initilize any state variables. Read the Depex from the FV and store it
+ and initialise any state variables. Read the Depex from the FV and store it
in DriverEntry. Pre-process the Depex to set the Before and After state.
- The Discovered list is never free'ed and contains booleans that represent the
+ The Discovered list is never freed and contains booleans that represent the
other possible MM driver states.
- @param Fv Fv protocol, needed to read Depex info out of
- FLASH.
- @param FvHandle Handle for Fv, needed in the
- EFI_MM_DRIVER_ENTRY so that the PE image can be
- read out of the FV at a later time.
- @param DriverName Name of driver to add to mDiscoveredList.
+ @param [in] FwVolHeader Pointer to the formware volume header.
+ @param [in] Pe32Data Pointer to the PE data.
+ @param [in] Pe32DataSize Size of the PE data.
+ @param [in] Depex Pointer to the Depex info.
+ @param [in] DepexSize Size of the Depex info.
+ @param [in] DriverName Name of driver to add to mDiscoveredList.
@retval EFI_SUCCESS If driver was added to the mDiscoveredList.
- @retval EFI_ALREADY_STARTED The driver has already been started. Only one
- DriverName may be active in the system at any one
- time.
-
**/
EFI_STATUS
MmAddToDriverList (
@@ -885,7 +882,7 @@ MmAddToDriverList (
/**
Traverse the discovered list for any drivers that were discovered but not loaded
- because the dependency experessions evaluated to false.
+ because the dependency expressions evaluated to false.
**/
VOID
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/FwVol.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/FwVol.c
index d2238fc9081..e7941d9fa78 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/FwVol.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/FwVol.c
@@ -1,8 +1,9 @@
-/**@file
+/** @file
+ Firmware volume helper interfaces.
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -42,23 +43,24 @@ FvIsBeingProcessed (
IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
);
-EFI_STATUS
-MmCoreFfsFindMmDriver (
- IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
- )
-/*++
-
-Routine Description:
+/**
Given the pointer to the Firmware Volume Header find the
MM driver and return its PE32 image.
-Arguments:
- FwVolHeader - Pointer to memory mapped FV
+ @param [in] FwVolHeader Pointer to memory mapped FV
-Returns:
- other - Failure
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Could not find section data.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_VOLUME_CORRUPTED Firmware volume is corrupted.
+ @retval EFI_UNSUPPORTED Operation not supported.
---*/
+**/
+EFI_STATUS
+MmCoreFfsFindMmDriver (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+ )
{
EFI_STATUS Status;
EFI_STATUS DepexStatus;
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Locate.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Locate.c
index d1ab16df37a..bc8be157821 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Locate.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Locate.c
@@ -2,7 +2,7 @@
Locate handle functions
Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -173,8 +173,8 @@ MmGetNextLocateByProtocol (
/**
Return the first Protocol Interface that matches the Protocol GUID. If
- Registration is pasased in return a Protocol Instance that was just add
- to the system. If Retistration is NULL return the first Protocol Interface
+ Registration is passed in return a Protocol Instance that was just add
+ to the system. If Registration is NULL return the first Protocol Interface
you find.
@param Protocol The protocol to search for
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Mmi.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Mmi.c
index faef4b10224..1a3c84c6270 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Mmi.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Mmi.c
@@ -2,7 +2,7 @@
MMI management.
Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -220,7 +220,7 @@ MmiManage (
/**
Registers a handler to execute within MM.
- @param Handler Handler service funtion pointer.
+ @param Handler Handler service function pointer.
@param HandlerType Points to the handler type or NULL for root MMI handlers.
@param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Pool.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Pool.c
index 8098c7f8607..3d263ec384e 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Pool.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/Pool.c
@@ -2,7 +2,7 @@
SMM Memory pool management functions.
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -50,7 +50,7 @@ MmInitializeMemoryServices (
continue;
}
DEBUG ((DEBUG_INFO, "MmAddMemoryRegion %d : 0x%016lx - 0x%016lx\n",
- Index, MmramRanges[Index].CpuStart, MmramRanges[Index].PhysicalSize));
+ Index, MmramRanges[Index].CpuStart, MmramRanges[Index].PhysicalSize));
MmAddMemoryRegion (
MmramRanges[Index].CpuStart,
MmramRanges[Index].PhysicalSize,
@@ -86,7 +86,7 @@ InternalAllocPoolByIndex (
Hdr = NULL;
if (PoolIndex == MAX_POOL_INDEX) {
Status = MmInternalAllocatePages (
- AllocateAnyPages,
+ AllocateAnyPages,
EfiRuntimeServicesData,
EFI_SIZE_TO_PAGES (MAX_POOL_SIZE << 1),
&Address
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.c
index 5f42eb5cca5..a7cb1ad94f8 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.c
@@ -2,7 +2,7 @@
MM Core Main Entry Point
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -149,9 +149,10 @@ MmExitBootServiceHandler (
)
{
EFI_HANDLE MmHandle;
- EFI_STATUS Status = EFI_SUCCESS;
+ EFI_STATUS Status;
STATIC BOOLEAN mInExitBootServices = FALSE;
+ Status = EFI_SUCCESS;
if (!mInExitBootServices) {
MmHandle = NULL;
Status = MmInstallProtocolInterface (
@@ -187,9 +188,10 @@ MmReadyToBootHandler (
)
{
EFI_HANDLE MmHandle;
- EFI_STATUS Status = EFI_SUCCESS;
+ EFI_STATUS Status;
STATIC BOOLEAN mInReadyToBoot = FALSE;
+ Status = EFI_SUCCESS;
if (!mInReadyToBoot) {
MmHandle = NULL;
Status = MmInstallProtocolInterface (
@@ -412,6 +414,15 @@ MmEntryPoint (
DEBUG ((DEBUG_INFO, "MmEntryPoint Done\n"));
}
+/** Register the MM Entry Point provided by the MM Core with the
+ MM Configuration protocol.
+
+ @param [in] Protocol Pointer to the protocol.
+ @param [in] Interface Pointer to the MM Configuration protocol.
+ @param [in] Handle Handle.
+
+ @retval EFI_SUCCESS Success.
+**/
EFI_STATUS
EFIAPI
MmConfigurationMmNotify (
@@ -446,6 +457,12 @@ MmConfigurationMmNotify (
return EFI_SUCCESS;
}
+/** Returns the HOB list size.
+
+ @param [in] HobStart Pointer to the start of the HOB list.
+
+ @retval Size of the HOB list.
+**/
UINTN
GetHobListSize (
IN VOID *HobStart
@@ -473,12 +490,10 @@ GetHobListSize (
Note: This function is called for both DXE invocation and MMRAM invocation.
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval Other Some error occurred when executing this entry point.
+ @param HobStart Pointer to the start of the HOB list.
+ @retval EFI_SUCCESS Success.
+ @retval EFI_UNSUPPORTED Unsupported operation.
**/
EFI_STATUS
EFIAPI
@@ -496,7 +511,7 @@ StandaloneMmMain (
EFI_HOB_GUID_TYPE *MmramRangesHob;
EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
EFI_MMRAM_DESCRIPTOR *MmramRanges;
- UINT32 MmramRangeCount;
+ UINTN MmramRangeCount;
EFI_HOB_FIRMWARE_VOLUME *BfvHob;
ProcessLibraryConstructorList (HobStart, &gMmCoreMmst);
@@ -531,7 +546,7 @@ StandaloneMmMain (
MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob);
ASSERT (MmramRangesHobData != NULL);
MmramRanges = MmramRangesHobData->Descriptor;
- MmramRangeCount = MmramRangesHobData->NumberOfMmReservedRegions;
+ MmramRangeCount = (UINTN)MmramRangesHobData->NumberOfMmReservedRegions;
ASSERT (MmramRanges);
ASSERT (MmramRangeCount);
@@ -539,7 +554,7 @@ StandaloneMmMain (
// Copy the MMRAM ranges into MM_CORE_PRIVATE_DATA table just in case any
// code relies on them being present there
//
- gMmCorePrivate->MmramRangeCount = MmramRangeCount;
+ gMmCorePrivate->MmramRangeCount = (UINT64)MmramRangeCount;
gMmCorePrivate->MmramRanges =
(EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (MmramRangeCount * sizeof (EFI_MMRAM_DESCRIPTOR));
ASSERT (gMmCorePrivate->MmramRanges != 0);
@@ -552,7 +567,7 @@ StandaloneMmMain (
DataInHob = GET_GUID_HOB_DATA (GuidHob);
gMmCorePrivate = (MM_CORE_PRIVATE_DATA *)(UINTN)DataInHob->Address;
MmramRanges = (EFI_MMRAM_DESCRIPTOR *)(UINTN)gMmCorePrivate->MmramRanges;
- MmramRangeCount = gMmCorePrivate->MmramRangeCount;
+ MmramRangeCount = (UINTN)gMmCorePrivate->MmramRangeCount;
}
//
@@ -590,9 +605,9 @@ StandaloneMmMain (
//
// No need to initialize memory service.
- // It is done in constructor of StandaloneMmCoreMemoryAllocationLib(),
- // so that the library linked with StandaloneMmCore can use AllocatePool() in constuctor.
- //
+ // It is done in the constructor of StandaloneMmCoreMemoryAllocationLib(),
+ // so that the library linked with StandaloneMmCore can use AllocatePool() in
+ // the constructor.
DEBUG ((DEBUG_INFO, "MmInstallConfigurationTable For HobList\n"));
//
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.h
index 5da811dc749..a08c34cb8a5 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.h
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.h
@@ -3,7 +3,7 @@
internal structure and functions used by MmCore module.
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -131,7 +131,7 @@ typedef struct {
EFI_GUID ProtocolID;
/// All protocol interfaces
LIST_ENTRY Protocols;
- /// Registerd notification handlers
+ /// Registered notification handlers
LIST_ENTRY Notify;
} PROTOCOL_ENTRY;
@@ -516,8 +516,8 @@ MmLocateHandle (
/**
Return the first Protocol Interface that matches the Protocol GUID. If
- Registration is pasased in return a Protocol Instance that was just add
- to the system. If Retistration is NULL return the first Protocol Interface
+ Registration is passed in return a Protocol Instance that was just add
+ to the system. If Registration is NULL return the first Protocol Interface
you find.
@param Protocol The protocol to search for
@@ -564,7 +564,7 @@ MmiManage (
/**
Registers a handler to execute within MM.
- @param Handler Handler service funtion pointer.
+ @param Handler Handler service function pointer.
@param HandlerType Points to the handler type or NULL for root MMI handlers.
@param DispatchHandle On return, contains a unique handle which can be used to later unregister the handler function.
@@ -728,7 +728,7 @@ MmEfiNotAvailableYetArg5 (
);
//
-//Functions used during debug buils
+//Functions used during debug builds
//
/**
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.inf
index 358992ee483..cd33ce21a33 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Core/StandaloneMmCore.inf
@@ -69,8 +69,13 @@
gEdkiiMemoryProfileGuid
gZeroGuid ## SOMETIMES_CONSUMES ## GUID
gEfiHobListGuid
+ gEfiHobMemoryAllocModuleGuid
gMmCoreDataHobGuid
gMmFvDispatchGuid
gEfiEventLegacyBootGuid
gEfiEventExitBootServicesGuid
gEfiEventReadyToBootGuid
+
+[BuildOptions]
+ GCC:*_*_*_CC_FLAGS = -fpie
+ GCC:*_*_*_DLINK_FLAGS = -Wl,-z,text,-Bsymbolic,-pie
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c
index a92a7d750aa..c5139bece67 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/EventHandle.c
@@ -1,7 +1,7 @@
/** @file
Copyright (c) 2016 HP Development Company, L.P.
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -22,6 +22,7 @@
#include <Guid/ZeroGuid.h>
#include <Guid/MmramMemoryReserve.h>
+#include <IndustryStandard/ArmFfaSvc.h>
#include <IndustryStandard/ArmStdSmc.h>
#include "StandaloneMmCpu.h"
@@ -58,6 +59,19 @@ EFI_MM_CONFIGURATION_PROTOCOL mMmConfig = {
STATIC EFI_MM_ENTRY_POINT mMmEntryPoint = NULL;
+/**
+ The PI Standalone MM entry point for the TF-A CPU driver.
+
+ @param [in] EventId The event Id.
+ @param [in] CpuNumber The CPU number.
+ @param [in] NsCommBufferAddr Address of the NS common buffer.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_ACCESS_DENIED Access not permitted.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Operation not supported.
+**/
EFI_STATUS
PiMmStandaloneArmTfCpuDriverEntry (
IN UINTN EventId,
@@ -65,8 +79,8 @@ PiMmStandaloneArmTfCpuDriverEntry (
IN UINTN NsCommBufferAddr
)
{
- EFI_MM_COMMUNICATE_HEADER *GuidedEventContext = NULL;
- EFI_MM_ENTRY_CONTEXT MmEntryPointContext = {0};
+ EFI_MM_COMMUNICATE_HEADER *GuidedEventContext;
+ EFI_MM_ENTRY_CONTEXT MmEntryPointContext;
EFI_STATUS Status;
UINTN NsCommBufferSize;
@@ -78,18 +92,25 @@ PiMmStandaloneArmTfCpuDriverEntry (
// receipt of a synchronous MM request. Use the Event ID to distinguish
// between synchronous and asynchronous events.
//
- if (ARM_SMC_ID_MM_COMMUNICATE_AARCH64 != EventId) {
+ if ((ARM_SMC_ID_MM_COMMUNICATE_AARCH64 != EventId) &&
+ (ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64 != EventId)) {
DEBUG ((DEBUG_INFO, "UnRecognized Event - 0x%x\n", EventId));
return EFI_INVALID_PARAMETER;
}
// Perform parameter validation of NsCommBufferAddr
- if (NsCommBufferAddr && (NsCommBufferAddr < mNsCommBuffer.PhysicalStart))
+ if (NsCommBufferAddr == (UINTN)NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (NsCommBufferAddr < mNsCommBuffer.PhysicalStart) {
return EFI_ACCESS_DENIED;
+ }
if ((NsCommBufferAddr + sizeof (EFI_MM_COMMUNICATE_HEADER)) >=
- (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize))
+ (mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)) {
return EFI_INVALID_PARAMETER;
+ }
// Find out the size of the buffer passed
NsCommBufferSize = ((EFI_MM_COMMUNICATE_HEADER *) NsCommBufferAddr)->MessageLength +
@@ -97,10 +118,11 @@ PiMmStandaloneArmTfCpuDriverEntry (
// perform bounds check.
if (NsCommBufferAddr + NsCommBufferSize >=
- mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize)
+ mNsCommBuffer.PhysicalStart + mNsCommBuffer.PhysicalSize) {
return EFI_ACCESS_DENIED;
+ }
-
+ GuidedEventContext = NULL;
// Now that the secure world can see the normal world buffer, allocate
// memory to copy the communication buffer to the secure world.
Status = mMmst->MmAllocatePool (
@@ -121,6 +143,8 @@ PiMmStandaloneArmTfCpuDriverEntry (
// Stash the pointer to the allocated Event Context for this CPU
PerCpuGuidedEventContext[CpuNumber] = GuidedEventContext;
+ ZeroMem (&MmEntryPointContext, sizeof (EFI_MM_ENTRY_CONTEXT));
+
MmEntryPointContext.CurrentlyExecutingCpu = CpuNumber;
MmEntryPointContext.NumberOfCpus = mMpInformationHobData->NumberOfProcessors;
@@ -150,6 +174,14 @@ PiMmStandaloneArmTfCpuDriverEntry (
return Status;
}
+/**
+ Registers the MM foundation entry point.
+
+ @param [in] This Pointer to the MM Configuration protocol.
+ @param [in] MmEntryPoint Function pointer to the MM Entry point.
+
+ @retval EFI_SUCCESS Success.
+**/
EFI_STATUS
EFIAPI
MmFoundationEntryRegister (
@@ -166,10 +198,13 @@ MmFoundationEntryRegister (
This function is the main entry point for an MM handler dispatch
or communicate-based callback.
- @param DispatchHandle The unique handle assigned to this handler by MmiHandlerRegister().
- @param Context Points to an optional handler context which was specified when the handler was registered.
+ @param DispatchHandle The unique handle assigned to this handler by
+ MmiHandlerRegister().
+ @param Context Points to an optional handler context which was
+ specified when the handler was registered.
@param CommBuffer A pointer to a collection of data in memory that will
- be conveyed from a non-MM environment into an MM environment.
+ be conveyed from a non-MM environment into an
+ MM environment.
@param CommBufferSize The size of the CommBuffer.
@return Status Code
@@ -192,8 +227,9 @@ PiMmCpuTpFwRootMmiHandler (
ASSERT (CommBufferSize == NULL);
CpuNumber = mMmst->CurrentlyExecutingCpu;
- if (!PerCpuGuidedEventContext[CpuNumber])
+ if (PerCpuGuidedEventContext[CpuNumber] == NULL) {
return EFI_NOT_FOUND;
+ }
DEBUG ((DEBUG_INFO, "CommBuffer - 0x%x, CommBufferSize - 0x%x\n",
PerCpuGuidedEventContext[CpuNumber],
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c
index 1470df75a84..b543733e53c 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.c
@@ -2,7 +2,7 @@
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
Copyright (c) 2016 HP Development Company, L.P.
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -44,6 +44,16 @@ EFI_MM_SYSTEM_TABLE *mMmst = NULL;
//
STATIC EFI_HANDLE mMmCpuHandle = NULL;
+/** Returns the HOB data for the matching HOB GUID.
+
+ @param [in] HobList Pointer to the HOB list.
+ @param [in] HobGuid The GUID for the HOB.
+ @param [out] HobData Pointer to the HOB data.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_NOT_FOUND Could not find HOB with matching GUID.
+**/
EFI_STATUS
GetGuidedHobData (
IN VOID *HobList,
@@ -53,23 +63,37 @@ GetGuidedHobData (
{
EFI_HOB_GUID_TYPE *Hob;
- if (!HobList || !HobGuid || !HobData)
+ if ((HobList == NULL) || (HobGuid == NULL) || (HobData == NULL)) {
return EFI_INVALID_PARAMETER;
+ }
Hob = GetNextGuidHob (HobGuid, HobList);
- if (!Hob)
+ if (Hob == NULL) {
return EFI_NOT_FOUND;
+ }
*HobData = GET_GUID_HOB_DATA (Hob);
- if (!HobData)
+ if (*HobData == NULL) {
return EFI_NOT_FOUND;
+ }
return EFI_SUCCESS;
}
+/** Entry point for the Standalone MM CPU driver.
+
+ @param [in] ImageHandle Unused. Not actual image handle.
+ @param [in] SystemTable Pointer to MM System table.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_NOT_FOUND Failed to find the HOB for the CPU
+ driver endpoint descriptor.
+**/
EFI_STATUS
StandaloneMmCpuInitialize (
- IN EFI_HANDLE ImageHandle, // not actual imagehandle
+ IN EFI_HANDLE ImageHandle, // not actual imagehandle
IN EFI_MM_SYSTEM_TABLE *SystemTable // not actual systemtable
)
{
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h
index 5e73e005a46..9058428d1e1 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.h
@@ -2,7 +2,7 @@
Private header with declarations and definitions specific to the MM Standalone
CPU driver
- Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+ Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -33,6 +33,19 @@ extern EFI_MMRAM_DESCRIPTOR mNsCommBuffer;
extern MP_INFORMATION_HOB_DATA *mMpInformationHobData;
extern EFI_MM_CONFIGURATION_PROTOCOL mMmConfig;
+/**
+ The PI Standalone MM entry point for the TF-A CPU driver.
+
+ @param [in] EventId The event Id.
+ @param [in] CpuNumber The CPU number.
+ @param [in] NsCommBufferAddr Address of the NS common buffer.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_ACCESS_DENIED Access not permitted.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Operation not supported.
+**/
EFI_STATUS
PiMmStandaloneArmTfCpuDriverEntry (
IN UINTN EventId,
@@ -40,6 +53,22 @@ PiMmStandaloneArmTfCpuDriverEntry (
IN UINTN NsCommBufferAddr
);
+/**
+ This function is the main entry point for an MM handler dispatch
+ or communicate-based callback.
+
+ @param DispatchHandle The unique handle assigned to this handler by
+ MmiHandlerRegister().
+ @param Context Points to an optional handler context which was
+ specified when the handler was registered.
+ @param CommBuffer A pointer to a collection of data in memory that will
+ be conveyed from a non-MM environment into an
+ MM environment.
+ @param CommBufferSize The size of the CommBuffer.
+
+ @return Status Code
+
+**/
EFI_STATUS
EFIAPI
PiMmCpuTpFwRootMmiHandler (
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf
index 9b245383590..460d9ce8c0c 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf
@@ -1,14 +1,12 @@
-#/** @file
-#
+## @file
# Standalone MM CPU driver for ARM Standard Platforms
#
# Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
# Copyright (c) 2016 HP Development Company, L.P.
-# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
+# Copyright (c) 2017 - 2021, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#**/
+##
[Defines]
INF_VERSION = 0x0001001A
@@ -21,6 +19,7 @@
[Sources]
StandaloneMmCpu.c
+ StandaloneMmCpu.h
EventHandle.c
[Packages]
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Guid/MmCoreData.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Guid/MmCoreData.h
index 2596f96d0db..6c33b4bedf9 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Guid/MmCoreData.h
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Guid/MmCoreData.h
@@ -2,7 +2,7 @@
MM Core data.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2018, ARM Limited. All rights reserved.<BR>
+Copyright (c) 2018 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -98,14 +98,14 @@ typedef struct {
EFI_PHYSICAL_ADDRESS Mmst;
///
- /// This field is used by the MM Communicatioon Protocol to pass a buffer into
+ /// This field is used by the MM Communication Protocol to pass a buffer into
/// a software MMI handler and for the software MMI handler to pass a buffer back to
/// the caller of the MM Communication Protocol.
///
EFI_PHYSICAL_ADDRESS CommunicationBuffer;
///
- /// This field is used by the MM Communicatioon Protocol to pass the size of a buffer,
+ /// This field is used by the MM Communication Protocol to pass the size of a buffer,
/// in bytes, into a software MMI handler and for the software MMI handler to pass the
/// size, in bytes, of a buffer back to the caller of the MM Communication Protocol.
///
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
index 80128f9a5a1..d13b0665597 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
@@ -2,7 +2,7 @@
Entry point to the Standalone MM Foundation when initialized during the SEC
phase on ARM platforms
-Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -70,18 +70,20 @@ typedef RETURN_STATUS (*REGION_PERMISSION_UPDATE_FUNC) (
sections in the Standalone MM Core module to be able to access RO and RW data
and make further progress in the boot process.
- @param ImageContext Pointer to PE/COFF image context
- @param SectionHeaderOffset Offset of PE/COFF image section header
- @param NumberOfSections Number of Sections
- @param TextUpdater Function to change code permissions
- @param ReadOnlyUpdater Function to change RO permissions
- @param ReadWriteUpdater Function to change RW permissions
+ @param [in] ImageContext Pointer to PE/COFF image context
+ @param [in] ImageBase Base of image in memory
+ @param [in] SectionHeaderOffset Offset of PE/COFF image section header
+ @param [in] NumberOfSections Number of Sections
+ @param [in] TextUpdater Function to change code permissions
+ @param [in] ReadOnlyUpdater Function to change RO permissions
+ @param [in] ReadWriteUpdater Function to change RW permissions
**/
EFI_STATUS
EFIAPI
UpdateMmFoundationPeCoffPermissions (
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_PHYSICAL_ADDRESS ImageBase,
IN UINT32 SectionHeaderOffset,
IN CONST UINT16 NumberOfSections,
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
@@ -96,10 +98,11 @@ UpdateMmFoundationPeCoffPermissions (
the Standalone MM Core module to be able to change permissions of the
individual sections later in the boot process.
- @param TeData Pointer to PE/COFF image data
- @param ImageContext Pointer to PE/COFF image context
- @param SectionHeaderOffset Offset of PE/COFF image section header
- @param NumberOfSections Number of Sections
+ @param [in] TeData Pointer to PE/COFF image data
+ @param [in, out] ImageContext Pointer to PE/COFF image context
+ @param [out] ImageBase Pointer to ImageBase variable
+ @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header
+ @param [in, out] NumberOfSections Number of Sections
**/
EFI_STATUS
@@ -107,6 +110,7 @@ EFIAPI
GetStandaloneMmCorePeCoffSections (
IN VOID *TeData,
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_PHYSICAL_ADDRESS *ImageBase,
IN OUT UINT32 *SectionHeaderOffset,
IN OUT UINT16 *NumberOfSections
);
@@ -117,10 +121,10 @@ GetStandaloneMmCorePeCoffSections (
by the Boot Firmware Volume. This function locates the Standalone MM Core
module PE/COFF image in the BFV and returns this information.
- @param BfvAddress Base Address of Boot Firmware Volume
- @param TeData Pointer to address for allocating memory for
- PE/COFF image data
- @param TeDataSize Pointer to size of PE/COFF image data
+ @param [in] BfvAddress Base Address of Boot Firmware Volume
+ @param [in, out] TeData Pointer to address for allocating memory
+ for PE/COFF image data
+ @param [in, out] TeDataSize Pointer to size of PE/COFF image data
**/
EFI_STATUS
@@ -136,8 +140,9 @@ LocateStandaloneMmCorePeCoffData (
Use the boot information passed by privileged firmware to populate a HOB list
suitable for consumption by the MM Core and drivers.
- @param CpuDriverEntryPoint Address of MM CPU driver entrypoint
- @param PayloadBootInfo Boot information passed by privileged firmware
+ @param [in, out] CpuDriverEntryPoint Address of MM CPU driver entrypoint
+ @param [in] PayloadBootInfo Boot information passed by privileged
+ firmware
**/
VOID *
@@ -151,9 +156,11 @@ CreateHobListFromBootInfo (
/**
The entry point of Standalone MM Foundation.
- @param SharedBufAddress Pointer to the Buffer between SPM and SP.
- @param cookie1.
- @param cookie2.
+ @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP.
+ @param [in] SharedBufSize Size of the shared buffer.
+ @param [in] cookie1 Cookie 1
+ @param [in] cookie2 Cookie 2
+
**/
VOID
EFIAPI
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/FvLib.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/FvLib.h
index 5e4ee664798..038fff97d3a 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/FvLib.h
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/FvLib.h
@@ -50,6 +50,7 @@ FfsFindNextFile (
@retval EFI_SUCCESS
**/
EFI_STATUS
+EFIAPI
FfsFindSection (
IN EFI_SECTION_TYPE SectionType,
IN EFI_FFS_FILE_HEADER *FfsFileHeader,
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmDriverEntryPoint.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmDriverEntryPoint.h
deleted file mode 100644
index 3f557884599..00000000000
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmDriverEntryPoint.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/** @file
- Module entry point library for Standalone MM Drivers.
-
-Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
-
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef __MODULE_ENTRY_POINT_H__
-#define __MODULE_ENTRY_POINT_H__
-
-///
-///Declare the PI Specification Revision that this driver requires to execute correctly.
-///
-extern CONST UINT32 _gMmRevision;
-
-/**
- The entry point of PE/COFF Image for a Standalone MM Driver.
-
- This function is the entry point for a Standalone MM Driver.
- This function must call ProcessLibraryConstructorList() and
- ProcessModuleEntryPointList().
- If the return status from ProcessModuleEntryPointList()
- is an error status, then ProcessLibraryDestructorList() must be called.
- The return value from ProcessModuleEntryPointList() is returned.
- If _gDriverUnloadImageCount is greater
- than zero, then an unload handler must be registered for this image and
- the unload handler must invoke ProcessModuleUnloadList().
- If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is
- less than _gUefiDriverRevison, then return EFI_INCOMPATIBLE_VERSION.
-
- @param ImageHandle The image handle of the Standalone MM Driver.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The Standalone MM Driver exited normally.
- @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
- SystemTable->Hdr.Revision.
- @retval Other Return value from
- ProcessModuleEntryPointList().
-
-**/
-EFI_STATUS
-EFIAPI
-_ModuleEntryPoint (
- IN EFI_HANDLE ImageHandle,
- IN EFI_MM_SYSTEM_TABLE *MmSystemTable
- );
-
-
-/**
- Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
-
- This function is required to call _ModuleEntryPoint() passing in ImageHandle, and SystemTable.
-
- @param ImageHandle The image handle of the Standalone MM Driver.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The Standalone MM Driver exited normally.
- @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
- SystemTable->Hdr.Revision.
- @retval Other Return value from ProcessModuleEntryPointList().
-**/
-EFI_STATUS
-EFIAPI
-EfiMain (
- IN EFI_HANDLE ImageHandle,
- IN EFI_MM_SYSTEM_TABLE *MmSystemTable
- );
-
-/**
- Auto generated function that calls the library constructors for all of the module's
- dependent libraries.
-
- This function must be called by _ModuleEntryPoint().
- This function calls the set of library constructors for the set of library instances
- that a module depends on. This includes library instances that a module depends on
- directly and library instances that a module depends on indirectly through other libraries.
- This function is auto generated by build tools and those build tools are responsible
- for collecting the set of library instances, determine which ones have constructors,
- and calling the library constructors in the proper order based upon each of the library
- instances own dependencies.
-
- @param ImageHandle The image handle of the Standalone MM Driver.
- @param SystemTable A pointer to the EFI System Table.
-
-**/
-VOID
-EFIAPI
-ProcessLibraryConstructorList (
- IN EFI_HANDLE ImageHandle,
- IN EFI_MM_SYSTEM_TABLE *MmSystemTable
- );
-
-
-/**
- Auto generated function that calls the library descructors for all of the module's
- dependent libraries.
-
- This function may be called by _ModuleEntryPoint() or ExitDriver().
- This function calls the set of library destructors for the set of library instances
- that a module depends on. This includes library instances that a module depends on
- directly and library instances that a module depends on indirectly through other libraries.
- This function is auto generated by build tools and those build tools are responsible for
- collecting the set of library instances, determine which ones have destructors, and calling
- the library destructors in the proper order based upon each of the library instances own dependencies.
-
- @param ImageHandle The image handle of the Standalone MM Driver.
- @param SystemTable A pointer to the EFI System Table.
-
-**/
-VOID
-EFIAPI
-ProcessLibraryDestructorList (
- IN EFI_HANDLE ImageHandle,
- IN EFI_MM_SYSTEM_TABLE *MmSystemTable
- );
-
-
-/**
- Auto generated function that calls a set of module entry points.
-
- This function must be called by _ModuleEntryPoint().
- This function calls the set of module entry points.
- This function is auto generated by build tools and those build tools are responsible
- for collecting the module entry points and calling them in a specified order.
-
- @param ImageHandle The image handle of the Standalone MM Driver.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The Standalone MMDriver executed normally.
- @retval !EFI_SUCCESS The Standalone MM Driver failed to execute normally.
-**/
-EFI_STATUS
-EFIAPI
-ProcessModuleEntryPointList (
- IN EFI_HANDLE ImageHandle,
- IN EFI_MM_SYSTEM_TABLE *MmSystemTable
- );
-
-#endif
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmMemLib.h b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmMemLib.h
index 8b55194b40f..20b0c0c8ecb 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmMemLib.h
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Include/Library/StandaloneMmMemLib.h
@@ -6,7 +6,7 @@
from non-MMRAM to non-MMRAM, or set data in non-MMRAM.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -69,7 +69,7 @@ MmCopyMemToMmram (
@param SourceBuffer The pointer to the source buffer of the memory copy.
@param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
- @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with MMRAM.
+ @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM.
@retval EFI_SUCCESS Memory is copied.
**/
@@ -94,7 +94,7 @@ MmCopyMemFromMmram (
@param SourceBuffer The pointer to the source buffer of the memory copy.
@param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
- @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with MMRAM.
+ @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM.
@retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM.
@retval EFI_SUCCESS Memory is copied.
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c
index 6a6caceda58..dd2db78a783 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/CreateHobList.c
@@ -2,7 +2,7 @@
Creates HOB during Standalone MM Foundation entry point
on ARM platforms.
-Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -46,7 +46,9 @@ extern EFI_GUID gEfiArmTfCpuDriverEpDescriptorGuid;
Use the boot information passed by privileged firmware to populate a HOB list
suitable for consumption by the MM Core and drivers.
- @param PayloadBootInfo Boot information passed by privileged firmware
+ @param [in, out] CpuDriverEntryPoint Address of MM CPU driver entrypoint
+ @param [in] PayloadBootInfo Boot information passed by privileged
+ firmware
**/
VOID *
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
index 87bad88186f..f0db0eb597e 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/SetPermissions.c
@@ -2,7 +2,7 @@
Locate, get and update PE/COFF permissions during Standalone MM
Foundation Entry point on ARM platforms.
-Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -25,10 +25,26 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <IndustryStandard/ArmStdSmc.h>
+/**
+ Privileged firmware assigns RO & Executable attributes to all memory occupied
+ by the Boot Firmware Volume. This function sets the correct permissions of
+ sections in the Standalone MM Core module to be able to access RO and RW data
+ and make further progress in the boot process.
+
+ @param [in] ImageContext Pointer to PE/COFF image context
+ @param [in] ImageBase Base of image in memory
+ @param [in] SectionHeaderOffset Offset of PE/COFF image section header
+ @param [in] NumberOfSections Number of Sections
+ @param [in] TextUpdater Function to change code permissions
+ @param [in] ReadOnlyUpdater Function to change RO permissions
+ @param [in] ReadWriteUpdater Function to change RW permissions
+
+**/
EFI_STATUS
EFIAPI
UpdateMmFoundationPeCoffPermissions (
IN CONST PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ IN EFI_PHYSICAL_ADDRESS ImageBase,
IN UINT32 SectionHeaderOffset,
IN CONST UINT16 NumberOfSections,
IN REGION_PERMISSION_UPDATE_FUNC TextUpdater,
@@ -87,7 +103,7 @@ UpdateMmFoundationPeCoffPermissions (
// if it is a writeable section then mark it appropriately as well.
//
if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_MEM_EXECUTE) == 0) {
- Base = ImageContext->ImageAddress + SectionHeader.VirtualAddress;
+ Base = ImageBase + SectionHeader.VirtualAddress;
TextUpdater (Base, SectionHeader.Misc.VirtualSize);
@@ -112,6 +128,17 @@ UpdateMmFoundationPeCoffPermissions (
return RETURN_SUCCESS;
}
+/**
+ Privileged firmware assigns RO & Executable attributes to all memory occupied
+ by the Boot Firmware Volume. This function locates the Standalone MM Core
+ module PE/COFF image in the BFV and returns this information.
+
+ @param [in] BfvAddress Base Address of Boot Firmware Volume
+ @param [in, out] TeData Pointer to address for allocating memory
+ for PE/COFF image data
+ @param [in, out] TeDataSize Pointer to size of PE/COFF image data
+
+**/
EFI_STATUS
EFIAPI
LocateStandaloneMmCorePeCoffData (
@@ -120,9 +147,10 @@ LocateStandaloneMmCorePeCoffData (
IN OUT UINTN *TeDataSize
)
{
- EFI_FFS_FILE_HEADER *FileHeader = NULL;
+ EFI_FFS_FILE_HEADER *FileHeader;
EFI_STATUS Status;
+ FileHeader = NULL;
Status = FfsFindNextFile (
EFI_FV_FILETYPE_SECURITY_CORE,
BfvAddress,
@@ -149,10 +177,20 @@ LocateStandaloneMmCorePeCoffData (
return Status;
}
+/**
+ Returns the PC COFF section information.
+
+ @param [in, out] ImageContext Pointer to PE/COFF image context
+ @param [out] ImageBase Base of image in memory
+ @param [out] SectionHeaderOffset Offset of PE/COFF image section header
+ @param [out] NumberOfSections Number of Sections
+
+**/
STATIC
EFI_STATUS
GetPeCoffSectionInformation (
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_PHYSICAL_ADDRESS *ImageBase,
OUT UINT32 *SectionHeaderOffset,
OUT UINT16 *NumberOfSections
)
@@ -212,6 +250,7 @@ GetPeCoffSectionInformation (
return Status;
}
+ *ImageBase = ImageContext->ImageAddress;
if (!ImageContext->IsTeImage) {
ASSERT (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE);
@@ -232,16 +271,30 @@ GetPeCoffSectionInformation (
} else {
*SectionHeaderOffset = (UINTN)(sizeof (EFI_TE_IMAGE_HEADER));
*NumberOfSections = Hdr.Te->NumberOfSections;
- ImageContext->ImageAddress -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
+ *ImageBase -= (UINT32)Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER);
}
return RETURN_SUCCESS;
}
+/**
+ Privileged firmware assigns RO & Executable attributes to all memory occupied
+ by the Boot Firmware Volume. This function locates the section information of
+ the Standalone MM Core module to be able to change permissions of the
+ individual sections later in the boot process.
+
+ @param [in] TeData Pointer to PE/COFF image data
+ @param [in, out] ImageContext Pointer to PE/COFF image context
+ @param [out] ImageBase Pointer to ImageBase variable
+ @param [in, out] SectionHeaderOffset Offset of PE/COFF image section header
+ @param [in, out] NumberOfSections Number of Sections
+
+**/
EFI_STATUS
EFIAPI
GetStandaloneMmCorePeCoffSections (
IN VOID *TeData,
IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext,
+ OUT EFI_PHYSICAL_ADDRESS *ImageBase,
IN OUT UINT32 *SectionHeaderOffset,
IN OUT UINT16 *NumberOfSections
)
@@ -255,7 +308,8 @@ GetStandaloneMmCorePeCoffSections (
DEBUG ((DEBUG_INFO, "Found Standalone MM PE data - 0x%x\n", TeData));
- Status = GetPeCoffSectionInformation (ImageContext, SectionHeaderOffset, NumberOfSections);
+ Status = GetPeCoffSectionInformation (ImageContext, ImageBase,
+ SectionHeaderOffset, NumberOfSections);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Unable to locate Standalone MM Core PE-COFF Section information - %r\n", Status));
return Status;
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
index 51825e50d56..5f4e0f74b2b 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/StandaloneMmCoreEntryPoint.c
@@ -2,7 +2,7 @@
Entry point to the Standalone MM Foundation when initialized during the SEC
phase on ARM platforms
-Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -23,26 +23,33 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/SerialPortLib.h>
+#include <Library/PcdLib.h>
#include <IndustryStandard/ArmStdSmc.h>
#include <IndustryStandard/ArmMmSvc.h>
+#include <IndustryStandard/ArmFfaSvc.h>
#define SPM_MAJOR_VER_MASK 0xFFFF0000
#define SPM_MINOR_VER_MASK 0x0000FFFF
#define SPM_MAJOR_VER_SHIFT 16
+#define FFA_NOT_SUPPORTED -1
-CONST UINT32 SPM_MAJOR_VER = 0;
-CONST UINT32 SPM_MINOR_VER = 1;
+STATIC CONST UINT32 mSpmMajorVer = SPM_MAJOR_VERSION;
+STATIC CONST UINT32 mSpmMinorVer = SPM_MINOR_VERSION;
-CONST UINT8 BOOT_PAYLOAD_VERSION = 1;
+STATIC CONST UINT32 mSpmMajorVerFfa = SPM_MAJOR_VERSION_FFA;
+STATIC CONST UINT32 mSpmMinorVerFfa = SPM_MINOR_VERSION_FFA;
+
+#define BOOT_PAYLOAD_VERSION 1
PI_MM_ARM_TF_CPU_DRIVER_ENTRYPOINT CpuDriverEntryPoint = NULL;
/**
Retrieve a pointer to and print the boot information passed by privileged
- secure firmware
+ secure firmware.
- @param SharedBufAddress The pointer memory shared with privileged firmware
+ @param [in] SharedBufAddress The pointer memory shared with privileged
+ firmware.
**/
EFI_SECURE_PARTITION_BOOT_INFO *
@@ -101,12 +108,19 @@ GetAndPrintBootinformation (
return PayloadBootInfo;
}
+/**
+ A loop to delegated events.
+
+ @param [in] EventCompleteSvcArgs Pointer to the event completion arguments.
+
+**/
VOID
EFIAPI
DelegatedEventLoop (
IN ARM_SVC_ARGS *EventCompleteSvcArgs
)
{
+ BOOLEAN FfaEnabled;
EFI_STATUS Status;
UINTN SvcStatus;
@@ -118,16 +132,32 @@ DelegatedEventLoop (
DEBUG ((DEBUG_INFO, "X1 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg1));
DEBUG ((DEBUG_INFO, "X2 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg2));
DEBUG ((DEBUG_INFO, "X3 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg3));
-
- Status = CpuDriverEntryPoint (
- EventCompleteSvcArgs->Arg0,
- EventCompleteSvcArgs->Arg3,
- EventCompleteSvcArgs->Arg1
- );
-
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
- EventCompleteSvcArgs->Arg0, Status));
+ DEBUG ((DEBUG_INFO, "X4 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg4));
+ DEBUG ((DEBUG_INFO, "X5 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg5));
+ DEBUG ((DEBUG_INFO, "X6 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg6));
+ DEBUG ((DEBUG_INFO, "X7 : 0x%x\n", (UINT32) EventCompleteSvcArgs->Arg7));
+
+ FfaEnabled = FeaturePcdGet (PcdFfaEnable);
+ if (FfaEnabled) {
+ Status = CpuDriverEntryPoint (
+ EventCompleteSvcArgs->Arg0,
+ EventCompleteSvcArgs->Arg6,
+ EventCompleteSvcArgs->Arg3
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
+ EventCompleteSvcArgs->Arg3, Status));
+ }
+ } else {
+ Status = CpuDriverEntryPoint (
+ EventCompleteSvcArgs->Arg0,
+ EventCompleteSvcArgs->Arg3,
+ EventCompleteSvcArgs->Arg1
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed delegated event 0x%x, Status 0x%x\n",
+ EventCompleteSvcArgs->Arg0, Status));
+ }
}
switch (Status) {
@@ -151,29 +181,58 @@ DelegatedEventLoop (
break;
}
- EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
- EventCompleteSvcArgs->Arg1 = SvcStatus;
+ if (FfaEnabled) {
+ EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64;
+ EventCompleteSvcArgs->Arg1 = 0;
+ EventCompleteSvcArgs->Arg2 = 0;
+ EventCompleteSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
+ EventCompleteSvcArgs->Arg4 = SvcStatus;
+ } else {
+ EventCompleteSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
+ EventCompleteSvcArgs->Arg1 = SvcStatus;
+ }
}
}
+/**
+ Query the SPM version, check compatibility and return success if compatible.
+
+ @retval EFI_SUCCESS SPM versions compatible.
+ @retval EFI_UNSUPPORTED SPM versions not compatible.
+**/
STATIC
EFI_STATUS
GetSpmVersion (VOID)
{
EFI_STATUS Status;
- UINT16 SpmMajorVersion;
- UINT16 SpmMinorVersion;
+ UINT16 CalleeSpmMajorVer;
+ UINT16 CallerSpmMajorVer;
+ UINT16 CalleeSpmMinorVer;
+ UINT16 CallerSpmMinorVer;
UINT32 SpmVersion;
ARM_SVC_ARGS SpmVersionArgs;
- SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32;
+ if (FeaturePcdGet (PcdFfaEnable)) {
+ SpmVersionArgs.Arg0 = ARM_SVC_ID_FFA_VERSION_AARCH32;
+ SpmVersionArgs.Arg1 = mSpmMajorVerFfa << SPM_MAJOR_VER_SHIFT;
+ SpmVersionArgs.Arg1 |= mSpmMinorVerFfa;
+ CallerSpmMajorVer = mSpmMajorVerFfa;
+ CallerSpmMinorVer = mSpmMinorVerFfa;
+ } else {
+ SpmVersionArgs.Arg0 = ARM_SVC_ID_SPM_VERSION_AARCH32;
+ CallerSpmMajorVer = mSpmMajorVer;
+ CallerSpmMinorVer = mSpmMinorVer;
+ }
ArmCallSvc (&SpmVersionArgs);
SpmVersion = SpmVersionArgs.Arg0;
+ if (SpmVersion == FFA_NOT_SUPPORTED) {
+ return EFI_UNSUPPORTED;
+ }
- SpmMajorVersion = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT);
- SpmMinorVersion = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0);
+ CalleeSpmMajorVer = ((SpmVersion & SPM_MAJOR_VER_MASK) >> SPM_MAJOR_VER_SHIFT);
+ CalleeSpmMinorVer = ((SpmVersion & SPM_MINOR_VER_MASK) >> 0);
// Different major revision values indicate possibly incompatible functions.
// For two revisions, A and B, for which the major revision values are
@@ -182,17 +241,17 @@ GetSpmVersion (VOID)
// revision A must work in a compatible way with revision B.
// However, it is possible for revision B to have a higher
// function count than revision A.
- if ((SpmMajorVersion == SPM_MAJOR_VER) &&
- (SpmMinorVersion >= SPM_MINOR_VER))
+ if ((CalleeSpmMajorVer == CallerSpmMajorVer) &&
+ (CalleeSpmMinorVer >= CallerSpmMinorVer))
{
DEBUG ((DEBUG_INFO, "SPM Version: Major=0x%x, Minor=0x%x\n",
- SpmMajorVersion, SpmMinorVersion));
+ CalleeSpmMajorVer, CalleeSpmMinorVer));
Status = EFI_SUCCESS;
}
else
{
- DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Current Version: Major=0x%x, Minor=0x%x.\n Expected: Major=0x%x, Minor>=0x%x.\n",
- SpmMajorVersion, SpmMinorVersion, SPM_MAJOR_VER, SPM_MINOR_VER));
+ DEBUG ((DEBUG_INFO, "Incompatible SPM Versions.\n Callee Version: Major=0x%x, Minor=0x%x.\n Caller: Major=0x%x, Minor>=0x%x.\n",
+ CalleeSpmMajorVer, CalleeSpmMinorVer, CallerSpmMajorVer, CallerSpmMinorVer));
Status = EFI_UNSUPPORTED;
}
@@ -200,11 +259,38 @@ GetSpmVersion (VOID)
}
/**
+ Initialize parameters to be sent via SVC call.
+
+ @param[out] InitMmFoundationSvcArgs Args structure
+ @param[out] Ret Return Code
+
+**/
+STATIC
+VOID
+InitArmSvcArgs (
+ OUT ARM_SVC_ARGS *InitMmFoundationSvcArgs,
+ OUT INT32 *Ret
+ )
+{
+ if (FeaturePcdGet (PcdFfaEnable)) {
+ InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64;
+ InitMmFoundationSvcArgs->Arg1 = 0;
+ InitMmFoundationSvcArgs->Arg2 = 0;
+ InitMmFoundationSvcArgs->Arg3 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
+ InitMmFoundationSvcArgs->Arg4 = *Ret;
+ } else {
+ InitMmFoundationSvcArgs->Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
+ InitMmFoundationSvcArgs->Arg1 = *Ret;
+ }
+}
+
+/**
The entry point of Standalone MM Foundation.
- @param SharedBufAddress Pointer to the Buffer between SPM and SP.
- @param cookie1.
- @param cookie2.
+ @param [in] SharedBufAddress Pointer to the Buffer between SPM and SP.
+ @param [in] SharedBufSize Size of the shared buffer.
+ @param [in] cookie1 Cookie 1
+ @param [in] cookie2 Cookie 2
**/
VOID
@@ -220,11 +306,13 @@ _ModuleEntryPoint (
EFI_SECURE_PARTITION_BOOT_INFO *PayloadBootInfo;
ARM_SVC_ARGS InitMmFoundationSvcArgs;
EFI_STATUS Status;
+ INT32 Ret;
UINT32 SectionHeaderOffset;
UINT16 NumberOfSections;
VOID *HobStart;
VOID *TeData;
UINTN TeDataSize;
+ EFI_PHYSICAL_ADDRESS ImageBase;
// Get Secure Partition Manager Version Information
Status = GetSpmVersion ();
@@ -253,6 +341,7 @@ _ModuleEntryPoint (
Status = GetStandaloneMmCorePeCoffSections (
TeData,
&ImageContext,
+ &ImageBase,
&SectionHeaderOffset,
&NumberOfSections
);
@@ -261,10 +350,21 @@ _ModuleEntryPoint (
goto finish;
}
+ //
+ // ImageBase may deviate from ImageContext.ImageAddress if we are dealing
+ // with a TE image, in which case the latter points to the actual offset
+ // of the image, whereas ImageBase refers to the address where the image
+ // would start if the stripped PE headers were still in place. In either
+ // case, we need to fix up ImageBase so it refers to the actual current
+ // load address.
+ //
+ ImageBase += (UINTN)TeData - ImageContext.ImageAddress;
+
// Update the memory access permissions of individual sections in the
// Standalone MM core module
Status = UpdateMmFoundationPeCoffPermissions (
&ImageContext,
+ ImageBase,
SectionHeaderOffset,
NumberOfSections,
ArmSetMemoryRegionNoExec,
@@ -276,6 +376,15 @@ _ModuleEntryPoint (
goto finish;
}
+ if (ImageContext.ImageAddress != (UINTN)TeData) {
+ ImageContext.ImageAddress = (UINTN)TeData;
+ ArmSetMemoryRegionNoExec (ImageBase, SIZE_4KB);
+ ArmClearMemoryRegionReadOnly (ImageBase, SIZE_4KB);
+
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ ASSERT_EFI_ERROR (Status);
+ }
+
//
// Create Hoblist based upon boot information passed by privileged software
//
@@ -289,8 +398,16 @@ _ModuleEntryPoint (
DEBUG ((DEBUG_INFO, "Shared Cpu Driver EP 0x%lx\n", (UINT64) CpuDriverEntryPoint));
finish:
+ if (Status == RETURN_UNSUPPORTED) {
+ Ret = -1;
+ } else if (Status == RETURN_INVALID_PARAMETER) {
+ Ret = -2;
+ } else if (Status == EFI_NOT_FOUND) {
+ Ret = -7;
+ } else {
+ Ret = 0;
+ }
ZeroMem (&InitMmFoundationSvcArgs, sizeof(InitMmFoundationSvcArgs));
- InitMmFoundationSvcArgs.Arg0 = ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64;
- InitMmFoundationSvcArgs.Arg1 = Status;
+ InitArmSvcArgs (&InitMmFoundationSvcArgs, &Ret);
DelegatedEventLoop (&InitMmFoundationSvcArgs);
}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
index 04674b89b6f..c71929b7a18 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
@@ -1,7 +1,7 @@
## @file
# Module entry point library for DXE core.
#
-# Copyright (c) 2017 - 2018, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -26,6 +26,9 @@
AArch64/SetPermissions.c
AArch64/CreateHobList.c
+[Sources.X64]
+ X64/StandaloneMmCoreEntryPoint.c
+
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
@@ -33,7 +36,6 @@
[Packages.AARCH64]
ArmPkg/ArmPkg.dec
- ArmPlatformPkg/ArmPlatformPkg.dec
[LibraryClasses]
BaseLib
@@ -48,3 +50,9 @@
gEfiMmPeiMmramMemoryReserveGuid
gEfiStandaloneMmNonSecureBufferGuid
gEfiArmTfCpuDriverEpDescriptorGuid
+
+[FeaturePcd.AARCH64]
+ gArmTokenSpaceGuid.PcdFfaEnable
+
+[BuildOptions]
+ GCC:*_*_*_CC_FLAGS = -fpie
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c
new file mode 100644
index 00000000000..10b3dbac5e9
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c
@@ -0,0 +1,71 @@
+/** @file
+ Entry point to the Standalone Mm Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include <PiMm.h>
+
+#include <Library/StandaloneMmCoreEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+/**
+ The entry point of PE/COFF Image for the STANDALONE MM Core.
+
+ This function is the entry point for the STANDALONE MM Core. This function is required to call
+ ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return.
+ The STANDALONE MM Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI
+ System Table and the image handle for the STANDALONE MM Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+_ModuleEntryPoint (
+ IN VOID *HobStart
+ )
+{
+ //
+ // Cache a pointer to the HobList
+ //
+ gHobList = HobStart;
+
+ //
+ // Call the Standalone MM Core entry point
+ //
+ ProcessModuleEntryPointList (HobStart);
+
+ //
+ // TODO: Set page table here?? AARCH64 has this step for some reason
+ //
+}
+
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in HobStart.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN VOID *HobStart
+ )
+{
+ _ModuleEntryPoint (HobStart);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c
new file mode 100644
index 00000000000..5bb77515589
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/AArch64/StandaloneMmCoreHobLib.c
@@ -0,0 +1,330 @@
+/** @file
+ HOB Library implementation for Standalone MM Core.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Guid/MemoryAllocationHob.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+VOID *
+CreateHob (
+ IN UINT16 HobType,
+ IN UINT16 HobLength
+ )
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+ EFI_PHYSICAL_ADDRESS FreeMemory;
+ VOID *Hob;
+
+ HandOffHob = GetHobList ();
+
+ HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+
+ FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
+
+ if (FreeMemory < HobLength) {
+ return NULL;
+ }
+
+ Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
+ ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType;
+ ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength;
+ ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0;
+
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength);
+ HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+ HobEnd++;
+ HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ return Hob;
+}
+
+/**
+ Builds a HOB for a loaded PE32 module.
+
+ This function builds a HOB for a loaded PE32 module.
+ If ModuleName is NULL, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ModuleName The GUID File Name of the module.
+ @param MemoryAllocationModule The 64 bit physical address of the module.
+ @param ModuleLength The length of the module in bytes.
+ @param EntryPoint The 64 bit physical address of the module entry point.
+
+**/
+VOID
+EFIAPI
+BuildModuleHob (
+ IN CONST EFI_GUID *ModuleName,
+ IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule,
+ IN UINT64 ModuleLength,
+ IN EFI_PHYSICAL_ADDRESS EntryPoint
+ )
+{
+ EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob;
+
+ ASSERT (((MemoryAllocationModule & (EFI_PAGE_SIZE - 1)) == 0) &&
+ ((ModuleLength & (EFI_PAGE_SIZE - 1)) == 0));
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE));
+
+ CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid);
+ Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule;
+ Hob->MemoryAllocationHeader.MemoryLength = ModuleLength;
+ Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode;
+
+ //
+ // Zero the reserved space to match HOB spec
+ //
+ ZeroMem (Hob->MemoryAllocationHeader.Reserved, sizeof (Hob->MemoryAllocationHeader.Reserved));
+
+ CopyGuid (&Hob->ModuleName, ModuleName);
+ Hob->EntryPoint = EntryPoint;
+}
+
+/**
+ Builds a HOB that describes a chunk of system memory.
+
+ This function builds a HOB that describes a chunk of system memory.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ResourceType The type of resource described by this HOB.
+ @param ResourceAttribute The resource attributes of the memory described by this HOB.
+ @param PhysicalStart The 64 bit physical address of memory described by this HOB.
+ @param NumberOfBytes The length of the memory described by this HOB in bytes.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorHob (
+ IN EFI_RESOURCE_TYPE ResourceType,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 NumberOfBytes
+ )
+{
+ EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
+ ASSERT (Hob != NULL);
+
+ Hob->ResourceType = ResourceType;
+ Hob->ResourceAttribute = ResourceAttribute;
+ Hob->PhysicalStart = PhysicalStart;
+ Hob->ResourceLength = NumberOfBytes;
+}
+
+/**
+ Builds a GUID HOB with a certain data length.
+
+ This function builds a customized HOB tagged with a GUID for identification
+ and returns the start address of GUID HOB data so that caller can fill the customized data.
+ The HOB Header and Name field is already stripped.
+ If Guid is NULL, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+ If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+
+ @param Guid The GUID to tag the customized HOB.
+ @param DataLength The size of the data payload for the GUID HOB.
+
+ @return The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidHob (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN DataLength
+ )
+{
+ EFI_HOB_GUID_TYPE *Hob;
+
+ //
+ // Make sure that data length is not too long.
+ //
+ ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE)));
+
+ Hob = CreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength));
+ CopyGuid (&Hob->Name, Guid);
+ return Hob + 1;
+}
+
+
+/**
+ Copies a data buffer to a newly-built HOB.
+
+ This function builds a customized HOB tagged with a GUID for identification,
+ copies the input data to the HOB data field and returns the start address of the GUID HOB data.
+ The HOB Header and Name field is already stripped.
+ If Guid is NULL, then ASSERT().
+ If Data is NULL and DataLength > 0, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+ If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+
+ @param Guid The GUID to tag the customized HOB.
+ @param Data The data to be copied into the data field of the GUID HOB.
+ @param DataLength The size of the data payload for the GUID HOB.
+
+ @return The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidDataHob (
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN DataLength
+ )
+{
+ VOID *HobData;
+
+ ASSERT (Data != NULL || DataLength == 0);
+
+ HobData = BuildGuidHob (Guid, DataLength);
+
+ return CopyMem (HobData, Data, DataLength);
+}
+
+/**
+ Builds a Firmware Volume HOB.
+
+ This function builds a Firmware Volume HOB.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildFvHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ EFI_HOB_FIRMWARE_VOLUME *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME));
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+}
+
+
+/**
+ Builds a EFI_HOB_TYPE_FV2 HOB.
+
+ This function builds a EFI_HOB_TYPE_FV2 HOB.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+ @param FvName The name of the Firmware Volume.
+ @param FileName The name of the file.
+
+**/
+VOID
+EFIAPI
+BuildFv2Hob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN CONST EFI_GUID *FvName,
+ IN CONST EFI_GUID *FileName
+ )
+{
+ EFI_HOB_FIRMWARE_VOLUME2 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV2, sizeof (EFI_HOB_FIRMWARE_VOLUME2));
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+ CopyGuid (&Hob->FvName, FvName);
+ CopyGuid (&Hob->FileName, FileName);
+}
+
+
+/**
+ Builds a HOB for the CPU.
+
+ This function builds a HOB for the CPU.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param SizeOfMemorySpace The maximum physical memory addressability of the processor.
+ @param SizeOfIoSpace The maximum physical I/O addressability of the processor.
+
+**/
+VOID
+EFIAPI
+BuildCpuHob (
+ IN UINT8 SizeOfMemorySpace,
+ IN UINT8 SizeOfIoSpace
+ )
+{
+ EFI_HOB_CPU *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU));
+
+ Hob->SizeOfMemorySpace = SizeOfMemorySpace;
+ Hob->SizeOfIoSpace = SizeOfIoSpace;
+
+ //
+ // Zero the reserved space to match HOB spec
+ //
+ ZeroMem (Hob->Reserved, sizeof (Hob->Reserved));
+}
+
+/**
+ Builds a HOB for the memory allocation.
+
+ This function builds a HOB for the memory allocation.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the memory.
+ @param Length The length of the memory allocation in bytes.
+ @param MemoryType Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildMemoryAllocationHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ EFI_HOB_MEMORY_ALLOCATION *Hob;
+
+ ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
+ ((Length & (EFI_PAGE_SIZE - 1)) == 0));
+
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
+
+ ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+ Hob->AllocDescriptor.MemoryLength = Length;
+ Hob->AllocDescriptor.MemoryType = MemoryType;
+ //
+ // Zero the reserved space to match HOB spec
+ //
+ ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
+}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Common.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Common.c
new file mode 100644
index 00000000000..967fe7382e4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/Common.c
@@ -0,0 +1,291 @@
+/** @file
+ HOB Library implementation for Standalone MM Core.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/StandaloneMmCoreEntryPoint.h>
+
+#include <Guid/MemoryAllocationHob.h>
+
+/**
+ Returns the pointer to the HOB list.
+
+ This function returns the pointer to first HOB in the list.
+ If the pointer to the HOB list is NULL, then ASSERT().
+
+ @return The pointer to the HOB list.
+
+**/
+VOID *
+EFIAPI
+GetHobList (
+ VOID
+ )
+{
+ ASSERT (gHobList != NULL);
+ return gHobList;
+}
+
+/**
+ Returns the next instance of a HOB type from the starting HOB.
+
+ This function searches the first instance of a HOB type from the starting HOB pointer.
+ If there does not exist such HOB type from the starting HOB pointer, it will return NULL.
+ In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
+ unconditionally: it returns HobStart back if HobStart itself meets the requirement;
+ caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+
+ If HobStart is NULL, then ASSERT().
+
+ @param Type The HOB type to return.
+ @param HobStart The starting HOB pointer to search from.
+
+ @return The next instance of a HOB type from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetNextHob (
+ IN UINT16 Type,
+ IN CONST VOID *HobStart
+ )
+{
+ EFI_PEI_HOB_POINTERS Hob;
+
+ ASSERT (HobStart != NULL);
+
+ Hob.Raw = (UINT8 *) HobStart;
+ //
+ // Parse the HOB list until end of list or matching type is found.
+ //
+ while (!END_OF_HOB_LIST (Hob)) {
+ if (Hob.Header->HobType == Type) {
+ return Hob.Raw;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
+ return NULL;
+}
+
+/**
+ Returns the first instance of a HOB type among the whole HOB list.
+
+ This function searches the first instance of a HOB type among the whole HOB list.
+ If there does not exist such HOB type in the HOB list, it will return NULL.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+
+ @param Type The HOB type to return.
+
+ @return The next instance of a HOB type from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetFirstHob (
+ IN UINT16 Type
+ )
+{
+ VOID *HobList;
+
+ HobList = GetHobList ();
+ return GetNextHob (Type, HobList);
+}
+
+/**
+ Returns the next instance of the matched GUID HOB from the starting HOB.
+
+ This function searches the first instance of a HOB from the starting HOB pointer.
+ Such HOB should satisfy two conditions:
+ its HOB type is EFI_HOB_TYPE_GUID_EXTENSION, and its GUID Name equals to the input Guid.
+ If such a HOB from the starting HOB pointer does not exist, it will return NULL.
+ Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
+ to extract the data section and its size information, respectively.
+ In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
+ unconditionally: it returns HobStart back if HobStart itself meets the requirement;
+ caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
+
+ If Guid is NULL, then ASSERT().
+ If HobStart is NULL, then ASSERT().
+
+ @param Guid The GUID to match with in the HOB list.
+ @param HobStart A pointer to a Guid.
+
+ @return The next instance of the matched GUID HOB from the starting HOB.
+
+**/
+VOID *
+EFIAPI
+GetNextGuidHob (
+ IN CONST EFI_GUID *Guid,
+ IN CONST VOID *HobStart
+ )
+{
+ EFI_PEI_HOB_POINTERS GuidHob;
+
+ GuidHob.Raw = (UINT8 *) HobStart;
+ while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) {
+ if (CompareGuid (Guid, &GuidHob.Guid->Name)) {
+ break;
+ }
+ GuidHob.Raw = GET_NEXT_HOB (GuidHob);
+ }
+ return GuidHob.Raw;
+}
+
+/**
+ Returns the first instance of the matched GUID HOB among the whole HOB list.
+
+ This function searches the first instance of a HOB among the whole HOB list.
+ Such HOB should satisfy two conditions:
+ its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
+ If such a HOB from the starting HOB pointer does not exist, it will return NULL.
+ Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
+ to extract the data section and its size information, respectively.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+ If Guid is NULL, then ASSERT().
+
+ @param Guid The GUID to match with in the HOB list.
+
+ @return The first instance of the matched GUID HOB among the whole HOB list.
+
+**/
+VOID *
+EFIAPI
+GetFirstGuidHob (
+ IN CONST EFI_GUID *Guid
+ )
+{
+ VOID *HobList;
+
+ HobList = GetHobList ();
+ return GetNextGuidHob (Guid, HobList);
+}
+
+/**
+ Get the system boot mode from the HOB list.
+
+ This function returns the system boot mode information from the
+ PHIT HOB in HOB list.
+
+ If the pointer to the HOB list is NULL, then ASSERT().
+
+ @param VOID
+
+ @return The Boot Mode.
+
+**/
+EFI_BOOT_MODE
+EFIAPI
+GetBootModeHob (
+ VOID
+ )
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+
+ HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList ();
+
+ return HandOffHob->BootMode;
+}
+
+
+/**
+ Builds a HOB that describes a chunk of system memory with Owner GUID.
+
+ This function builds a HOB that describes a chunk of system memory.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ResourceType The type of resource described by this HOB.
+ @param ResourceAttribute The resource attributes of the memory described by this HOB.
+ @param PhysicalStart The 64 bit physical address of memory described by this HOB.
+ @param NumberOfBytes The length of the memory described by this HOB in bytes.
+ @param OwnerGUID GUID for the owner of this resource.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorWithOwnerHob (
+ IN EFI_RESOURCE_TYPE ResourceType,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 NumberOfBytes,
+ IN EFI_GUID *OwnerGUID
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a Capsule Volume HOB.
+
+ This function builds a Capsule Volume HOB.
+ If the platform does not support Capsule Volume HOBs, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Capsule Volume.
+ @param Length The size of the Capsule Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildCvHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ ASSERT (FALSE);
+}
+
+
+/**
+ Builds a HOB for the BSP store.
+
+ This function builds a HOB for BSP store.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the BSP.
+ @param Length The length of the BSP store in bytes.
+ @param MemoryType Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildBspStoreHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the Stack.
+
+ This function builds a HOB for the stack.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the Stack.
+ @param Length The length of the stack in bytes.
+
+**/
+VOID
+EFIAPI
+BuildStackHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ ASSERT (FALSE);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
index 283e896ba67..4f77414d12c 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
@@ -22,16 +22,21 @@
LIBRARY_CLASS = HobLib|MM_CORE_STANDALONE
#
-# VALID_ARCHITECTURES = AARCH64
+# VALID_ARCHITECTURES = X64 AARCH64
#
-[Sources.Common]
- StandaloneMmCoreHobLib.c
+[Sources.common]
+ Common.c
+
+[Sources.X64]
+ X64/StandaloneMmCoreHobLib.c
[Sources.AARCH64]
+ AArch64/StandaloneMmCoreHobLib.c
AArch64/StandaloneMmCoreHobLibInternal.c
[Packages]
MdePkg/MdePkg.dec
+ StandaloneMmPkg/StandaloneMmPkg.dec
[LibraryClasses]
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/X64/StandaloneMmCoreHobLib.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/X64/StandaloneMmCoreHobLib.c
new file mode 100644
index 00000000000..bb440da4bbd
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/X64/StandaloneMmCoreHobLib.c
@@ -0,0 +1,298 @@
+/** @file
+ HOB Library implementation for Standalone MM Core.
+
+Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/HobLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+
+#include <Guid/MemoryAllocationHob.h>
+
+/**
+ Builds a HOB for a loaded PE32 module.
+
+ This function builds a HOB for a loaded PE32 module.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If ModuleName is NULL, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ModuleName The GUID File Name of the module.
+ @param MemoryAllocationModule The 64 bit physical address of the module.
+ @param ModuleLength The length of the module in bytes.
+ @param EntryPoint The 64 bit physical address of the module entry point.
+
+**/
+VOID
+EFIAPI
+BuildModuleHob (
+ IN CONST EFI_GUID *ModuleName,
+ IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule,
+ IN UINT64 ModuleLength,
+ IN EFI_PHYSICAL_ADDRESS EntryPoint
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB that describes a chunk of system memory.
+
+ This function builds a HOB that describes a chunk of system memory.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ResourceType The type of resource described by this HOB.
+ @param ResourceAttribute The resource attributes of the memory described by this HOB.
+ @param PhysicalStart The 64 bit physical address of memory described by this HOB.
+ @param NumberOfBytes The length of the memory described by this HOB in bytes.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorHob (
+ IN EFI_RESOURCE_TYPE ResourceType,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 NumberOfBytes
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a customized HOB tagged with a GUID for identification and returns
+ the start address of GUID HOB data.
+
+ This function builds a customized HOB tagged with a GUID for identification
+ and returns the start address of GUID HOB data so that caller can fill the customized data.
+ The HOB Header and Name field is already stripped.
+ It can only be invoked during PEI phase.
+ For MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If Guid is NULL, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+ If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+ HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8.
+
+ @param Guid The GUID to tag the customized HOB.
+ @param DataLength The size of the data payload for the GUID HOB.
+
+ @retval NULL The GUID HOB could not be allocated.
+ @retval others The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidHob (
+ IN CONST EFI_GUID *Guid,
+ IN UINTN DataLength
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Builds a customized HOB tagged with a GUID for identification, copies the input data to the HOB
+ data field, and returns the start address of the GUID HOB data.
+
+ This function builds a customized HOB tagged with a GUID for identification and copies the input
+ data to the HOB data field and returns the start address of the GUID HOB data. It can only be
+ invoked during PEI phase; for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+ The HOB Header and Name field is already stripped.
+ It can only be invoked during PEI phase.
+ For MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If Guid is NULL, then ASSERT().
+ If Data is NULL and DataLength > 0, then ASSERT().
+ If there is no additional space for HOB creation, then ASSERT().
+ If DataLength > (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
+ HobLength is UINT16 and multiples of 8 bytes, so the max HobLength is 0xFFF8.
+
+ @param Guid The GUID to tag the customized HOB.
+ @param Data The data to be copied into the data field of the GUID HOB.
+ @param DataLength The size of the data payload for the GUID HOB.
+
+ @retval NULL The GUID HOB could not be allocated.
+ @retval others The start address of GUID HOB data.
+
+**/
+VOID *
+EFIAPI
+BuildGuidDataHob (
+ IN CONST EFI_GUID *Guid,
+ IN VOID *Data,
+ IN UINTN DataLength
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+ return NULL;
+}
+
+/**
+ Builds a Firmware Volume HOB.
+
+ This function builds a Firmware Volume HOB.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+ If the FvImage buffer is not at its required alignment, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+
+**/
+VOID
+EFIAPI
+BuildFvHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a EFI_HOB_TYPE_FV2 HOB.
+
+ This function builds a EFI_HOB_TYPE_FV2 HOB.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+ If the FvImage buffer is not at its required alignment, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+ @param FvName The name of the Firmware Volume.
+ @param FileName The name of the file.
+
+**/
+VOID
+EFIAPI
+BuildFv2Hob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN CONST EFI_GUID *FvName,
+ IN CONST EFI_GUID *FileName
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a EFI_HOB_TYPE_FV3 HOB.
+
+ This function builds a EFI_HOB_TYPE_FV3 HOB.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() since PEI HOB is read-only for MM phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+ If the FvImage buffer is not at its required alignment, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+ @param AuthenticationStatus The authentication status.
+ @param ExtractedFv TRUE if the FV was extracted as a file within
+ another firmware volume. FALSE otherwise.
+ @param FvName The name of the Firmware Volume.
+ Valid only if IsExtractedFv is TRUE.
+ @param FileName The name of the file.
+ Valid only if IsExtractedFv is TRUE.
+
+**/
+VOID
+EFIAPI
+BuildFv3Hob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT32 AuthenticationStatus,
+ IN BOOLEAN ExtractedFv,
+ IN CONST EFI_GUID *FvName, OPTIONAL
+ IN CONST EFI_GUID *FileName OPTIONAL
+ )
+{
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the CPU.
+
+ This function builds a HOB for the CPU.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param SizeOfMemorySpace The maximum physical memory addressability of the processor.
+ @param SizeOfIoSpace The maximum physical I/O addressability of the processor.
+
+**/
+VOID
+EFIAPI
+BuildCpuHob (
+ IN UINT8 SizeOfMemorySpace,
+ IN UINT8 SizeOfIoSpace
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Builds a HOB for the memory allocation.
+
+ This function builds a HOB for the memory allocation.
+ It can only be invoked during PEI phase;
+ for MM phase, it will ASSERT() because PEI HOB is read-only for MM phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The 64 bit physical address of the memory.
+ @param Length The length of the memory allocation in bytes.
+ @param MemoryType Type of memory allocated by this HOB.
+
+**/
+VOID
+EFIAPI
+BuildMemoryAllocationHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN EFI_MEMORY_TYPE MemoryType
+ )
+{
+ //
+ // PEI HOB is read only for MM phase
+ //
+ ASSERT (FALSE);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.c
index c7dbe50a71b..bdf33f620d0 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.c
@@ -2,7 +2,7 @@
Support routines for memory allocation routines based on Standalone MM Core internal functions.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, ARM Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -822,8 +822,8 @@ FreePool (
The constructor function calls MmInitializeMemoryServices to initialize
memory in MMRAM and caches EFI_MM_SYSTEM_TABLE pointer.
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the Management mode System Table.
+ @param [in] ImageHandle The firmware allocated handle for the EFI image.
+ @param [in] MmSystemTable A pointer to the Management mode System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
@@ -841,7 +841,7 @@ MemoryAllocationLibConstructor (
VOID *HobStart;
EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
EFI_MMRAM_DESCRIPTOR *MmramRanges;
- UINT32 MmramRangeCount;
+ UINTN MmramRangeCount;
EFI_HOB_GUID_TYPE *MmramRangesHob;
HobStart = GetHobList ();
@@ -868,7 +868,7 @@ MemoryAllocationLibConstructor (
return EFI_UNSUPPORTED;
}
- MmramRangeCount = MmramRangesHobData->NumberOfMmReservedRegions;
+ MmramRangeCount = (UINTN) MmramRangesHobData->NumberOfMmReservedRegions;
if (MmramRanges == NULL) {
return EFI_UNSUPPORTED;
}
@@ -877,7 +877,7 @@ MemoryAllocationLibConstructor (
DataInHob = GET_GUID_HOB_DATA (GuidHob);
MmCorePrivate = (MM_CORE_PRIVATE_DATA *)(UINTN)DataInHob->Address;
MmramRanges = (EFI_MMRAM_DESCRIPTOR *)(UINTN)MmCorePrivate->MmramRanges;
- MmramRangeCount = MmCorePrivate->MmramRangeCount;
+ MmramRangeCount = (UINTN) MmCorePrivate->MmramRangeCount;
}
{
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf
index 3a9e7c4e57f..b0bbe28f4be 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf
@@ -1,11 +1,11 @@
## @file
# Memory Allocation Library instance dedicated to MM Core.
# The implementation borrows the MM Core Memory Allocation services as the primitive
-# for memory allocation instead of using MM System Table servces in an indirect way.
+# for memory allocation instead of using MM System Table services in an indirect way.
# It is assumed that this library instance must be linked with MM Core in this package.
#
# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
-# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c
index b69c9383d2a..8f92a997a54 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/AArch64/StandaloneMmMemLibInternal.c
@@ -40,4 +40,31 @@ MmMemLibInternalCalculateMaximumSupportAddress (
DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress));
}
+/**
+ Initialize cached Mmram Ranges from HOB.
+
+ @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information.
+ @retval EFI_SUCCESS MmRanges are populated successfully.
+
+**/
+EFI_STATUS
+MmMemLibInternalPopulateMmramRanges (
+ VOID
+ )
+{
+ // Not implemented for AARCH64.
+ return EFI_SUCCESS;
+}
+
+/**
+ Deinitialize cached Mmram Ranges.
+
+**/
+VOID
+MmMemLibInternalFreeMmramRanges (
+ VOID
+ )
+{
+ // Not implemented for AARCH64.
+}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c
index dea5b9390f9..38117ea6403 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c
@@ -7,7 +7,7 @@
and MM driver) and/or specific dedicated hardware.
Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -38,6 +38,27 @@ MmMemLibInternalCalculateMaximumSupportAddress (
);
/**
+ Initialize cached Mmram Ranges from HOB.
+
+ @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information.
+ @retval EFI_SUCCESS MmRanges are populated successfully.
+
+**/
+EFI_STATUS
+MmMemLibInternalPopulateMmramRanges (
+ VOID
+ );
+
+/**
+ Deinitialize cached Mmram Ranges.
+
+**/
+VOID
+MmMemLibInternalFreeMmramRanges (
+ VOID
+ );
+
+/**
This function check if the buffer is valid per processor architecture and not overlap with MMRAM.
@param Buffer The buffer start address to be checked.
@@ -145,7 +166,7 @@ MmCopyMemToMmram (
@param SourceBuffer The pointer to the source buffer of the memory copy.
@param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
- @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with MMRAM.
+ @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM.
@retval EFI_SUCCESS Memory is copied.
**/
@@ -179,7 +200,7 @@ MmCopyMemFromMmram (
@param SourceBuffer The pointer to the source buffer of the memory copy.
@param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
- @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with MMRAM.
+ @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM.
@retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM.
@retval EFI_SUCCESS Memory is copied.
@@ -240,8 +261,8 @@ MmSetMem (
/**
The constructor function initializes the Mm Mem library
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
+ @param [in] ImageHandle The firmware allocated handle for the EFI image.
+ @param [in] MmSystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
@@ -253,11 +274,42 @@ MemLibConstructor (
IN EFI_MM_SYSTEM_TABLE *MmSystemTable
)
{
+ EFI_STATUS Status;
//
// Calculate and save maximum support address
//
MmMemLibInternalCalculateMaximumSupportAddress ();
+ //
+ // Initialize cached Mmram Ranges from HOB.
+ //
+ Status = MmMemLibInternalPopulateMmramRanges ();
+
+ return Status;
+}
+
+/**
+ Destructor for Mm Mem library.
+
+ @param ImageHandle The image handle of the process.
+ @param MmSystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
+
+**/
+EFI_STATUS
+EFIAPI
+MemLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+
+ //
+ // Deinitialize cached Mmram Ranges.
+ //
+ MmMemLibInternalFreeMmramRanges ();
+
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
index 691e12b7438..bc2f3eeaee1 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
@@ -8,6 +8,7 @@
#
# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -22,16 +23,20 @@
PI_SPECIFICATION_VERSION = 0x00010032
LIBRARY_CLASS = MemLib|MM_STANDALONE MM_CORE_STANDALONE
CONSTRUCTOR = MemLibConstructor
+ DESTRUCTOR = MemLibDestructor
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = AARCH64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources.Common]
StandaloneMmMemLib.c
+[Sources.IA32, Sources.X64]
+ X86StandaloneMmMemLibInternal.c
+
[Sources.AARCH64]
AArch64/StandaloneMmMemLibInternal.c
@@ -42,3 +47,9 @@
[LibraryClasses]
BaseMemoryLib
DebugLib
+ HobLib
+ MemoryAllocationLib
+
+[Guids]
+ gMmCoreDataHobGuid ## SOMETIMES_CONSUMES ## HOB
+ gEfiMmPeiMmramMemoryReserveGuid ## SOMETIMES_CONSUMES ## HOB
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c
new file mode 100644
index 00000000000..530105a639e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmMemLib/X86StandaloneMmMemLibInternal.c
@@ -0,0 +1,155 @@
+/** @file
+ Internal ARCH Specific file of MM memory check library.
+
+ MM memory check library implementation. This library consumes MM_ACCESS_PROTOCOL
+ to get MMRAM information. In order to use this library instance, the platform should produce
+ all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core
+ and MM driver) and/or specific dedicated hardware.
+
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiMm.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+
+#include <Guid/MmCoreData.h>
+#include <Guid/MmramMemoryReserve.h>
+
+//
+// Maximum support address used to check input buffer
+//
+extern EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress;
+extern EFI_MMRAM_DESCRIPTOR *mMmMemLibInternalMmramRanges;
+extern UINTN mMmMemLibInternalMmramCount;
+
+/**
+ Calculate and save the maximum support address.
+
+**/
+VOID
+MmMemLibInternalCalculateMaximumSupportAddress (
+ VOID
+ )
+{
+ VOID *Hob;
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ //
+ // Save the maximum support address in one global variable
+ //
+ mMmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1);
+ DEBUG ((DEBUG_INFO, "mMmMemLibInternalMaximumSupportAddress = 0x%lx\n", mMmMemLibInternalMaximumSupportAddress));
+}
+
+/**
+ Initialize cached Mmram Ranges from HOB.
+
+ @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information.
+ @retval EFI_SUCCESS MmRanges are populated successfully.
+
+**/
+EFI_STATUS
+MmMemLibInternalPopulateMmramRanges (
+ VOID
+ )
+{
+ VOID *HobStart;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ MM_CORE_DATA_HOB_DATA *DataInHob;
+ MM_CORE_PRIVATE_DATA *MmCorePrivateData;
+ EFI_HOB_GUID_TYPE *MmramRangesHob;
+ EFI_MMRAM_HOB_DESCRIPTOR_BLOCK *MmramRangesHobData;
+ EFI_MMRAM_DESCRIPTOR *MmramDescriptors;
+
+ HobStart = GetHobList ();
+ DEBUG ((DEBUG_INFO, "%a - 0x%x\n", __FUNCTION__, HobStart));
+
+ //
+ // Extract MM Core Private context from the Hob. If absent search for
+ // a Hob containing the MMRAM ranges
+ //
+ GuidHob = GetNextGuidHob (&gMmCoreDataHobGuid, HobStart);
+ if (GuidHob == NULL) {
+ MmramRangesHob = GetFirstGuidHob (&gEfiMmPeiMmramMemoryReserveGuid);
+ if (MmramRangesHob == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ MmramRangesHobData = GET_GUID_HOB_DATA (MmramRangesHob);
+ if (MmramRangesHobData == NULL || MmramRangesHobData->Descriptor == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mMmMemLibInternalMmramCount = MmramRangesHobData->NumberOfMmReservedRegions;
+ MmramDescriptors = MmramRangesHobData->Descriptor;
+ } else {
+ DataInHob = GET_GUID_HOB_DATA (GuidHob);
+ if (DataInHob == NULL) {
+ return EFI_UNSUPPORTED;
+ }
+
+ MmCorePrivateData = (MM_CORE_PRIVATE_DATA *) (UINTN) DataInHob->Address;
+ if (MmCorePrivateData == NULL || MmCorePrivateData->MmramRanges == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mMmMemLibInternalMmramCount = (UINTN) MmCorePrivateData->MmramRangeCount;
+ MmramDescriptors = (EFI_MMRAM_DESCRIPTOR *) (UINTN) MmCorePrivateData->MmramRanges;
+ }
+
+ mMmMemLibInternalMmramRanges = AllocatePool (mMmMemLibInternalMmramCount * sizeof (EFI_MMRAM_DESCRIPTOR));
+ if (mMmMemLibInternalMmramRanges) {
+ CopyMem (mMmMemLibInternalMmramRanges,
+ MmramDescriptors,
+ mMmMemLibInternalMmramCount * sizeof (EFI_MMRAM_DESCRIPTOR));
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Deinitialize cached Mmram Ranges.
+
+**/
+VOID
+MmMemLibInternalFreeMmramRanges (
+ VOID
+ )
+{
+ if (mMmMemLibInternalMmramRanges != NULL) {
+ FreePool (mMmMemLibInternalMmramRanges);
+ }
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.c b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.c
index c7e7696102a..b09cfd2441a 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.c
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.c
@@ -1,10 +1,10 @@
/** @file
- Runtime DXE part corresponding to StanaloneMM variable module.
+ Runtime DXE part corresponding to StandaloneMM variable module.
This module installs variable arch protocol and variable write arch protocol
to StandaloneMM runtime variable service.
-Copyright (c) 2019, ARM Ltd. All rights reserved.
+Copyright (c) 2019 - 2021, Arm Ltd. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
index 022dad5f067..7e23987f45d 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
@@ -1,10 +1,10 @@
## @file
-# Runtime DXE part corresponding to StanaloneMM variable module.
+# Runtime DXE part corresponding to StandaloneMM variable module.
#
# This module installs variable arch protocol and variable write arch protocol
# to StandaloneMM runtime variable service.
#
-# Copyright (c) 2019, ARM Ltd. All rights reserved.
+# Copyright (c) 2019 - 2021, Arm Ltd. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
new file mode 100644
index 00000000000..12f4b573785
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.ci.yaml
@@ -0,0 +1,84 @@
+## @file
+# CI configuration for StandaloneMmPkg
+#
+# Copyright (c) 2020 - 2021, Arm Limited. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+{
+ ## options defined .pytool/Plugin/CompilerPlugin
+ "CompilerPlugin": {
+ "DscPath": "StandaloneMmPkg.dsc"
+ },
+
+ ## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
+ "HostUnitTestCompilerPlugin": {
+ "DscPath": "" # Don't support this test
+ },
+
+ ## options defined .pytool/Plugin/CharEncodingCheck
+ "CharEncodingCheck": {
+ "IgnoreFiles": []
+ },
+
+ ## options defined .pytool/Plugin/DependencyCheck
+ "DependencyCheck": {
+ "AcceptableDependencies": [
+ "ArmPkg/ArmPkg.dec",
+ "EmbeddedPkg/EmbeddedPkg.dec",
+ "StandaloneMmPkg/StandaloneMmPkg.dec",
+ "MdeModulePkg/MdeModulePkg.dec",
+ "MdePkg/MdePkg.dec"
+ ],
+ # For host based unit tests
+ "AcceptableDependencies-HOST_APPLICATION":[
+ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
+ ],
+ # For UEFI shell based apps
+ "AcceptableDependencies-UEFI_APPLICATION":[],
+ "IgnoreInf": []
+ },
+
+ ## options defined .pytool/Plugin/DscCompleteCheck
+ "DscCompleteCheck": {
+ "IgnoreInf": [],
+ "DscPath": "StandaloneMmPkg.dsc"
+ },
+
+ ## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck
+ "HostUnitTestDscCompleteCheck": {
+ "IgnoreInf": [""],
+ "DscPath": "" # Don't support this test
+ },
+
+ ## options defined .pytool/Plugin/GuidCheck
+ "GuidCheck": {
+ "IgnoreGuidName": [],
+ "IgnoreGuidValue": [],
+ "IgnoreFoldersAndFiles": [],
+ "IgnoreDuplicates": [],
+ },
+
+ ## options defined .pytool/Plugin/LibraryClassCheck
+ "LibraryClassCheck": {
+ "IgnoreHeaderFile": []
+ },
+
+ ## options defined .pytool/Plugin/SpellCheck
+ "SpellCheck": {
+ "AuditOnly": False,
+ "IgnoreFiles": [], # use gitignore syntax to ignore errors
+ # in matching files
+ "ExtendWords": [
+ "Bsymbolic",
+ "FwVol",
+ "mpidr",
+ "mstrict",
+ "schedulable",
+ "StandaloneMMCore",
+ ], # words to extend to the dictionary for this package
+ "IgnoreStandardPaths": [], # Standard Plugin defined paths that
+ # should be ignore
+ "AdditionalIncludePaths": [] # Additional paths to spell check
+ # (wildcards supported)
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dec b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dec
index 037af2a557d..e7408b5d2d6 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dec
@@ -2,7 +2,7 @@
# This package is a platform package that provide platform module/library
# required by Standalone MM platform.
#
-# Copyright (c) 2016-2018, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2016-2021, Arm Ltd. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -19,6 +19,21 @@
[LibraryClasses]
+ ## @libraryclass Defines a set of helper methods.
+ FvLib|Include/Library/FvLib.h
+
+ ## @libraryclass Defines a set of interfaces for the MM core entrypoint.
+ StandaloneMmCoreEntryPoint|Include/Library/StandaloneMmCoreEntryPoint.h
+
+ ## @libraryclass Defines a set of interfaces that provides services for
+ ## MM Memory Operation.
+ MemLib|Include/Library/StandaloneMmMemLib.h
+
+[LibraryClasses.AArch64]
+ ## @libraryclass Defines a set of interfaces for the MM core entrypoint for
+ ## AArch64.
+ StandaloneMmCoreEntryPoint|Include/Library/AArch64/StandaloneMmCoreEntryPoint.h
+
[Guids]
gStandaloneMmPkgTokenSpaceGuid = { 0x18fe7632, 0xf5c8, 0x4e63, { 0x8d, 0xe8, 0x17, 0xa5, 0x5c, 0x59, 0x13, 0xbd }}
gMpInformationHobGuid = { 0xba33f15d, 0x4000, 0x45c1, { 0x8e, 0x88, 0xf9, 0x16, 0x92, 0xd4, 0x57, 0xe3 }}
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dsc b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dsc
index 20d1c2840d7..9dd838af8dd 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/StandaloneMmPkg.dsc
@@ -1,8 +1,9 @@
## @file
# Standalone MM Platform.
#
-# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
-# Copyright (c) 2016 - 2019, ARM Limited. All rights reserved.<BR>
+# Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
+# Copyright (C) Microsoft Corporation<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -19,7 +20,7 @@
PLATFORM_VERSION = 1.0
DSC_SPECIFICATION = 0x00010011
OUTPUT_DIRECTORY = Build/StandaloneMm
- SUPPORTED_ARCHITECTURES = AARCH64
+ SUPPORTED_ARCHITECTURES = AARCH64|X64
BUILD_TARGETS = DEBUG|RELEASE
SKUID_IDENTIFIER = DEFAULT
@@ -31,12 +32,16 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
#
# Basic
#
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
ExtractGuidedSectionLib|EmbeddedPkg/Library/PrePiExtractGuidedSectionLib/PrePiExtractGuidedSectionLib.inf
@@ -47,18 +52,20 @@
MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf
MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- PeCoffExtraActionLib|StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
+ PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
StandaloneMmCoreEntryPoint|StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
+ VariableMmDependency|StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
[LibraryClasses.AARCH64]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
StandaloneMmMmuLib|ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf
ArmSvcLib|ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
+ PeCoffExtraActionLib|StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
@@ -66,6 +73,9 @@
[LibraryClasses.common.MM_CORE_STANDALONE]
HobLib|StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
+[LibraryClasses.common.MM_STANDALONE]
+ MemoryAllocationLib|StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
+
################################################################################
#
# Pcd Section - list of all EDK II PCD Entries defined by this Platform
@@ -99,9 +109,18 @@
# MM Core
#
StandaloneMmPkg/Core/StandaloneMmCore.inf
+ StandaloneMmPkg/Library/FvLib/FvLib.inf
+ StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
+ StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.inf
+ StandaloneMmPkg/Library/StandaloneMmCoreMemoryAllocationLib/StandaloneMmCoreMemoryAllocationLib.inf
+ StandaloneMmPkg/Library/StandaloneMmHobLib/StandaloneMmHobLib.inf
+ StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.inf
+ StandaloneMmPkg/Library/StandaloneMmMemoryAllocationLib/StandaloneMmMemoryAllocationLib.inf
+ StandaloneMmPkg/Library/VariableMmDependency/VariableMmDependency.inf
[Components.AARCH64]
StandaloneMmPkg/Drivers/StandaloneMmCpu/AArch64/StandaloneMmCpu.inf
+ StandaloneMmPkg/Library/StandaloneMmPeCoffExtraActionLib/StandaloneMmPeCoffExtraActionLib.inf
###################################################################################################
#
@@ -115,3 +134,7 @@
[BuildOptions.AARCH64]
GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000 -march=armv8-a+nofp -mstrict-align
GCC:*_*_*_CC_FLAGS = -mstrict-align
+
+[BuildOptions.X64]
+ MSFT:*_*_*_DLINK_FLAGS = /ALIGN:4096
+ GCC:*_GCC*_*_DLINK_FLAGS = -z common-page-size=0x1000
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.c
index e3d7419aac6..999e28010d5 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.c
@@ -10,9 +10,6 @@
#include "CpuMp.h"
#include "CpuPageTable.h"
-#define CACHE_ATTRIBUTE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | EFI_MEMORY_WT | EFI_MEMORY_WB | EFI_MEMORY_UCE | EFI_MEMORY_WP)
-#define MEMORY_ATTRIBUTE_MASK (EFI_MEMORY_RP | EFI_MEMORY_XP | EFI_MEMORY_RO)
-
//
// Global Variables
//
@@ -417,8 +414,8 @@ CpuSetMemoryAttributes (
return EFI_SUCCESS;
}
- CacheAttributes = Attributes & CACHE_ATTRIBUTE_MASK;
- MemoryAttributes = Attributes & MEMORY_ATTRIBUTE_MASK;
+ CacheAttributes = Attributes & EFI_CACHE_ATTRIBUTE_MASK;
+ MemoryAttributes = Attributes & EFI_MEMORY_ATTRIBUTE_MASK;
if (Attributes != (CacheAttributes | MemoryAttributes)) {
return EFI_INVALID_PARAMETER;
@@ -677,7 +674,7 @@ SetGcdMemorySpaceAttributes (
gDS->SetMemorySpaceAttributes (
RegionStart,
RegionLength,
- (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
+ (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
);
}
@@ -754,7 +751,7 @@ RefreshMemoryAttributesFromMtrr (
gDS->SetMemorySpaceAttributes (
MemorySpaceMap[Index].BaseAddress,
MemorySpaceMap[Index].Length,
- (MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) |
+ (MemorySpaceMap[Index].Attributes & ~EFI_CACHE_ATTRIBUTE_MASK) |
(MemorySpaceMap[Index].Capabilities & DefaultAttributes)
);
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.h
index 548a9765197..9ed0134e10d 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuDxe.h
@@ -39,18 +39,6 @@
#include <Guid/IdleLoopEvent.h>
#include <Guid/VectorHandoffTable.h>
-#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | \
- EFI_MEMORY_WC | \
- EFI_MEMORY_WT | \
- EFI_MEMORY_WB | \
- EFI_MEMORY_UCE \
- )
-
-#define EFI_MEMORY_PAGETYPE_MASK (EFI_MEMORY_RP | \
- EFI_MEMORY_XP | \
- EFI_MEMORY_RO \
- )
-
#define HEAP_GUARD_NONSTOP_MODE \
((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT6|BIT4|BIT1|BIT0)) > BIT6)
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c
index 31d4ecf698d..8fed620928f 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c
@@ -2,7 +2,7 @@
C based implementation of IA32 interrupt handling only
requiring a minimal assembly interrupt entry point.
- Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -13,7 +13,7 @@
//
// Global descriptor table (GDT) Template
//
-STATIC GDT_ENTRIES GdtTemplate = {
+STATIC GDT_ENTRIES mGdtTemplate = {
//
// NULL_SEL
//
@@ -70,14 +70,14 @@ STATIC GDT_ENTRIES GdtTemplate = {
0x0,
},
//
- // SPARE4_SEL
+ // SYS_CODE16_SEL
//
{
- 0x0, // limit 15:0
+ 0x0FFFF, // limit 15:0
0x0, // base 15:0
0x0, // base 23:16
- 0x0, // type
- 0x0, // limit 19:16, flags
+ 0x09A, // present, ring 0, code, execute/read
+ 0x08F, // page-granular, 16-bit
0x0, // base 31:24
},
//
@@ -124,14 +124,31 @@ InitGlobalDescriptorTable (
VOID
)
{
- GDT_ENTRIES *gdt;
- IA32_DESCRIPTOR gdtPtr;
+#ifndef VBOX
+ EFI_STATUS Status;
+#endif
+ GDT_ENTRIES *Gdt;
+ IA32_DESCRIPTOR Gdtr;
+#ifndef VBOX
+ EFI_PHYSICAL_ADDRESS Memory;
+#endif
//
- // Allocate Runtime Data for the GDT
+ // Allocate Runtime Data below 4GB for the GDT
+ // AP uses the same GDT when it's waken up from real mode so
+ // the GDT needs to be below 4GB.
//
#ifndef VBOX
- gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8);
+ Memory = SIZE_4GB - 1;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiRuntimeServicesData,
+ EFI_SIZE_TO_PAGES (sizeof (mGdtTemplate)),
+ &Memory
+ );
+ ASSERT_EFI_ERROR (Status);
+ ASSERT ((Memory != 0) && (Memory < SIZE_4GB));
+ Gdt = (GDT_ENTRIES *) (UINTN) Memory;
#else
/*
* Apples bootloader boot.efi for at least OS X Tiger, Leopard and Snow Leopard
@@ -141,22 +158,22 @@ InitGlobalDescriptorTable (
* (search for PeiServicesAllocatePages()) for a more detailed explanation of a
* related bug in Apples bootloader.
*/
- gdt = AllocateReservedPool (sizeof (GdtTemplate) + 8);
+ Gdt = AllocateReservedPool (sizeof (mGdtTemplate) + 8);
+ ASSERT (Gdt != NULL);
+ Gdt = ALIGN_POINTER (Gdt, 8);
#endif
- ASSERT (gdt != NULL);
- gdt = ALIGN_POINTER (gdt, 8);
//
// Initialize all GDT entries
//
- CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
+ CopyMem (Gdt, &mGdtTemplate, sizeof (mGdtTemplate));
//
// Write GDT register
//
- gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
- gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
- AsmWriteGdtr (&gdtPtr);
+ Gdtr.Base = (UINT32) (UINTN) Gdt;
+ Gdtr.Limit = (UINT16) (sizeof (mGdtTemplate) - 1);
+ AsmWriteGdtr (&Gdtr);
//
// Update selector (segment) registers base on new GDT
@@ -164,4 +181,3 @@ InitGlobalDescriptorTable (
SetCodeSelector ((UINT16)CPU_CODE_SEL);
SetDataSelectors ((UINT16)CPU_DATA_SEL);
}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.h
index 866235e86e7..fa54e674d0e 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.h
@@ -36,7 +36,7 @@ struct _GDT_ENTRIES {
GDT_ENTRY LinearCode;
GDT_ENTRY SysData;
GDT_ENTRY SysCode;
- GDT_ENTRY Spare4;
+ GDT_ENTRY SysCode16;
GDT_ENTRY LinearData64;
GDT_ENTRY LinearCode64;
GDT_ENTRY Spare5;
@@ -49,7 +49,7 @@ struct _GDT_ENTRIES {
#define LINEAR_CODE_SEL OFFSET_OF (GDT_ENTRIES, LinearCode)
#define SYS_DATA_SEL OFFSET_OF (GDT_ENTRIES, SysData)
#define SYS_CODE_SEL OFFSET_OF (GDT_ENTRIES, SysCode)
-#define SPARE4_SEL OFFSET_OF (GDT_ENTRIES, Spare4)
+#define SYS_CODE16_SEL OFFSET_OF (GDT_ENTRIES, SysCode16)
#define LINEAR_DATA64_SEL OFFSET_OF (GDT_ENTRIES, LinearData64)
#define LINEAR_CODE64_SEL OFFSET_OF (GDT_ENTRIES, LinearCode64)
#define SPARE5_SEL OFFSET_OF (GDT_ENTRIES, Spare5)
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuPageTable.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuPageTable.c
index 97f9ccd6afc..3f1411b548c 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuPageTable.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuPageTable.c
@@ -789,7 +789,7 @@ ConvertMemoryPageAttributes (
return RETURN_INVALID_PARAMETER;
}
- if ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP)) != 0) {
+ if ((Attributes & ~EFI_MEMORY_ATTRIBUTE_MASK) != 0) {
DEBUG ((DEBUG_ERROR, "Attributes(0x%lx) has unsupported bit\n", Attributes));
return EFI_UNSUPPORTED;
}
@@ -1090,9 +1090,9 @@ RefreshGcdMemoryAttributesFromPaging (
Length = MIN (PageLength, MemorySpaceLength);
if (Attributes != (MemorySpaceMap[Index].Attributes &
- EFI_MEMORY_PAGETYPE_MASK)) {
+ EFI_MEMORY_ATTRIBUTE_MASK)) {
NewAttributes = (MemorySpaceMap[Index].Attributes &
- ~EFI_MEMORY_PAGETYPE_MASK) | Attributes;
+ ~EFI_MEMORY_ATTRIBUTE_MASK) | Attributes;
Status = gDS->SetMemorySpaceAttributes (
BaseAddress,
Length,
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/X64/CpuAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/X64/CpuAsm.nasm
index cb3778b8bec..046071270b6 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/X64/CpuAsm.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/X64/CpuAsm.nasm
@@ -20,13 +20,11 @@
;------------------------------------------------------------------------------
global ASM_PFX(SetCodeSelector)
ASM_PFX(SetCodeSelector):
- sub rsp, 0x10
+ push rcx
lea rax, [setCodeSelectorLongJump]
- mov [rsp], rax
- mov [rsp+4], cx
- jmp dword far [rsp]
+ push rax
+ o64 retf
setCodeSelectorLongJump:
- add rsp, 0x10
ret
;------------------------------------------------------------------------------
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.c
new file mode 100644
index 00000000000..4ad96b194d3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.c
@@ -0,0 +1,402 @@
+/** @file
+ Produces the SMM CPU I/O Protocol.
+
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CpuIo2Mm.h"
+
+//
+// Handle for the SMM CPU I/O Protocol
+//
+EFI_HANDLE mHandle = NULL;
+
+//
+// SMM CPU I/O Protocol instance
+//
+EFI_SMM_CPU_IO2_PROTOCOL mSmmCpuIo2 = {
+ {
+ CpuMemoryServiceRead,
+ CpuMemoryServiceWrite
+ },
+ {
+ CpuIoServiceRead,
+ CpuIoServiceWrite
+ }
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mStride[] = {
+ 1, // SMM_IO_UINT8
+ 2, // SMM_IO_UINT16
+ 4, // SMM_IO_UINT32
+ 8 // SMM_IO_UINT64
+};
+
+/**
+ Check parameters to a SMM CPU I/O Protocol service request.
+
+ @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+
+**/
+EFI_STATUS
+CpuIoCheckParameter (
+ IN BOOLEAN MmioOperation,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ UINT64 MaxCount;
+ UINT64 Limit;
+
+ //
+ // Check to see if Buffer is NULL
+ //
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range
+ //
+ if ((UINT32)Width > SMM_IO_UINT64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if Width is in the valid range for I/O Port operations
+ //
+ if (!MmioOperation && (Width == SMM_IO_UINT64)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Check to see if any address associated with this transfer exceeds the maximum
+ // allowed address. The maximum address implied by the parameters passed in is
+ // Address + Size * Count. If the following condition is met, then the transfer
+ // is not supported.
+ //
+ // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
+ //
+ // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
+ // can also be the maximum integer value supported by the CPU, this range
+ // check must be adjusted to avoid all overflow conditions.
+ //
+ // The following form of the range check is equivalent but assumes that
+ // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
+ //
+ Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
+ if (Count == 0) {
+ if (Address > Limit) {
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ MaxCount = RShiftU64 (Limit, Width);
+ if (MaxCount < (Count - 1)) {
+ return EFI_UNSUPPORTED;
+ }
+ if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // Check to see if Address is aligned
+ //
+ if ((Address & ((UINT64)mStride[Width] - 1)) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceRead (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT16) {
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT32) {
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT64) {
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Writes memory-mapped registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuMemoryServiceWrite (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (Width == SMM_IO_UINT16) {
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else if (Width == SMM_IO_UINT32) {
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ } else if (Width == SMM_IO_UINT64) {
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Reads I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[out] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceRead (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ *Uint8Buffer = IoRead8 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT16) {
+ *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
+ } else if (Width == SMM_IO_UINT32) {
+ *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Write I/O registers.
+
+ The I/O operations are carried out exactly as requested. The caller is
+ responsible for any alignment and I/O width issues that the bus, device,
+ platform, or type of I/O might require.
+
+ @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform.
+ @param[in] Buffer For read operations, the destination buffer to store
+ the results. For write operations, the source buffer
+ from which to write data.
+
+ @retval EFI_SUCCESS The data was read from or written to the device.
+ @retval EFI_UNSUPPORTED The Address is not valid for this system.
+ @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
+ lack of resources
+
+**/
+EFI_STATUS
+EFIAPI
+CpuIoServiceWrite (
+ IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
+ IN EFI_SMM_IO_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 Stride;
+ UINT8 *Uint8Buffer;
+
+ //
+ // Make sure the parameters are valid
+ //
+ Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Select loop based on the width of the transfer
+ //
+ Stride = mStride[Width];
+ for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
+ if (Width == SMM_IO_UINT8) {
+ IoWrite8 ((UINTN)Address, *Uint8Buffer);
+ } else if (Width == SMM_IO_UINT16) {
+ IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ } else if (Width == SMM_IO_UINT32) {
+ IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The module Entry Point SmmCpuIoProtocol driver
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+CommonCpuIo2Initialize (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Copy the SMM CPU I/O Protocol instance into the System Management System Table
+ //
+ CopyMem (&gMmst->MmIo, &mSmmCpuIo2, sizeof (mSmmCpuIo2));
+
+ //
+ // Install the SMM CPU I/O Protocol into the MM protocol database
+ //
+ Status = gMmst->MmInstallProtocolInterface (
+ &mHandle,
+ &gEfiSmmCpuIo2ProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mSmmCpuIo2
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.h
index a43bc73d8b0..3237b5852a4 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Mm.h
@@ -16,7 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
#include <Library/IoLib.h>
-#include <Library/SmmServicesTableLib.h>
+#include <Library/MmServicesTableLib.h>
#include <Library/BaseMemoryLib.h>
#define MAX_IO_PORT_ADDRESS 0xFFFF
@@ -153,4 +153,16 @@ CpuIoServiceWrite (
IN VOID *Buffer
);
+/**
+ The module Entry Point SmmCpuIoProtocol driver
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+CommonCpuIo2Initialize (
+ VOID
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c
index 54455bcf746..ee37f540267 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.c
@@ -2,374 +2,17 @@
Produces the SMM CPU I/O Protocol.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "CpuIo2Smm.h"
+#include <PiSmm.h>
-//
-// Handle for the SMM CPU I/O Protocol
-//
-EFI_HANDLE mHandle = NULL;
-
-//
-// SMM CPU I/O Protocol instance
-//
-EFI_SMM_CPU_IO2_PROTOCOL mSmmCpuIo2 = {
- {
- CpuMemoryServiceRead,
- CpuMemoryServiceWrite
- },
- {
- CpuIoServiceRead,
- CpuIoServiceWrite
- }
-};
-
-//
-// Lookup table for increment values based on transfer widths
-//
-UINT8 mStride[] = {
- 1, // SMM_IO_UINT8
- 2, // SMM_IO_UINT16
- 4, // SMM_IO_UINT32
- 8 // SMM_IO_UINT64
-};
-
-/**
- Check parameters to a SMM CPU I/O Protocol service request.
-
- @param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of I/O operations to perform.
- @param[in] Buffer For read operations, the destination buffer to store
- the results. For write operations, the source buffer
- from which to write data.
-
- @retval EFI_SUCCESS The data was read from or written to the device.
- @retval EFI_UNSUPPORTED The Address is not valid for this system.
- @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
-
-**/
-EFI_STATUS
-CpuIoCheckParameter (
- IN BOOLEAN MmioOperation,
- IN EFI_SMM_IO_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
-{
- UINT64 MaxCount;
- UINT64 Limit;
-
- //
- // Check to see if Buffer is NULL
- //
- if (Buffer == NULL) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check to see if Width is in the valid range
- //
- if ((UINT32)Width > SMM_IO_UINT64) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check to see if Width is in the valid range for I/O Port operations
- //
- if (!MmioOperation && (Width == SMM_IO_UINT64)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Check to see if any address associated with this transfer exceeds the maximum
- // allowed address. The maximum address implied by the parameters passed in is
- // Address + Size * Count. If the following condition is met, then the transfer
- // is not supported.
- //
- // Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
- //
- // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
- // can also be the maximum integer value supported by the CPU, this range
- // check must be adjusted to avoid all overflow conditions.
- //
- // The following form of the range check is equivalent but assumes that
- // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
- //
- Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
- if (Count == 0) {
- if (Address > Limit) {
- return EFI_UNSUPPORTED;
- }
- } else {
- MaxCount = RShiftU64 (Limit, Width);
- if (MaxCount < (Count - 1)) {
- return EFI_UNSUPPORTED;
- }
- if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
- return EFI_UNSUPPORTED;
- }
- }
-
- //
- // Check to see if Address is aligned
- //
- if ((Address & ((UINT64)mStride[Width] - 1)) != 0) {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Reads memory-mapped registers.
-
- The I/O operations are carried out exactly as requested. The caller is
- responsible for any alignment and I/O width issues that the bus, device,
- platform, or type of I/O might require.
-
- @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of I/O operations to perform.
- @param[out] Buffer For read operations, the destination buffer to store
- the results. For write operations, the source buffer
- from which to write data.
-
- @retval EFI_SUCCESS The data was read from or written to the device.
- @retval EFI_UNSUPPORTED The Address is not valid for this system.
- @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
- lack of resources
-
-**/
-EFI_STATUS
-EFIAPI
-CpuMemoryServiceRead (
- IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
- IN EFI_SMM_IO_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINT8 Stride;
- UINT8 *Uint8Buffer;
-
- Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Select loop based on the width of the transfer
- //
- Stride = mStride[Width];
- for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
- if (Width == SMM_IO_UINT8) {
- *Uint8Buffer = MmioRead8 ((UINTN)Address);
- } else if (Width == SMM_IO_UINT16) {
- *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
- } else if (Width == SMM_IO_UINT32) {
- *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
- } else if (Width == SMM_IO_UINT64) {
- *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
- }
- }
- return EFI_SUCCESS;
-}
+#include "CpuIo2Mm.h"
/**
- Writes memory-mapped registers.
-
- The I/O operations are carried out exactly as requested. The caller is
- responsible for any alignment and I/O width issues that the bus, device,
- platform, or type of I/O might require.
-
- @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of I/O operations to perform.
- @param[in] Buffer For read operations, the destination buffer to store
- the results. For write operations, the source buffer
- from which to write data.
-
- @retval EFI_SUCCESS The data was read from or written to the device.
- @retval EFI_UNSUPPORTED The Address is not valid for this system.
- @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
- lack of resources
-
-**/
-EFI_STATUS
-EFIAPI
-CpuMemoryServiceWrite (
- IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
- IN EFI_SMM_IO_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINT8 Stride;
- UINT8 *Uint8Buffer;
-
- Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Select loop based on the width of the transfer
- //
- Stride = mStride[Width];
- for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
- if (Width == SMM_IO_UINT8) {
- MmioWrite8 ((UINTN)Address, *Uint8Buffer);
- } else if (Width == SMM_IO_UINT16) {
- MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
- } else if (Width == SMM_IO_UINT32) {
- MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
- } else if (Width == SMM_IO_UINT64) {
- MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
- }
- }
- return EFI_SUCCESS;
-}
-
-/**
- Reads I/O registers.
-
- The I/O operations are carried out exactly as requested. The caller is
- responsible for any alignment and I/O width issues that the bus, device,
- platform, or type of I/O might require.
-
- @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of I/O operations to perform.
- @param[out] Buffer For read operations, the destination buffer to store
- the results. For write operations, the source buffer
- from which to write data.
-
- @retval EFI_SUCCESS The data was read from or written to the device.
- @retval EFI_UNSUPPORTED The Address is not valid for this system.
- @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
- lack of resources
-
-**/
-EFI_STATUS
-EFIAPI
-CpuIoServiceRead (
- IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
- IN EFI_SMM_IO_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- OUT VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINT8 Stride;
- UINT8 *Uint8Buffer;
-
- Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Select loop based on the width of the transfer
- //
- Stride = mStride[Width];
- for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
- if (Width == SMM_IO_UINT8) {
- *Uint8Buffer = IoRead8 ((UINTN)Address);
- } else if (Width == SMM_IO_UINT16) {
- *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
- } else if (Width == SMM_IO_UINT32) {
- *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Write I/O registers.
-
- The I/O operations are carried out exactly as requested. The caller is
- responsible for any alignment and I/O width issues that the bus, device,
- platform, or type of I/O might require.
-
- @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance.
- @param[in] Width Signifies the width of the I/O operations.
- @param[in] Address The base address of the I/O operations. The caller is
- responsible for aligning the Address if required.
- @param[in] Count The number of I/O operations to perform.
- @param[in] Buffer For read operations, the destination buffer to store
- the results. For write operations, the source buffer
- from which to write data.
-
- @retval EFI_SUCCESS The data was read from or written to the device.
- @retval EFI_UNSUPPORTED The Address is not valid for this system.
- @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid.
- @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a
- lack of resources
-
-**/
-EFI_STATUS
-EFIAPI
-CpuIoServiceWrite (
- IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This,
- IN EFI_SMM_IO_WIDTH Width,
- IN UINT64 Address,
- IN UINTN Count,
- IN VOID *Buffer
- )
-{
- EFI_STATUS Status;
- UINT8 Stride;
- UINT8 *Uint8Buffer;
-
- //
- // Make sure the parameters are valid
- //
- Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // Select loop based on the width of the transfer
- //
- Stride = mStride[Width];
- for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) {
- if (Width == SMM_IO_UINT8) {
- IoWrite8 ((UINTN)Address, *Uint8Buffer);
- } else if (Width == SMM_IO_UINT16) {
- IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
- } else if (Width == SMM_IO_UINT32) {
- IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
- }
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- The module Entry Point SmmCpuIoProtocol driver
+ The module Entry Point for Traditional MM CpuIoProtocol driver
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@@ -385,23 +28,5 @@ SmmCpuIo2Initialize (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- EFI_STATUS Status;
-
- //
- // Copy the SMM CPU I/O Protocol instance into the System Management System Table
- //
- CopyMem (&gSmst->SmmIo, &mSmmCpuIo2, sizeof (mSmmCpuIo2));
-
- //
- // Install the SMM CPU I/O Protocol into the SMM protocol database
- //
- Status = gSmst->SmmInstallProtocolInterface (
- &mHandle,
- &gEfiSmmCpuIo2ProtocolGuid,
- EFI_NATIVE_INTERFACE,
- &mSmmCpuIo2
- );
- ASSERT_EFI_ERROR (Status);
-
- return Status;
+ return CommonCpuIo2Initialize ();
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
index 7bc142b5794..8d15f3c6573 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
@@ -24,7 +24,8 @@
[Sources]
CpuIo2Smm.c
- CpuIo2Smm.h
+ CpuIo2Mm.c
+ CpuIo2Mm.h
[Packages]
MdePkg/MdePkg.dec
@@ -34,7 +35,7 @@
BaseLib
DebugLib
IoLib
- SmmServicesTableLib
+ MmServicesTableLib
BaseMemoryLib
[Protocols]
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.c
new file mode 100644
index 00000000000..10eb60588a4
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.c
@@ -0,0 +1,32 @@
+/** @file
+ Produces the SMM CPU I/O Protocol.
+
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include "CpuIo2Mm.h"
+
+/**
+ The module Entry Point for Standalone MM CpuIoProtocol driver
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval Other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmCpuIo2Initialize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ return CommonCpuIo2Initialize ();
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.inf
new file mode 100644
index 00000000000..f7a5c806e1f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.inf
@@ -0,0 +1,45 @@
+## @file
+# Produces the SMM CPU I/O 2 Protocol by using the services of the I/O Library.
+#
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = CpuIo2StandaloneMm
+ FILE_GUID = E3121A26-BB1C-4A18-8E23-2EA3F0412248
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ ENTRY_POINT = StandaloneMmCpuIo2Initialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ CpuIo2StandaloneMm.c
+ CpuIo2Mm.c
+ CpuIo2Mm.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ StandaloneMmDriverEntryPoint
+ BaseLib
+ DebugLib
+ IoLib
+ MmServicesTableLib
+ BaseMemoryLib
+
+[Protocols]
+ gEfiSmmCpuIo2ProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.c
index cf61927bee9..07b950f3b97 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.c
@@ -1,7 +1,7 @@
/** @file
CPU PEI Module installs CPU Multiple Processor PPI.
- Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -495,13 +495,9 @@ InitializeMpExceptionStackSwitchHandlers (
ExceptionNumber = FixedPcdGetSize (PcdCpuStackSwitchExceptionList);
NewStackSize = FixedPcdGet32 (PcdCpuKnownGoodStackSize) * ExceptionNumber;
- Status = PeiServicesAllocatePool (
- NewStackSize * NumberOfProcessors,
- (VOID **)&StackTop
- );
+ StackTop = AllocatePages (EFI_SIZE_TO_PAGES (NewStackSize * NumberOfProcessors));
ASSERT(StackTop != NULL);
- if (EFI_ERROR (Status)) {
- ASSERT_EFI_ERROR (Status);
+ if (StackTop == NULL) {
return;
}
StackTop += NewStackSize * NumberOfProcessors;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.h
index fe846679403..1a6068f4b65 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.h
@@ -1,7 +1,7 @@
/** @file
Definitions to install Multiple Processor PPI.
- Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -27,6 +27,7 @@
#include <Library/CpuExceptionHandlerLib.h>
#include <Library/MpInitLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
extern EFI_PEI_PPI_DESCRIPTOR mPeiCpuMpPpiDesc;
@@ -398,6 +399,18 @@ SecPlatformInformation2 (
);
/**
+ Migrates the Global Descriptor Table (GDT) to permanent memory.
+
+ @retval EFI_SUCCESS The GDT was migrated successfully.
+ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.
+
+**/
+EFI_STATUS
+MigrateGdt (
+ VOID
+ );
+
+/**
Initializes MP and exceptions handlers.
@param PeiServices The pointer to the PEI Services Table.
@@ -412,7 +425,7 @@ InitializeCpuMpWorker (
);
/**
- Enabl/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE.
+ Enable/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE.
Doing this in the memory-discovered callback is to make sure the Stack Guard
feature to cover as most PEI code as possible.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
index 4ab4cebfe76..c56d1e0181c 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuMpPei.inf
@@ -1,7 +1,7 @@
## @file
# CPU driver installs CPU PI Multi-processor PPI.
#
-# Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -45,6 +45,10 @@
MpInitLib
BaseMemoryLib
CpuLib
+ MemoryAllocationLib
+
+[Guids]
+ gEdkiiMigratedFvInfoGuid ## SOMETIMES_CONSUMES ## HOB
[Ppis]
gEfiPeiMpServicesPpiGuid ## PRODUCES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c
index e27e9df9b14..23c5cca4661 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuMpPei/CpuPaging.c
@@ -12,6 +12,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/MemoryAllocationLib.h>
#include <Library/CpuLib.h>
#include <Library/BaseLib.h>
+#include <Guid/MigratedFvInfo.h>
#ifdef VBOX
# define IN_RING0
# include <iprt/asm.h>
@@ -180,7 +181,7 @@ GetPhysicalAddressWidth (
Get the type of top level page table.
@retval Page512G PML4 paging.
- @retval Page1G PAE paing.
+ @retval Page1G PAE paging.
**/
PAGE_ATTRIBUTE
@@ -643,7 +644,7 @@ SetupStackGuardPage (
}
/**
- Enabl/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE.
+ Enable/setup stack guard for each processor if PcdCpuStackGuard is set to TRUE.
Doing this in the memory-discovered callback is to make sure the Stack Guard
feature to cover as most PEI code as possible.
@@ -663,8 +664,10 @@ MemoryDiscoveredPpiNotifyCallback (
IN VOID *Ppi
)
{
- EFI_STATUS Status;
- BOOLEAN InitStackGuard;
+ EFI_STATUS Status;
+ BOOLEAN InitStackGuard;
+ EDKII_MIGRATED_FV_INFO *MigratedFvInfo;
+ EFI_PEI_HOB_POINTERS Hob;
//
// Paging must be setup first. Otherwise the exception TSS setup during MP
@@ -672,9 +675,14 @@ MemoryDiscoveredPpiNotifyCallback (
// the task switch (for the sake of stack switch).
//
InitStackGuard = FALSE;
- if (IsIa32PaeSupported () && PcdGetBool (PcdCpuStackGuard)) {
+ Hob.Raw = NULL;
+ if (IsIa32PaeSupported ()) {
+ Hob.Raw = GetFirstGuidHob (&gEdkiiMigratedFvInfoGuid);
+ InitStackGuard = PcdGetBool (PcdCpuStackGuard);
+ }
+
+ if (InitStackGuard || Hob.Raw != NULL) {
EnablePaging ();
- InitStackGuard = TRUE;
}
Status = InitializeCpuMpWorker ((CONST EFI_PEI_SERVICES **)PeiServices);
@@ -684,6 +692,20 @@ MemoryDiscoveredPpiNotifyCallback (
SetupStackGuardPage ();
}
+ while (Hob.Raw != NULL) {
+ MigratedFvInfo = GET_GUID_HOB_DATA (Hob);
+
+ //
+ // Enable #PF exception, so if the code access SPI after disable NEM, it will generate
+ // the exception to avoid potential vulnerability.
+ //
+ ConvertMemoryPageAttributes (MigratedFvInfo->FvOrgBase, MigratedFvInfo->FvLength, 0);
+
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ Hob.Raw = GetNextGuidHob (&gEdkiiMigratedFvInfoGuid, Hob.Raw);
+ }
+ CpuFlushTlb ();
+
return Status;
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
index 1c01d109f95..040d23e8163 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
@@ -165,10 +165,6 @@ CpuS3DataInitialize (
UINTN NumberOfCpus;
UINTN NumberOfEnabledProcessors;
VOID *Stack;
- UINTN TableSize;
- CPU_REGISTER_TABLE *RegisterTable;
- UINTN Index;
- EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
UINTN GdtSize;
UINTN IdtSize;
VOID *Gdt;
@@ -255,34 +251,6 @@ CpuS3DataInitialize (
AcpiCpuData->PreSmmInitRegisterTable = OldAcpiCpuData->PreSmmInitRegisterTable;
AcpiCpuData->ApLocation = OldAcpiCpuData->ApLocation;
CopyMem (&AcpiCpuData->CpuStatus, &OldAcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));
- } else {
- //
- // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
- //
- TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
- RegisterTable = (CPU_REGISTER_TABLE *)AllocateZeroPages (TableSize);
- ASSERT (RegisterTable != NULL);
-
- for (Index = 0; Index < NumberOfCpus; Index++) {
- Status = MpServices->GetProcessorInfo (
- MpServices,
- Index,
- &ProcessorInfoBuffer
- );
- ASSERT_EFI_ERROR (Status);
-
- RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
- RegisterTable[Index].TableLength = 0;
- RegisterTable[Index].AllocatedSize = 0;
- RegisterTable[Index].RegisterTableEntry = 0;
-
- RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
- RegisterTable[NumberOfCpus + Index].TableLength = 0;
- RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;
- RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
- }
- AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
- AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
}
//
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/AcpiCpuData.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/AcpiCpuData.h
index 5a7fab59c49..6265a47a115 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/AcpiCpuData.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/AcpiCpuData.h
@@ -1,7 +1,7 @@
/** @file
Definitions for CPU S3 data.
-Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2013 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -60,14 +60,24 @@ typedef struct {
UINT32 MaxThreadCount;
//
// This field points to an array.
- // This array saves valid core count (type UINT32) of each package.
+ // This array saves thread count (type UINT32) of each package.
// The array has PackageCount elements.
//
// If the platform does not support MSR setting at S3 resume, and
// therefore it doesn't need the dependency semaphores, it should set
// this field to 0.
//
- EFI_PHYSICAL_ADDRESS ValidCoreCountPerPackage;
+ EFI_PHYSICAL_ADDRESS ThreadCountPerPackage;
+ //
+ // This field points to an array.
+ // This array saves thread count (type UINT8) of each core.
+ // The array has PackageCount * MaxCoreCount elements.
+ //
+ // If the platform does not support MSR setting at S3 resume, and
+ // therefore it doesn't need the dependency semaphores, it should set
+ // this field to 0.
+ //
+ EFI_PHYSICAL_ADDRESS ThreadCountPerCore;
} CPU_STATUS_INFORMATION;
//
@@ -168,6 +178,8 @@ typedef struct {
// If TableLength is > 0, then elements of RegisterTableEntry are used to
// initialize the CPU that matches InitialApicId, during an ACPI S3 resume,
// before SMBASE relocation is performed.
+ // If a register table is not required for any one of the CPUs, then
+ // PreSmmInitRegisterTable may be set to 0.
//
EFI_PHYSICAL_ADDRESS PreSmmInitRegisterTable;
//
@@ -177,6 +189,8 @@ typedef struct {
// If TableLength is > 0, then elements of RegisterTableEntry are used to
// initialize the CPU that matches InitialApicId, during an ACPI S3 resume,
// after SMBASE relocation is performed.
+ // If a register table is not required for any one of the CPUs, then
+ // RegisterTable may be set to 0.
//
EFI_PHYSICAL_ADDRESS RegisterTable;
//
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h
new file mode 100644
index 00000000000..67b0fb40ec2
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/CpuCacheInfoLib.h
@@ -0,0 +1,85 @@
+/** @file
+ Header file for CPU Cache info Library.
+
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _CPU_CACHE_INFO_LIB_H_
+#define _CPU_CACHE_INFO_LIB_H_
+
+typedef struct {
+ //
+ // Package number.
+ //
+ UINT32 Package;
+ //
+ // Core type of logical processor.
+ // Value = CPUID.1Ah:EAX[31:24]
+ //
+ UINT8 CoreType;
+ //
+ // Level of the cache that this package's this type of logical processor corresponds to.
+ // Value = CPUID.04h:EAX[07:05]
+ //
+ UINT8 CacheLevel : 3;
+ //
+ // Type of the cache that this package's this type of logical processor corresponds to.
+ // Value = CPUID.04h:EAX[04:00]
+ //
+ UINT8 CacheType : 5;
+ //
+ // Ways of associativity.
+ // Value = CPUID.04h:EBX[31:22]
+ //
+ UINT16 CacheWays : 10;
+ //
+ // Fully associative cache.
+ // Value = CPUID.04h:EAX[09]
+ //
+ UINT16 FullyAssociativeCache : 1;
+ //
+ // Direct mapped cache.
+ // Value = CPUID.04h:EDX[02]
+ //
+ UINT16 DirectMappedCache : 1;
+ UINT16 Reserved : 4;
+ //
+ // Size of single cache that this package's this type of logical processor corresponds to.
+ // Value = (CPUID.04h:EBX[31:22] + 1) * (CPUID.04h:EBX[21:12] + 1) *
+ // (CPUID.04h:EBX[11:00] + 1) * (CPUID.04h:ECX[31:00] + 1)
+ //
+ UINT32 CacheSizeinKB;
+ //
+ // Number of the cache that this package's this type of logical processor corresponds to.
+ // Have subtracted the number of caches that are shared.
+ //
+ UINT16 CacheCount;
+} CPU_CACHE_INFO;
+
+/**
+ Get CpuCacheInfo data array.
+
+ @param[in, out] CpuCacheInfo Pointer to the CpuCacheInfo array.
+ @param[in, out] CpuCacheInfoCount As input, point to the length of response CpuCacheInfo array.
+ As output, point to the actual length of response CpuCacheInfo array.
+
+ @retval EFI_SUCCESS Function completed successfully.
+ @retval EFI_INVALID_PARAMETER CpuCacheInfoCount is NULL.
+ @retval EFI_INVALID_PARAMETER CpuCacheInfo is NULL while CpuCacheInfoCount contains the value
+ greater than zero.
+ @retval EFI_UNSUPPORTED Processor does not support CPUID_CACHE_PARAMS Leaf.
+ @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
+ @retval EFI_BUFFER_TOO_SMALL CpuCacheInfoCount is too small to hold the response CpuCacheInfo
+ array. CpuCacheInfoCount has been updated with the length needed
+ to complete the request.
+**/
+EFI_STATUS
+EFIAPI
+GetCpuCacheInfo (
+ IN OUT CPU_CACHE_INFO *CpuCacheInfo,
+ IN OUT UINTN *CpuCacheInfoCount
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MicrocodeLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MicrocodeLib.h
new file mode 100644
index 00000000000..c23fe5bd416
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MicrocodeLib.h
@@ -0,0 +1,120 @@
+/** @file
+ Public include file for Microcode library.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef MICROCODE_LIB_H_
+#define MICROCODE_LIB_H_
+
+#include <Register/Intel/Microcode.h>
+#include <Ppi/ShadowMicrocode.h>
+
+/**
+ Get microcode update signature of currently loaded microcode update.
+
+ @return Microcode signature.
+**/
+UINT32
+EFIAPI
+GetProcessorMicrocodeSignature (
+ VOID
+ );
+
+/**
+ Get the processor signature and platform ID for current processor.
+
+ @param MicrocodeCpuId Return the processor signature and platform ID.
+**/
+VOID
+EFIAPI
+GetProcessorMicrocodeCpuId (
+ EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId
+ );
+
+/**
+ Return the total size of the microcode entry.
+
+ Logic follows pseudo code in SDM as below:
+
+ N = 512
+ If (Update.DataSize != 00000000H)
+ N = Update.TotalSize / 4
+
+ If Microcode is NULL, then ASSERT.
+
+ @param Microcode Pointer to the microcode entry.
+
+ @return The microcode total size.
+**/
+UINT32
+EFIAPI
+GetMicrocodeLength (
+ IN CPU_MICROCODE_HEADER *Microcode
+ );
+
+/**
+ Load the microcode to the processor.
+
+ If Microcode is NULL, then ASSERT.
+
+ @param Microcode Pointer to the microcode entry.
+**/
+VOID
+EFIAPI
+LoadMicrocode (
+ IN CPU_MICROCODE_HEADER *Microcode
+ );
+
+/**
+ Detect whether specified processor can find matching microcode patch and load it.
+
+ Microcode format is as below:
+ +----------------------------------------+-------------------------------------------------+
+ | CPU_MICROCODE_HEADER | |
+ +----------------------------------------+ V
+ | Update Data | CPU_MICROCODE_HEADER.Checksum
+ +----------------------------------------+-------+ ^
+ | CPU_MICROCODE_EXTENDED_TABLE_HEADER | | |
+ +----------------------------------------+ V |
+ | CPU_MICROCODE_EXTENDED_TABLE[0] | CPU_MICROCODE_EXTENDED_TABLE_HEADER.Checksum |
+ | CPU_MICROCODE_EXTENDED_TABLE[1] | ^ |
+ | ... | | |
+ +----------------------------------------+-------+-----------------------------------------+
+
+ There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.
+ The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignatureCount
+ of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.
+
+ If Microcode is NULL, then ASSERT.
+
+ @param Microcode Pointer to a microcode entry.
+ @param MicrocodeLength The total length of the microcode entry.
+ @param MinimumRevision The microcode whose revision <= MinimumRevision is treated as invalid.
+ Caller can supply value get from GetProcessorMicrocodeSignature() to check
+ whether the microcode is newer than loaded one.
+ Caller can supply 0 to treat any revision (except 0) microcode as valid.
+ @param MicrocodeCpuIds Pointer to an array of processor signature and platform ID that represents
+ a set of processors.
+ Caller can supply zero-element array to skip the processor signature and
+ platform ID check.
+ @param MicrocodeCpuIdCount The number of elements in MicrocodeCpuIds.
+ @param VerifyChecksum FALSE to skip all the checksum verifications.
+
+ @retval TRUE The microcode is valid.
+ @retval FALSE The microcode is invalid.
+**/
+BOOLEAN
+EFIAPI
+IsValidMicrocode (
+ IN CPU_MICROCODE_HEADER *Microcode,
+ IN UINTN MicrocodeLength,
+ IN UINT32 MinimumRevision,
+ IN EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuIds,
+ IN UINTN MicrocodeCpuIdCount,
+ IN BOOLEAN VerifyChecksum
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MtrrLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MtrrLib.h
index fafdbc19e58..02c046a94f0 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MtrrLib.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/MtrrLib.h
@@ -1,7 +1,7 @@
/** @file
MTRR setting library
- Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -186,36 +186,6 @@ MtrrGetMemoryAttribute (
/**
- This function will get the raw value in variable MTRRs
-
- @param[out] VariableSettings A buffer to hold variable MTRRs content.
-
- @return The buffer point to MTRR_VARIABLE_SETTINGS in which holds the content of the variable MTRR
-
-**/
-MTRR_VARIABLE_SETTINGS*
-EFIAPI
-MtrrGetVariableMtrr (
- OUT MTRR_VARIABLE_SETTINGS *VariableSettings
- );
-
-
-/**
- This function sets variable MTRRs
-
- @param[in] VariableSettings A buffer to hold variable MTRRs content.
-
- @return The pointer of VariableSettings
-
-**/
-MTRR_VARIABLE_SETTINGS*
-EFIAPI
-MtrrSetVariableMtrr (
- IN MTRR_VARIABLE_SETTINGS *VariableSettings
- );
-
-
-/**
This function gets the content in fixed MTRRs
@param[out] FixedSettings A buffer to hold fixed MTRRs content.
@@ -231,21 +201,6 @@ MtrrGetFixedMtrr (
/**
- This function sets fixed MTRRs
-
- @param[in] FixedSettings A buffer holding fixed MTRRs content.
-
- @return The pointer of FixedSettings
-
-**/
-MTRR_FIXED_SETTINGS*
-EFIAPI
-MtrrSetFixedMtrr (
- IN MTRR_FIXED_SETTINGS *FixedSettings
- );
-
-
-/**
This function gets the content in all MTRRs (variable and fixed)
@param[out] MtrrSetting A buffer to hold all MTRRs content.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/UefiCpuLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/UefiCpuLib.h
index c62eb93faf4..fb8dd8cdeea 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/UefiCpuLib.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/UefiCpuLib.h
@@ -5,6 +5,7 @@
to be UEFI specification compliant.
Copyright (c) 2009, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -29,4 +30,17 @@ InitializeFloatingPointUnits (
VOID
);
+/**
+ Determine if the standard CPU signature is "AuthenticAMD".
+
+ @retval TRUE The CPU signature matches.
+ @retval FALSE The CPU signature does not match.
+
+**/
+BOOLEAN
+EFIAPI
+StandardSignatureIsAuthenticAMD (
+ VOID
+ );
+
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/VmgExitLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/VmgExitLib.h
new file mode 100644
index 00000000000..6df1682f038
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Library/VmgExitLib.h
@@ -0,0 +1,146 @@
+/** @file
+ Public header file for the VMGEXIT Support library class.
+
+ This library class defines some routines used when invoking the VMGEXIT
+ instruction in support of SEV-ES and to handle #VC exceptions.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __VMG_EXIT_LIB_H__
+#define __VMG_EXIT_LIB_H__
+
+#include <Protocol/DebugSupport.h>
+#include <Register/Amd/Ghcb.h>
+
+
+/**
+ Perform VMGEXIT.
+
+ Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
+ then handles the return actions.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] ExitCode VMGEXIT code to be assigned to the SwExitCode
+ field of the GHCB.
+ @param[in] ExitInfo1 VMGEXIT information to be assigned to the
+ SwExitInfo1 field of the GHCB.
+ @param[in] ExitInfo2 VMGEXIT information to be assigned to the
+ SwExitInfo2 field of the GHCB.
+
+ @retval 0 VMGEXIT succeeded.
+ @return Exception number to be propagated, VMGEXIT
+ processing did not succeed.
+
+**/
+UINT64
+EFIAPI
+VmgExit (
+ IN OUT GHCB *Ghcb,
+ IN UINT64 ExitCode,
+ IN UINT64 ExitInfo1,
+ IN UINT64 ExitInfo2
+ );
+
+/**
+ Perform pre-VMGEXIT initialization/preparation.
+
+ Performs the necessary steps in preparation for invoking VMGEXIT. Must be
+ called before setting any fields within the GHCB.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in, out] InterruptState A pointer to hold the current interrupt
+ state, used for restoring in VmgDone ()
+
+**/
+VOID
+EFIAPI
+VmgInit (
+ IN OUT GHCB *Ghcb,
+ IN OUT BOOLEAN *InterruptState
+ );
+
+/**
+ Perform post-VMGEXIT cleanup.
+
+ Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
+ called after obtaining needed fields within the GHCB.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] InterruptState An indicator to conditionally (re)enable
+ interrupts
+
+**/
+VOID
+EFIAPI
+VmgDone (
+ IN OUT GHCB *Ghcb,
+ IN BOOLEAN InterruptState
+ );
+
+/**
+ Marks a specified offset as valid in the GHCB.
+
+ The ValidBitmap area represents the areas of the GHCB that have been marked
+ valid. Set the bit in ValidBitmap for the input offset.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] Offset Qword offset in the GHCB to mark valid
+
+**/
+VOID
+EFIAPI
+VmgSetOffsetValid (
+ IN OUT GHCB *Ghcb,
+ IN GHCB_REGISTER Offset
+ );
+
+/**
+ Checks if a specified offset is valid in the GHCB.
+
+ The ValidBitmap area represents the areas of the GHCB that have been marked
+ valid. Return whether the bit in the ValidBitmap is set for the input offset.
+
+ @param[in] Ghcb A pointer to the GHCB
+ @param[in] Offset Qword offset in the GHCB to mark valid
+
+ @retval TRUE Offset is marked valid in the GHCB
+ @retval FALSE Offset is not marked valid in the GHCB
+
+**/
+BOOLEAN
+EFIAPI
+VmgIsOffsetValid (
+ IN GHCB *Ghcb,
+ IN GHCB_REGISTER Offset
+ );
+
+/**
+ Handle a #VC exception.
+
+ Performs the necessary processing to handle a #VC exception.
+
+ The base library function returns an error equal to VC_EXCEPTION,
+ to be propagated to the standard exception handling stack.
+
+ @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
+ as value to use on error.
+ @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS Exception handled
+ @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
+ propagate provided
+ @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
+ propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+VmgExitHandleVc (
+ IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h
new file mode 100644
index 00000000000..5b5a08791ba
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Include/Ppi/RepublishSecPpi.h
@@ -0,0 +1,54 @@
+/** @file
+ This file declares Sec Platform Information PPI.
+
+ This service is the primary handoff state into the PEI Foundation.
+ The Security (SEC) component creates the early, transitory memory
+ environment and also encapsulates knowledge of at least the
+ location of the Boot Firmware Volume (BFV).
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Revision Reference:
+ This PPI is introduced in PI Version 1.0.
+
+**/
+
+#ifndef __REPUBLISH_SEC_PPI_H__
+#define __REPUBLISH_SEC_PPI_H__
+
+#include <Pi/PiPeiCis.h>
+
+#define REPUBLISH_SEC_PPI_PPI_GUID \
+ { \
+ 0x27a71b1e, 0x73ee, 0x43d6, { 0xac, 0xe3, 0x52, 0x1a, 0x2d, 0xc5, 0xd0, 0x92 } \
+ }
+
+typedef struct _REPUBLISH_SEC_PPI_PPI REPUBLISH_SEC_PPI_PPI;
+
+/**
+ This interface re-installs PPIs installed in SecCore from a post-memory PEIM.
+
+ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory
+ copy from a PEIM that has been shadowed to permanent memory.
+
+ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully.
+ @retval Others An error occurred re-installing the SecCore PPIs.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *REPUBLISH_SEC_PPI_REPUBLISH_SEC_PPIS)(
+ VOID
+ );
+
+///
+/// Republish SEC PPIs
+///
+struct _REPUBLISH_SEC_PPI_PPI {
+ REPUBLISH_SEC_PPI_REPUBLISH_SEC_PPIS RepublishSecPpis;
+};
+
+extern EFI_GUID gRepublishSecPpiPpiGuid;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c
new file mode 100644
index 00000000000..6b066671824
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.c
@@ -0,0 +1,38 @@
+/** @file
+ This library defines some routines that are generic for IA32 family CPU.
+
+ The library routines are UEFI specification compliant.
+
+ Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Register/Intel/Cpuid.h>
+#include <Register/Amd/Cpuid.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiCpuLib.h>
+
+/**
+ Determine if the standard CPU signature is "AuthenticAMD".
+
+ @retval TRUE The CPU signature matches.
+ @retval FALSE The CPU signature does not match.
+
+**/
+BOOLEAN
+EFIAPI
+StandardSignatureIsAuthenticAMD (
+ VOID
+ )
+{
+ UINT32 RegEbx;
+ UINT32 RegEcx;
+ UINT32 RegEdx;
+
+ AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx);
+ return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_AMD_EBX &&
+ RegEcx == CPUID_SIGNATURE_AUTHENTIC_AMD_ECX &&
+ RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
index 75fdc86fada..894917a3360 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
@@ -4,6 +4,7 @@
# The library routines are UEFI specification compliant.
#
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -29,6 +30,12 @@
[Sources.X64]
X64/InitializeFpu.nasm
+[Sources]
+ BaseUefiCpuLib.c
+
[Packages]
MdePkg/MdePkg.dec
UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
index 1fe6da2ffa6..434647ad3eb 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
@@ -4,7 +4,7 @@
This local APIC library instance supports xAPIC mode only.
Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -21,34 +21,13 @@
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
+#include <Library/UefiCpuLib.h>
//
// Library internal functions
//
/**
- Determine if the standard CPU signature is "AuthenticAMD".
-
- @retval TRUE The CPU signature matches.
- @retval FALSE The CPU signature does not match.
-
-**/
-BOOLEAN
-StandardSignatureIsAuthenticAMD (
- VOID
- )
-{
- UINT32 RegEbx;
- UINT32 RegEcx;
- UINT32 RegEdx;
-
- AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx);
- return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_AMD_EBX &&
- RegEcx == CPUID_SIGNATURE_AUTHENTIC_AMD_ECX &&
- RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX);
-}
-
-/**
Determine if the CPU supports the Local APIC Base Address MSR.
@retval TRUE The CPU supports the Local APIC Base Address MSR.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
index 7c4ea7eb952..c55a7382a20 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.inf
@@ -5,6 +5,7 @@
# where local APIC is disabled.
#
# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -37,6 +38,7 @@
TimerLib
IoLib
PcdLib
+ UefiCpuLib
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
index 485630e84ef..5bd4c2b7b7a 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
@@ -5,7 +5,7 @@
which have xAPIC and x2APIC modes.
Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
- Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -22,34 +22,13 @@
#include <Library/IoLib.h>
#include <Library/TimerLib.h>
#include <Library/PcdLib.h>
+#include <Library/UefiCpuLib.h>
//
// Library internal functions
//
/**
- Determine if the standard CPU signature is "AuthenticAMD".
-
- @retval TRUE The CPU signature matches.
- @retval FALSE The CPU signature does not match.
-
-**/
-BOOLEAN
-StandardSignatureIsAuthenticAMD (
- VOID
- )
-{
- UINT32 RegEbx;
- UINT32 RegEcx;
- UINT32 RegEdx;
-
- AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx);
- return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_AMD_EBX &&
- RegEcx == CPUID_SIGNATURE_AUTHENTIC_AMD_ECX &&
- RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX);
-}
-
-/**
Determine if the CPU supports the Local APIC Base Address MSR.
@retval TRUE The CPU supports the Local APIC Base Address MSR.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
index 218761ec3ae..564c1a97d41 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
@@ -5,6 +5,7 @@
# where local APIC is disabled.
#
# Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -37,6 +38,7 @@
TimerLib
IoLib
PcdLib
+ UefiCpuLib
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuInitIpiDelayInMicroSeconds ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
new file mode 100644
index 00000000000..8eee5b77cd7
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
@@ -0,0 +1,441 @@
+/** @file
+ Provides cache info for each package, core type, cache level and cache type.
+
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCpuCacheInfoLib.h"
+
+/**
+ Print CpuCacheInfo array.
+
+ @param[in] CpuCacheInfo Pointer to the CpuCacheInfo array.
+ @param[in] CpuCacheInfoCount The length of CpuCacheInfo array.
+
+**/
+VOID
+CpuCacheInfoPrintCpuCacheInfoTable (
+ IN CPU_CACHE_INFO *CpuCacheInfo,
+ IN UINTN CpuCacheInfoCount
+ )
+{
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));
+ DEBUG ((DEBUG_INFO, "| Index | Packge CoreType CacheLevel CacheType CacheWays (FA|DM) CacheSizeinKB CacheCount |\n"));
+ DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));
+
+ for (Index = 0; Index < CpuCacheInfoCount; Index++) {
+ DEBUG ((DEBUG_INFO, "| %4x | %4x %2x %2x %2x %4x ( %x| %x) %8x %4x |\n",
+ Index, CpuCacheInfo[Index].Package, CpuCacheInfo[Index].CoreType, CpuCacheInfo[Index].CacheLevel,
+ CpuCacheInfo[Index].CacheType, CpuCacheInfo[Index].CacheWays, CpuCacheInfo[Index].FullyAssociativeCache,
+ CpuCacheInfo[Index].DirectMappedCache, CpuCacheInfo[Index].CacheSizeinKB, CpuCacheInfo[Index].CacheCount));
+ }
+
+ DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));
+}
+
+/**
+ Get the total number of package and package ID in the platform.
+
+ @param[in] ProcessorInfo Pointer to the ProcessorInfo array.
+ @param[in] NumberOfProcessors Total number of logical processors in the platform.
+ @param[in, out] Package Pointer to the Package array.
+
+ @retval Return the total number of package and package ID in the platform.
+**/
+UINT32
+CpuCacheInfoGetNumberOfPackages (
+ IN CPUID_PROCESSOR_INFO *ProcessorInfo,
+ IN UINTN NumberOfProcessors,
+ IN OUT UINT32 *Package
+ )
+{
+ UINTN ProcessorIndex;
+ UINT32 PackageIndex;
+ UINT32 PackageCount;
+ UINT32 CurrentPackage;
+
+ PackageCount = 0;
+
+ for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {
+ CurrentPackage = ProcessorInfo[ProcessorIndex].Package;
+
+ //
+ // For the package that already exists in Package array, break out the loop.
+ //
+ for (PackageIndex = 0; PackageIndex < PackageCount; PackageIndex++) {
+ if (CurrentPackage == Package[PackageIndex]) {
+ break;
+ }
+ }
+
+ //
+ // For the new package, save it in Package array.
+ //
+ if (PackageIndex == PackageCount) {
+ ASSERT (PackageCount < MAX_NUM_OF_PACKAGE);
+ Package[PackageCount++] = CurrentPackage;
+ }
+ }
+
+ return PackageCount;
+}
+
+/**
+ Get the number of CoreType of requested package.
+
+ @param[in] ProcessorInfo Pointer to the ProcessorInfo array.
+ @param[in] NumberOfProcessors Total number of logical processors in the platform.
+ @param[in] Package The requested package number.
+
+ @retval Return the number of CoreType of requested package.
+**/
+UINTN
+CpuCacheInfoGetNumberOfCoreTypePerPackage(
+ IN CPUID_PROCESSOR_INFO *ProcessorInfo,
+ IN UINTN NumberOfProcessors,
+ IN UINTN Package
+ )
+{
+ UINTN ProcessorIndex;
+ //
+ // Core Type value comes from CPUID.1Ah.EAX[31:24].
+ // So max number of core types should be MAX_UINT8.
+ //
+ UINT8 CoreType[MAX_UINT8];
+ UINTN CoreTypeIndex;
+ UINTN CoreTypeCount;
+ UINT8 CurrentCoreType;
+
+ //
+ // CoreType array is empty.
+ //
+ CoreTypeCount = 0;
+
+ for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {
+ CurrentCoreType = ProcessorInfo[ProcessorIndex].CoreType;
+
+ if (ProcessorInfo[ProcessorIndex].Package != Package) {
+ continue;
+ }
+
+ //
+ // For the type that already exists in CoreType array, break out the loop.
+ //
+ for (CoreTypeIndex = 0; CoreTypeIndex < CoreTypeCount; CoreTypeIndex++) {
+ if (CurrentCoreType == CoreType[CoreTypeIndex]) {
+ break;
+ }
+ }
+
+ //
+ // For the new type, save it in CoreType array.
+ //
+ if (CoreTypeIndex == CoreTypeCount) {
+ ASSERT (CoreTypeCount < MAX_UINT8);
+ CoreType[CoreTypeCount++] = CurrentCoreType;
+ }
+ }
+
+ return CoreTypeCount;
+}
+
+/**
+ Collect core and cache information of calling processor via CPUID instructions.
+
+ @param[in, out] Buffer The pointer to private data buffer.
+**/
+VOID
+EFIAPI
+CpuCacheInfoCollectCoreAndCacheData (
+ IN OUT VOID *Buffer
+ )
+{
+ UINTN ProcessorIndex;
+ UINT32 CpuidMaxInput;
+ UINT8 CacheParamLeafIndex;
+ CPUID_CACHE_PARAMS_EAX CacheParamEax;
+ CPUID_CACHE_PARAMS_EBX CacheParamEbx;
+ UINT32 CacheParamEcx;
+ CPUID_CACHE_PARAMS_EDX CacheParamEdx;
+ CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX NativeModelIdAndCoreTypeEax;
+ COLLECT_CPUID_CACHE_DATA_CONTEXT *Context;
+ CPUID_CACHE_DATA *CacheData;
+
+ Context = (COLLECT_CPUID_CACHE_DATA_CONTEXT *)Buffer;
+ ProcessorIndex = CpuCacheInfoWhoAmI (Context->MpServices);
+ CacheData = &Context->CacheData[MAX_NUM_OF_CACHE_PARAMS_LEAF * ProcessorIndex];
+
+ AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);
+
+ //
+ // get CoreType if CPUID_HYBRID_INFORMATION leaf is supported.
+ //
+ Context->ProcessorInfo[ProcessorIndex].CoreType = 0;
+ if (CpuidMaxInput >= CPUID_HYBRID_INFORMATION) {
+ AsmCpuidEx (CPUID_HYBRID_INFORMATION, CPUID_HYBRID_INFORMATION_MAIN_LEAF, &NativeModelIdAndCoreTypeEax.Uint32, NULL, NULL, NULL);
+ Context->ProcessorInfo[ProcessorIndex].CoreType = (UINT8) NativeModelIdAndCoreTypeEax.Bits.CoreType;
+ }
+
+ //
+ // cache hierarchy starts with an index value of 0.
+ //
+ CacheParamLeafIndex = 0;
+
+ while (CacheParamLeafIndex < MAX_NUM_OF_CACHE_PARAMS_LEAF) {
+ AsmCpuidEx (CPUID_CACHE_PARAMS, CacheParamLeafIndex, &CacheParamEax.Uint32, &CacheParamEbx.Uint32, &CacheParamEcx, &CacheParamEdx.Uint32);
+
+ if (CacheParamEax.Bits.CacheType == 0) {
+ break;
+ }
+
+ CacheData[CacheParamLeafIndex].CacheLevel = (UINT8)CacheParamEax.Bits.CacheLevel;
+ CacheData[CacheParamLeafIndex].CacheType = (UINT8)CacheParamEax.Bits.CacheType;
+ CacheData[CacheParamLeafIndex].CacheWays = (UINT16)CacheParamEbx.Bits.Ways;
+ CacheData[CacheParamLeafIndex].FullyAssociativeCache = (UINT8)CacheParamEax.Bits.FullyAssociativeCache;
+ CacheData[CacheParamLeafIndex].DirectMappedCache = (UINT8)CacheParamEdx.Bits.ComplexCacheIndexing;
+ CacheData[CacheParamLeafIndex].CacheShareBits = (UINT16)CacheParamEax.Bits.MaximumAddressableIdsForLogicalProcessors;
+ CacheData[CacheParamLeafIndex].CacheSizeinKB = (CacheParamEbx.Bits.Ways + 1) *
+ (CacheParamEbx.Bits.LinePartitions + 1) * (CacheParamEbx.Bits.LineSize + 1) * (CacheParamEcx + 1) / SIZE_1KB;
+
+ CacheParamLeafIndex++;
+ }
+}
+
+/**
+ Collect CacheInfo data from the CacheData.
+
+ @param[in] CacheData Pointer to the CacheData array.
+ @param[in] ProcessorInfo Pointer to the ProcessorInfo array.
+ @param[in] NumberOfProcessors Total number of logical processors in the platform.
+ @param[in, out] CacheInfo Pointer to the CacheInfo array.
+ @param[in, out] CacheInfoCount As input, point to the length of response CacheInfo array.
+ As output, point to the actual length of response CacheInfo array.
+
+ @retval EFI_SUCCESS Function completed successfully.
+ @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
+ @retval EFI_BUFFER_TOO_SMALL CacheInfoCount is too small to hold the response CacheInfo
+ array. CacheInfoCount has been updated with the length needed
+ to complete the request.
+**/
+EFI_STATUS
+CpuCacheInfoCollectCpuCacheInfoData (
+ IN CPUID_CACHE_DATA *CacheData,
+ IN CPUID_PROCESSOR_INFO *ProcessorInfo,
+ IN UINTN NumberOfProcessors,
+ IN OUT CPU_CACHE_INFO *CacheInfo,
+ IN OUT UINTN *CacheInfoCount
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NumberOfPackage;
+ UINT32 Package[MAX_NUM_OF_PACKAGE];
+ UINTN PackageIndex;
+ UINTN TotalNumberOfCoreType;
+ UINTN MaxCacheInfoCount;
+ CPU_CACHE_INFO *LocalCacheInfo;
+ UINTN CacheInfoIndex;
+ UINTN LocalCacheInfoCount;
+ UINTN Index;
+ UINTN NextIndex;
+
+ //
+ // Get number of Packages and Package ID.
+ //
+ NumberOfPackage = CpuCacheInfoGetNumberOfPackages (ProcessorInfo, NumberOfProcessors, Package);
+
+ //
+ // Get number of core types for each package and count the total number.
+ // E.g. If Package1 and Package2 both have 2 core types, the total number is 4.
+ //
+ TotalNumberOfCoreType = 0;
+ for (PackageIndex = 0; PackageIndex < NumberOfPackage; PackageIndex++) {
+ TotalNumberOfCoreType += CpuCacheInfoGetNumberOfCoreTypePerPackage (ProcessorInfo, NumberOfProcessors, Package[PackageIndex]);
+ }
+
+ MaxCacheInfoCount = TotalNumberOfCoreType * MAX_NUM_OF_CACHE_PARAMS_LEAF;
+ LocalCacheInfo = AllocatePages (EFI_SIZE_TO_PAGES (MaxCacheInfoCount * sizeof (*LocalCacheInfo)));
+ ASSERT (LocalCacheInfo != NULL);
+ if (LocalCacheInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ LocalCacheInfoCount = 0;
+
+ for (Index = 0; Index < NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF; Index++) {
+ if (CacheData[Index].CacheSizeinKB == 0) {
+ continue;
+ }
+
+ //
+ // For the sharing caches, clear their CacheSize.
+ //
+ for (NextIndex = Index + 1; NextIndex < NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF; NextIndex++) {
+ if (CacheData[NextIndex].CacheSizeinKB == 0) {
+ continue;
+ }
+
+ if (CacheData[Index].CacheLevel == CacheData[NextIndex].CacheLevel &&
+ CacheData[Index].CacheType == CacheData[NextIndex].CacheType &&
+ ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&
+ ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&
+ (ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId & ~CacheData[Index].CacheShareBits) ==
+ (ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId & ~CacheData[NextIndex].CacheShareBits)) {
+ CacheData[NextIndex].CacheSizeinKB = 0; // uses the sharing cache
+ }
+ }
+
+ //
+ // For the cache that already exists in LocalCacheInfo, increase its CacheCount.
+ //
+ for (CacheInfoIndex = 0; CacheInfoIndex < LocalCacheInfoCount; CacheInfoIndex++) {
+ if (LocalCacheInfo[CacheInfoIndex].Package == ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&
+ LocalCacheInfo[CacheInfoIndex].CoreType == ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&
+ LocalCacheInfo[CacheInfoIndex].CacheLevel == CacheData[Index].CacheLevel &&
+ LocalCacheInfo[CacheInfoIndex].CacheType == CacheData[Index].CacheType) {
+ LocalCacheInfo[CacheInfoIndex].CacheCount++;
+ break;
+ }
+ }
+
+ //
+ // For the new cache with different Package, CoreType, CacheLevel or CacheType, copy its
+ // data into LocalCacheInfo buffer.
+ //
+ if (CacheInfoIndex == LocalCacheInfoCount) {
+ ASSERT (LocalCacheInfoCount < MaxCacheInfoCount);
+
+ LocalCacheInfo[LocalCacheInfoCount].Package = ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package;
+ LocalCacheInfo[LocalCacheInfoCount].CoreType = ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType;
+ LocalCacheInfo[LocalCacheInfoCount].CacheLevel = CacheData[Index].CacheLevel;
+ LocalCacheInfo[LocalCacheInfoCount].CacheType = CacheData[Index].CacheType;
+ LocalCacheInfo[LocalCacheInfoCount].CacheWays = CacheData[Index].CacheWays;
+ LocalCacheInfo[LocalCacheInfoCount].FullyAssociativeCache = CacheData[Index].FullyAssociativeCache;
+ LocalCacheInfo[LocalCacheInfoCount].DirectMappedCache = CacheData[Index].DirectMappedCache;
+ LocalCacheInfo[LocalCacheInfoCount].CacheSizeinKB = CacheData[Index].CacheSizeinKB;
+ LocalCacheInfo[LocalCacheInfoCount].CacheCount = 1;
+
+ LocalCacheInfoCount++;
+ }
+ }
+
+ if (*CacheInfoCount < LocalCacheInfoCount) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ } else {
+ CopyMem (CacheInfo, LocalCacheInfo, sizeof (*CacheInfo) * LocalCacheInfoCount);
+ DEBUG_CODE (
+ CpuCacheInfoPrintCpuCacheInfoTable (CacheInfo, LocalCacheInfoCount);
+ );
+ Status = EFI_SUCCESS;
+ }
+
+ *CacheInfoCount = LocalCacheInfoCount;
+
+ FreePages (LocalCacheInfo, EFI_SIZE_TO_PAGES (MaxCacheInfoCount * sizeof (*LocalCacheInfo)));
+
+ return Status;
+}
+
+/**
+ Get CpuCacheInfo data array.
+
+ @param[in, out] CpuCacheInfo Pointer to the CpuCacheInfo array.
+ @param[in, out] CpuCacheInfoCount As input, point to the length of response CpuCacheInfo array.
+ As output, point to the actual length of response CpuCacheInfo array.
+
+ @retval EFI_SUCCESS Function completed successfully.
+ @retval EFI_INVALID_PARAMETER CpuCacheInfoCount is NULL.
+ @retval EFI_INVALID_PARAMETER CpuCacheInfo is NULL while CpuCacheInfoCount contains the value
+ greater than zero.
+ @retval EFI_UNSUPPORTED Processor does not support CPUID_CACHE_PARAMS Leaf.
+ @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.
+ @retval EFI_BUFFER_TOO_SMALL CpuCacheInfoCount is too small to hold the response CpuCacheInfo
+ array. CpuCacheInfoCount has been updated with the length needed
+ to complete the request.
+**/
+EFI_STATUS
+EFIAPI
+GetCpuCacheInfo (
+ IN OUT CPU_CACHE_INFO *CpuCacheInfo,
+ IN OUT UINTN *CpuCacheInfoCount
+ )
+{
+ EFI_STATUS Status;
+ UINT32 CpuidMaxInput;
+ UINT32 NumberOfProcessors;
+ UINTN CacheDataCount;
+ UINTN ProcessorIndex;
+ EFI_PROCESSOR_INFORMATION ProcessorInfo;
+ COLLECT_CPUID_CACHE_DATA_CONTEXT Context;
+
+ if (CpuCacheInfoCount == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (*CpuCacheInfoCount != 0 && CpuCacheInfo == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);
+ if (CpuidMaxInput < CPUID_CACHE_PARAMS) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.MpServices.
+ //
+ CpuCacheInfoGetMpServices (&Context.MpServices);
+
+ NumberOfProcessors = CpuCacheInfoGetNumberOfProcessors (Context.MpServices);
+
+ //
+ // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.ProcessorInfo.
+ //
+ Context.ProcessorInfo = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));
+ ASSERT (Context.ProcessorInfo != NULL);
+ if (Context.ProcessorInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.CacheData.
+ // CacheData array consists of CPUID_CACHE_DATA data structure for each Cpuid Cache Parameter Leaf
+ // per logical processor. The array begin with data of each Cache Parameter Leaf of processor 0, followed
+ // by data of each Cache Parameter Leaf of processor 1 ...
+ //
+ CacheDataCount = NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF;
+ Context.CacheData = AllocatePages (EFI_SIZE_TO_PAGES (CacheDataCount * sizeof (*Context.CacheData)));
+ ASSERT (Context.CacheData != NULL);
+ if (Context.CacheData == NULL) {
+ FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ZeroMem (Context.CacheData, CacheDataCount * sizeof (*Context.CacheData));
+
+ //
+ // Collect Package ID and APIC ID of all processors.
+ //
+ for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {
+ CpuCacheInfoGetProcessorInfo (Context.MpServices, ProcessorIndex, &ProcessorInfo);
+ Context.ProcessorInfo[ProcessorIndex].Package = ProcessorInfo.Location.Package;
+ Context.ProcessorInfo[ProcessorIndex].ApicId = (UINT32) ProcessorInfo.ProcessorId;
+ }
+
+ //
+ // Wakeup all processors for CacheData(core type and cache data) collection.
+ //
+ CpuCacheInfoStartupAllCPUs (Context.MpServices, CpuCacheInfoCollectCoreAndCacheData, &Context);
+
+ //
+ // Collect CpuCacheInfo data from CacheData.
+ //
+ Status = CpuCacheInfoCollectCpuCacheInfoData (Context.CacheData, Context.ProcessorInfo, NumberOfProcessors, CpuCacheInfo, CpuCacheInfoCount);
+
+ FreePages (Context.CacheData, EFI_SIZE_TO_PAGES (CacheDataCount * sizeof (*Context.CacheData)));
+ FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni
new file mode 100644
index 00000000000..1bc801f15f8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.uni
@@ -0,0 +1,15 @@
+// /** @file
+// CPU Cache Info Library
+//
+// Provides cache info for each package, core type, cache level and cache type.
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "CPU Cache Info Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Provides cache info for each package, core type, cache level and cache type."
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c
new file mode 100644
index 00000000000..aa00ddebcac
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.c
@@ -0,0 +1,127 @@
+/** @file
+ Provides cache info for each package, core type, cache level and cache type.
+
+ Copyright (c) 2020 Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/CpuCacheInfoLib.h>
+#include <InternalCpuCacheInfoLib.h>
+
+/**
+ Get EFI_MP_SERVICES_PROTOCOL pointer.
+
+ @param[out] MpServices A pointer to the buffer where EFI_MP_SERVICES_PROTOCOL is stored
+
+ @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is returned
+ @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not found
+**/
+EFI_STATUS
+CpuCacheInfoGetMpServices (
+ OUT MP_SERVICES *MpServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpServices->Protocol);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Activate all of the logical processors.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure A pointer to the function to be run on enabled logical processors.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all enabled logical processors.
+**/
+VOID
+CpuCacheInfoStartupAllCPUs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *ProcedureArgument
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MpServices.Protocol->StartupAllAPs (MpServices.Protocol, Procedure, FALSE, NULL, 0, ProcedureArgument, NULL);
+ if (Status == EFI_NOT_STARTED) {
+ //
+ // EFI_NOT_STARTED is returned when there is no enabled AP.
+ // Treat this case as EFI_SUCCESS.
+ //
+ Status = EFI_SUCCESS;
+ }
+ ASSERT_EFI_ERROR (Status);
+
+ Procedure (ProcedureArgument);
+}
+
+/**
+ Get detailed information of the requested logical processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNum The requested logical processor number.
+ @param[out] ProcessorInfo A pointer to the buffer where the processor information is stored
+**/
+VOID
+CpuCacheInfoGetProcessorInfo (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNum,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfo
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MpServices.Protocol->GetProcessorInfo (MpServices.Protocol, ProcessorNum, ProcessorInfo);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Get the logical processor number.
+
+ @param[in] MpServices MP_SERVICES structure.
+
+ @retval Return the logical processor number.
+**/
+UINT32
+CpuCacheInfoWhoAmI (
+ IN MP_SERVICES MpServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNum;
+
+ Status = MpServices.Protocol->WhoAmI (MpServices.Protocol, &ProcessorNum);
+ ASSERT_EFI_ERROR (Status);
+
+ return (UINT32)ProcessorNum;
+}
+
+/**
+ Get the total number of logical processors in the platform.
+
+ @param[in] MpServices MP_SERVICES structure.
+
+ @retval Return the total number of logical processors.
+**/
+UINT32
+CpuCacheInfoGetNumberOfProcessors (
+ IN MP_SERVICES MpServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfProcessor;
+ UINTN NumberOfEnabledProcessor;
+
+ Status = MpServices.Protocol->GetNumberOfProcessors (MpServices.Protocol, &NumberOfProcessor, &NumberOfEnabledProcessor);
+ ASSERT_EFI_ERROR (Status);
+
+ return (UINT32)NumberOfProcessor;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
new file mode 100644
index 00000000000..770e96e797a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
@@ -0,0 +1,43 @@
+## @file
+# CPU Cache Info Library instance for DXE driver.
+#
+# Provides cache info for each package, core type, cache level and cache type.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCpuCacheInfoLib
+ FILE_GUID = B25C288F-C309-41F1-8325-37E64DC5EA3D
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuCacheInfoLib|DXE_DRIVER UEFI_APPLICATION
+ MODULE_UNI_FILE = CpuCacheInfoLib.uni
+
+[Sources]
+ InternalCpuCacheInfoLib.h
+ CpuCacheInfoLib.c
+ DxeCpuCacheInfoLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gEfiMpServiceProtocolGuid
+
+[Pcd]
+
+[Depex]
+ gEfiMpServiceProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h
new file mode 100644
index 00000000000..df132e8d190
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/InternalCpuCacheInfoLib.h
@@ -0,0 +1,170 @@
+/** @file
+ Internal header file for CPU Cache info Library.
+
+ Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _INTERNAL_CPU_CACHE_INFO_LIB_H_
+#define _INTERNAL_CPU_CACHE_INFO_LIB_H_
+
+#include <PiPei.h>
+#include <Register/Cpuid.h>
+#include <Ppi/MpServices2.h>
+#include <Protocol/MpService.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CpuCacheInfoLib.h>
+
+typedef struct {
+ //
+ // Package ID, the information comes from
+ // EFI_CPU_PHYSICAL_LOCATION.Package
+ //
+ UINT32 Package;
+ //
+ // APIC ID, the information comes from
+ // EFI_PROCESSOR_INFORMATION.ProcessorId
+ //
+ UINT32 ApicId;
+ //
+ // Core type of logical processor.
+ // Value = CPUID.1Ah:EAX[31:24]
+ //
+ UINT8 CoreType;
+} CPUID_PROCESSOR_INFO;
+
+typedef struct {
+ //
+ // Level of the cache.
+ // Value = CPUID.04h:EAX[07:05]
+ //
+ UINT8 CacheLevel : 3;
+ //
+ // Type of the cache.
+ // Value = CPUID.04h:EAX[04:00]
+ //
+ UINT8 CacheType : 5;
+ //
+ // Ways of associativity.
+ // Value = CPUID.04h:EBX[31:22]
+ //
+ UINT16 CacheWays : 10;
+ //
+ // Fully associative cache.
+ // Value = CPUID.04h:EAX[09]
+ //
+ UINT16 FullyAssociativeCache : 1;
+ //
+ // Direct mapped cache.
+ // Value = CPUID.04h:EDX[02]
+ //
+ UINT16 DirectMappedCache : 1;
+ UINT16 Reserved : 4;
+ //
+ // Cache share bits.
+ // Value = CPUID.04h:EAX[25:14]
+ //
+ UINT16 CacheShareBits;
+ //
+ // Size of single cache.
+ // Value = (CPUID.04h:EBX[31:22] + 1) * (CPUID.04h:EBX[21:12] + 1) *
+ // (CPUID.04h:EBX[11:00] + 1) * (CPUID.04h:ECX[31:00] + 1)
+ //
+ UINT32 CacheSizeinKB;
+} CPUID_CACHE_DATA;
+
+typedef union {
+ EDKII_PEI_MP_SERVICES2_PPI *Ppi;
+ EFI_MP_SERVICES_PROTOCOL *Protocol;
+} MP_SERVICES;
+
+typedef struct {
+ MP_SERVICES MpServices;
+ CPUID_PROCESSOR_INFO *ProcessorInfo;
+ CPUID_CACHE_DATA *CacheData;
+} COLLECT_CPUID_CACHE_DATA_CONTEXT;
+
+
+/*
+ Defines the maximum count of Deterministic Cache Parameters Leaf of all APs and BSP.
+ To save boot time, skip starting up all APs to calculate each AP's count of Deterministic
+ Cache Parameters Leaf, so use a definition instead.
+ Anyway, definition value will be checked in CpuCacheInfoCollectCoreAndCacheData function.
+*/
+#define MAX_NUM_OF_CACHE_PARAMS_LEAF 6
+
+/*
+ Defines the maximum count of packages.
+*/
+#define MAX_NUM_OF_PACKAGE 100
+
+/**
+ Get EDKII_PEI_MP_SERVICES2_PPI or EFI_MP_SERVICES_PROTOCOL pointer.
+
+ @param[out] MpServices A pointer to the buffer where EDKII_PEI_MP_SERVICES2_PPI or
+ EFI_MP_SERVICES_PROTOCOL is stored
+
+ @retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI or EFI_MP_SERVICES_PROTOCOL interface is returned
+ @retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI or EFI_MP_SERVICES_PROTOCOL interface is not found
+**/
+EFI_STATUS
+CpuCacheInfoGetMpServices (
+ OUT MP_SERVICES *MpServices
+ );
+
+/**
+ Activate all of the logical processors.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure A pointer to the function to be run on enabled logical processors.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all enabled logical processors.
+**/
+VOID
+CpuCacheInfoStartupAllCPUs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *ProcedureArgument
+ );
+
+/**
+ Get detailed information of the requested logical processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNum The requested logical processor number.
+ @param[out] ProcessorInfo A pointer to the buffer where the processor information is stored
+**/
+VOID
+CpuCacheInfoGetProcessorInfo (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNum,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfo
+ );
+
+/**
+ Get the logical processor number.
+
+ @param[in] MpServices MP_SERVICES structure.
+
+ @retval Return the logical processor number.
+**/
+UINT32
+CpuCacheInfoWhoAmI (
+ IN MP_SERVICES MpServices
+ );
+
+/**
+ Get the total number of logical processors in the platform.
+
+ @param[in] MpServices MP_SERVICES structure.
+
+ @retval Return the total number of logical processors.
+**/
+UINT32
+CpuCacheInfoGetNumberOfProcessors (
+ IN MP_SERVICES MpServices
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c
new file mode 100644
index 00000000000..382a54e2370
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.c
@@ -0,0 +1,119 @@
+/** @file
+ Provides cache info for each package, core type, cache level and cache type.
+
+ 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/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/CpuCacheInfoLib.h>
+#include <InternalCpuCacheInfoLib.h>
+
+/**
+ Get EDKII_PEI_MP_SERVICES2_PPI pointer.
+
+ @param[out] MpServices A pointer to the buffer where EDKII_PEI_MP_SERVICES2_PPI is stored
+
+ @retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI interface is returned
+ @retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI interface is not found
+**/
+EFI_STATUS
+CpuCacheInfoGetMpServices (
+ OUT MP_SERVICES *MpServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOID **)&MpServices->Ppi);
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Activate all of the logical processors.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] Procedure A pointer to the function to be run on enabled logical processors.
+ @param[in] ProcedureArgument The parameter passed into Procedure for all enabled logical processors.
+**/
+VOID
+CpuCacheInfoStartupAllCPUs (
+ IN MP_SERVICES MpServices,
+ IN EFI_AP_PROCEDURE Procedure,
+ IN VOID *ProcedureArgument
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MpServices.Ppi->StartupAllCPUs (MpServices.Ppi, Procedure, 0, ProcedureArgument);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Get detailed information of the requested logical processor.
+
+ @param[in] MpServices MP_SERVICES structure.
+ @param[in] ProcessorNum The requested logical processor number.
+ @param[out] ProcessorInfo A pointer to the buffer where the processor information is stored
+**/
+VOID
+CpuCacheInfoGetProcessorInfo (
+ IN MP_SERVICES MpServices,
+ IN UINTN ProcessorNum,
+ OUT EFI_PROCESSOR_INFORMATION *ProcessorInfo
+ )
+{
+ EFI_STATUS Status;
+
+ Status = MpServices.Ppi->GetProcessorInfo (MpServices.Ppi, ProcessorNum, ProcessorInfo);
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Get the logical processor number.
+
+ @param[in] MpServices MP_SERVICES structure.
+
+ @retval Return the logical processor number.
+**/
+UINT32
+CpuCacheInfoWhoAmI (
+ IN MP_SERVICES MpServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNum;
+
+ Status = MpServices.Ppi->WhoAmI (MpServices.Ppi, &ProcessorNum);
+ ASSERT_EFI_ERROR (Status);
+
+ return (UINT32)ProcessorNum;
+}
+
+/**
+ Get the total number of logical processors in the platform.
+
+ @param[in] MpServices MP_SERVICES structure.
+
+ @retval Return the total number of logical processors.
+**/
+UINT32
+CpuCacheInfoGetNumberOfProcessors (
+ IN MP_SERVICES MpServices
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfProcessor;
+ UINTN NumberOfEnabledProcessor;
+
+ Status = MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi, &NumberOfProcessor, &NumberOfEnabledProcessor);
+ ASSERT_EFI_ERROR (Status);
+
+ return (UINT32)NumberOfProcessor;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
new file mode 100644
index 00000000000..4b7bc54f7a6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
@@ -0,0 +1,43 @@
+## @file
+# CPU Cache Info Library instance for PEI module.
+#
+# Provides cache info for each package, core type, cache level and cache type.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PeiCpuCacheInfoLib
+ FILE_GUID = CFEE2DBE-53B2-4916-84CA-0BA83C3DDA6E
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = CpuCacheInfoLib|PEIM
+ MODULE_UNI_FILE = CpuCacheInfoLib.uni
+
+[Sources]
+ InternalCpuCacheInfoLib.h
+ CpuCacheInfoLib.c
+ PeiCpuCacheInfoLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ PeiServicesTablePointerLib
+
+[Ppis]
+ gEdkiiPeiMpServices2PpiGuid
+
+[Pcd]
+
+[Depex]
+ gEdkiiPeiMpServices2PpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c
index 4e8d758406d..59e213cec28 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuCommonFeaturesLib/MachineCheck.c
@@ -287,7 +287,7 @@ LmceSupport (
McgCap.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_CAP);
if (ProcessorNumber == 0) {
- DEBUG ((EFI_D_INFO, "LMCE eanble = %x\n", (BOOLEAN) (McgCap.Bits.MCG_LMCE_P != 0)));
+ DEBUG ((DEBUG_INFO, "LMCE enable = %x\n", (BOOLEAN) (McgCap.Bits.MCG_LMCE_P != 0)));
}
return (BOOLEAN) (McgCap.Bits.MCG_LMCE_P != 0);
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
index d59ca5530d4..82823bb685a 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.c
@@ -14,7 +14,7 @@
//
// 1 means an error code will be pushed, otherwise 0
//
-CONST UINT32 mErrorCodeFlag = 0x00227d00;
+CONST UINT32 mErrorCodeFlag = 0x20227d00;
//
// Define the maximum message length
@@ -44,7 +44,15 @@ CONST CHAR8 *mExceptionNameStr[] = {
"#MC - Machine-Check",
"#XM - SIMD floating-point",
"#VE - Virtualization",
- "#CP - Control Protection"
+ "#CP - Control Protection",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "#VC - VMM Communication",
};
#define EXCEPTION_KNOWN_NAME_NUM (sizeof (mExceptionNameStr) / sizeof (CHAR8 *))
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
index c5c08da8dec..800a2abf0da 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/CpuExceptionCommon.h
@@ -90,8 +90,8 @@ AsmGetTemplateAddressMap (
**/
VOID
ArchUpdateIdtEntry (
- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
- IN UINTN InterruptHandler
+ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
);
/**
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
index 785cca6f8a5..42cc04eac29 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
@@ -43,6 +43,9 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuStackSwitchExceptionList
gUefiCpuPkgTokenSpaceGuid.PcdCpuKnownGoodStackSize
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES
+
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
@@ -57,3 +60,4 @@
PeCoffGetEntryPointLib
MemoryAllocationLib
DebugLib
+ VmgExitLib
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
index f6ce44488e6..2662551dbbb 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
@@ -18,8 +18,8 @@
**/
VOID
ArchUpdateIdtEntry (
- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
- IN UINTN InterruptHandler
+ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
)
{
IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
index 536b88d1e17..53fbee20151 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiCpuExceptionHandlerLib.inf
@@ -52,7 +52,11 @@
HobLib
MemoryAllocationLib
SynchronizationLib
+ VmgExitLib
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard # CONSUMES
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
index 65b068a2c28..a0a0860eb69 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/PeiDxeSmmCpuException.c
@@ -6,8 +6,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "CpuExceptionCommon.h"
#include <Library/DebugLib.h>
+#include <Library/VmgExitLib.h>
+#include "CpuExceptionCommon.h"
/**
Internal worker function for common exception handler.
@@ -27,6 +28,23 @@ CommonExceptionHandlerWorker (
RESERVED_VECTORS_DATA *ReservedVectors;
EFI_CPU_INTERRUPT_HANDLER *ExternalInterruptHandler;
+ if (ExceptionType == VC_EXCEPTION) {
+ EFI_STATUS Status;
+ //
+ // #VC needs to be handled immediately upon enabling exception handling
+ // and therefore can't use the RegisterCpuInterruptHandler() interface.
+ //
+ // Handle the #VC:
+ // On EFI_SUCCESS - Exception has been handled, return
+ // On other - ExceptionType contains (possibly new) exception
+ // value
+ //
+ Status = VmgExitHandleVc (&ExceptionType, SystemContext);
+ if (!EFI_ERROR (Status)) {
+ return;
+ }
+ }
+
ExceptionHandlerContext = (EXCEPTION_HANDLER_CONTEXT *) (UINTN) (SystemContext.SystemContextIa32);
ReservedVectors = ExceptionHandlerData->ReservedVectors;
ExternalInterruptHandler = ExceptionHandlerData->ExternalInterruptHandler;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
index 965666d6fdb..7cc87955846 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuException.c
@@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
+#include <Library/VmgExitLib.h>
#include "CpuExceptionCommon.h"
CONST UINTN mDoFarReturnFlag = 0;
@@ -24,6 +25,24 @@ CommonExceptionHandler (
IN EFI_SYSTEM_CONTEXT SystemContext
)
{
+ if (ExceptionType == VC_EXCEPTION) {
+ EFI_STATUS Status;
+ //
+ // #VC needs to be handled immediately upon enabling exception handling
+ // and therefore can't use the RegisterCpuInterruptHandler() interface
+ // (which isn't supported under Sec and Pei anyway).
+ //
+ // Handle the #VC:
+ // On EFI_SUCCESS - Exception has been handled, return
+ // On other - ExceptionType contains (possibly new) exception
+ // value
+ //
+ Status = VmgExitHandleVc (&ExceptionType, SystemContext);
+ if (!EFI_ERROR (Status)) {
+ return;
+ }
+ }
+
//
// Initialize the serial port before dumping.
//
@@ -87,7 +106,7 @@ InitializeCpuExceptionHandlers (
IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
if (IdtEntryCount > CPU_EXCEPTION_NUM) {
//
- // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most
+ // CPU exception library only setup CPU_EXCEPTION_NUM exception handler at most
//
IdtEntryCount = CPU_EXCEPTION_NUM;
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
index 9c011a2210a..4eaad47ba3b 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SecPeiCpuExceptionHandlerLib.inf
@@ -48,3 +48,8 @@
PrintLib
LocalApicLib
PeCoffGetEntryPointLib
+ VmgExitLib
+
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
index 55e4e89ba42..3cdab31845e 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
@@ -13,7 +13,7 @@
FILE_GUID = 8D2C439B-3981-42ff-9CE5-1B50ECA502D6
MODULE_TYPE = DXE_SMM_DRIVER
VERSION_STRING = 1.1
- LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_SMM_DRIVER
+ LIBRARY_CLASS = CpuExceptionHandlerLib|DXE_SMM_DRIVER MM_STANDALONE MM_CORE_STANDALONE
#
# The following information is for reference only and not required by the build tools.
@@ -51,4 +51,8 @@
LocalApicLib
PeCoffGetEntryPointLib
DebugLib
+ VmgExitLib
+
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
index 2bcbbe4c983..a0257aa8bdc 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
@@ -17,8 +17,8 @@
**/
VOID
ArchUpdateIdtEntry (
- IN IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
- IN UINTN InterruptHandler
+ OUT IA32_IDT_GATE_DESCRIPTOR *IdtEntry,
+ IN UINTN InterruptHandler
)
{
IdtEntry->Bits.OffsetLow = (UINT16)(UINTN)InterruptHandler;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
index 434b97c6ed1..1f112909d98 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ExceptionHandlerAsm.nasm
@@ -18,6 +18,8 @@
; CommonExceptionHandler()
;
+%define VC_EXCEPTION 29
+
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
extern ASM_PFX(CommonExceptionHandler)
@@ -224,6 +226,9 @@ HasErrorCode:
push rax
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ cmp qword [rbp + 8], VC_EXCEPTION
+ je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
+
mov rax, dr7
push rax
mov rax, dr6
@@ -236,7 +241,19 @@ HasErrorCode:
push rax
mov rax, dr0
push rax
+ jmp DrFinish
+
+VcDebugRegs:
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion
+ xor rax, rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+DrFinish:
;; FX_SAVE_STATE_X64 FxSaveState;
sub rsp, 512
mov rdi, rsp
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm
index 0c0f87d7b6b..a8edfc01059 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/Xcode5ExceptionHandlerAsm.nasm
@@ -13,14 +13,18 @@
; Notes:
;
;------------------------------------------------------------------------------
+%include "Nasm.inc"
;
; CommonExceptionHandler()
;
+%define VC_EXCEPTION 29
+
extern ASM_PFX(mErrorCodeFlag) ; Error code flags for exceptions
extern ASM_PFX(mDoFarReturnFlag) ; Do far return flag
extern ASM_PFX(CommonExceptionHandler)
+extern ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))
SECTION .data
@@ -225,6 +229,9 @@ HasErrorCode:
push rax
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
+ cmp qword [rbp + 8], VC_EXCEPTION
+ je VcDebugRegs ; For SEV-ES (#VC) Debug registers ignored
+
mov rax, dr7
push rax
mov rax, dr6
@@ -237,7 +244,19 @@ HasErrorCode:
push rax
mov rax, dr0
push rax
+ jmp DrFinish
+VcDebugRegs:
+;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7 are skipped for #VC to avoid exception recursion
+ xor rax, rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+ push rax
+
+DrFinish:
;; FX_SAVE_STATE_X64 FxSaveState;
sub rsp, 512
mov rdi, rsp
@@ -354,8 +373,48 @@ DoReturn:
push qword [rax + 0x18] ; save EFLAGS in new location
mov rax, [rax] ; restore rax
popfq ; restore EFLAGS
- DB 0x48 ; prefix to composite "retq" with next "retf"
- retf ; far return
+
+ ; The follow algorithm is used for clear shadow stack token busy bit.
+ ; The comment is based on the sample shadow stack.
+ ; The sample shadow stack layout :
+ ; Address | Context
+ ; +-------------------------+
+ ; 0xFD0 | FREE | it is 0xFD8|0x02|(LMA & CS.L), after SAVEPREVSSP.
+ ; +-------------------------+
+ ; 0xFD8 | Prev SSP |
+ ; +-------------------------+
+ ; 0xFE0 | RIP |
+ ; +-------------------------+
+ ; 0xFE8 | CS |
+ ; +-------------------------+
+ ; 0xFF0 | 0xFF0 | BUSY | BUSY flag cleared after CLRSSBSY
+ ; +-------------------------+
+ ; 0xFF8 | 0xFD8|0x02|(LMA & CS.L) |
+ ; +-------------------------+
+ ; Instructions for Intel Control Flow Enforcement Technology (CET) are supported since NASM version 2.15.01.
+ push rax ; SSP should be 0xFD8 at this point
+ cmp byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmStackGuard))], 0
+ jz CetDone
+ mov rax, cr4
+ and rax, 0x800000 ; check if CET is enabled
+ jz CetDone
+ mov rax, 0x04 ; advance past cs:lip:prevssp;supervisor shadow stack token
+ INCSSP_RAX ; After this SSP should be 0xFF8
+ SAVEPREVSSP ; now the shadow stack restore token will be created at 0xFD0
+ READSSP_RAX ; Read new SSP, SSP should be 0x1000
+ push rax
+ sub rax, 0x10
+ CLRSSBSY_RAX ; Clear token at 0xFF0, SSP should be 0 after this
+ sub rax, 0x20
+ RSTORSSP_RAX ; Restore to token at 0xFD0, new SSP will be 0xFD0
+ pop rax
+ mov rax, 0x01 ; Pop off the new save token created
+ INCSSP_RAX ; SSP should be 0xFD8 now
+CetDone:
+ pop rax ; restore rax
+
+ DB 0x48 ; prefix to composite "retq" with next "retf"
+ retf ; far return
DoIret:
iretq
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
index a9352e4c8be..76616cc4534 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuExceptionHandlerLib/Xcode5SecPeiCpuExceptionHandlerLib.inf
@@ -53,3 +53,8 @@
PrintLib
LocalApicLib
PeCoffGetEntryPointLib
+ VmgExitLib
+
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackGuard ## CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
index d631bc3dafa..658e28e8581 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
@@ -4,7 +4,7 @@
# Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
# counter features are provided by the processors time stamp counter.
#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -15,7 +15,7 @@
FILE_GUID = F10B5B91-D15A-496C-B044-B5235721AA08
MODULE_TYPE = BASE
VERSION_STRING = 1.0
- LIBRARY_CLASS = TimerLib|SEC PEI_CORE PEIM
+ LIBRARY_CLASS = TimerLib
MODULE_UNI_FILE = BaseCpuTimerLib.uni
[Sources]
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
deleted file mode 100644
index 525eae94b8d..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.c
+++ /dev/null
@@ -1,85 +0,0 @@
-/** @file
- CPUID Leaf 0x15 for Core Crystal Clock frequency instance of Timer Library.
-
- Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-#include <Library/TimerLib.h>
-#include <Library/BaseLib.h>
-#include <Library/HobLib.h>
-
-extern GUID mCpuCrystalFrequencyHobGuid;
-
-/**
- CPUID Leaf 0x15 for Core Crystal Clock Frequency.
-
- The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
- In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
- @return The number of TSC counts per second.
-
-**/
-UINT64
-CpuidCoreClockCalculateTscFrequency (
- VOID
- );
-
-//
-// Cached CPU Crystal counter frequency
-//
-UINT64 mCpuCrystalCounterFrequency = 0;
-
-
-/**
- Internal function to retrieves the 64-bit frequency in Hz.
-
- Internal function to retrieves the 64-bit frequency in Hz.
-
- @return The frequency in Hz.
-
-**/
-UINT64
-InternalGetPerformanceCounterFrequency (
- VOID
- )
-{
- return mCpuCrystalCounterFrequency;
-}
-
-/**
- The constructor function is to initialize CpuCrystalCounterFrequency.
-
- @param ImageHandle The firmware allocated handle for the EFI image.
- @param SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The constructor always returns RETURN_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-DxeCpuTimerLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- EFI_HOB_GUID_TYPE *GuidHob;
-
- //
- // Initialize CpuCrystalCounterFrequency
- //
- GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
- if (GuidHob != NULL) {
- mCpuCrystalCounterFrequency = *(UINT64*)GET_GUID_HOB_DATA (GuidHob);
- } else {
- mCpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
- }
-
- if (mCpuCrystalCounterFrequency == 0) {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
deleted file mode 100644
index 1f53758487f..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
+++ /dev/null
@@ -1,37 +0,0 @@
-## @file
-# DXE CPU Timer Library
-#
-# Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
-# counter features are provided by the processors time stamp counter.
-#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = DxeCpuTimerLib
- FILE_GUID = F22CC0DA-E7DB-4E4D-ABE2-A608188233A2
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- LIBRARY_CLASS = TimerLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER SMM_CORE
- CONSTRUCTOR = DxeCpuTimerLibConstructor
- MODULE_UNI_FILE = DxeCpuTimerLib.uni
-
-[Sources]
- CpuTimerLib.c
- DxeCpuTimerLib.c
-
-[Packages]
- MdePkg/MdePkg.dec
- UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
- BaseLib
- PcdLib
- DebugLib
- HobLib
-
-[Pcd]
- gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
deleted file mode 100644
index f55b92abace..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.uni
+++ /dev/null
@@ -1,17 +0,0 @@
-// /** @file
-// DXE CPU Timer Library
-//
-// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
-// counter features are provided by the processors time stamp counter.
-//
-// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "CPU Timer Library"
-
-#string STR_MODULE_DESCRIPTION #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
deleted file mode 100644
index ff2c796234a..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/** @file
- CPUID Leaf 0x15 for Core Crystal Clock frequency instance as PEI Timer Library.
-
- Copyright (c) 2019 Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiPei.h>
-#include <Library/TimerLib.h>
-#include <Library/BaseLib.h>
-#include <Library/HobLib.h>
-#include <Library/DebugLib.h>
-
-extern GUID mCpuCrystalFrequencyHobGuid;
-
-/**
- CPUID Leaf 0x15 for Core Crystal Clock Frequency.
-
- The TSC counting frequency is determined by using CPUID leaf 0x15. Frequency in MHz = Core XTAL frequency * EBX/EAX.
- In newer flavors of the CPU, core xtal frequency is returned in ECX or 0 if not supported.
- @return The number of TSC counts per second.
-
-**/
-UINT64
-CpuidCoreClockCalculateTscFrequency (
- VOID
- );
-
-/**
- Internal function to retrieves the 64-bit frequency in Hz.
-
- Internal function to retrieves the 64-bit frequency in Hz.
-
- @return The frequency in Hz.
-
-**/
-UINT64
-InternalGetPerformanceCounterFrequency (
- VOID
- )
-{
- UINT64 *CpuCrystalCounterFrequency;
- EFI_HOB_GUID_TYPE *GuidHob;
-
- CpuCrystalCounterFrequency = NULL;
- GuidHob = GetFirstGuidHob (&mCpuCrystalFrequencyHobGuid);
- if (GuidHob == NULL) {
- CpuCrystalCounterFrequency = (UINT64*)BuildGuidHob(&mCpuCrystalFrequencyHobGuid, sizeof (*CpuCrystalCounterFrequency));
- ASSERT (CpuCrystalCounterFrequency != NULL);
- *CpuCrystalCounterFrequency = CpuidCoreClockCalculateTscFrequency ();
- } else {
- CpuCrystalCounterFrequency = (UINT64*)GET_GUID_HOB_DATA (GuidHob);
- }
-
- return *CpuCrystalCounterFrequency;
-}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
deleted file mode 100644
index ccc4a675a5a..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
+++ /dev/null
@@ -1,36 +0,0 @@
-## @file
-# PEI CPU Timer Library
-#
-# Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
-# counter features are provided by the processors time stamp counter.
-#
-# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = PeiCpuTimerLib
- FILE_GUID = 2B13DE00-1A5F-4DD7-A298-01B08AF1015A
- MODULE_TYPE = BASE
- VERSION_STRING = 1.0
- LIBRARY_CLASS = TimerLib|PEI_CORE PEIM
- MODULE_UNI_FILE = PeiCpuTimerLib.uni
-
-[Sources]
- CpuTimerLib.c
- PeiCpuTimerLib.c
-
-[Packages]
- MdePkg/MdePkg.dec
- UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
- BaseLib
- PcdLib
- DebugLib
- HobLib
-
-[Pcd]
- gUefiCpuPkgTokenSpaceGuid.PcdCpuCoreCrystalClockFrequency ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
deleted file mode 100644
index 49beb44908d..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.uni
+++ /dev/null
@@ -1,17 +0,0 @@
-// /** @file
-// PEI CPU Timer Library
-//
-// Provides basic timer support using CPUID Leaf 0x15 XTAL frequency. The performance
-// counter features are provided by the processors time stamp counter.
-//
-// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
-//
-// SPDX-License-Identifier: BSD-2-Clause-Patent
-//
-// **/
-
-
-#string STR_MODULE_ABSTRACT #language en-US "CPU Timer Library"
-
-#string STR_MODULE_DESCRIPTION #language en-US "Provides basic timer support using CPUID Leaf 0x15 XTAL frequency."
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.c
new file mode 100644
index 00000000000..e2f1cfc219b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.c
@@ -0,0 +1,322 @@
+/** @file
+ Implementation of MicrocodeLib.
+
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi/UefiBaseType.h>
+#include <Register/Intel/Cpuid.h>
+#include <Register/Intel/ArchitecturalMsr.h>
+#include <Register/Intel/Microcode.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Ppi/ShadowMicrocode.h>
+
+/**
+ Get microcode update signature of currently loaded microcode update.
+
+ @return Microcode signature.
+**/
+UINT32
+EFIAPI
+GetProcessorMicrocodeSignature (
+ VOID
+ )
+{
+ MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr;
+
+ AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
+ AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
+ BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
+ return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
+}
+
+/**
+ Get the processor signature and platform ID for current processor.
+
+ @param MicrocodeCpuId Return the processor signature and platform ID.
+**/
+VOID
+EFIAPI
+GetProcessorMicrocodeCpuId (
+ EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId
+ )
+{
+ MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;
+
+ ASSERT (MicrocodeCpuId != NULL);
+
+ PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
+ MicrocodeCpuId->PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;
+ AsmCpuid (CPUID_VERSION_INFO, &MicrocodeCpuId->ProcessorSignature, NULL, NULL, NULL);
+}
+
+/**
+ Return the total size of the microcode entry.
+
+ Logic follows pseudo code in SDM as below:
+
+ N = 512
+ If (Update.DataSize != 00000000H)
+ N = Update.TotalSize / 4
+
+ If Microcode is NULL, then ASSERT.
+
+ @param Microcode Pointer to the microcode entry.
+
+ @return The microcode total size.
+**/
+UINT32
+EFIAPI
+GetMicrocodeLength (
+ IN CPU_MICROCODE_HEADER *Microcode
+ )
+{
+ UINT32 TotalSize;
+
+ ASSERT (Microcode != NULL);
+
+ TotalSize = 2048;
+ if (Microcode->DataSize != 0) {
+ TotalSize = Microcode->TotalSize;
+ }
+ return TotalSize;
+}
+
+/**
+ Load the microcode to the processor.
+
+ If Microcode is NULL, then ASSERT.
+
+ @param Microcode Pointer to the microcode entry.
+**/
+VOID
+EFIAPI
+LoadMicrocode (
+ IN CPU_MICROCODE_HEADER *Microcode
+ )
+{
+ ASSERT (Microcode != NULL);
+
+ AsmWriteMsr64 (MSR_IA32_BIOS_UPDT_TRIG, (UINT64) (UINTN) (Microcode + 1));
+}
+
+/**
+ Determine if a microcode patch matchs the specific processor signature and flag.
+
+ @param[in] ProcessorSignature The processor signature field value in a
+ microcode patch.
+ @param[in] ProcessorFlags The processor flags field value in a
+ microcode patch.
+ @param[in] MicrocodeCpuId A pointer to an array of EDKII_PEI_MICROCODE_CPU_ID
+ structures.
+ @param[in] MicrocodeCpuIdCount Number of elements in MicrocodeCpuId array.
+
+ @retval TRUE The specified microcode patch matches to one of the MicrocodeCpuId.
+ @retval FALSE The specified microcode patch doesn't match to any of the MicrocodeCpuId.
+**/
+BOOLEAN
+IsProcessorMatchedMicrocode (
+ IN UINT32 ProcessorSignature,
+ IN UINT32 ProcessorFlags,
+ IN EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuId,
+ IN UINTN MicrocodeCpuIdCount
+ )
+{
+ UINTN Index;
+
+ if (MicrocodeCpuIdCount == 0) {
+ return TRUE;
+ }
+
+ for (Index = 0; Index < MicrocodeCpuIdCount; Index++) {
+ if ((ProcessorSignature == MicrocodeCpuId[Index].ProcessorSignature) &&
+ (ProcessorFlags & (1 << MicrocodeCpuId[Index].PlatformId)) != 0) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ Detect whether specified processor can find matching microcode patch and load it.
+
+ Microcode format is as below:
+ +----------------------------------------+-------------------------------------------------+
+ | CPU_MICROCODE_HEADER | |
+ +----------------------------------------+ V
+ | Update Data | CPU_MICROCODE_HEADER.Checksum
+ +----------------------------------------+-------+ ^
+ | CPU_MICROCODE_EXTENDED_TABLE_HEADER | | |
+ +----------------------------------------+ V |
+ | CPU_MICROCODE_EXTENDED_TABLE[0] | CPU_MICROCODE_EXTENDED_TABLE_HEADER.Checksum |
+ | CPU_MICROCODE_EXTENDED_TABLE[1] | ^ |
+ | ... | | |
+ +----------------------------------------+-------+-----------------------------------------+
+
+ There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.
+ The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignatureCount
+ of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.
+
+ If Microcode is NULL, then ASSERT.
+
+ @param Microcode Pointer to a microcode entry.
+ @param MicrocodeLength The total length of the microcode entry.
+ @param MinimumRevision The microcode whose revision <= MinimumRevision is treated as invalid.
+ Caller can supply value get from GetProcessorMicrocodeSignature() to check
+ whether the microcode is newer than loaded one.
+ Caller can supply 0 to treat any revision (except 0) microcode as valid.
+ @param MicrocodeCpuIds Pointer to an array of processor signature and platform ID that represents
+ a set of processors.
+ Caller can supply zero-element array to skip the processor signature and
+ platform ID check.
+ @param MicrocodeCpuIdCount The number of elements in MicrocodeCpuIds.
+ @param VerifyChecksum FALSE to skip all the checksum verifications.
+
+ @retval TRUE The microcode is valid.
+ @retval FALSE The microcode is invalid.
+**/
+BOOLEAN
+EFIAPI
+IsValidMicrocode (
+ IN CPU_MICROCODE_HEADER *Microcode,
+ IN UINTN MicrocodeLength,
+ IN UINT32 MinimumRevision,
+ IN EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuIds,
+ IN UINTN MicrocodeCpuIdCount,
+ IN BOOLEAN VerifyChecksum
+ )
+{
+ UINTN Index;
+ UINT32 DataSize;
+ UINT32 TotalSize;
+ CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
+ CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
+ UINT32 ExtendedTableLength;
+ UINT32 Sum32;
+ BOOLEAN Match;
+
+ ASSERT (Microcode != NULL);
+
+ //
+ // It's invalid when:
+ // the input microcode buffer is so small that even cannot contain the header.
+ // the input microcode buffer is so large that exceeds MAX_ADDRESS.
+ //
+ if ((MicrocodeLength < sizeof (CPU_MICROCODE_HEADER)) || (MicrocodeLength > (MAX_ADDRESS - (UINTN) Microcode))) {
+ return FALSE;
+ }
+
+ //
+ // Per SDM, HeaderVersion and LoaderRevision should both be 1.
+ //
+ if ((Microcode->HeaderVersion != 1) || (Microcode->LoaderRevision != 1)) {
+ return FALSE;
+ }
+
+ //
+ // The microcode revision should be larger than the minimum revision.
+ //
+ if (Microcode->UpdateRevision <= MinimumRevision) {
+ return FALSE;
+ }
+
+ DataSize = Microcode->DataSize;
+ if (DataSize == 0) {
+ DataSize = 2000;
+ }
+
+ //
+ // Per SDM, DataSize should be multiple of DWORDs.
+ //
+ if ((DataSize % 4) != 0) {
+ return FALSE;
+ }
+
+ TotalSize = GetMicrocodeLength (Microcode);
+
+ //
+ // Check whether the whole microcode is within the buffer.
+ // TotalSize should be multiple of 1024.
+ //
+ if (((TotalSize % SIZE_1KB) != 0) || (TotalSize > MicrocodeLength)) {
+ return FALSE;
+ }
+
+ //
+ // The summation of all DWORDs in microcode should be zero.
+ //
+ if (VerifyChecksum && (CalculateSum32 ((UINT32 *) Microcode, TotalSize) != 0)) {
+ return FALSE;
+ }
+
+ Sum32 = Microcode->ProcessorSignature.Uint32 + Microcode->ProcessorFlags + Microcode->Checksum;
+
+ //
+ // Check the processor signature and platform ID in the primary header.
+ //
+ Match = IsProcessorMatchedMicrocode (
+ Microcode->ProcessorSignature.Uint32,
+ Microcode->ProcessorFlags,
+ MicrocodeCpuIds,
+ MicrocodeCpuIdCount
+ );
+ if (Match) {
+ return TRUE;
+ }
+
+ ExtendedTableLength = TotalSize - (DataSize + sizeof (CPU_MICROCODE_HEADER));
+ if ((ExtendedTableLength < sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER)) || ((ExtendedTableLength % 4) != 0)) {
+ return FALSE;
+ }
+ //
+ // Extended Table exist, check if the CPU in support list
+ //
+ ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINTN) (Microcode + 1) + DataSize);
+ if (ExtendedTableHeader->ExtendedSignatureCount > MAX_UINT32 / sizeof (CPU_MICROCODE_EXTENDED_TABLE)) {
+ return FALSE;
+ }
+ if (ExtendedTableHeader->ExtendedSignatureCount * sizeof (CPU_MICROCODE_EXTENDED_TABLE)
+ > ExtendedTableLength - sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER)) {
+ return FALSE;
+ }
+ //
+ // Check the extended table checksum
+ //
+ if (VerifyChecksum && (CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength) != 0)) {
+ return FALSE;
+ }
+
+ ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
+ for (Index = 0; Index < ExtendedTableHeader->ExtendedSignatureCount; Index ++) {
+ if (VerifyChecksum &&
+ (ExtendedTable[Index].ProcessorSignature.Uint32 + ExtendedTable[Index].ProcessorFlag
+ + ExtendedTable[Index].Checksum != Sum32)) {
+ //
+ // The extended table entry is valid when the summation of Processor Signature, Processor Flags
+ // and Checksum equal to the coresponding summation from primary header. Because:
+ // CalculateSum32 (Header + Update Binary) == 0
+ // CalculateSum32 (Header + Update Binary)
+ // - (Header.ProcessorSignature + Header.ProcessorFlag + Header.Checksum)
+ // + (Extended.ProcessorSignature + Extended.ProcessorFlag + Extended.Checksum) == 0
+ // So,
+ // (Header.ProcessorSignature + Header.ProcessorFlag + Header.Checksum)
+ // == (Extended.ProcessorSignature + Extended.ProcessorFlag + Extended.Checksum)
+ //
+ continue;
+ }
+ Match = IsProcessorMatchedMicrocode (
+ ExtendedTable[Index].ProcessorSignature.Uint32,
+ ExtendedTable[Index].ProcessorFlag,
+ MicrocodeCpuIds,
+ MicrocodeCpuIdCount
+ );
+ if (Match) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
new file mode 100644
index 00000000000..f076eea7c8e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
@@ -0,0 +1,32 @@
+## @file
+# Library for microcode verification and load.
+#
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = MicrocodeLib
+ FILE_GUID = EB8C72BC-8A48-4F80-996B-E52F68416D57
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = MicrocodeLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources.common]
+ MicrocodeLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
index 4c8de42b981..e260e17d145 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
@@ -1,7 +1,7 @@
## @file
# MP Initialize Library instance for DXE driver.
#
-# Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -22,14 +22,13 @@
#
[Sources.IA32]
- Ia32/MpEqu.inc
Ia32/MpFuncs.nasm
[Sources.X64]
- X64/MpEqu.inc
X64/MpFuncs.nasm
[Sources.common]
+ MpEqu.inc
DxeMpLib.c
MpLib.c
MpLib.h
@@ -52,6 +51,8 @@
DebugAgentLib
SynchronizationLib
PcdLib
+ VmgExitLib
+ MicrocodeLib
[Protocols]
gEfiTimerArchProtocolGuid ## SOMETIMES_CONSUMES
@@ -71,4 +72,7 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApStatusCheckIntervalInMicroSeconds ## CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled ## CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
index fd465a4efef..16c8e9ca498 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
@@ -12,6 +12,9 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugAgentLib.h>
#include <Library/DxeServicesTableLib.h>
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Fam17Msr.h>
+#include <Register/Amd/Ghcb.h>
#include <Protocol/Timer.h>
@@ -83,6 +86,13 @@ GetWakeupBuffer (
{
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS StartAddress;
+ EFI_MEMORY_TYPE MemoryType;
+
+ if (PcdGetBool (PcdSevEsIsEnabled)) {
+ MemoryType = EfiReservedMemoryType;
+ } else {
+ MemoryType = EfiBootServicesData;
+ }
//
// Try to allocate buffer below 1M for waking vector.
@@ -95,7 +105,7 @@ GetWakeupBuffer (
StartAddress = 0x88000;
Status = gBS->AllocatePages (
AllocateMaxAddress,
- EfiBootServicesData,
+ MemoryType,
EFI_SIZE_TO_PAGES (WakeupBufferSize),
&StartAddress
);
@@ -145,6 +155,52 @@ GetModeTransitionBuffer (
}
/**
+ Return the address of the SEV-ES AP jump table.
+
+ This buffer is required in order for an SEV-ES guest to transition from
+ UEFI into an OS.
+
+ @return Return SEV-ES AP jump table buffer
+**/
+UINTN
+GetSevEsAPMemory (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS StartAddress;
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ GHCB *Ghcb;
+ BOOLEAN InterruptState;
+
+ //
+ // Allocate 1 page for AP jump table page
+ //
+ StartAddress = BASE_4GB - 1;
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ 1,
+ &StartAddress
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "Dxe: SevEsAPMemory = %lx\n", (UINTN) StartAddress));
+
+ //
+ // Save the SevEsAPMemory as the AP jump table.
+ //
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+ Ghcb = Msr.Ghcb;
+
+ VmgInit (Ghcb, &InterruptState);
+ VmgExit (Ghcb, SVM_EXIT_AP_JUMP_TABLE, 0, (UINT64) (UINTN) StartAddress);
+ VmgDone (Ghcb, InterruptState);
+
+ return (UINTN) StartAddress;
+}
+
+/**
Checks APs status and updates APs status if needed.
**/
@@ -219,6 +275,38 @@ CheckApsStatus (
}
/**
+ Get Protected mode code segment with 16-bit default addressing
+ from current GDT table.
+
+ @return Protected mode 16-bit code segment value.
+**/
+UINT16
+GetProtectedMode16CS (
+ VOID
+ )
+{
+ IA32_DESCRIPTOR GdtrDesc;
+ IA32_SEGMENT_DESCRIPTOR *GdtEntry;
+ UINTN GdtEntryCount;
+ UINT16 Index;
+
+ Index = (UINT16) -1;
+ AsmReadGdtr (&GdtrDesc);
+ GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
+ GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
+ for (Index = 0; Index < GdtEntryCount; Index++) {
+ if (GdtEntry->Bits.L == 0) {
+ if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.DB == 0) {
+ break;
+ }
+ }
+ GdtEntry++;
+ }
+ ASSERT (Index != GdtEntryCount);
+ return Index * 8;
+}
+
+/**
Get Protected mode code segment from current GDT table.
@return Protected mode code segment value.
@@ -238,7 +326,7 @@ GetProtectedModeCS (
GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
for (Index = 0; Index < GdtEntryCount; Index++) {
if (GdtEntry->Bits.L == 0) {
- if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {
+ if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.DB == 1) {
break;
}
}
@@ -263,17 +351,26 @@ RelocateApLoop (
BOOLEAN MwaitSupport;
ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc;
UINTN ProcessorNumber;
+ UINTN StackStart;
MpInitLibWhoAmI (&ProcessorNumber);
CpuMpData = GetCpuMpData ();
MwaitSupport = IsMwaitSupport ();
+ if (CpuMpData->SevEsIsEnabled) {
+ StackStart = CpuMpData->SevEsAPResetStackStart;
+ } else {
+ StackStart = mReservedTopOfApStack;
+ }
AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc;
AsmRelocateApLoopFunc (
MwaitSupport,
CpuMpData->ApTargetCState,
CpuMpData->PmCodeSegment,
- mReservedTopOfApStack - ProcessorNumber * AP_SAFE_STACK_SIZE,
- (UINTN) &mNumberToFinish
+ StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
+ (UINTN) &mNumberToFinish,
+ CpuMpData->Pm16CodeSegment,
+ CpuMpData->SevEsAPBuffer,
+ CpuMpData->WakeupBuffer
);
//
// It should never reach here
@@ -300,12 +397,28 @@ MpInitChangeApLoopCallback (
CpuMpData = GetCpuMpData ();
CpuMpData->PmCodeSegment = GetProtectedModeCS ();
+ CpuMpData->Pm16CodeSegment = GetProtectedMode16CS ();
CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode);
mNumberToFinish = CpuMpData->CpuCount - 1;
WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE);
while (mNumberToFinish > 0) {
CpuPause ();
}
+
+ if (CpuMpData->SevEsIsEnabled && (CpuMpData->WakeupBuffer != (UINTN) -1)) {
+ //
+ // There are APs present. Re-use reserved memory area below 1MB from
+ // WakeupBuffer as the area to be used for transitioning to 16-bit mode
+ // in support of booting of the AP by an OS.
+ //
+ CopyMem (
+ (VOID *) CpuMpData->WakeupBuffer,
+ (VOID *) (CpuMpData->AddressMap.RendezvousFunnelAddress +
+ CpuMpData->AddressMap.SwitchToRealPM16ModeOffset),
+ CpuMpData->AddressMap.SwitchToRealPM16ModeSize
+ );
+ }
+
DEBUG ((DEBUG_INFO, "%a() done!\n", __FUNCTION__));
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc
deleted file mode 100644
index 46b5b35280a..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpEqu.inc
+++ /dev/null
@@ -1,43 +0,0 @@
-;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Module Name:
-;
-; MpEqu.inc
-;
-; Abstract:
-;
-; This is the equates file for Multiple Processor support
-;
-;-------------------------------------------------------------------------------
-
-VacantFlag equ 00h
-NotVacantFlag equ 0ffh
-
-CPU_SWITCH_STATE_IDLE equ 0
-CPU_SWITCH_STATE_STORED equ 1
-CPU_SWITCH_STATE_LOADED equ 2
-
-LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
-StackStartAddressLocation equ LockLocation + 04h
-StackSizeLocation equ LockLocation + 08h
-ApProcedureLocation equ LockLocation + 0Ch
-GdtrLocation equ LockLocation + 10h
-IdtrLocation equ LockLocation + 16h
-BufferStartLocation equ LockLocation + 1Ch
-ModeOffsetLocation equ LockLocation + 20h
-ApIndexLocation equ LockLocation + 24h
-CodeSegmentLocation equ LockLocation + 28h
-DataSegmentLocation equ LockLocation + 2Ch
-EnableExecuteDisableLocation equ LockLocation + 30h
-Cr3Location equ LockLocation + 34h
-InitFlagLocation equ LockLocation + 38h
-CpuInfoLocation equ LockLocation + 3Ch
-NumApsExecutingLocation equ LockLocation + 40h
-InitializeFloatingPointUnitsAddress equ LockLocation + 48h
-ModeTransitionMemoryLocation equ LockLocation + 4Ch
-ModeTransitionSegmentLocation equ LockLocation + 50h
-ModeHighMemoryLocation equ LockLocation + 52h
-ModeHighSegmentLocation equ LockLocation + 56h
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
index 951a2b7abc6..352c7b3d30f 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
@@ -1,5 +1,5 @@
;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -39,21 +39,21 @@ BITS 16
mov fs, ax
mov gs, ax
- mov si, BufferStartLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (BufferStart)
mov ebx, [si]
- mov si, DataSegmentLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (DataSegment)
mov edx, [si]
;
; Get start address of 32-bit code in low memory (<1MB)
;
- mov edi, ModeTransitionMemoryLocation
+ mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeTransitionMemory)
- mov si, GdtrLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (GdtrProfile)
o32 lgdt [cs:si]
- mov si, IdtrLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (IdtrProfile)
o32 lidt [cs:si]
;
@@ -82,7 +82,7 @@ Flat32Start: ; protected mode entry point
mov esi, ebx
mov edi, esi
- add edi, EnableExecuteDisableLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (EnableExecuteDisable)
cmp byte [edi], 0
jz SkipEnableExecuteDisable
@@ -96,7 +96,7 @@ Flat32Start: ; protected mode entry point
wrmsr
mov edi, esi
- add edi, Cr3Location
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (Cr3)
mov eax, dword [edi]
mov cr3, eax
@@ -110,43 +110,31 @@ Flat32Start: ; protected mode entry point
SkipEnableExecuteDisable:
mov edi, esi
- add edi, InitFlagLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)
cmp dword [edi], 1 ; 1 == ApInitConfig
jnz GetApicId
; Increment the number of APs executing here as early as possible
; This is decremented in C code when AP is finished executing
mov edi, esi
- add edi, NumApsExecutingLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (NumApsExecuting)
lock inc dword [edi]
; AP init
mov edi, esi
- add edi, LockLocation
- mov eax, NotVacantFlag
-
-TestLock:
- xchg [edi], eax
- cmp eax, NotVacantFlag
- jz TestLock
-
- mov ecx, esi
- add ecx, ApIndexLocation
- inc dword [ecx]
- mov ebx, [ecx]
-
-Releaselock:
- mov eax, VacantFlag
- xchg [edi], eax
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (ApIndex)
+ mov ebx, 1
+ lock xadd dword [edi], ebx ; EBX = ApIndex++
+ inc ebx ; EBX is CpuNumber
mov edi, esi
- add edi, StackSizeLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)
mov eax, [edi]
mov ecx, ebx
inc ecx
mul ecx ; EAX = StackSize * (CpuNumber + 1)
mov edi, esi
- add edi, StackStartAddressLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackStart)
add eax, [edi]
mov esp, eax
jmp CProcedureInvoke
@@ -179,18 +167,18 @@ GetProcessorNumber:
; Note that BSP may become an AP due to SwitchBsp()
;
xor ebx, ebx
- lea eax, [esi + CpuInfoLocation]
+ lea eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]
mov edi, [eax]
GetNextProcNumber:
- cmp [edi], edx ; APIC ID match?
+ cmp dword [edi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?
jz ProgramStack
- add edi, 20
+ add edi, CPU_INFO_IN_HOB_size
inc ebx
jmp GetNextProcNumber
ProgramStack:
- mov esp, [edi + 12]
+ mov esp, dword [edi + CPU_INFO_IN_HOB.ApTopOfStack]
CProcedureInvoke:
push ebp ; push BIST data at top of AP stack
@@ -203,11 +191,11 @@ CProcedureInvoke:
push ebx ; Push ApIndex
mov eax, esi
- add eax, LockLocation
+ add eax, MP_CPU_EXCHANGE_INFO_OFFSET
push eax ; push address of exchange info data buffer
mov edi, esi
- add edi, ApProcedureLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (CFunction)
mov eax, [edi]
call eax ; Invoke C function
@@ -216,7 +204,20 @@ CProcedureInvoke:
RendezvousFunnelProcEnd:
;-------------------------------------------------------------------------------------
-; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
+;SwitchToRealProc procedure follows.
+;NOT USED IN 32 BIT MODE.
+;-------------------------------------------------------------------------------------
+global ASM_PFX(SwitchToRealProc)
+ASM_PFX(SwitchToRealProc):
+SwitchToRealProcStart:
+ jmp $ ; Never reach here
+SwitchToRealProcEnd:
+
+;-------------------------------------------------------------------------------------
+; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
+;
+; The last three parameters (Pm16CodeSegment, SevEsAPJumpTable and WakeupBuffer) are
+; specific to SEV-ES support and are not applicable on IA32.
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmRelocateApLoop)
ASM_PFX(AsmRelocateApLoop):
@@ -257,12 +258,17 @@ ASM_PFX(AsmGetAddressMap):
mov ebp,esp
mov ebx, [ebp + 24h]
- mov dword [ebx], RendezvousFunnelProcStart
- mov dword [ebx + 4h], Flat32Start - RendezvousFunnelProcStart
- mov dword [ebx + 8h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
- mov dword [ebx + 0Ch], AsmRelocateApLoopStart
- mov dword [ebx + 10h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
- mov dword [ebx + 14h], Flat32Start - RendezvousFunnelProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], RendezvousFunnelProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], Flat32Start - RendezvousFunnelProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], AsmRelocateApLoopStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealSize], SwitchToRealProcEnd - SwitchToRealProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealOffset], SwitchToRealProcStart - RendezvousFunnelProcStart
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], 0
+ mov dword [ebx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeSize], 0
popad
ret
@@ -292,18 +298,18 @@ ASM_PFX(AsmExchangeRole):
mov eax, cr0
push eax
- sgdt [esi + 8]
- sidt [esi + 14]
+ sgdt [esi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
+ sidt [esi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; Store the its StackPointer
- mov [esi + 4],esp
+ mov [esi + CPU_EXCHANGE_ROLE_INFO.StackPointer],esp
; update its switch state to STORED
- mov byte [esi], CPU_SWITCH_STATE_STORED
+ mov byte [esi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
WaitForOtherStored:
; wait until the other CPU finish storing its state
- cmp byte [edi], CPU_SWITCH_STATE_STORED
+ cmp byte [edi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
jz OtherStored
pause
jmp WaitForOtherStored
@@ -311,21 +317,21 @@ WaitForOtherStored:
OtherStored:
; Since another CPU already stored its state, load them
; load GDTR value
- lgdt [edi + 8]
+ lgdt [edi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
; load IDTR value
- lidt [edi + 14]
+ lidt [edi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; load its future StackPointer
- mov esp, [edi + 4]
+ mov esp, [edi + CPU_EXCHANGE_ROLE_INFO.StackPointer]
; update the other CPU's switch state to LOADED
- mov byte [edi], CPU_SWITCH_STATE_LOADED
+ mov byte [edi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded:
; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt
- cmp byte [esi], CPU_SWITCH_STATE_LOADED
+ cmp byte [esi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
jz OtherLoaded
pause
jmp WaitForOtherLoaded
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Microcode.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Microcode.c
index f8ef198c183..a10430506ab 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Microcode.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/Microcode.c
@@ -1,7 +1,7 @@
/** @file
Implementation of loading microcode on processors.
- Copyright (c) 2015 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -9,62 +9,8 @@
#include "MpLib.h"
/**
- Get microcode update signature of currently loaded microcode update.
-
- @return Microcode signature.
-**/
-UINT32
-GetCurrentMicrocodeSignature (
- VOID
- )
-{
- MSR_IA32_BIOS_SIGN_ID_REGISTER BiosSignIdMsr;
-
- AsmWriteMsr64 (MSR_IA32_BIOS_SIGN_ID, 0);
- AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, NULL);
- BiosSignIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_BIOS_SIGN_ID);
- return BiosSignIdMsr.Bits.MicrocodeUpdateSignature;
-}
-
-/**
Detect whether specified processor can find matching microcode patch and load it.
- Microcode Payload as the following format:
- +----------------------------------------+------------------+
- | CPU_MICROCODE_HEADER | |
- +----------------------------------------+ CheckSum Part1 |
- | Microcode Binary | |
- +----------------------------------------+------------------+
- | CPU_MICROCODE_EXTENDED_TABLE_HEADER | |
- +----------------------------------------+ CheckSum Part2 |
- | CPU_MICROCODE_EXTENDED_TABLE | |
- | ... | |
- +----------------------------------------+------------------+
-
- There may by multiple CPU_MICROCODE_EXTENDED_TABLE in this format.
- The count of CPU_MICROCODE_EXTENDED_TABLE is indicated by ExtendedSignatureCount
- of CPU_MICROCODE_EXTENDED_TABLE_HEADER structure.
-
- When we are trying to verify the CheckSum32 with extended table.
- We should use the fields of exnteded table to replace the corresponding
- fields in CPU_MICROCODE_HEADER structure, and recalculate the
- CheckSum32 with CPU_MICROCODE_HEADER + Microcode Binary. We named
- it as CheckSum Part3.
-
- The CheckSum Part2 is used to verify the CPU_MICROCODE_EXTENDED_TABLE_HEADER
- and CPU_MICROCODE_EXTENDED_TABLE parts. We should make sure CheckSum Part2
- is correct before we are going to verify each CPU_MICROCODE_EXTENDED_TABLE.
-
- Only ProcessorSignature, ProcessorFlag and CheckSum are different between
- CheckSum Part1 and CheckSum Part3. To avoid multiple computing CheckSum Part3.
- Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
- When we are going to calculate CheckSum32, just should use the corresponding part
- of the ProcessorSignature, ProcessorFlag and CheckSum with in-complete CheckSum32.
-
- Notes: CheckSum32 is not a strong verification.
- It does not guarantee that the data has not been modified.
- CPU has its own mechanism to verify Microcode Binary part.
-
@param[in] CpuMpData The pointer to CPU MP Data structure.
@param[in] ProcessorNumber The handle number of the processor. The range is
from 0 to the total number of logical processors
@@ -76,26 +22,13 @@ MicrocodeDetect (
IN UINTN ProcessorNumber
)
{
- UINT32 ExtendedTableLength;
- UINT32 ExtendedTableCount;
- CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
- CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
- CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
+ CPU_MICROCODE_HEADER *Microcode;
UINTN MicrocodeEnd;
- UINTN Index;
- UINT8 PlatformId;
- CPUID_VERSION_INFO_EAX Eax;
- CPU_AP_DATA *CpuData;
- UINT32 CurrentRevision;
+ CPU_AP_DATA *BspData;
UINT32 LatestRevision;
- UINTN TotalSize;
- UINT32 CheckSum32;
- UINT32 InCompleteCheckSum32;
- BOOLEAN CorrectMicrocode;
- VOID *MicrocodeData;
- MSR_IA32_PLATFORM_ID_REGISTER PlatformIdMsr;
+ CPU_MICROCODE_HEADER *LatestMicrocode;
UINT32 ThreadId;
- BOOLEAN IsBspCallIn;
+ EDKII_PEI_MICROCODE_CPU_ID MicrocodeCpuId;
if (CpuMpData->MicrocodePatchRegionSize == 0) {
//
@@ -104,9 +37,6 @@ MicrocodeDetect (
return;
}
- CurrentRevision = GetCurrentMicrocodeSignature ();
- IsBspCallIn = (ProcessorNumber == (UINTN)CpuMpData->BspNumber) ? TRUE : FALSE;
-
GetProcessorLocationByApicId (GetInitialApicId (), NULL, NULL, &ThreadId);
if (ThreadId != 0) {
//
@@ -115,156 +45,35 @@ MicrocodeDetect (
return;
}
- ExtendedTableLength = 0;
- //
- // Here data of CPUID leafs have not been collected into context buffer, so
- // GetProcessorCpuid() cannot be used here to retrieve CPUID data.
- //
- AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, NULL, NULL);
-
- //
- // The index of platform information resides in bits 50:52 of MSR IA32_PLATFORM_ID
- //
- PlatformIdMsr.Uint64 = AsmReadMsr64 (MSR_IA32_PLATFORM_ID);
- PlatformId = (UINT8) PlatformIdMsr.Bits.PlatformId;
+ GetProcessorMicrocodeCpuId (&MicrocodeCpuId);
-
- //
- // Check whether AP has same processor with BSP.
- // If yes, direct use microcode info saved by BSP.
- //
- if (!IsBspCallIn) {
+ if (ProcessorNumber != (UINTN) CpuMpData->BspNumber) {
//
- // Get the CPU data for BSP
+ // Direct use microcode of BSP if AP is the same as BSP.
+ // Assume BSP calls this routine() before AP.
//
- CpuData = &(CpuMpData->CpuData[CpuMpData->BspNumber]);
- if ((CpuData->ProcessorSignature == Eax.Uint32) &&
- (CpuData->PlatformId == PlatformId) &&
- (CpuData->MicrocodeEntryAddr != 0)) {
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *)(UINTN) CpuData->MicrocodeEntryAddr;
- MicrocodeData = (VOID *) (MicrocodeEntryPoint + 1);
- LatestRevision = MicrocodeEntryPoint->UpdateRevision;
- goto Done;
+ BspData = &(CpuMpData->CpuData[CpuMpData->BspNumber]);
+ if ((BspData->ProcessorSignature == MicrocodeCpuId.ProcessorSignature) &&
+ (BspData->PlatformId == MicrocodeCpuId.PlatformId) &&
+ (BspData->MicrocodeEntryAddr != 0)) {
+ LatestMicrocode = (CPU_MICROCODE_HEADER *)(UINTN) BspData->MicrocodeEntryAddr;
+ LatestRevision = LatestMicrocode->UpdateRevision;
+ goto LoadMicrocode;
}
}
- LatestRevision = 0;
- MicrocodeData = NULL;
- MicrocodeEnd = (UINTN) (CpuMpData->MicrocodePatchAddress + CpuMpData->MicrocodePatchRegionSize);
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;
+ //
+ // BSP or AP which is different from BSP runs here
+ // Use 0 as the starting revision to search for microcode because MicrocodePatchInfo HOB needs
+ // the latest microcode location even it's loaded to the processor.
+ //
+ LatestRevision = 0;
+ LatestMicrocode = NULL;
+ Microcode = (CPU_MICROCODE_HEADER *) (UINTN) CpuMpData->MicrocodePatchAddress;
+ MicrocodeEnd = (UINTN) Microcode + (UINTN) CpuMpData->MicrocodePatchRegionSize;
do {
- //
- // Check if the microcode is for the Cpu and the version is newer
- // and the update can be processed on the platform
- //
- CorrectMicrocode = FALSE;
-
- if (MicrocodeEntryPoint->DataSize == 0) {
- TotalSize = sizeof (CPU_MICROCODE_HEADER) + 2000;
- } else {
- TotalSize = sizeof (CPU_MICROCODE_HEADER) + MicrocodeEntryPoint->DataSize;
- }
-
- ///
- /// 0x0 MicrocodeBegin MicrocodeEntry MicrocodeEnd 0xffffffff
- /// |--------------|---------------|---------------|---------------|
- /// valid TotalSize
- /// TotalSize is only valid between 0 and (MicrocodeEnd - MicrocodeEntry).
- /// And it should be aligned with 4 bytes.
- /// If the TotalSize is invalid, skip 1KB to check next entry.
- ///
- if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||
- ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||
- (TotalSize & 0x3) != 0
- ) {
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
- continue;
- }
-
- //
- // Save an in-complete CheckSum32 from CheckSum Part1 for common parts.
- //
- InCompleteCheckSum32 = CalculateSum32 (
- (UINT32 *) MicrocodeEntryPoint,
- TotalSize
- );
- InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorSignature.Uint32;
- InCompleteCheckSum32 -= MicrocodeEntryPoint->ProcessorFlags;
- InCompleteCheckSum32 -= MicrocodeEntryPoint->Checksum;
-
- if (MicrocodeEntryPoint->HeaderVersion == 0x1) {
- //
- // It is the microcode header. It is not the padding data between microcode patches
- // because the padding data should not include 0x00000001 and it should be the repeated
- // byte format (like 0xXYXYXYXY....).
- //
- if (MicrocodeEntryPoint->ProcessorSignature.Uint32 == Eax.Uint32 &&
- MicrocodeEntryPoint->UpdateRevision > LatestRevision &&
- (MicrocodeEntryPoint->ProcessorFlags & (1 << PlatformId))
- ) {
- //
- // Calculate CheckSum Part1.
- //
- CheckSum32 = InCompleteCheckSum32;
- CheckSum32 += MicrocodeEntryPoint->ProcessorSignature.Uint32;
- CheckSum32 += MicrocodeEntryPoint->ProcessorFlags;
- CheckSum32 += MicrocodeEntryPoint->Checksum;
- if (CheckSum32 == 0) {
- CorrectMicrocode = TRUE;
- }
- } else if ((MicrocodeEntryPoint->DataSize != 0) &&
- (MicrocodeEntryPoint->UpdateRevision > LatestRevision)) {
- ExtendedTableLength = MicrocodeEntryPoint->TotalSize - (MicrocodeEntryPoint->DataSize +
- sizeof (CPU_MICROCODE_HEADER));
- if (ExtendedTableLength != 0) {
- //
- // Extended Table exist, check if the CPU in support list
- //
- ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
- + MicrocodeEntryPoint->DataSize + sizeof (CPU_MICROCODE_HEADER));
- //
- // Calculate Extended Checksum
- //
- if ((ExtendedTableLength % 4) == 0) {
- //
- // Calculate CheckSum Part2.
- //
- CheckSum32 = CalculateSum32 ((UINT32 *) ExtendedTableHeader, ExtendedTableLength);
- if (CheckSum32 == 0) {
- //
- // Checksum correct
- //
- ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
- ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
- for (Index = 0; Index < ExtendedTableCount; Index ++) {
- //
- // Calculate CheckSum Part3.
- //
- CheckSum32 = InCompleteCheckSum32;
- CheckSum32 += ExtendedTable->ProcessorSignature.Uint32;
- CheckSum32 += ExtendedTable->ProcessorFlag;
- CheckSum32 += ExtendedTable->Checksum;
- if (CheckSum32 == 0) {
- //
- // Verify Header
- //
- if ((ExtendedTable->ProcessorSignature.Uint32 == Eax.Uint32) &&
- (ExtendedTable->ProcessorFlag & (1 << PlatformId)) ) {
- //
- // Find one
- //
- CorrectMicrocode = TRUE;
- break;
- }
- }
- ExtendedTable ++;
- }
- }
- }
- }
- }
- } else {
+ if (!IsValidMicrocode (Microcode, MicrocodeEnd - (UINTN) Microcode, LatestRevision, &MicrocodeCpuId, 1, TRUE)) {
//
// It is the padding data between the microcode patches for microcode patches alignment.
// Because the microcode patch is the multiple of 1-KByte, the padding data should not
@@ -272,165 +81,40 @@ MicrocodeDetect (
// alignment value should be larger than 1-KByte. We could skip SIZE_1KB padding data to
// find the next possible microcode patch header.
//
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
+ Microcode = (CPU_MICROCODE_HEADER *) ((UINTN) Microcode + SIZE_1KB);
continue;
}
- //
- // Get the next patch.
- //
- if (MicrocodeEntryPoint->DataSize == 0) {
- TotalSize = 2048;
- } else {
- TotalSize = MicrocodeEntryPoint->TotalSize;
- }
-
- if (CorrectMicrocode) {
- LatestRevision = MicrocodeEntryPoint->UpdateRevision;
- MicrocodeData = (VOID *) ((UINTN) MicrocodeEntryPoint + sizeof (CPU_MICROCODE_HEADER));
- }
+ LatestMicrocode = Microcode;
+ LatestRevision = LatestMicrocode->UpdateRevision;
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
- } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
+ Microcode = (CPU_MICROCODE_HEADER *) (((UINTN) Microcode) + GetMicrocodeLength (Microcode));
+ } while ((UINTN) Microcode < MicrocodeEnd);
-Done:
+LoadMicrocode:
if (LatestRevision != 0) {
//
- // Save the detected microcode patch entry address (including the
- // microcode patch header) for each processor.
+ // Save the detected microcode patch entry address (including the microcode
+ // patch header) for each processor even it's the same as the loaded one.
// It will be used when building the microcode patch cache HOB.
//
- CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr =
- (UINTN) MicrocodeData - sizeof (CPU_MICROCODE_HEADER);
+ CpuMpData->CpuData[ProcessorNumber].MicrocodeEntryAddr = (UINTN) LatestMicrocode;
}
- if (LatestRevision > CurrentRevision) {
+ if (LatestRevision > GetProcessorMicrocodeSignature ()) {
//
// BIOS only authenticate updates that contain a numerically larger revision
// than the currently loaded revision, where Current Signature < New Update
// Revision. A processor with no loaded update is considered to have a
// revision equal to zero.
//
- ASSERT (MicrocodeData != NULL);
- AsmWriteMsr64 (
- MSR_IA32_BIOS_UPDT_TRIG,
- (UINT64) (UINTN) MicrocodeData
- );
- //
- // Get and check new microcode signature
- //
- CurrentRevision = GetCurrentMicrocodeSignature ();
- if (CurrentRevision != LatestRevision) {
- AcquireSpinLock(&CpuMpData->MpLock);
- DEBUG ((EFI_D_ERROR, "Updated microcode signature [0x%08x] does not match \
- loaded microcode signature [0x%08x]\n", CurrentRevision, LatestRevision));
- ReleaseSpinLock(&CpuMpData->MpLock);
- }
+ LoadMicrocode (LatestMicrocode);
}
-}
-
-/**
- Determine if a microcode patch matchs the specific processor signature and flag.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
- @param[in] ProcessorSignature The processor signature field value
- supported by a microcode patch.
- @param[in] ProcessorFlags The prcessor flags field value supported by
- a microcode patch.
-
- @retval TRUE The specified microcode patch will be loaded.
- @retval FALSE The specified microcode patch will not be loaded.
-**/
-BOOLEAN
-IsProcessorMatchedMicrocodePatch (
- IN CPU_MP_DATA *CpuMpData,
- IN UINT32 ProcessorSignature,
- IN UINT32 ProcessorFlags
- )
-{
- UINTN Index;
- CPU_AP_DATA *CpuData;
-
- for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
- CpuData = &CpuMpData->CpuData[Index];
- if ((ProcessorSignature == CpuData->ProcessorSignature) &&
- (ProcessorFlags & (1 << CpuData->PlatformId)) != 0) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Check the 'ProcessorSignature' and 'ProcessorFlags' of the microcode
- patch header with the CPUID and PlatformID of the processors within
- system to decide if it will be copied into memory.
-
- @param[in] CpuMpData The pointer to CPU MP Data structure.
- @param[in] MicrocodeEntryPoint The pointer to the microcode patch header.
-
- @retval TRUE The specified microcode patch need to be loaded.
- @retval FALSE The specified microcode patch dosen't need to be loaded.
-**/
-BOOLEAN
-IsMicrocodePatchNeedLoad (
- IN CPU_MP_DATA *CpuMpData,
- CPU_MICROCODE_HEADER *MicrocodeEntryPoint
- )
-{
- BOOLEAN NeedLoad;
- UINTN DataSize;
- UINTN TotalSize;
- CPU_MICROCODE_EXTENDED_TABLE_HEADER *ExtendedTableHeader;
- UINT32 ExtendedTableCount;
- CPU_MICROCODE_EXTENDED_TABLE *ExtendedTable;
- UINTN Index;
-
- //
- // Check the 'ProcessorSignature' and 'ProcessorFlags' in microcode patch header.
- //
- NeedLoad = IsProcessorMatchedMicrocodePatch (
- CpuMpData,
- MicrocodeEntryPoint->ProcessorSignature.Uint32,
- MicrocodeEntryPoint->ProcessorFlags
- );
-
//
- // If the Extended Signature Table exists, check if the processor is in the
- // support list
+ // It's possible that the microcode fails to load. Just capture the CPU microcode revision after loading.
//
- DataSize = MicrocodeEntryPoint->DataSize;
- TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
- if ((!NeedLoad) && (DataSize != 0) &&
- (TotalSize - DataSize > sizeof (CPU_MICROCODE_HEADER) +
- sizeof (CPU_MICROCODE_EXTENDED_TABLE_HEADER))) {
- ExtendedTableHeader = (CPU_MICROCODE_EXTENDED_TABLE_HEADER *) ((UINT8 *) (MicrocodeEntryPoint)
- + DataSize + sizeof (CPU_MICROCODE_HEADER));
- ExtendedTableCount = ExtendedTableHeader->ExtendedSignatureCount;
- ExtendedTable = (CPU_MICROCODE_EXTENDED_TABLE *) (ExtendedTableHeader + 1);
-
- for (Index = 0; Index < ExtendedTableCount; Index ++) {
- //
- // Check the 'ProcessorSignature' and 'ProcessorFlag' of the Extended
- // Signature Table entry with the CPUID and PlatformID of the processors
- // within system to decide if it will be copied into memory
- //
- NeedLoad = IsProcessorMatchedMicrocodePatch (
- CpuMpData,
- ExtendedTable->ProcessorSignature.Uint32,
- ExtendedTable->ProcessorFlag
- );
- if (NeedLoad) {
- break;
- }
- ExtendedTable ++;
- }
- }
-
- return NeedLoad;
+ CpuMpData->CpuData[ProcessorNumber].MicrocodeRevision = GetProcessorMicrocodeSignature ();
}
-
/**
Actual worker function that shadows the required microcode patches into memory.
@@ -500,14 +184,16 @@ ShadowMicrocodePatchByPcd (
IN OUT CPU_MP_DATA *CpuMpData
)
{
+ UINTN Index;
CPU_MICROCODE_HEADER *MicrocodeEntryPoint;
UINTN MicrocodeEnd;
- UINTN DataSize;
UINTN TotalSize;
MICROCODE_PATCH_INFO *PatchInfoBuffer;
UINTN MaxPatchNumber;
UINTN PatchCount;
UINTN TotalLoadSize;
+ EDKII_PEI_MICROCODE_CPU_ID *MicrocodeCpuIds;
+ BOOLEAN Valid;
//
// Initialize the microcode patch related fields in CpuMpData as the values
@@ -535,12 +221,34 @@ ShadowMicrocodePatchByPcd (
return;
}
+ MicrocodeCpuIds = AllocatePages (
+ EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * sizeof (EDKII_PEI_MICROCODE_CPU_ID))
+ );
+ if (MicrocodeCpuIds == NULL) {
+ FreePool (PatchInfoBuffer);
+ return;
+ }
+
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
+ MicrocodeCpuIds[Index].PlatformId = CpuMpData->CpuData[Index].PlatformId;
+ MicrocodeCpuIds[Index].ProcessorSignature = CpuMpData->CpuData[Index].ProcessorSignature;
+ }
+
//
// Process the header of each microcode patch within the region.
// The purpose is to decide which microcode patch(es) will be loaded into memory.
+ // Microcode checksum is not verified because it's slow when performing on flash.
//
do {
- if (MicrocodeEntryPoint->HeaderVersion != 0x1) {
+ Valid = IsValidMicrocode (
+ MicrocodeEntryPoint,
+ MicrocodeEnd - (UINTN) MicrocodeEntryPoint,
+ 0,
+ MicrocodeCpuIds,
+ CpuMpData->CpuCount,
+ FALSE
+ );
+ if (!Valid) {
//
// Padding data between the microcode patches, skip 1KB to check next entry.
//
@@ -548,59 +256,44 @@ ShadowMicrocodePatchByPcd (
continue;
}
- DataSize = MicrocodeEntryPoint->DataSize;
- TotalSize = (DataSize == 0) ? 2048 : MicrocodeEntryPoint->TotalSize;
- if ( (UINTN)MicrocodeEntryPoint > (MAX_ADDRESS - TotalSize) ||
- ((UINTN)MicrocodeEntryPoint + TotalSize) > MicrocodeEnd ||
- (DataSize & 0x3) != 0 ||
- (TotalSize & (SIZE_1KB - 1)) != 0 ||
- TotalSize < DataSize
- ) {
+ PatchCount++;
+ if (PatchCount > MaxPatchNumber) {
//
- // Not a valid microcode header, skip 1KB to check next entry.
+ // Current 'PatchInfoBuffer' cannot hold the information, double the size
+ // and allocate a new buffer.
//
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + SIZE_1KB);
- continue;
- }
-
- if (IsMicrocodePatchNeedLoad (CpuMpData, MicrocodeEntryPoint)) {
- PatchCount++;
- if (PatchCount > MaxPatchNumber) {
+ if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {
//
- // Current 'PatchInfoBuffer' cannot hold the information, double the size
- // and allocate a new buffer.
+ // Overflow check for MaxPatchNumber
//
- if (MaxPatchNumber > MAX_UINTN / 2 / sizeof (MICROCODE_PATCH_INFO)) {
- //
- // Overflow check for MaxPatchNumber
- //
- goto OnExit;
- }
-
- PatchInfoBuffer = ReallocatePool (
- MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),
- 2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),
- PatchInfoBuffer
- );
- if (PatchInfoBuffer == NULL) {
- goto OnExit;
- }
- MaxPatchNumber = MaxPatchNumber * 2;
+ goto OnExit;
}
- //
- // Store the information of this microcode patch
- //
- PatchInfoBuffer[PatchCount - 1].Address = (UINTN) MicrocodeEntryPoint;
- PatchInfoBuffer[PatchCount - 1].Size = TotalSize;
- TotalLoadSize += TotalSize;
+ PatchInfoBuffer = ReallocatePool (
+ MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),
+ 2 * MaxPatchNumber * sizeof (MICROCODE_PATCH_INFO),
+ PatchInfoBuffer
+ );
+ if (PatchInfoBuffer == NULL) {
+ goto OnExit;
+ }
+ MaxPatchNumber = MaxPatchNumber * 2;
}
+ TotalSize = GetMicrocodeLength (MicrocodeEntryPoint);
+
+ //
+ // Store the information of this microcode patch
+ //
+ PatchInfoBuffer[PatchCount - 1].Address = (UINTN) MicrocodeEntryPoint;
+ PatchInfoBuffer[PatchCount - 1].Size = TotalSize;
+ TotalLoadSize += TotalSize;
+
//
// Process the next microcode patch
//
- MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) (((UINTN) MicrocodeEntryPoint) + TotalSize);
- } while (((UINTN) MicrocodeEntryPoint < MicrocodeEnd));
+ MicrocodeEntryPoint = (CPU_MICROCODE_HEADER *) ((UINTN) MicrocodeEntryPoint + TotalSize);
+ } while ((UINTN) MicrocodeEntryPoint < MicrocodeEnd);
if (PatchCount != 0) {
DEBUG ((
@@ -616,7 +309,7 @@ OnExit:
if (PatchInfoBuffer != NULL) {
FreePool (PatchInfoBuffer);
}
- return;
+ FreePages (MicrocodeCpuIds, EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * sizeof (EDKII_PEI_MICROCODE_CPU_ID)));
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpEqu.inc b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
new file mode 100644
index 00000000000..b2e5d27f405
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpEqu.inc
@@ -0,0 +1,99 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; MpEqu.inc
+;
+; Abstract:
+;
+; This is the equates file for Multiple Processor support
+;
+;-------------------------------------------------------------------------------
+%include "Nasm.inc"
+
+CPU_SWITCH_STATE_IDLE equ 0
+CPU_SWITCH_STATE_STORED equ 1
+CPU_SWITCH_STATE_LOADED equ 2
+
+;
+; Equivalent NASM structure of MP_ASSEMBLY_ADDRESS_MAP
+;
+struc MP_ASSEMBLY_ADDRESS_MAP
+ .RendezvousFunnelAddress CTYPE_UINTN 1
+ .ModeEntryOffset CTYPE_UINTN 1
+ .RendezvousFunnelSize CTYPE_UINTN 1
+ .RelocateApLoopFuncAddress CTYPE_UINTN 1
+ .RelocateApLoopFuncSize CTYPE_UINTN 1
+ .ModeTransitionOffset CTYPE_UINTN 1
+ .SwitchToRealSize CTYPE_UINTN 1
+ .SwitchToRealOffset CTYPE_UINTN 1
+ .SwitchToRealNoNxOffset CTYPE_UINTN 1
+ .SwitchToRealPM16ModeOffset CTYPE_UINTN 1
+ .SwitchToRealPM16ModeSize CTYPE_UINTN 1
+endstruc
+
+;
+; Equivalent NASM structure of IA32_DESCRIPTOR
+;
+struc IA32_DESCRIPTOR
+ .Limit CTYPE_UINT16 1
+ .Base CTYPE_UINTN 1
+endstruc
+
+;
+; Equivalent NASM structure of CPU_EXCHANGE_ROLE_INFO
+;
+struc CPU_EXCHANGE_ROLE_INFO
+ ; State is defined as UINT8 in C header file
+ ; Define it as UINTN here to guarantee the fields that follow State
+ ; is naturally aligned. The structure layout doesn't change.
+ .State CTYPE_UINTN 1
+ .StackPointer CTYPE_UINTN 1
+ .Gdtr CTYPE_UINT8 IA32_DESCRIPTOR_size
+ .Idtr CTYPE_UINT8 IA32_DESCRIPTOR_size
+endstruc
+
+;
+; Equivalent NASM structure of CPU_INFO_IN_HOB
+;
+struc CPU_INFO_IN_HOB
+ .InitialApicId CTYPE_UINT32 1
+ .ApicId CTYPE_UINT32 1
+ .Health CTYPE_UINT32 1
+ .ApTopOfStack CTYPE_UINT64 1
+endstruc
+
+;
+; Equivalent NASM structure of MP_CPU_EXCHANGE_INFO
+;
+struc MP_CPU_EXCHANGE_INFO
+ .StackStart: CTYPE_UINTN 1
+ .StackSize: CTYPE_UINTN 1
+ .CFunction: CTYPE_UINTN 1
+ .GdtrProfile: CTYPE_UINT8 IA32_DESCRIPTOR_size
+ .IdtrProfile: CTYPE_UINT8 IA32_DESCRIPTOR_size
+ .BufferStart: CTYPE_UINTN 1
+ .ModeOffset: CTYPE_UINTN 1
+ .ApIndex: CTYPE_UINTN 1
+ .CodeSegment: CTYPE_UINTN 1
+ .DataSegment: CTYPE_UINTN 1
+ .EnableExecuteDisable: CTYPE_UINTN 1
+ .Cr3: CTYPE_UINTN 1
+ .InitFlag: CTYPE_UINTN 1
+ .CpuInfo: CTYPE_UINTN 1
+ .NumApsExecuting: CTYPE_UINTN 1
+ .CpuMpData: CTYPE_UINTN 1
+ .InitializeFloatingPointUnits: CTYPE_UINTN 1
+ .ModeTransitionMemory: CTYPE_UINT32 1
+ .ModeTransitionSegment: CTYPE_UINT16 1
+ .ModeHighMemory: CTYPE_UINT32 1
+ .ModeHighSegment: CTYPE_UINT16 1
+ .Enable5LevelPaging: CTYPE_BOOLEAN 1
+ .SevEsIsEnabled: CTYPE_BOOLEAN 1
+ .GhcbBase: CTYPE_UINTN 1
+endstruc
+
+MP_CPU_EXCHANGE_INFO_OFFSET equ (SwitchToRealProcEnd - RendezvousFunnelProcStart)
+%define MP_CPU_EXCHANGE_INFO_FIELD(Field) (MP_CPU_EXCHANGE_INFO_OFFSET + MP_CPU_EXCHANGE_INFO. %+ Field)
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.c
index f96156b0d88..630d404fd45 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -1,7 +1,7 @@
/** @file
CPU MP Initialize Library common functions.
- Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -9,6 +9,9 @@
**/
#include "MpLib.h"
+#include <Library/VmgExitLib.h>
+#include <Register/Amd/Fam17Msr.h>
+#include <Register/Amd/Ghcb.h>
#ifdef VBOX
# include <Library/IoLib.h>
# include "../../../../DevEFI.h"
@@ -18,29 +21,6 @@ EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
/**
- Determine if the standard CPU signature is "AuthenticAMD".
-
- @retval TRUE The CPU signature matches.
- @retval FALSE The CPU signature does not match.
-
-**/
-STATIC
-BOOLEAN
-StandardSignatureIsAuthenticAMD (
- VOID
- )
-{
- UINT32 RegEbx;
- UINT32 RegEcx;
- UINT32 RegEdx;
-
- AsmCpuid (CPUID_SIGNATURE, NULL, &RegEbx, &RegEcx, &RegEdx);
- return (RegEbx == CPUID_SIGNATURE_AUTHENTIC_AMD_EBX &&
- RegEcx == CPUID_SIGNATURE_AUTHENTIC_AMD_ECX &&
- RegEdx == CPUID_SIGNATURE_AUTHENTIC_AMD_EDX);
-}
-
-/**
The function will check if BSP Execute Disable is enabled.
DxeIpl may have enabled Execute Disable for BSP, APs need to
@@ -318,6 +298,14 @@ GetApLoopMode (
//
ApLoopMode = ApInHltLoop;
}
+
+ if (PcdGetBool (PcdSevEsIsEnabled)) {
+ //
+ // For SEV-ES, force AP in Hlt-loop mode in order to use the GHCB
+ // protocol for starting APs
+ //
+ ApLoopMode = ApInHltLoop;
+ }
}
if (ApLoopMode != ApInMwaitLoop) {
@@ -522,14 +510,12 @@ CollectProcessorCount (
CpuMpData->InitFlag = ApInitConfig;
WakeUpAP (CpuMpData, TRUE, 0, NULL, NULL, TRUE);
CpuMpData->InitFlag = ApInitDone;
- ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
//
- // Wait for all APs finished the initialization
+ // When InitFlag == ApInitConfig, WakeUpAP () guarantees all APs are checked in.
+ // FinishedCount is the number of check-in APs.
//
- while (CpuMpData->FinishedCount < (CpuMpData->CpuCount - 1)) {
- CpuPause ();
- }
-
+ CpuMpData->CpuCount = CpuMpData->FinishedCount + 1;
+ ASSERT (CpuMpData->CpuCount <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
//
// Enable x2APIC mode if
@@ -642,6 +628,117 @@ InitializeApData (
}
/**
+ Get Protected mode code segment with 16-bit default addressing
+ from current GDT table.
+
+ @return Protected mode 16-bit code segment value.
+**/
+STATIC
+UINT16
+GetProtectedMode16CS (
+ VOID
+ )
+{
+ IA32_DESCRIPTOR GdtrDesc;
+ IA32_SEGMENT_DESCRIPTOR *GdtEntry;
+ UINTN GdtEntryCount;
+ UINT16 Index;
+
+ Index = (UINT16) -1;
+ AsmReadGdtr (&GdtrDesc);
+ GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
+ GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
+ for (Index = 0; Index < GdtEntryCount; Index++) {
+ if (GdtEntry->Bits.L == 0 &&
+ GdtEntry->Bits.DB == 0 &&
+ GdtEntry->Bits.Type > 8) {
+ break;
+ }
+ GdtEntry++;
+ }
+ ASSERT (Index != GdtEntryCount);
+ return Index * 8;
+}
+
+/**
+ Get Protected mode code segment with 32-bit default addressing
+ from current GDT table.
+
+ @return Protected mode 32-bit code segment value.
+**/
+STATIC
+UINT16
+GetProtectedMode32CS (
+ VOID
+ )
+{
+ IA32_DESCRIPTOR GdtrDesc;
+ IA32_SEGMENT_DESCRIPTOR *GdtEntry;
+ UINTN GdtEntryCount;
+ UINT16 Index;
+
+ Index = (UINT16) -1;
+ AsmReadGdtr (&GdtrDesc);
+ GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);
+ GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
+ for (Index = 0; Index < GdtEntryCount; Index++) {
+ if (GdtEntry->Bits.L == 0 &&
+ GdtEntry->Bits.DB == 1 &&
+ GdtEntry->Bits.Type > 8) {
+ break;
+ }
+ GdtEntry++;
+ }
+ ASSERT (Index != GdtEntryCount);
+ return Index * 8;
+}
+
+/**
+ Reset an AP when in SEV-ES mode.
+
+ If successful, this function never returns.
+
+ @param[in] Ghcb Pointer to the GHCB
+ @param[in] CpuMpData Pointer to CPU MP Data
+
+**/
+STATIC
+VOID
+MpInitLibSevEsAPReset (
+ IN GHCB *Ghcb,
+ IN CPU_MP_DATA *CpuMpData
+ )
+{
+ EFI_STATUS Status;
+ UINTN ProcessorNumber;
+ UINT16 Code16, Code32;
+ AP_RESET *APResetFn;
+ UINTN BufferStart;
+ UINTN StackStart;
+
+ Status = GetProcessorNumber (CpuMpData, &ProcessorNumber);
+ ASSERT_EFI_ERROR (Status);
+
+ Code16 = GetProtectedMode16CS ();
+ Code32 = GetProtectedMode32CS ();
+
+ if (CpuMpData->WakeupBufferHigh != 0) {
+ APResetFn = (AP_RESET *) (CpuMpData->WakeupBufferHigh + CpuMpData->AddressMap.SwitchToRealNoNxOffset);
+ } else {
+ APResetFn = (AP_RESET *) (CpuMpData->MpCpuExchangeInfo->BufferStart + CpuMpData->AddressMap.SwitchToRealOffset);
+ }
+
+ BufferStart = CpuMpData->MpCpuExchangeInfo->BufferStart;
+ StackStart = CpuMpData->SevEsAPResetStackStart -
+ (AP_RESET_STACK_SIZE * ProcessorNumber);
+
+ //
+ // This call never returns.
+ //
+ APResetFn (BufferStart, Code16, Code32, StackStart);
+}
+
+/**
This function will be called from AP reset code if BSP uses WakeUpAP.
@param[in] ExchangeInfo Pointer to the MP exchange info buffer
@@ -683,10 +780,6 @@ ApWakeupFunction (
CurrentApicMode = GetApicMode ();
while (TRUE) {
if (CpuMpData->InitFlag == ApInitConfig) {
- //
- // Add CPU number
- //
- InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount);
ProcessorNumber = ApIndex;
//
// This is first time AP wakeup, get BIST information from AP stack
@@ -701,8 +794,6 @@ ApWakeupFunction (
RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
-
- InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
} else {
//
// Execute AP function if AP is ready
@@ -791,25 +882,83 @@ ApWakeupFunction (
}
}
+ if (CpuMpData->ApLoopMode == ApInHltLoop) {
+ //
+ // Save AP volatile registers
+ //
+ SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
+ }
+
//
// AP finished executing C code
//
InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount);
+ if (CpuMpData->InitFlag == ApInitConfig) {
+ //
+ // Delay decrementing the APs executing count when SEV-ES is enabled
+ // to allow the APs to issue an AP_RESET_HOLD before the BSP possibly
+ // performs another INIT-SIPI-SIPI sequence.
+ //
+ if (!CpuMpData->SevEsIsEnabled) {
+ InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
+ }
+ }
+
//
// Place AP is specified loop mode
//
if (CpuMpData->ApLoopMode == ApInHltLoop) {
//
- // Save AP volatile registers
- //
- SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters);
- //
// Place AP in HLT-loop
//
while (TRUE) {
DisableInterrupts ();
- CpuSleep ();
+ if (CpuMpData->SevEsIsEnabled) {
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ GHCB *Ghcb;
+ UINT64 Status;
+ BOOLEAN DoDecrement;
+ BOOLEAN InterruptState;
+
+ DoDecrement = (BOOLEAN) (CpuMpData->InitFlag == ApInitConfig);
+
+ while (TRUE) {
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+ Ghcb = Msr.Ghcb;
+
+ VmgInit (Ghcb, &InterruptState);
+
+ if (DoDecrement) {
+ DoDecrement = FALSE;
+
+ //
+ // Perform the delayed decrement just before issuing the first
+ // VMGEXIT with AP_RESET_HOLD.
+ //
+ InterlockedDecrement ((UINT32 *) &CpuMpData->MpCpuExchangeInfo->NumApsExecuting);
+ }
+
+ Status = VmgExit (Ghcb, SVM_EXIT_AP_RESET_HOLD, 0, 0);
+ if ((Status == 0) && (Ghcb->SaveArea.SwExitInfo2 != 0)) {
+ VmgDone (Ghcb, InterruptState);
+ break;
+ }
+
+ VmgDone (Ghcb, InterruptState);
+ }
+
+ //
+ // Awakened in a new phase? Use the new CpuMpData
+ //
+ if (CpuMpData->NewCpuMpData != NULL) {
+ CpuMpData = CpuMpData->NewCpuMpData;
+ }
+
+ MpInitLibSevEsAPReset (Ghcb, CpuMpData);
+ } else {
+ CpuSleep ();
+ }
CpuPause ();
}
}
@@ -888,7 +1037,6 @@ FillExchangeInfoData (
IA32_CR4 Cr4;
ExchangeInfo = CpuMpData->MpCpuExchangeInfo;
- ExchangeInfo->Lock = 0;
ExchangeInfo->StackStart = CpuMpData->Buffer;
ExchangeInfo->StackSize = CpuMpData->CpuApStackSize;
ExchangeInfo->BufferStart = CpuMpData->WakeupBuffer;
@@ -922,6 +1070,9 @@ FillExchangeInfoData (
ExchangeInfo->Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);
DEBUG ((DEBUG_INFO, "%a: 5-Level Paging = %d\n", gEfiCallerBaseName, ExchangeInfo->Enable5LevelPaging));
+ ExchangeInfo->SevEsIsEnabled = CpuMpData->SevEsIsEnabled;
+ ExchangeInfo->GhcbBase = (UINTN) CpuMpData->GhcbBase;
+
//
// Get the BSP's data of GDT and IDT
//
@@ -948,8 +1099,9 @@ FillExchangeInfoData (
// EfiBootServicesCode to avoid page fault if NX memory protection is enabled.
//
if (CpuMpData->WakeupBufferHigh != 0) {
- Size = CpuMpData->AddressMap.RendezvousFunnelSize -
- CpuMpData->AddressMap.ModeTransitionOffset;
+ Size = CpuMpData->AddressMap.RendezvousFunnelSize +
+ CpuMpData->AddressMap.SwitchToRealSize -
+ CpuMpData->AddressMap.ModeTransitionOffset;
CopyMem (
(VOID *)CpuMpData->WakeupBufferHigh,
CpuMpData->AddressMap.RendezvousFunnelAddress +
@@ -1002,7 +1154,8 @@ BackupAndPrepareWakeupBuffer(
CopyMem (
(VOID *) CpuMpData->WakeupBuffer,
(VOID *) CpuMpData->AddressMap.RendezvousFunnelAddress,
- CpuMpData->AddressMap.RendezvousFunnelSize
+ CpuMpData->AddressMap.RendezvousFunnelSize +
+ CpuMpData->AddressMap.SwitchToRealSize
);
}
@@ -1024,6 +1177,42 @@ RestoreWakeupBuffer(
}
/**
+ Calculate the size of the reset vector.
+
+ @param[in] AddressMap The pointer to Address Map structure.
+
+ @return Total amount of memory required for the AP reset area
+**/
+STATIC
+UINTN
+GetApResetVectorSize (
+ IN MP_ASSEMBLY_ADDRESS_MAP *AddressMap
+ )
+{
+ UINTN Size;
+
+ Size = AddressMap->RendezvousFunnelSize +
+ AddressMap->SwitchToRealSize +
+ sizeof (MP_CPU_EXCHANGE_INFO);
+
+ //
+ // The AP reset stack is only used by SEV-ES guests. Do not add to the
+ // allocation if SEV-ES is not enabled.
+ //
+ if (PcdGetBool (PcdSevEsIsEnabled)) {
+ //
+ // Stack location is based on APIC ID, so use the total number of
+ // processors for calculating the total stack area.
+ //
+ Size += AP_RESET_STACK_SIZE * PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+
+ Size = ALIGN_VALUE (Size, CPU_STACK_ALIGNMENT);
+ }
+
+ return Size;
+}
+
+/**
Allocate reset vector buffer.
@param[in, out] CpuMpData The pointer to CPU MP Data structure.
@@ -1036,16 +1225,22 @@ AllocateResetVector (
UINTN ApResetVectorSize;
if (CpuMpData->WakeupBuffer == (UINTN) -1) {
- ApResetVectorSize = CpuMpData->AddressMap.RendezvousFunnelSize +
- sizeof (MP_CPU_EXCHANGE_INFO);
+ ApResetVectorSize = GetApResetVectorSize (&CpuMpData->AddressMap);
CpuMpData->WakeupBuffer = GetWakeupBuffer (ApResetVectorSize);
CpuMpData->MpCpuExchangeInfo = (MP_CPU_EXCHANGE_INFO *) (UINTN)
- (CpuMpData->WakeupBuffer + CpuMpData->AddressMap.RendezvousFunnelSize);
+ (CpuMpData->WakeupBuffer +
+ CpuMpData->AddressMap.RendezvousFunnelSize +
+ CpuMpData->AddressMap.SwitchToRealSize);
CpuMpData->WakeupBufferHigh = GetModeTransitionBuffer (
- CpuMpData->AddressMap.RendezvousFunnelSize -
+ CpuMpData->AddressMap.RendezvousFunnelSize +
+ CpuMpData->AddressMap.SwitchToRealSize -
CpuMpData->AddressMap.ModeTransitionOffset
);
+ //
+ // The reset stack starts at the end of the buffer.
+ //
+ CpuMpData->SevEsAPResetStackStart = CpuMpData->WakeupBuffer + ApResetVectorSize;
}
BackupAndPrepareWakeupBuffer (CpuMpData);
}
@@ -1060,7 +1255,80 @@ FreeResetVector (
IN CPU_MP_DATA *CpuMpData
)
{
- RestoreWakeupBuffer (CpuMpData);
+ //
+ // If SEV-ES is enabled, the reset area is needed for AP parking and
+ // and AP startup in the OS, so the reset area is reserved. Do not
+ // perform the restore as this will overwrite memory which has data
+ // needed by SEV-ES.
+ //
+ if (!CpuMpData->SevEsIsEnabled) {
+ RestoreWakeupBuffer (CpuMpData);
+ }
+}
+
+/**
+ Allocate the SEV-ES AP jump table buffer.
+
+ @param[in, out] CpuMpData The pointer to CPU MP Data structure.
+**/
+VOID
+AllocateSevEsAPMemory (
+ IN OUT CPU_MP_DATA *CpuMpData
+ )
+{
+ if (CpuMpData->SevEsAPBuffer == (UINTN) -1) {
+ CpuMpData->SevEsAPBuffer =
+ CpuMpData->SevEsIsEnabled ? GetSevEsAPMemory () : 0;
+ }
+}
+
+/**
+ Program the SEV-ES AP jump table buffer.
+
+ @param[in] SipiVector The SIPI vector used for the AP Reset
+**/
+VOID
+SetSevEsJumpTable (
+ IN UINTN SipiVector
+ )
+{
+ SEV_ES_AP_JMP_FAR *JmpFar;
+ UINT32 Offset, InsnByte;
+ UINT8 LoNib, HiNib;
+
+ JmpFar = (SEV_ES_AP_JMP_FAR *) (UINTN) FixedPcdGet32 (PcdSevEsWorkAreaBase);
+ ASSERT (JmpFar != NULL);
+
+ //
+ // Obtain the address of the Segment/Rip location in the workarea.
+ // This will be set to a value derived from the SIPI vector and will
+ // be the memory address used for the far jump below.
+ //
+ Offset = FixedPcdGet32 (PcdSevEsWorkAreaBase);
+ Offset += sizeof (JmpFar->InsnBuffer);
+ LoNib = (UINT8) Offset;
+ HiNib = (UINT8) (Offset >> 8);
+
+ //
+ // Program the workarea (which is the initial AP boot address) with
+ // far jump to the SIPI vector (where XX and YY represent the
+ // address of where the SIPI vector is stored.
+ //
+ // JMP FAR [CS:XXYY] => 2E FF 2E YY XX
+ //
+ InsnByte = 0;
+ JmpFar->InsnBuffer[InsnByte++] = 0x2E; // CS override prefix
+ JmpFar->InsnBuffer[InsnByte++] = 0xFF; // JMP (FAR)
+ JmpFar->InsnBuffer[InsnByte++] = 0x2E; // ModRM (JMP memory location)
+ JmpFar->InsnBuffer[InsnByte++] = LoNib; // YY offset ...
+ JmpFar->InsnBuffer[InsnByte++] = HiNib; // XX offset ...
+
+ //
+ // Program the Segment/Rip based on the SIPI vector (always at least
+ // 16-byte aligned, so Rip is set to 0).
+ //
+ JmpFar->Rip = 0;
+ JmpFar->Segment = (UINT16) (SipiVector >> 4);
}
/**
@@ -1097,6 +1365,7 @@ WakeUpAP (
CpuMpData->InitFlag != ApInitDone) {
ResetVectorRequired = TRUE;
AllocateResetVector (CpuMpData);
+ AllocateSevEsAPMemory (CpuMpData);
FillExchangeInfoData (CpuMpData);
SaveLocalApicTimerSetting (CpuMpData);
}
@@ -1134,6 +1403,15 @@ WakeUpAP (
}
if (ResetVectorRequired) {
//
+ // For SEV-ES, the initial AP boot address will be defined by
+ // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address
+ // from the original INIT-SIPI-SIPI.
+ //
+ if (CpuMpData->SevEsIsEnabled) {
+ SetSevEsJumpTable (ExchangeInfo->BufferStart);
+ }
+
+ //
// Wakeup all APs
//
SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart);
@@ -1224,6 +1502,16 @@ WakeUpAP (
*(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL;
if (ResetVectorRequired) {
CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
+
+ //
+ // For SEV-ES, the initial AP boot address will be defined by
+ // PcdSevEsWorkAreaBase. The Segment/Rip must be the jump address
+ // from the original INIT-SIPI-SIPI.
+ //
+ if (CpuMpData->SevEsIsEnabled) {
+ SetSevEsJumpTable (ExchangeInfo->BufferStart);
+ }
+
SendInitSipiSipi (
CpuInfoInHob[ProcessorNumber].ApicId,
(UINT32) ExchangeInfo->BufferStart
@@ -1700,7 +1988,7 @@ MpInitLibInitialize (
ASSERT (MaxLogicalProcessorNumber != 0);
AsmGetAddressMap (&AddressMap);
- ApResetVectorSize = AddressMap.RendezvousFunnelSize + sizeof (MP_CPU_EXCHANGE_INFO);
+ ApResetVectorSize = GetApResetVectorSize (&AddressMap);
ApStackSize = PcdGet32(PcdCpuApStackSize);
ApLoopMode = GetApLoopMode (&MonitorFilterSize);
@@ -1758,6 +2046,9 @@ MpInitLibInitialize (
CpuMpData->CpuData = (CPU_AP_DATA *) (CpuMpData + 1);
CpuMpData->CpuInfoInHob = (UINT64) (UINTN) (CpuMpData->CpuData + MaxLogicalProcessorNumber);
InitializeSpinLock(&CpuMpData->MpLock);
+ CpuMpData->SevEsIsEnabled = PcdGetBool (PcdSevEsIsEnabled);
+ CpuMpData->SevEsAPBuffer = (UINTN) -1;
+ CpuMpData->GhcbBase = PcdGet64 (PcdGhcbBase);
//
// Make sure no memory usage outside of the allocated buffer.
@@ -1816,6 +2107,7 @@ MpInitLibInitialize (
// APs have been wakeup before, just get the CPU Information
// from HOB
//
+ OldCpuMpData->NewCpuMpData = CpuMpData;
CpuMpData->CpuCount = OldCpuMpData->CpuCount;
CpuMpData->BspNumber = OldCpuMpData->BspNumber;
CpuMpData->CpuInfoInHob = OldCpuMpData->CpuInfoInHob;
@@ -1875,6 +2167,31 @@ MpInitLibInitialize (
}
//
+ // Dump the microcode revision for each core.
+ //
+ DEBUG_CODE (
+ UINT32 ThreadId;
+ UINT32 ExpectedMicrocodeRevision;
+ CpuInfoInHob = (CPU_INFO_IN_HOB *) (UINTN) CpuMpData->CpuInfoInHob;
+ for (Index = 0; Index < CpuMpData->CpuCount; Index++) {
+ GetProcessorLocationByApicId (CpuInfoInHob[Index].InitialApicId, NULL, NULL, &ThreadId);
+ if (ThreadId == 0) {
+ //
+ // MicrocodeDetect() loads microcode in first thread of each core, so,
+ // CpuMpData->CpuData[Index].MicrocodeEntryAddr is initialized only for first thread of each core.
+ //
+ ExpectedMicrocodeRevision = 0;
+ if (CpuMpData->CpuData[Index].MicrocodeEntryAddr != 0) {
+ ExpectedMicrocodeRevision = ((CPU_MICROCODE_HEADER *)(UINTN)CpuMpData->CpuData[Index].MicrocodeEntryAddr)->UpdateRevision;
+ }
+ DEBUG ((
+ DEBUG_INFO, "CPU[%04d]: Microcode revision = %08x, expected = %08x\n",
+ Index, CpuMpData->CpuData[Index].MicrocodeRevision, ExpectedMicrocodeRevision
+ ));
+ }
+ }
+ );
+ //
// Initialize global data for MP support
//
InitMpGlobalData (CpuMpData);
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 0f3b549b3d7..aea1d27e1da 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -1,7 +1,7 @@
/** @file
Common header file for MP Initialize Library.
- Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -32,6 +32,7 @@
#include <Library/MtrrLib.h>
#include <Library/HobLib.h>
#include <Library/PcdLib.h>
+#include <Library/MicrocodeLib.h>
#include <Guid/MicrocodePatchHob.h>
@@ -144,6 +145,7 @@ typedef struct {
UINT32 ProcessorSignature;
UINT8 PlatformId;
UINT64 MicrocodeEntryAddr;
+ UINT32 MicrocodeRevision;
} CPU_AP_DATA;
//
@@ -173,6 +175,11 @@ typedef struct {
UINT8 *RelocateApLoopFuncAddress;
UINTN RelocateApLoopFuncSize;
UINTN ModeTransitionOffset;
+ UINTN SwitchToRealSize;
+ UINTN SwitchToRealOffset;
+ UINTN SwitchToRealNoNxOffset;
+ UINTN SwitchToRealPM16ModeOffset;
+ UINTN SwitchToRealPM16ModeSize;
} MP_ASSEMBLY_ADDRESS_MAP;
typedef struct _CPU_MP_DATA CPU_MP_DATA;
@@ -185,7 +192,6 @@ typedef struct _CPU_MP_DATA CPU_MP_DATA;
// into this structure are used in assembly code in this module
//
typedef struct {
- UINTN Lock;
UINTN StackStart;
UINTN StackSize;
UINTN CFunction;
@@ -211,6 +217,8 @@ typedef struct {
// Enable5LevelPaging indicates whether 5-level paging is enabled in long mode.
//
BOOLEAN Enable5LevelPaging;
+ BOOLEAN SevEsIsEnabled;
+ UINTN GhcbBase;
} MP_CPU_EXCHANGE_INFO;
#pragma pack()
@@ -257,6 +265,7 @@ struct _CPU_MP_DATA {
UINT8 ApLoopMode;
UINT8 ApTargetCState;
UINT16 PmCodeSegment;
+ UINT16 Pm16CodeSegment;
CPU_AP_DATA *CpuData;
volatile MP_CPU_EXCHANGE_INFO *MpCpuExchangeInfo;
@@ -276,8 +285,50 @@ struct _CPU_MP_DATA {
// driver.
//
BOOLEAN WakeUpByInitSipiSipi;
+
+ BOOLEAN SevEsIsEnabled;
+ UINTN SevEsAPBuffer;
+ UINTN SevEsAPResetStackStart;
+ CPU_MP_DATA *NewCpuMpData;
+
+ UINT64 GhcbBase;
};
+#define AP_SAFE_STACK_SIZE 128
+#define AP_RESET_STACK_SIZE AP_SAFE_STACK_SIZE
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 InsnBuffer[8];
+ UINT16 Rip;
+ UINT16 Segment;
+} SEV_ES_AP_JMP_FAR;
+
+#pragma pack()
+
+/**
+ Assembly code to move an AP from long mode to real mode.
+
+ Move an AP from long mode to real mode in preparation to invoking
+ the reset vector. This is used for SEV-ES guests where a hypervisor
+ is not allowed to set the CS and RIP to point to the reset vector.
+
+ @param[in] BufferStart The reset vector target.
+ @param[in] Code16 16-bit protected mode code segment value.
+ @param[in] Code32 32-bit protected mode code segment value.
+ @param[in] StackStart The start of a stack to be used for transitioning
+ from long mode to real mode.
+**/
+typedef
+VOID
+(EFIAPI AP_RESET) (
+ IN UINTN BufferStart,
+ IN UINT16 Code16,
+ IN UINT16 Code32,
+ IN UINTN StackStart
+ );
+
extern EFI_GUID mCpuInitMpLibHobGuid;
/**
@@ -301,7 +352,10 @@ VOID
IN UINTN ApTargetCState,
IN UINTN PmCodeSegment,
IN UINTN TopOfApStack,
- IN UINTN NumberToFinish
+ IN UINTN NumberToFinish,
+ IN UINTN Pm16CodeSegment,
+ IN UINTN SevEsAPJumpTable,
+ IN UINTN WakeupBuffer
);
/**
@@ -384,6 +438,19 @@ GetModeTransitionBuffer (
);
/**
+ Return the address of the SEV-ES AP jump table.
+
+ This buffer is required in order for an SEV-ES guest to transition from
+ UEFI into an OS.
+
+ @return Return SEV-ES AP jump table buffer
+**/
+UINTN
+GetSevEsAPMemory (
+ VOID
+ );
+
+/**
This function will be called by BSP to wakeup AP.
@param[in] CpuMpData Pointer to CPU MP Data
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
index 54e2ab4c42a..bd9a6b5fffb 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
@@ -1,7 +1,7 @@
## @file
# MP Initialize Library instance for PEI driver.
#
-# Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -22,14 +22,13 @@
#
[Sources.IA32]
- Ia32/MpEqu.inc
Ia32/MpFuncs.nasm
[Sources.X64]
- X64/MpEqu.inc
X64/MpFuncs.nasm
[Sources.common]
+ MpEqu.inc
PeiMpLib.c
MpLib.c
MpLib.h
@@ -51,6 +50,8 @@
SynchronizationLib
PeiServicesLib
PcdLib
+ VmgExitLib
+ MicrocodeLib
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## CONSUMES
@@ -61,6 +62,9 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuMicrocodePatchRegionSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApLoopMode ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuApTargetCstate ## SOMETIMES_CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled ## CONSUMES
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
[Ppis]
gEdkiiPeiShadowMicrocodePpiGuid ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
index b39b9993936..4ee7ef6ac42 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
@@ -281,6 +281,25 @@ GetModeTransitionBuffer (
}
/**
+ Return the address of the SEV-ES AP jump table.
+
+ This buffer is required in order for an SEV-ES guest to transition from
+ UEFI into an OS.
+
+ @return Return SEV-ES AP jump table buffer
+**/
+UINTN
+GetSevEsAPMemory (
+ VOID
+ )
+{
+ //
+ // PEI phase doesn't need to do such transition. So simply return 0.
+ //
+ return 0;
+}
+
+/**
Checks APs status and updates APs status if needed.
**/
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc
deleted file mode 100644
index 6f16116c7ba..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpEqu.inc
+++ /dev/null
@@ -1,43 +0,0 @@
-;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Module Name:
-;
-; MpEqu.inc
-;
-; Abstract:
-;
-; This is the equates file for Multiple Processor support
-;
-;-------------------------------------------------------------------------------
-
-VacantFlag equ 00h
-NotVacantFlag equ 0ffh
-
-CPU_SWITCH_STATE_IDLE equ 0
-CPU_SWITCH_STATE_STORED equ 1
-CPU_SWITCH_STATE_LOADED equ 2
-
-LockLocation equ (RendezvousFunnelProcEnd - RendezvousFunnelProcStart)
-StackStartAddressLocation equ LockLocation + 08h
-StackSizeLocation equ LockLocation + 10h
-ApProcedureLocation equ LockLocation + 18h
-GdtrLocation equ LockLocation + 20h
-IdtrLocation equ LockLocation + 2Ah
-BufferStartLocation equ LockLocation + 34h
-ModeOffsetLocation equ LockLocation + 3Ch
-ApIndexLocation equ LockLocation + 44h
-CodeSegmentLocation equ LockLocation + 4Ch
-DataSegmentLocation equ LockLocation + 54h
-EnableExecuteDisableLocation equ LockLocation + 5Ch
-Cr3Location equ LockLocation + 64h
-InitFlagLocation equ LockLocation + 6Ch
-CpuInfoLocation equ LockLocation + 74h
-NumApsExecutingLocation equ LockLocation + 7Ch
-InitializeFloatingPointUnitsAddress equ LockLocation + 8Ch
-ModeTransitionMemoryLocation equ LockLocation + 94h
-ModeTransitionSegmentLocation equ LockLocation + 98h
-ModeHighMemoryLocation equ LockLocation + 9Ah
-ModeHighSegmentLocation equ LockLocation + 9Eh
-Enable5LevelPagingLocation equ LockLocation + 0A0h
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index 2a01628cc38..cfc3085d012 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -1,5 +1,5 @@
;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -43,21 +43,21 @@ BITS 16
mov fs, ax
mov gs, ax
- mov si, BufferStartLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (BufferStart)
mov ebx, [si]
- mov si, DataSegmentLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (DataSegment)
mov edx, [si]
;
; Get start address of 32-bit code in low memory (<1MB)
;
- mov edi, ModeTransitionMemoryLocation
+ mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeTransitionMemory)
- mov si, GdtrLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (GdtrProfile)
o32 lgdt [cs:si]
- mov si, IdtrLocation
+ mov si, MP_CPU_EXCHANGE_INFO_FIELD (IdtrProfile)
o32 lidt [cs:si]
;
@@ -85,7 +85,7 @@ Flat32Start: ; protected mode entry point
;
; Enable execute disable bit
;
- mov esi, EnableExecuteDisableLocation
+ mov esi, MP_CPU_EXCHANGE_INFO_FIELD (EnableExecuteDisable)
cmp byte [ebx + esi], 0
jz SkipEnableExecuteDisableBit
@@ -101,7 +101,7 @@ SkipEnableExecuteDisableBit:
mov eax, cr4
bts eax, 5
- mov esi, Enable5LevelPagingLocation
+ mov esi, MP_CPU_EXCHANGE_INFO_FIELD (Enable5LevelPaging)
cmp byte [ebx + esi], 0
jz SkipEnable5LevelPaging
@@ -117,7 +117,7 @@ SkipEnable5LevelPaging:
;
; Load page table
;
- mov esi, Cr3Location ; Save CR3 in ecx
+ mov esi, MP_CPU_EXCHANGE_INFO_FIELD (Cr3) ; Save CR3 in ecx
mov ecx, [ebx + esi]
mov cr3, ecx ; Load CR3
@@ -139,54 +139,132 @@ SkipEnable5LevelPaging:
;
; Far jump to 64-bit code
;
- mov edi, ModeHighMemoryLocation
+ mov edi, MP_CPU_EXCHANGE_INFO_FIELD (ModeHighMemory)
add edi, ebx
jmp far [edi]
BITS 64
LongModeStart:
mov esi, ebx
- lea edi, [esi + InitFlagLocation]
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitFlag)]
cmp qword [edi], 1 ; ApInitConfig
jnz GetApicId
; Increment the number of APs executing here as early as possible
; This is decremented in C code when AP is finished executing
mov edi, esi
- add edi, NumApsExecutingLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (NumApsExecuting)
lock inc dword [edi]
; AP init
mov edi, esi
- add edi, LockLocation
- mov rax, NotVacantFlag
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (ApIndex)
+ mov ebx, 1
+ lock xadd dword [edi], ebx ; EBX = ApIndex++
+ inc ebx ; EBX is CpuNumber
-TestLock:
- xchg qword [edi], rax
- cmp rax, NotVacantFlag
- jz TestLock
-
- lea ecx, [esi + ApIndexLocation]
- inc dword [ecx]
- mov ebx, [ecx]
-
-Releaselock:
- mov rax, VacantFlag
- xchg qword [edi], rax
; program stack
mov edi, esi
- add edi, StackSizeLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackSize)
mov eax, dword [edi]
mov ecx, ebx
inc ecx
mul ecx ; EAX = StackSize * (CpuNumber + 1)
mov edi, esi
- add edi, StackStartAddressLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (StackStart)
add rax, qword [edi]
mov rsp, rax
+
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
+ cmp byte [edi], 1 ; SevEsIsEnabled
+ jne CProcedureInvoke
+
+ ;
+ ; program GHCB
+ ; Each page after the GHCB is a per-CPU page, so the calculation programs
+ ; a GHCB to be every 8KB.
+ ;
+ mov eax, SIZE_4KB
+ shl eax, 1 ; EAX = SIZE_4K * 2
+ mov ecx, ebx
+ mul ecx ; EAX = SIZE_4K * 2 * CpuNumber
+ mov edi, esi
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (GhcbBase)
+ add rax, qword [edi]
+ mov rdx, rax
+ shr rdx, 32
+ mov rcx, 0xc0010130
+ wrmsr
jmp CProcedureInvoke
GetApicId:
+ lea edi, [esi + MP_CPU_EXCHANGE_INFO_FIELD (SevEsIsEnabled)]
+ cmp byte [edi], 1 ; SevEsIsEnabled
+ jne DoCpuid
+
+ ;
+ ; Since we don't have a stack yet, we can't take a #VC
+ ; exception. Use the GHCB protocol to perform the CPUID
+ ; calls.
+ ;
+ mov rcx, 0xc0010130
+ rdmsr
+ shl rdx, 32
+ or rax, rdx
+ mov rdi, rax ; RDI now holds the original GHCB GPA
+
+ mov rdx, 0 ; CPUID function 0
+ mov rax, 0 ; RAX register requested
+ or rax, 4
+ wrmsr
+ rep vmmcall
+ rdmsr
+ cmp edx, 0bh
+ jb NoX2ApicSevEs ; CPUID level below CPUID_EXTENDED_TOPOLOGY
+
+ mov rdx, 0bh ; CPUID function 0x0b
+ mov rax, 040000000h ; RBX register requested
+ or rax, 4
+ wrmsr
+ rep vmmcall
+ rdmsr
+ test edx, 0ffffh
+ jz NoX2ApicSevEs ; CPUID.0BH:EBX[15:0] is zero
+
+ mov rdx, 0bh ; CPUID function 0x0b
+ mov rax, 0c0000000h ; RDX register requested
+ or rax, 4
+ wrmsr
+ rep vmmcall
+ rdmsr
+
+ ; Processor is x2APIC capable; 32-bit x2APIC ID is now in EDX
+ jmp RestoreGhcb
+
+NoX2ApicSevEs:
+ ; Processor is not x2APIC capable, so get 8-bit APIC ID
+ mov rdx, 1 ; CPUID function 1
+ mov rax, 040000000h ; RBX register requested
+ or rax, 4
+ wrmsr
+ rep vmmcall
+ rdmsr
+ shr edx, 24
+
+RestoreGhcb:
+ mov rbx, rdx ; Save x2APIC/APIC ID
+
+ mov rdx, rdi ; RDI holds the saved GHCB GPA
+ shr rdx, 32
+ mov eax, edi
+ wrmsr
+
+ mov rdx, rbx
+
+ ; x2APIC ID or APIC ID is in EDX
+ jmp GetProcessorNumber
+
+DoCpuid:
mov eax, 0
cpuid
cmp eax, 0bh
@@ -214,18 +292,18 @@ GetProcessorNumber:
; Note that BSP may become an AP due to SwitchBsp()
;
xor ebx, ebx
- lea eax, [esi + CpuInfoLocation]
- mov edi, [eax]
+ lea eax, [esi + MP_CPU_EXCHANGE_INFO_FIELD (CpuInfo)]
+ mov rdi, [eax]
GetNextProcNumber:
- cmp dword [edi], edx ; APIC ID match?
+ cmp dword [rdi + CPU_INFO_IN_HOB.InitialApicId], edx ; APIC ID match?
jz ProgramStack
- add edi, 20
+ add rdi, CPU_INFO_IN_HOB_size
inc ebx
jmp GetNextProcNumber
ProgramStack:
- mov rsp, qword [edi + 12]
+ mov rsp, qword [rdi + CPU_INFO_IN_HOB.ApTopOfStack]
CProcedureInvoke:
push rbp ; Push BIST data at top of AP stack
@@ -233,17 +311,17 @@ CProcedureInvoke:
push rbp
mov rbp, rsp
- mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
+ mov rax, qword [esi + MP_CPU_EXCHANGE_INFO_FIELD (InitializeFloatingPointUnits)]
sub rsp, 20h
call rax ; Call assembly function to initialize FPU per UEFI spec
add rsp, 20h
mov edx, ebx ; edx is ApIndex
mov ecx, esi
- add ecx, LockLocation ; rcx is address of exchange info data buffer
+ add ecx, MP_CPU_EXCHANGE_INFO_OFFSET ; rcx is address of exchange info data buffer
mov edi, esi
- add edi, ApProcedureLocation
+ add edi, MP_CPU_EXCHANGE_INFO_FIELD (CFunction)
mov rax, qword [edi]
sub rsp, 20h
@@ -254,31 +332,251 @@ CProcedureInvoke:
RendezvousFunnelProcEnd:
;-------------------------------------------------------------------------------------
-; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish);
+;SwitchToRealProc procedure follows.
+;ALSO THIS PROCEDURE IS EXECUTED BY APs TRANSITIONING TO 16 BIT MODE. HENCE THIS PROC
+;IS IN MACHINE CODE.
+; SwitchToRealProc (UINTN BufferStart, UINT16 Code16, UINT16 Code32, UINTN StackStart)
+; rcx - Buffer Start
+; rdx - Code16 Selector Offset
+; r8 - Code32 Selector Offset
+; r9 - Stack Start
+;-------------------------------------------------------------------------------------
+global ASM_PFX(SwitchToRealProc)
+ASM_PFX(SwitchToRealProc):
+SwitchToRealProcStart:
+BITS 64
+ cli
+
+ ;
+ ; Get RDX reset value before changing stacks since the
+ ; new stack won't be able to accomodate a #VC exception.
+ ;
+ push rax
+ push rbx
+ push rcx
+ push rdx
+
+ mov rax, 1
+ cpuid
+ mov rsi, rax ; Save off the reset value for RDX
+
+ pop rdx
+ pop rcx
+ pop rbx
+ pop rax
+
+ ;
+ ; Establish stack below 1MB
+ ;
+ mov rsp, r9
+
+ ;
+ ; Push ultimate Reset Vector onto the stack
+ ;
+ mov rax, rcx
+ shr rax, 4
+ push word 0x0002 ; RFLAGS
+ push ax ; CS
+ push word 0x0000 ; RIP
+ push word 0x0000 ; For alignment, will be discarded
+
+ ;
+ ; Get address of "16-bit operand size" label
+ ;
+ lea rbx, [PM16Mode]
+
+ ;
+ ; Push addresses used to change to compatibility mode
+ ;
+ lea rax, [CompatMode]
+ push r8
+ push rax
+
+ ;
+ ; Clear R8 - R15, for reset, before going into 32-bit mode
+ ;
+ xor r8, r8
+ xor r9, r9
+ xor r10, r10
+ xor r11, r11
+ xor r12, r12
+ xor r13, r13
+ xor r14, r14
+ xor r15, r15
+
+ ;
+ ; Far return into 32-bit mode
+ ;
+o64 retf
+
+BITS 32
+CompatMode:
+ ;
+ ; Set up stack to prepare for exiting protected mode
+ ;
+ push edx ; Code16 CS
+ push ebx ; PM16Mode label address
+
+ ;
+ ; Disable paging
+ ;
+ mov eax, cr0 ; Read CR0
+ btr eax, 31 ; Set PG=0
+ mov cr0, eax ; Write CR0
+
+ ;
+ ; Disable long mode
+ ;
+ mov ecx, 0c0000080h ; EFER MSR number
+ rdmsr ; Read EFER
+ btr eax, 8 ; Set LME=0
+ wrmsr ; Write EFER
+
+ ;
+ ; Disable PAE
+ ;
+ mov eax, cr4 ; Read CR4
+ btr eax, 5 ; Set PAE=0
+ mov cr4, eax ; Write CR4
+
+ mov edx, esi ; Restore RDX reset value
+
+ ;
+ ; Switch to 16-bit operand size
+ ;
+ retf
+
+BITS 16
+ ;
+ ; At entry to this label
+ ; - RDX will have its reset value
+ ; - On the top of the stack
+ ; - Alignment data (two bytes) to be discarded
+ ; - IP for Real Mode (two bytes)
+ ; - CS for Real Mode (two bytes)
+ ;
+ ; This label is also used with AsmRelocateApLoop. During MP finalization,
+ ; the code from PM16Mode to SwitchToRealProcEnd is copied to the start of
+ ; the WakeupBuffer, allowing a parked AP to be booted by an OS.
+ ;
+PM16Mode:
+ mov eax, cr0 ; Read CR0
+ btr eax, 0 ; Set PE=0
+ mov cr0, eax ; Write CR0
+
+ pop ax ; Discard alignment data
+
+ ;
+ ; Clear registers (except RDX and RSP) before going into 16-bit mode
+ ;
+ xor eax, eax
+ xor ebx, ebx
+ xor ecx, ecx
+ xor esi, esi
+ xor edi, edi
+ xor ebp, ebp
+
+ iret
+
+SwitchToRealProcEnd:
+
+;-------------------------------------------------------------------------------------
+; AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
;-------------------------------------------------------------------------------------
global ASM_PFX(AsmRelocateApLoop)
ASM_PFX(AsmRelocateApLoop):
AsmRelocateApLoopStart:
+BITS 64
+ cmp qword [rsp + 56], 0 ; SevEsAPJumpTable
+ je NoSevEs
+
+ ;
+ ; Perform some SEV-ES related setup before leaving 64-bit mode
+ ;
+ push rcx
+ push rdx
+
+ ;
+ ; Get the RDX reset value using CPUID
+ ;
+ mov rax, 1
+ cpuid
+ mov rsi, rax ; Save off the reset value for RDX
+
+ ;
+ ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call
+ ; - Must be done while in 64-bit long mode so that writes to
+ ; the GHCB memory will be unencrypted.
+ ; - No NAE events can be generated once this is set otherwise
+ ; the AP_RESET_HOLD SW_EXITCODE will be overwritten.
+ ;
+ mov rcx, 0xc0010130
+ rdmsr ; Retrieve current GHCB address
+ shl rdx, 32
+ or rdx, rax
+
+ mov rdi, rdx
+ xor rax, rax
+ mov rcx, 0x800
+ shr rcx, 3
+ rep stosq ; Clear the GHCB
+
+ mov rax, 0x80000004 ; VMGEXIT AP_RESET_HOLD
+ mov [rdx + 0x390], rax
+ mov rax, 114 ; Set SwExitCode valid bit
+ bts [rdx + 0x3f0], rax
+ inc rax ; Set SwExitInfo1 valid bit
+ bts [rdx + 0x3f0], rax
+ inc rax ; Set SwExitInfo2 valid bit
+ bts [rdx + 0x3f0], rax
+
+ pop rdx
+ pop rcx
+
+NoSevEs:
cli ; Disable interrupt before switching to 32-bit mode
mov rax, [rsp + 40] ; CountTofinish
lock dec dword [rax] ; (*CountTofinish)--
- mov rsp, r9
- push rcx
- push rdx
- lea rsi, [PmEntry] ; rsi <- The start address of transition code
+ mov r10, [rsp + 48] ; Pm16CodeSegment
+ mov rax, [rsp + 56] ; SevEsAPJumpTable
+ mov rbx, [rsp + 64] ; WakeupBuffer
+ mov rsp, r9 ; TopOfApStack
+
+ push rax ; Save SevEsAPJumpTable
+ push rbx ; Save WakeupBuffer
+ push r10 ; Save Pm16CodeSegment
+ push rcx ; Save MwaitSupport
+ push rdx ; Save ApTargetCState
+
+ lea rax, [PmEntry] ; rax <- The start address of transition code
push r8
- push rsi
- DB 0x48
- retf
+ push rax
+
+ ;
+ ; Clear R8 - R15, for reset, before going into 32-bit mode
+ ;
+ xor r8, r8
+ xor r9, r9
+ xor r10, r10
+ xor r11, r11
+ xor r12, r12
+ xor r13, r13
+ xor r14, r14
+ xor r15, r15
+
+ ;
+ ; Far return into 32-bit mode
+ ;
+o64 retf
+
BITS 32
PmEntry:
mov eax, cr0
btr eax, 31 ; Clear CR0.PG
mov cr0, eax ; Disable paging and caches
- mov ebx, edx ; Save EntryPoint to rbx, for rdmsr will overwrite rdx
mov ecx, 0xc0000080
rdmsr
and ah, ~ 1 ; Clear LME
@@ -291,6 +589,8 @@ PmEntry:
add esp, 4
pop ecx,
add esp, 4
+
+MwaitCheck:
cmp cl, 1 ; Check mwait-monitor support
jnz HltLoop
mov ebx, edx ; Save C-State to ebx
@@ -304,10 +604,50 @@ MwaitLoop:
shl eax, 4
mwait
jmp MwaitLoop
+
HltLoop:
+ pop edx ; PM16CodeSegment
+ add esp, 4
+ pop ebx ; WakeupBuffer
+ add esp, 4
+ pop eax ; SevEsAPJumpTable
+ add esp, 4
+ cmp eax, 0 ; Check for SEV-ES
+ je DoHlt
+
+ cli
+ ;
+ ; SEV-ES is enabled, use VMGEXIT (GHCB information already
+ ; set by caller)
+ ;
+BITS 64
+ rep vmmcall
+BITS 32
+
+ ;
+ ; Back from VMGEXIT AP_HLT_LOOP
+ ; Push the FLAGS/CS/IP values to use
+ ;
+ push word 0x0002 ; EFLAGS
+ xor ecx, ecx
+ mov cx, [eax + 2] ; CS
+ push cx
+ mov cx, [eax] ; IP
+ push cx
+ push word 0x0000 ; For alignment, will be discarded
+
+ push edx
+ push ebx
+
+ mov edx, esi ; Restore RDX reset value
+
+ retf
+
+DoHlt:
cli
hlt
- jmp HltLoop
+ jmp DoHlt
+
BITS 64
AsmRelocateApLoopEnd:
@@ -317,13 +657,18 @@ AsmRelocateApLoopEnd:
global ASM_PFX(AsmGetAddressMap)
ASM_PFX(AsmGetAddressMap):
lea rax, [ASM_PFX(RendezvousFunnelProc)]
- mov qword [rcx], rax
- mov qword [rcx + 8h], LongModeStart - RendezvousFunnelProcStart
- mov qword [rcx + 10h], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelAddress], rax
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeEntryOffset], LongModeStart - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RendezvousFunnelSize], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
lea rax, [ASM_PFX(AsmRelocateApLoop)]
- mov qword [rcx + 18h], rax
- mov qword [rcx + 20h], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
- mov qword [rcx + 28h], Flat32Start - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncAddress], rax
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.RelocateApLoopFuncSize], AsmRelocateApLoopEnd - AsmRelocateApLoopStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.ModeTransitionOffset], Flat32Start - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealSize], SwitchToRealProcEnd - SwitchToRealProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealOffset], SwitchToRealProcStart - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealNoNxOffset], SwitchToRealProcStart - Flat32Start
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeOffset], PM16Mode - RendezvousFunnelProcStart
+ mov qword [rcx + MP_ASSEMBLY_ADDRESS_MAP.SwitchToRealPM16ModeSize], SwitchToRealProcEnd - PM16Mode
ret
;-------------------------------------------------------------------------------------
@@ -366,18 +711,18 @@ ASM_PFX(AsmExchangeRole):
;Store EFLAGS, GDTR and IDTR regiter to stack
pushfq
- sgdt [rsi + 16]
- sidt [rsi + 26]
+ sgdt [rsi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
+ sidt [rsi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; Store the its StackPointer
- mov [rsi + 8], rsp
+ mov [rsi + CPU_EXCHANGE_ROLE_INFO.StackPointer], rsp
; update its switch state to STORED
- mov byte [rsi], CPU_SWITCH_STATE_STORED
+ mov byte [rsi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
WaitForOtherStored:
; wait until the other CPU finish storing its state
- cmp byte [rdi], CPU_SWITCH_STATE_STORED
+ cmp byte [rdi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_STORED
jz OtherStored
pause
jmp WaitForOtherStored
@@ -385,21 +730,21 @@ WaitForOtherStored:
OtherStored:
; Since another CPU already stored its state, load them
; load GDTR value
- lgdt [rdi + 16]
+ lgdt [rdi + CPU_EXCHANGE_ROLE_INFO.Gdtr]
; load IDTR value
- lidt [rdi + 26]
+ lidt [rdi + CPU_EXCHANGE_ROLE_INFO.Idtr]
; load its future StackPointer
- mov rsp, [rdi + 8]
+ mov rsp, [rdi + CPU_EXCHANGE_ROLE_INFO.StackPointer]
; update the other CPU's switch state to LOADED
- mov byte [rdi], CPU_SWITCH_STATE_LOADED
+ mov byte [rdi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
WaitForOtherLoaded:
; wait until the other CPU finish loading new state,
; otherwise the data in stack may corrupt
- cmp byte [rsi], CPU_SWITCH_STATE_LOADED
+ cmp byte [rsi + CPU_EXCHANGE_ROLE_INFO.State], CPU_SWITCH_STATE_LOADED
jz OtherLoaded
pause
jmp WaitForOtherLoaded
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
index 8d138a8a56b..85ae1700adf 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/MtrrLib.c
@@ -5,7 +5,7 @@
Most of services in this library instance are suggested to be invoked by BSP only,
except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.
- Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2008 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -457,31 +457,6 @@ MtrrGetVariableMtrrWorker (
}
/**
- This function will get the raw value in variable MTRRs
-
- @param[out] VariableSettings A buffer to hold variable MTRRs content.
-
- @return The VariableSettings input pointer
-
-**/
-MTRR_VARIABLE_SETTINGS*
-EFIAPI
-MtrrGetVariableMtrr (
- OUT MTRR_VARIABLE_SETTINGS *VariableSettings
- )
-{
- if (!IsMtrrSupported ()) {
- return VariableSettings;
- }
-
- return MtrrGetVariableMtrrWorker (
- NULL,
- GetVariableMtrrCountWorker (),
- VariableSettings
- );
-}
-
-/**
Programs fixed MTRRs registers.
@param[in] Type The memory type to set.
@@ -2583,35 +2558,6 @@ MtrrSetVariableMtrrWorker (
}
}
-
-/**
- This function sets variable MTRRs
-
- @param[in] VariableSettings A buffer to hold variable MTRRs content.
-
- @return The pointer of VariableSettings
-
-**/
-MTRR_VARIABLE_SETTINGS*
-EFIAPI
-MtrrSetVariableMtrr (
- IN MTRR_VARIABLE_SETTINGS *VariableSettings
- )
-{
- MTRR_CONTEXT MtrrContext;
-
- if (!IsMtrrSupported ()) {
- return VariableSettings;
- }
-
- MtrrLibPreMtrrChange (&MtrrContext);
- MtrrSetVariableMtrrWorker (VariableSettings);
- MtrrLibPostMtrrChange (&MtrrContext);
- MtrrDebugPrintAllMtrrs ();
-
- return VariableSettings;
-}
-
/**
Worker function setting fixed MTRRs
@@ -2635,35 +2581,6 @@ MtrrSetFixedMtrrWorker (
/**
- This function sets fixed MTRRs
-
- @param[in] FixedSettings A buffer to hold fixed MTRRs content.
-
- @retval The pointer of FixedSettings
-
-**/
-MTRR_FIXED_SETTINGS*
-EFIAPI
-MtrrSetFixedMtrr (
- IN MTRR_FIXED_SETTINGS *FixedSettings
- )
-{
- MTRR_CONTEXT MtrrContext;
-
- if (!IsMtrrSupported ()) {
- return FixedSettings;
- }
-
- MtrrLibPreMtrrChange (&MtrrContext);
- MtrrSetFixedMtrrWorker (FixedSettings);
- MtrrLibPostMtrrChange (&MtrrContext);
- MtrrDebugPrintAllMtrrs ();
-
- return FixedSettings;
-}
-
-
-/**
This function gets the content in all MTRRs (variable and fixed)
@param[out] MtrrSetting A buffer to hold all MTRRs content.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
new file mode 100644
index 00000000000..d978a1a8017
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
@@ -0,0 +1,1163 @@
+/** @file
+ Unit tests of the MtrrLib instance of the MtrrLib class
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MtrrLibUnitTest.h"
+
+STATIC CONST MTRR_LIB_SYSTEM_PARAMETER mDefaultSystemParameter = {
+ 42, TRUE, TRUE, CacheUncacheable, 12
+};
+
+STATIC MTRR_LIB_SYSTEM_PARAMETER mSystemParameters[] = {
+ { 38, TRUE, TRUE, CacheUncacheable, 12 },
+ { 38, TRUE, TRUE, CacheWriteBack, 12 },
+ { 38, TRUE, TRUE, CacheWriteThrough, 12 },
+ { 38, TRUE, TRUE, CacheWriteProtected, 12 },
+ { 38, TRUE, TRUE, CacheWriteCombining, 12 },
+
+ { 42, TRUE, TRUE, CacheUncacheable, 12 },
+ { 42, TRUE, TRUE, CacheWriteBack, 12 },
+ { 42, TRUE, TRUE, CacheWriteThrough, 12 },
+ { 42, TRUE, TRUE, CacheWriteProtected, 12 },
+ { 42, TRUE, TRUE, CacheWriteCombining, 12 },
+
+ { 48, TRUE, TRUE, CacheUncacheable, 12 },
+ { 48, TRUE, TRUE, CacheWriteBack, 12 },
+ { 48, TRUE, TRUE, CacheWriteThrough, 12 },
+ { 48, TRUE, TRUE, CacheWriteProtected, 12 },
+ { 48, TRUE, TRUE, CacheWriteCombining, 12 },
+};
+
+UINT32 mFixedMtrrsIndex[] = {
+ MSR_IA32_MTRR_FIX64K_00000,
+ MSR_IA32_MTRR_FIX16K_80000,
+ MSR_IA32_MTRR_FIX16K_A0000,
+ MSR_IA32_MTRR_FIX4K_C0000,
+ MSR_IA32_MTRR_FIX4K_C8000,
+ MSR_IA32_MTRR_FIX4K_D0000,
+ MSR_IA32_MTRR_FIX4K_D8000,
+ MSR_IA32_MTRR_FIX4K_E0000,
+ MSR_IA32_MTRR_FIX4K_E8000,
+ MSR_IA32_MTRR_FIX4K_F0000,
+ MSR_IA32_MTRR_FIX4K_F8000
+};
+STATIC_ASSERT (
+ (ARRAY_SIZE (mFixedMtrrsIndex) == MTRR_NUMBER_OF_FIXED_MTRR),
+ "gFixedMtrrIndex does NOT contain all the fixed MTRRs!"
+ );
+
+//
+// Context structure to be used for most of the test cases.
+//
+typedef struct {
+ CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
+} MTRR_LIB_TEST_CONTEXT;
+
+//
+// Context structure to be used for GetFirmwareVariableMtrrCount() test.
+//
+typedef struct {
+ UINT32 NumberOfReservedVariableMtrrs;
+ CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
+} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT;
+
+STATIC CHAR8 *mCacheDescription[] = { "UC", "WC", "N/A", "N/A", "WT", "WP", "WB" };
+
+/**
+ Compare the actual memory ranges against expected memory ranges and return PASS when they match.
+
+ @param ExpectedMemoryRanges Expected memory ranges.
+ @param ExpectedMemoryRangeCount Count of expected memory ranges.
+ @param ActualRanges Actual memory ranges.
+ @param ActualRangeCount Count of actual memory ranges.
+
+ @retval UNIT_TEST_PASSED Test passed.
+ @retval others Test failed.
+**/
+UNIT_TEST_STATUS
+VerifyMemoryRanges (
+ IN MTRR_MEMORY_RANGE *ExpectedMemoryRanges,
+ IN UINTN ExpectedMemoryRangeCount,
+ IN MTRR_MEMORY_RANGE *ActualRanges,
+ IN UINTN ActualRangeCount
+ )
+{
+ UINTN Index;
+ UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualRangeCount);
+ for (Index = 0; Index < ExpectedMemoryRangeCount; Index++) {
+ UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].BaseAddress, ActualRanges[Index].BaseAddress);
+ UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Length, ActualRanges[Index].Length);
+ UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, ActualRanges[Index].Type);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Dump the memory ranges.
+
+ @param Ranges Memory ranges to dump.
+ @param RangeCount Count of memory ranges.
+**/
+VOID
+DumpMemoryRanges (
+ MTRR_MEMORY_RANGE *Ranges,
+ UINTN RangeCount
+ )
+{
+ UINTN Index;
+ for (Index = 0; Index < RangeCount; Index++) {
+ UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a },\n", Ranges[Index].BaseAddress, Ranges[Index].Length, mCacheDescription[Ranges[Index].Type]);
+ }
+}
+
+/**
+**/
+
+/**
+ Generate random count of MTRRs for each cache type.
+
+ @param TotalCount Total MTRR count.
+ @param UcCount Return count of Uncacheable type.
+ @param WtCount Return count of Write Through type.
+ @param WbCount Return count of Write Back type.
+ @param WpCount Return count of Write Protected type.
+ @param WcCount Return count of Write Combining type.
+**/
+VOID
+GenerateRandomMemoryTypeCombination (
+ IN UINT32 TotalCount,
+ OUT UINT32 *UcCount,
+ OUT UINT32 *WtCount,
+ OUT UINT32 *WbCount,
+ OUT UINT32 *WpCount,
+ OUT UINT32 *WcCount
+ )
+{
+ UINTN Index;
+ UINT32 TotalMtrrCount;
+ UINT32 *CountPerType[5];
+
+ CountPerType[0] = UcCount;
+ CountPerType[1] = WtCount;
+ CountPerType[2] = WbCount;
+ CountPerType[3] = WpCount;
+ CountPerType[4] = WcCount;
+
+ //
+ // Initialize the count of each cache type to 0.
+ //
+ for (Index = 0; Index < ARRAY_SIZE (CountPerType); Index++) {
+ *(CountPerType[Index]) = 0;
+ }
+
+ //
+ // Pick a random count of MTRRs
+ //
+ TotalMtrrCount = Random32 (1, TotalCount);
+ for (Index = 0; Index < TotalMtrrCount; Index++) {
+ //
+ // For each of them, pick a random cache type.
+ //
+ (*(CountPerType[Random32 (0, ARRAY_SIZE (CountPerType) - 1)]))++;
+ }
+}
+
+/**
+ Unit test of MtrrLib service MtrrSetMemoryAttribute()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrSetMemoryAttributesInMtrrSettings (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
+ RETURN_STATUS Status;
+ UINT32 UcCount;
+ UINT32 WtCount;
+ UINT32 WbCount;
+ UINT32 WpCount;
+ UINT32 WcCount;
+
+ UINT32 MtrrIndex;
+ UINT8 *Scratch;
+ UINTN ScratchSize;
+ MTRR_SETTINGS LocalMtrrs;
+
+ MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
+ UINT32 ExpectedVariableMtrrUsage;
+ UINTN ExpectedMemoryRangesCount;
+
+ MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
+ UINT32 ActualVariableMtrrUsage;
+ UINTN ActualMemoryRangesCount;
+
+ MTRR_SETTINGS *Mtrrs[2];
+
+ SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) Context;
+ GenerateRandomMemoryTypeCombination (
+ SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs),
+ &UcCount, &WtCount, &WbCount, &WpCount, &WcCount
+ );
+ GenerateValidAndConfigurableMtrrPairs (
+ SystemParameter->PhysicalAddressBits, RawMtrrRange,
+ UcCount, WtCount, WbCount, WpCount, WcCount
+ );
+
+ ExpectedVariableMtrrUsage = UcCount + WtCount + WbCount + WpCount + WcCount;
+ ExpectedMemoryRangesCount = ARRAY_SIZE (ExpectedMemoryRanges);
+ GetEffectiveMemoryRanges (
+ SystemParameter->DefaultCacheType,
+ SystemParameter->PhysicalAddressBits,
+ RawMtrrRange, ExpectedVariableMtrrUsage,
+ ExpectedMemoryRanges, &ExpectedMemoryRangesCount
+ );
+
+ UT_LOG_INFO (
+ "Total MTRR [%d]: UC=%d, WT=%d, WB=%d, WP=%d, WC=%d\n",
+ ExpectedVariableMtrrUsage, UcCount, WtCount, WbCount, WpCount, WcCount
+ );
+ UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRangesCount);
+ DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount);
+
+ //
+ // Default cache type is always an INPUT
+ //
+ ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
+ LocalMtrrs.MtrrDefType = MtrrGetDefaultMemoryType ();
+ ScratchSize = SCRATCH_BUFFER_SIZE;
+ Mtrrs[0] = &LocalMtrrs;
+ Mtrrs[1] = NULL;
+
+ for (MtrrIndex = 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) {
+ Scratch = calloc (ScratchSize, sizeof (UINT8));
+ Status = MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
+ if (Status == RETURN_BUFFER_TOO_SMALL) {
+ Scratch = realloc (Scratch, ScratchSize);
+ Status = MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], Scratch, &ScratchSize, ExpectedMemoryRanges, ExpectedMemoryRangesCount);
+ }
+ UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS);
+
+ if (Mtrrs[MtrrIndex] == NULL) {
+ ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
+ MtrrGetAllMtrrs (&LocalMtrrs);
+ }
+ ActualMemoryRangesCount = ARRAY_SIZE (ActualMemoryRanges);
+ CollectTestResult (
+ SystemParameter->DefaultCacheType, SystemParameter->PhysicalAddressBits, SystemParameter->VariableMtrrCount,
+ &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &ActualVariableMtrrUsage
+ );
+
+ UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRangesCount);
+ DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount);
+ VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ActualMemoryRanges, ActualMemoryRangesCount);
+ UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= ActualVariableMtrrUsage);
+
+ ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
+ }
+
+ free (Scratch);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Test routine to check whether invalid base/size can be rejected.
+
+ @param Context Pointer to MTRR_LIB_SYSTEM_PARAMETER.
+
+ @return Test status.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestInvalidMemoryLayouts (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
+ MTRR_MEMORY_RANGE Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1];
+ UINTN RangeCount;
+ UINT64 MaxAddress;
+ UINT32 Index;
+ UINT64 BaseAddress;
+ UINT64 Length;
+ RETURN_STATUS Status;
+ UINTN ScratchSize;
+
+ SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) Context;
+
+ RangeCount = Random32 (1, ARRAY_SIZE (Ranges));
+ MaxAddress = 1ull << SystemParameter->PhysicalAddressBits;
+
+ for (Index = 0; Index < RangeCount; Index++) {
+ do {
+ BaseAddress = Random64 (0, MaxAddress);
+ Length = Random64 (1, MaxAddress - BaseAddress);
+ } while (((BaseAddress & 0xFFF) == 0) || ((Length & 0xFFF) == 0));
+
+ Ranges[Index].BaseAddress = BaseAddress;
+ Ranges[Index].Length = Length;
+ Ranges[Index].Type = GenerateRandomCacheType ();
+
+ Status = MtrrSetMemoryAttribute (
+ Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Type
+ );
+ UT_ASSERT_TRUE (RETURN_ERROR (Status));
+ }
+
+ ScratchSize = 0;
+ Status = MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, &ScratchSize, Ranges, RangeCount);
+ UT_ASSERT_TRUE (RETURN_ERROR (Status));
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service IsMtrrSupported()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestIsMtrrSupported (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+ //
+ // MTRR capability off in CPUID leaf.
+ //
+ SystemParameter.MtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_ASSERT_FALSE (IsMtrrSupported ());
+
+ //
+ // MTRR capability on in CPUID leaf, but no variable or fixed MTRRs.
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = 0;
+ SystemParameter.FixedMtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_ASSERT_FALSE (IsMtrrSupported ());
+
+ //
+ // MTRR capability on in CPUID leaf, but no variable MTRRs.
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = 0;
+ SystemParameter.FixedMtrrSupported = TRUE;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_ASSERT_FALSE (IsMtrrSupported ());
+
+ //
+ // MTRR capability on in CPUID leaf, but no fixed MTRRs.
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = 7;
+ SystemParameter.FixedMtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_ASSERT_FALSE (IsMtrrSupported ());
+
+ //
+ // MTRR capability on in CPUID leaf with both variable and fixed MTRRs.
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = 7;
+ SystemParameter.FixedMtrrSupported = TRUE;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_ASSERT_TRUE (IsMtrrSupported ());
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service GetVariableMtrrCount()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestGetVariableMtrrCount (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 Result;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+ //
+ // If MTRR capability off in CPUID leaf, then the count is always 0.
+ //
+ SystemParameter.MtrrSupported = FALSE;
+ for (SystemParameter.VariableMtrrCount = 1; SystemParameter.VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) {
+ InitializeMtrrRegs (&SystemParameter);
+ Result = GetVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, 0);
+ }
+
+ //
+ // Try all supported variable MTRR counts.
+ // If variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR, then an ASSERT()
+ // is generated.
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ for (SystemParameter.VariableMtrrCount = 1; SystemParameter.VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR; SystemParameter.VariableMtrrCount++) {
+ InitializeMtrrRegs (&SystemParameter);
+ Result = GetVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount);
+ }
+
+ //
+ // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
+ //
+ SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
+
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = MAX_UINT8;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service GetFirmwareVariableMtrrCount()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestGetFirmwareVariableMtrrCount (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT32 Result;
+ UINT32 ReservedMtrrs;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+
+ InitializeMtrrRegs (&SystemParameter);
+ //
+ // Positive test cases for VCNT = 10 and Reserved PCD in range 0..10
+ //
+ for (ReservedMtrrs = 0; ReservedMtrrs <= SystemParameter.VariableMtrrCount; ReservedMtrrs++) {
+ PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
+ Result = GetFirmwareVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - ReservedMtrrs);
+ }
+
+ //
+ // Negative test cases when Reserved PCD is larger than VCNT
+ //
+ for (ReservedMtrrs = SystemParameter.VariableMtrrCount + 1; ReservedMtrrs <= 255; ReservedMtrrs++) {
+ PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs);
+ Result = GetFirmwareVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, 0);
+ }
+
+ //
+ // Negative test cases when Reserved PCD is larger than VCNT
+ //
+ PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, MAX_UINT32);
+ Result = GetFirmwareVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, 0);
+
+ //
+ // Negative test case when MTRRs are not supported
+ //
+ SystemParameter.MtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2);
+ Result = GetFirmwareVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, 0);
+
+ //
+ // Negative test case when Fixed MTRRs are not supported
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.FixedMtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2);
+ Result = GetFirmwareVariableMtrrCount ();
+ UT_ASSERT_EQUAL (Result, 0);
+
+ //
+ // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
+ //
+ SystemParameter.FixedMtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_EXPECT_ASSERT_FAILURE (GetFirmwareVariableMtrrCount (), NULL);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrGetMemoryAttribute()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrGetMemoryAttribute (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrGetFixedMtrr()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrGetFixedMtrr (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_FIXED_SETTINGS *Result;
+ MTRR_FIXED_SETTINGS ExpectedFixedSettings;
+ MTRR_FIXED_SETTINGS FixedSettings;
+ UINTN Index;
+ UINTN MsrIndex;
+ UINTN ByteIndex;
+ UINT64 MsrValue;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+ InitializeMtrrRegs (&SystemParameter);
+ //
+ // Set random cache type to different ranges under 1MB and make sure
+ // the fixed MTRR settings are expected.
+ // Try 100 times.
+ //
+ for (Index = 0; Index < 100; Index++) {
+ for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); MsrIndex++) {
+ MsrValue = 0;
+ for (ByteIndex = 0; ByteIndex < sizeof (UINT64); ByteIndex++) {
+ MsrValue = MsrValue | LShiftU64 (GenerateRandomCacheType (), ByteIndex * 8);
+ }
+ ExpectedFixedSettings.Mtrr[MsrIndex] = MsrValue;
+ AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue);
+ }
+
+ Result = MtrrGetFixedMtrr (&FixedSettings);
+ UT_ASSERT_EQUAL (Result, &FixedSettings);
+ UT_ASSERT_MEM_EQUAL (&FixedSettings, &ExpectedFixedSettings, sizeof (FixedSettings));
+ }
+
+ //
+ // Negative test case when MTRRs are not supported
+ //
+ SystemParameter.MtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+
+ ZeroMem (&FixedSettings, sizeof (FixedSettings));
+ ZeroMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings));
+ Result = MtrrGetFixedMtrr (&FixedSettings);
+ UT_ASSERT_EQUAL (Result, &FixedSettings);
+ UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings, sizeof (ExpectedFixedSettings));
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrGetAllMtrrs()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrGetAllMtrrs (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_SETTINGS *Result;
+ MTRR_SETTINGS Mtrrs;
+ MTRR_SETTINGS ExpectedMtrrs;
+ MTRR_VARIABLE_SETTING VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ UINT32 Index;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+ InitializeMtrrRegs (&SystemParameter);
+
+ for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
+ GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &VariableMtrr[Index], NULL);
+ AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableMtrr[Index].Base);
+ AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableMtrr[Index].Mask);
+ }
+ Result = MtrrGetAllMtrrs (&Mtrrs);
+ UT_ASSERT_EQUAL (Result, &Mtrrs);
+ UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, sizeof (MTRR_VARIABLE_SETTING) * SystemParameter.VariableMtrrCount);
+
+ //
+ // Negative test case when MTRRs are not supported
+ //
+ ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs));
+ ZeroMem (&Mtrrs, sizeof (Mtrrs));
+
+ SystemParameter.MtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ Result = MtrrGetAllMtrrs (&Mtrrs);
+ UT_ASSERT_EQUAL (Result, &Mtrrs);
+ UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof (ExpectedMtrrs));
+
+ //
+ // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs), NULL);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrSetAllMtrrs()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrSetAllMtrrs (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_SETTINGS *Result;
+ MTRR_SETTINGS Mtrrs;
+ UINT32 Index;
+ MSR_IA32_MTRR_DEF_TYPE_REGISTER Default;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+ InitializeMtrrRegs (&SystemParameter);
+
+ Default.Uint64 = 0;
+ Default.Bits.E = 1;
+ Default.Bits.FE = 1;
+ Default.Bits.Type = GenerateRandomCacheType ();
+
+ ZeroMem (&Mtrrs, sizeof (Mtrrs));
+ Mtrrs.MtrrDefType = Default.Uint64;
+ for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
+ GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &Mtrrs.Variables.Mtrr[Index], NULL);
+ }
+ Result = MtrrSetAllMtrrs (&Mtrrs);
+ UT_ASSERT_EQUAL (Result, &Mtrrs);
+
+ UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE), Mtrrs.MtrrDefType);
+ for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
+ UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1)), Mtrrs.Variables.Mtrr[Index].Base);
+ UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1)), Mtrrs.Variables.Mtrr[Index].Mask);
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrGetMemoryAttributeInVariableMtrr()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrGetMemoryAttributeInVariableMtrr (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ UINT32 Result;
+ MTRR_VARIABLE_SETTING VariableSetting[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ UINT64 ValidMtrrBitsMask;
+ UINT64 ValidMtrrAddressMask;
+ UINT32 Index;
+ MSR_IA32_MTRR_PHYSBASE_REGISTER Base;
+ MSR_IA32_MTRR_PHYSMASK_REGISTER Mask;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+
+ InitializeMtrrRegs (&SystemParameter);
+
+ ValidMtrrBitsMask = (1ull << SystemParameter.PhysicalAddressBits) - 1;
+ ValidMtrrAddressMask = ValidMtrrBitsMask & 0xfffffffffffff000ULL;
+
+ for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
+ GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, GenerateRandomCacheType (), &VariableSetting[Index], NULL);
+ AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSetting[Index].Base);
+ AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSetting[Index].Mask);
+ }
+ Result = MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr);
+ UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount);
+
+ for (Index = 0; Index < SystemParameter.VariableMtrrCount; Index++) {
+ Base.Uint64 = VariableMtrr[Index].BaseAddress;
+ Base.Bits.Type = (UINT32) VariableMtrr[Index].Type;
+ UT_ASSERT_EQUAL (Base.Uint64, VariableSetting[Index].Base);
+
+ Mask.Uint64 = ~(VariableMtrr[Index].Length - 1) & ValidMtrrBitsMask;
+ Mask.Bits.V = 1;
+ UT_ASSERT_EQUAL (Mask.Uint64, VariableSetting[Index].Mask);
+ }
+
+ //
+ // Negative test case when MTRRs are not supported
+ //
+ SystemParameter.MtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ Result = MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr);
+ UT_ASSERT_EQUAL (Result, 0);
+
+ //
+ // Expect ASSERT() if variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR
+ //
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = MTRR_NUMBER_OF_VARIABLE_MTRR + 1;
+ InitializeMtrrRegs (&SystemParameter);
+ UT_EXPECT_ASSERT_FAILURE (MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr), NULL);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrDebugPrintAllMtrrs()
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrDebugPrintAllMtrrs (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrGetDefaultMemoryType().
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrGetDefaultMemoryType (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_LIB_TEST_CONTEXT *LocalContext;
+ UINTN Index;
+ MTRR_MEMORY_CACHE_TYPE Result;
+ MTRR_LIB_SYSTEM_PARAMETER SystemParameter;
+ MTRR_MEMORY_CACHE_TYPE CacheType[5];
+
+ CacheType[0] = CacheUncacheable;
+ CacheType[1] = CacheWriteCombining;
+ CacheType[2] = CacheWriteThrough;
+ CacheType[3] = CacheWriteProtected;
+ CacheType[4] = CacheWriteBack;
+
+ LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
+
+ CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof (SystemParameter));
+ //
+ // If MTRRs are supported, then always return the cache type in the MSR
+ // MSR_IA32_MTRR_DEF_TYPE
+ //
+ for (Index = 0; Index < ARRAY_SIZE (CacheType); Index++) {
+ SystemParameter.DefaultCacheType = CacheType[Index];
+ InitializeMtrrRegs (&SystemParameter);
+ Result = MtrrGetDefaultMemoryType ();
+ UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType);
+ }
+
+ //
+ // If MTRRs are not supported, then always return CacheUncacheable
+ //
+ SystemParameter.MtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ Result = MtrrGetDefaultMemoryType ();
+ UT_ASSERT_EQUAL (Result, CacheUncacheable);
+
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.FixedMtrrSupported = FALSE;
+ InitializeMtrrRegs (&SystemParameter);
+ Result = MtrrGetDefaultMemoryType ();
+ UT_ASSERT_EQUAL (Result, CacheUncacheable);
+
+ SystemParameter.MtrrSupported = TRUE;
+ SystemParameter.FixedMtrrSupported = TRUE;
+ SystemParameter.VariableMtrrCount = 0;
+ InitializeMtrrRegs (&SystemParameter);
+ Result = MtrrGetDefaultMemoryType ();
+ UT_ASSERT_EQUAL (Result, CacheUncacheable);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Unit test of MtrrLib service MtrrSetMemoryAttributeInMtrrSettings().
+
+ @param[in] Context Ignored
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+
+**/
+UNIT_TEST_STATUS
+EFIAPI
+UnitTestMtrrSetMemoryAttributeInMtrrSettings (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
+ RETURN_STATUS Status;
+ UINT32 UcCount;
+ UINT32 WtCount;
+ UINT32 WbCount;
+ UINT32 WpCount;
+ UINT32 WcCount;
+
+ UINTN MtrrIndex;
+ UINTN Index;
+ MTRR_SETTINGS LocalMtrrs;
+
+ MTRR_MEMORY_RANGE RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR];
+ MTRR_MEMORY_RANGE ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
+ UINT32 ExpectedVariableMtrrUsage;
+ UINTN ExpectedMemoryRangesCount;
+
+ MTRR_MEMORY_RANGE ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1];
+ UINT32 ActualVariableMtrrUsage;
+ UINTN ActualMemoryRangesCount;
+
+ MTRR_SETTINGS *Mtrrs[2];
+
+ SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) Context;
+ GenerateRandomMemoryTypeCombination (
+ SystemParameter->VariableMtrrCount - PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs),
+ &UcCount, &WtCount, &WbCount, &WpCount, &WcCount
+ );
+ GenerateValidAndConfigurableMtrrPairs (
+ SystemParameter->PhysicalAddressBits, RawMtrrRange,
+ UcCount, WtCount, WbCount, WpCount, WcCount
+ );
+
+ ExpectedVariableMtrrUsage = UcCount + WtCount + WbCount + WpCount + WcCount;
+ ExpectedMemoryRangesCount = ARRAY_SIZE (ExpectedMemoryRanges);
+ GetEffectiveMemoryRanges (
+ SystemParameter->DefaultCacheType,
+ SystemParameter->PhysicalAddressBits,
+ RawMtrrRange, ExpectedVariableMtrrUsage,
+ ExpectedMemoryRanges, &ExpectedMemoryRangesCount
+ );
+
+ UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", ExpectedMemoryRangesCount);
+ DumpMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount);
+ //
+ // Default cache type is always an INPUT
+ //
+ ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
+ LocalMtrrs.MtrrDefType = MtrrGetDefaultMemoryType ();
+ Mtrrs[0] = &LocalMtrrs;
+ Mtrrs[1] = NULL;
+
+ for (MtrrIndex = 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) {
+ for (Index = 0; Index < ExpectedMemoryRangesCount; Index++) {
+ Status = MtrrSetMemoryAttributeInMtrrSettings (
+ Mtrrs[MtrrIndex],
+ ExpectedMemoryRanges[Index].BaseAddress,
+ ExpectedMemoryRanges[Index].Length,
+ ExpectedMemoryRanges[Index].Type
+ );
+ UT_ASSERT_TRUE (Status == RETURN_SUCCESS || Status == RETURN_OUT_OF_RESOURCES || Status == RETURN_BUFFER_TOO_SMALL);
+ if (Status == RETURN_OUT_OF_RESOURCES || Status == RETURN_BUFFER_TOO_SMALL) {
+ return UNIT_TEST_SKIPPED;
+ }
+ }
+
+ if (Mtrrs[MtrrIndex] == NULL) {
+ ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
+ MtrrGetAllMtrrs (&LocalMtrrs);
+ }
+ ActualMemoryRangesCount = ARRAY_SIZE (ActualMemoryRanges);
+ CollectTestResult (
+ SystemParameter->DefaultCacheType, SystemParameter->PhysicalAddressBits, SystemParameter->VariableMtrrCount,
+ &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, &ActualVariableMtrrUsage
+ );
+ UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", ActualMemoryRangesCount);
+ DumpMemoryRanges (ActualMemoryRanges, ActualMemoryRangesCount);
+ VerifyMemoryRanges (ExpectedMemoryRanges, ExpectedMemoryRangesCount, ActualMemoryRanges, ActualMemoryRangesCount);
+ UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= ActualVariableMtrrUsage);
+
+ ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs));
+ }
+
+ return UNIT_TEST_PASSED;
+}
+
+
+/**
+ Prep routine for UnitTestGetFirmwareVariableMtrrCount().
+
+ @param Context Point to a UINT32 data to save the PcdCpuNumberOfReservedVariableMtrrs.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+SavePcdValue (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context;
+ LocalContext->NumberOfReservedVariableMtrrs = PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Clean up routine for UnitTestGetFirmwareVariableMtrrCount().
+
+ @param Context Point to a UINT32 data to save the PcdCpuNumberOfReservedVariableMtrrs.
+**/
+VOID
+EFIAPI
+RestorePcdValue (
+ UNIT_TEST_CONTEXT Context
+ )
+{
+ MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *LocalContext;
+
+ LocalContext = (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) Context;
+ PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, LocalContext->NumberOfReservedVariableMtrrs);
+}
+
+/**
+ Initialize the unit test framework, suite, and unit tests for the
+ ResetSystemLib and run the ResetSystemLib unit test.
+
+ @param Iteration Iteration of testing MtrrSetMemoryAttributeInMtrrSettings
+ and MtrrSetMemoryAttributesInMtrrSettings using random inputs.
+
+ @retval EFI_SUCCESS All test cases were dispatched.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
+ initialize the unit tests.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+UnitTestingEntry (
+ UINTN Iteration
+ )
+{
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE Framework;
+ UNIT_TEST_SUITE_HANDLE MtrrApiTests;
+ UINTN Index;
+ UINTN SystemIndex;
+ MTRR_LIB_TEST_CONTEXT Context;
+ MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT GetFirmwareVariableMtrrCountContext;
+
+ Context.SystemParameter = &mDefaultSystemParameter;
+ GetFirmwareVariableMtrrCountContext.SystemParameter = &mDefaultSystemParameter;
+ Framework = NULL;
+
+ //
+ // Setup the test framework for running the tests.
+ //
+ Status = InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status = %r\n", Status));
+ goto EXIT;
+ }
+
+ //
+ // --------------Suite-----------Description--------------Name----------Function--------Pre---Post-------------------Context-----------
+ //
+
+ //
+ // Populate the MtrrLib API Unit Test Suite.
+ //
+ Status = CreateUnitTestSuite (&MtrrApiTests, Framework, "MtrrLib API Tests", "MtrrLib.MtrrLib", NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib API Tests\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+ AddTestCase (MtrrApiTests, "Test IsMtrrSupported", "MtrrSupported", UnitTestIsMtrrSupported, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test GetVariableMtrrCount", "GetVariableMtrrCount", UnitTestGetVariableMtrrCount, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test GetFirmwareVariableMtrrCount", "GetFirmwareVariableMtrrCount", UnitTestGetFirmwareVariableMtrrCount, SavePcdValue, RestorePcdValue, &GetFirmwareVariableMtrrCountContext);
+ AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttribute", "MtrrGetMemoryAttribute", UnitTestMtrrGetMemoryAttribute, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", "MtrrGetFixedMtrr", UnitTestMtrrGetFixedMtrr, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs", "MtrrGetAllMtrrs", UnitTestMtrrGetAllMtrrs, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs", "MtrrSetAllMtrrs", UnitTestMtrrSetAllMtrrs, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttributeInVariableMtrr", "MtrrGetMemoryAttributeInVariableMtrr", UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test MtrrDebugPrintAllMtrrs", "MtrrDebugPrintAllMtrrs", UnitTestMtrrDebugPrintAllMtrrs, NULL, NULL, &Context);
+ AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", "MtrrGetDefaultMemoryType", UnitTestMtrrGetDefaultMemoryType, NULL, NULL, &Context);
+
+ for (SystemIndex = 0; SystemIndex < ARRAY_SIZE (mSystemParameters); SystemIndex++) {
+ for (Index = 0; Index < Iteration; Index++) {
+ AddTestCase (MtrrApiTests, "Test InvalidMemoryLayouts", "InvalidMemoryLayouts", UnitTestInvalidMemoryLayouts, InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
+ AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributeInMtrrSettings", "MtrrSetMemoryAttributeInMtrrSettings", UnitTestMtrrSetMemoryAttributeInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
+ AddTestCase (MtrrApiTests, "Test MtrrSetMemoryAttributesInMtrrSettings", "MtrrSetMemoryAttributesInMtrrSettings", UnitTestMtrrSetMemoryAttributesInMtrrSettings, InitializeSystem, NULL, &mSystemParameters[SystemIndex]);
+ }
+ }
+ //
+ // Execute the tests.
+ //
+ Status = RunAllTestSuites (Framework);
+
+EXIT:
+ if (Framework != NULL) {
+ FreeUnitTestFramework (Framework);
+ }
+
+ return Status;
+}
+
+/**
+ Standard POSIX C entry point for host based unit test execution.
+
+ @param Argc Number of arguments.
+ @param Argv Array of arguments.
+
+ @return Test application exit code.
+**/
+INT32
+main (
+ INT32 Argc,
+ CHAR8 *Argv[]
+ )
+{
+ UINTN Count;
+
+ DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION));
+ srand ((unsigned int) time (NULL));
+
+ //
+ // MtrrLibUnitTest generate-random-numbers <path to MtrrLib/UnitTest/RandomNumber.c> <random-number count>
+ //
+ if ((Argc == 4) && (AsciiStriCmp ("generate-random-numbers", Argv[1]) == 0)) {
+ Count = atoi (Argv[3]);
+ DEBUG ((DEBUG_INFO, "Generate %d random numbers to %a.\n", Count, Argv[2]));
+ GenerateRandomNumbers (Argv[2], Count);
+ return 0;
+ }
+
+ //
+ // MtrrLibUnitTest [<iterations>]
+ // <iterations> [fixed|random]
+ // Default <iterations> is 10.
+ // Default uses fixed inputs.
+ //
+ Count = 10;
+ mRandomInput = FALSE;
+ if ((Argc == 2) || (Argc == 3)) {
+ Count = atoi (Argv[1]);
+ if (Argc == 3) {
+ if (AsciiStriCmp ("fixed", Argv[2]) == 0) {
+ mRandomInput = FALSE;
+ } else if (AsciiStriCmp ("random", Argv[2]) == 0) {
+ mRandomInput = TRUE;
+ }
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "Iterations = %d\n", Count));
+ DEBUG ((DEBUG_INFO, "Input = %a\n", mRandomInput ? "random" : "fixed"));
+
+ return UnitTestingEntry (Count);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
new file mode 100644
index 00000000000..ffde1681c2b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
@@ -0,0 +1,195 @@
+/** @file
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _MTRR_SUPPORT_H_
+#define _MTRR_SUPPORT_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <time.h>
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UnitTestLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/UnitTestHostBaseLib.h>
+
+#include <Register/ArchitecturalMsr.h>
+#include <Register/Cpuid.h>
+#include <Register/Msr.h>
+
+#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests"
+#define UNIT_TEST_APP_VERSION "1.0"
+
+#define SCRATCH_BUFFER_SIZE SIZE_16KB
+
+typedef struct {
+ UINT8 PhysicalAddressBits;
+ BOOLEAN MtrrSupported;
+ BOOLEAN FixedMtrrSupported;
+ MTRR_MEMORY_CACHE_TYPE DefaultCacheType;
+ UINT32 VariableMtrrCount;
+} MTRR_LIB_SYSTEM_PARAMETER;
+
+extern UINT32 mFixedMtrrsIndex[];
+extern BOOLEAN mRandomInput;
+
+/**
+ Initialize the MTRR registers.
+
+ @param SystemParameter System parameter that controls the MTRR registers initialization.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+InitializeMtrrRegs (
+ IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
+ );
+
+/**
+ Initialize the MTRR registers.
+
+ @param Context System parameter that controls the MTRR registers initialization.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+InitializeSystem (
+ IN UNIT_TEST_CONTEXT Context
+ );
+
+/**
+ Return a random memory cache type.
+**/
+MTRR_MEMORY_CACHE_TYPE
+GenerateRandomCacheType (
+ VOID
+ );
+
+/**
+ Generate random MTRRs.
+
+ @param PhysicalAddressBits Physical address bits.
+ @param RawMemoryRanges Return the randomly generated MTRRs.
+ @param UcCount Count of Uncacheable MTRRs.
+ @param WtCount Count of Write Through MTRRs.
+ @param WbCount Count of Write Back MTRRs.
+ @param WpCount Count of Write Protected MTRRs.
+ @param WcCount Count of Write Combining MTRRs.
+**/
+VOID
+GenerateValidAndConfigurableMtrrPairs (
+ IN UINT32 PhysicalAddressBits,
+ IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
+ IN UINT32 UcCount,
+ IN UINT32 WtCount,
+ IN UINT32 WbCount,
+ IN UINT32 WpCount,
+ IN UINT32 WcCount
+ );
+
+/**
+ Convert the MTRR BASE/MASK array to memory ranges.
+
+ @param DefaultType Default memory type.
+ @param PhysicalAddressBits Physical address bits.
+ @param RawMemoryRanges Raw memory ranges.
+ @param RawMemoryRangeCount Count of raw memory ranges.
+ @param MemoryRanges Memory ranges.
+ @param MemoryRangeCount Count of memory ranges.
+**/
+VOID
+GetEffectiveMemoryRanges (
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,
+ IN UINT32 PhysicalAddressBits,
+ IN MTRR_MEMORY_RANGE *RawMemoryRanges,
+ IN UINT32 RawMemoryRangeCount,
+ OUT MTRR_MEMORY_RANGE *MemoryRanges,
+ OUT UINTN *MemoryRangeCount
+ );
+
+/**
+ Generate random MTRR BASE/MASK for a specified type.
+
+ @param PhysicalAddressBits Physical address bits.
+ @param CacheType Cache type.
+ @param MtrrPair Return the random MTRR.
+ @param MtrrMemoryRange Return the random memory range.
+**/
+VOID
+GenerateRandomMtrrPair (
+ IN UINT32 PhysicalAddressBits,
+ IN MTRR_MEMORY_CACHE_TYPE CacheType,
+ OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL
+ OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
+ );
+
+/**
+ Collect the test result.
+
+ @param DefaultType Default memory type.
+ @param PhysicalAddressBits Physical address bits.
+ @param VariableMtrrCount Count of variable MTRRs.
+ @param Mtrrs MTRR settings to collect from.
+ @param Ranges Return the memory ranges.
+ @param RangeCount Return the count of memory ranges.
+ @param MtrrCount Return the count of variable MTRRs being used.
+**/
+VOID
+CollectTestResult (
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,
+ IN UINT32 PhysicalAddressBits,
+ IN UINT32 VariableMtrrCount,
+ IN MTRR_SETTINGS *Mtrrs,
+ OUT MTRR_MEMORY_RANGE *Ranges,
+ IN OUT UINTN *RangeCount,
+ OUT UINT32 *MtrrCount
+ );
+
+/**
+ Return a 64bit random number.
+
+ @param Start Start of the random number range.
+ @param Limit Limit of the random number range.
+ @return 64bit random number
+**/
+UINT64
+Random64 (
+ UINT64 Start,
+ UINT64 Limit
+ );
+
+/**
+ Return a 32bit random number.
+
+ @param Start Start of the random number range.
+ @param Limit Limit of the random number range.
+ @return 32bit random number
+**/
+UINT32
+Random32 (
+ UINT32 Start,
+ UINT32 Limit
+ );
+
+/**
+ Generate Count random numbers in FilePath.
+
+ @param FilePath The file path to put the generated random numbers.
+ @param Count Count of random numbers.
+**/
+VOID
+GenerateRandomNumbers (
+ CHAR8 *FilePath,
+ UINTN Count
+ );
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
new file mode 100644
index 00000000000..c3ee21eb938
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
@@ -0,0 +1,43 @@
+## @file
+# Unit tests of the MtrrLib instance of the MtrrLib class
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = MtrrLibUnitTestHost
+ FILE_GUID = A1542D84-B64D-4847-885E-0509084376AB
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ MtrrLibUnitTest.c
+ MtrrLibUnitTest.h
+ Support.c
+ RandomNumber.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MtrrLib
+ UnitTestLib
+
+[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs ## SOMETIMES_CONSUMES
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = -D _CRT_SECURE_NO_WARNINGS
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/RandomNumber.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/RandomNumber.c
new file mode 100644
index 00000000000..e75859f7328
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/RandomNumber.c
@@ -0,0 +1,5009 @@
+/** @file
+ Pre-generated random number used by MtrrLib test.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+UINTN mNumberCount = 50000;
+UINTN mNumbers[] = {
+ 7791, 9427, 6867, 23807, 10984, 16661, 1863, 16690, 14810, 14550,
+ 11382, 15755, 19806, 32737, 209, 14661, 4112, 13680, 2425, 15502,
+ 25268, 2882, 29953, 12346, 27936, 8942, 21365, 17849, 13910, 21879,
+ 3995, 6982, 2032, 6432, 3448, 28770, 8385, 31106, 4630, 32385,
+ 31417, 21979, 22661, 18947, 10249, 22953, 30752, 32613, 2952, 25464,
+ 17, 12473, 28757, 19960, 27672, 1875, 17598, 20306, 22152, 15814,
+ 31841, 25276, 2962, 30223, 23953, 28748, 25029, 16399, 15868, 9993,
+ 31702, 25663, 29322, 15688, 22429, 18079, 30344, 2870, 20065, 30191,
+ 3589, 13233, 27221, 15138, 26492, 20316, 13666, 15632, 180, 19954,
+ 25895, 3179, 21221, 474, 2111, 11252, 2588, 2556, 6338, 26862,
+ 19424, 3540, 6158, 6099, 20758, 32708, 6087, 2375, 22306, 22959,
+ 21532, 19274, 11343, 1987, 17228, 2737, 23409, 30102, 15977, 10455,
+ 15049, 29045, 10077, 22928, 25128, 23033, 12330, 23902, 19543, 18906,
+ 10102, 11240, 10167, 13832, 28230, 8871, 6693, 12792, 31498, 3043,
+ 31776, 20028, 3546, 4574, 20270, 17751, 31231, 29263, 29563, 27343,
+ 10421, 1553, 24772, 4228, 14639, 28957, 26227, 22079, 25052, 3766,
+ 14092, 6030, 30441, 28131, 17095, 27600, 14855, 29218, 9599, 27788,
+ 22382, 27739, 11210, 13831, 13345, 16403, 13162, 22037, 29044, 26850,
+ 27364, 7471, 18892, 29735, 13422, 1478, 10919, 17146, 12302, 9687,
+ 12252, 10338, 12545, 24256, 25635, 14280, 8794, 16210, 27351, 22444,
+ 7915, 19495, 30459, 27799, 16488, 8757, 13180, 12369, 27082, 10148,
+ 181, 2387, 4338, 16093, 11064, 30335, 19343, 12260, 32716, 25359,
+ 9025, 15335, 24754, 30412, 29951, 3863, 16429, 13952, 24502, 1206,
+ 9281, 2221, 1586, 29041, 6074, 29311, 10306, 26609, 11376, 8448,
+ 22295, 11181, 29386, 4747, 18670, 17922, 2689, 29827, 4079, 29061,
+ 12454, 2372, 14420, 20376, 28391, 10842, 4557, 7227, 20494, 15090,
+ 10275, 21541, 15818, 7821, 12060, 276, 27570, 2044, 26016, 8289,
+ 29575, 13448, 13337, 22487, 1721, 26481, 2592, 27845, 22829, 14746,
+ 16213, 12626, 10558, 4482, 31630, 23569, 2306, 22390, 27189, 32213,
+ 19662, 14853, 15595, 2503, 17148, 5813, 16753, 9141, 6379, 23284,
+ 3785, 10413, 4424, 29009, 3480, 9675, 28556, 3820, 24527, 12623,
+ 15558, 29995, 27530, 23026, 18843, 31663, 3385, 8315, 4491, 30343,
+ 13565, 12173, 25462, 19619, 29525, 17859, 29534, 21131, 14585, 1535,
+ 14702, 15697, 19974, 8702, 16955, 16835, 17500, 4912, 21579, 13286,
+ 26948, 21959, 3796, 15008, 31319, 23054, 26053, 27573, 8603, 8189,
+ 7946, 25589, 31982, 12554, 13580, 12211, 13480, 27713, 17016, 6008,
+ 25980, 22679, 23362, 9465, 24991, 29052, 30441, 29767, 3372, 8623,
+ 20476, 9542, 22984, 24662, 23773, 352, 9602, 9294, 17861, 10618,
+ 252, 8640, 31752, 24615, 8400, 1525, 22171, 17436, 32301, 9579,
+ 22483, 3813, 27329, 20520, 111, 11222, 7132, 16462, 21465, 15171,
+ 28882, 22256, 29097, 22004, 30881, 6948, 26731, 9427, 31443, 12121,
+ 9634, 8424, 1958, 12523, 9997, 3975, 21355, 13813, 20776, 3784,
+ 24876, 23911, 3830, 17976, 16529, 9560, 7934, 4046, 25348, 31645,
+ 12691, 11553, 19476, 15514, 15449, 23767, 8471, 5208, 9989, 25697,
+ 23572, 30168, 13668, 25062, 9696, 7335, 21151, 31356, 7046, 19635,
+ 8637, 14494, 748, 17501, 30569, 11995, 12980, 5327, 8438, 13003,
+ 12641, 21648, 7328, 17479, 20411, 24661, 10005, 29913, 17012, 7707,
+ 16948, 25458, 32523, 30322, 6420, 8283, 24561, 30748, 25928, 3438,
+ 21483, 22998, 14689, 3718, 7351, 20086, 21685, 7732, 24818, 24374,
+ 25695, 6836, 5433, 16464, 21895, 24351, 143, 21451, 7396, 31969,
+ 24574, 20116, 6014, 10606, 28033, 13264, 26809, 13361, 20002, 6769,
+ 31119, 6341, 11104, 28935, 32029, 360, 31699, 13273, 7777, 19885,
+ 16147, 18741, 15170, 29041, 12501, 30724, 20688, 16399, 14167, 11425,
+ 31950, 30680, 4351, 32748, 14446, 8637, 1343, 13466, 12379, 6479,
+ 7355, 7887, 24060, 20714, 9390, 10734, 17912, 9772, 393, 28848,
+ 32757, 23212, 5342, 7027, 27558, 1257, 14973, 30933, 14084, 3457,
+ 8413, 1154, 6619, 3236, 189, 20554, 27273, 7111, 30730, 887,
+ 28674, 28573, 3076, 25693, 5400, 20035, 5789, 8242, 24826, 13755,
+ 8993, 17696, 22778, 18075, 32284, 8857, 12179, 18182, 31865, 1003,
+ 25770, 20956, 15847, 30996, 15124, 1582, 28289, 8663, 10073, 19189,
+ 19373, 12047, 7095, 31491, 28740, 3652, 21866, 3385, 11252, 29564,
+ 3883, 3323, 27107, 13651, 15607, 30433, 27285, 12110, 13585, 19887,
+ 21776, 7789, 27210, 31624, 25406, 11263, 7040, 21342, 11666, 6842,
+ 7269, 18093, 23022, 18955, 7041, 9065, 12741, 939, 2427, 28213,
+ 25469, 18291, 1428, 11477, 29463, 2417, 29556, 13542, 7697, 5691,
+ 7721, 21196, 13963, 4483, 3181, 23789, 14762, 17132, 27175, 1821,
+ 9530, 9500, 11061, 2648, 20631, 27411, 19305, 29879, 19661, 28603,
+ 20433, 13725, 4094, 17344, 27964, 14897, 28676, 19873, 30713, 11794,
+ 12376, 12296, 226, 13382, 10034, 27223, 17306, 11379, 15858, 26499,
+ 18962, 22609, 20671, 28453, 26962, 30047, 12654, 11470, 31606, 7893,
+ 20901, 16795, 31478, 3034, 22592, 5130, 25387, 32248, 9715, 21004,
+ 31247, 29645, 3377, 22876, 26437, 29699, 16717, 31246, 15449, 1154,
+ 16608, 18283, 21064, 8675, 16234, 27388, 8259, 19240, 21052, 11749,
+ 28592, 30123, 25749, 11381, 4466, 32085, 14091, 26618, 30826, 25872,
+ 28204, 10970, 23869, 31615, 29798, 29407, 20312, 14316, 13092, 21971,
+ 22322, 25474, 26426, 5197, 3537, 25276, 5251, 20170, 19856, 13085,
+ 23752, 4351, 24607, 28962, 15844, 10094, 19915, 31349, 31526, 29496,
+ 12800, 99, 13815, 12338, 14604, 7824, 31165, 24890, 11045, 18921,
+ 16127, 22220, 10414, 11227, 10697, 976, 31670, 15810, 1874, 5302,
+ 8898, 14501, 20188, 31941, 30924, 11552, 10716, 28080, 7819, 22433,
+ 18267, 28011, 2293, 1240, 32412, 32316, 22787, 6760, 1279, 3349,
+ 24756, 6115, 15141, 6689, 31060, 9205, 21845, 20381, 3838, 31199,
+ 25374, 31465, 1376, 19239, 31294, 7135, 22974, 27022, 2243, 32355,
+ 9785, 19779, 4720, 4667, 27218, 19286, 23906, 29986, 15530, 4207,
+ 20980, 25367, 18955, 13248, 4575, 251, 17836, 30264, 2726, 13659,
+ 11953, 506, 1841, 907, 3826, 15885, 1207, 7412, 5885, 2645,
+ 20194, 7342, 15198, 30658, 10030, 8530, 14110, 20679, 31635, 14601,
+ 6025, 1550, 28771, 21481, 13620, 21354, 16757, 12418, 15935, 12557,
+ 16003, 30387, 13784, 25851, 26321, 29891, 3328, 18622, 26639, 12972,
+ 14482, 5979, 1153, 20410, 26753, 22406, 9309, 24149, 17505, 13842,
+ 5749, 12827, 20777, 25771, 17429, 21555, 25655, 20679, 23599, 4573,
+ 18324, 18138, 14773, 22861, 29562, 21961, 2375, 22713, 275, 1698,
+ 29198, 5041, 14980, 15498, 17896, 25263, 27690, 20727, 31941, 4335,
+ 23331, 16415, 32593, 3200, 1297, 31152, 1235, 23708, 3354, 10689,
+ 2132, 21045, 31284, 3592, 6405, 9936, 10911, 11086, 2523, 32150,
+ 8370, 30497, 17532, 31400, 3291, 18889, 17246, 25780, 14562, 11389,
+ 30509, 1222, 14445, 22486, 7022, 14432, 713, 30339, 15971, 27084,
+ 23015, 63, 46, 25265, 8869, 16640, 19768, 11493, 4687, 24689,
+ 6100, 30082, 21862, 32163, 21792, 9788, 5024, 13055, 16684, 10481,
+ 29999, 5760, 11871, 2434, 3398, 2591, 25622, 27106, 19930, 28814,
+ 20621, 31852, 26790, 6696, 4611, 30842, 16753, 32297, 6937, 15667,
+ 21907, 5146, 30332, 5796, 15542, 24976, 28099, 22803, 9946, 4118,
+ 6043, 18063, 31644, 8040, 4385, 29388, 32439, 2018, 26255, 6446,
+ 7627, 24887, 28443, 6436, 19293, 24934, 8220, 3255, 2847, 18410,
+ 7023, 11619, 4978, 2353, 32025, 31525, 10282, 20048, 11309, 22997,
+ 4753, 7413, 13041, 6326, 23214, 15261, 25148, 6220, 9671, 9735,
+ 17442, 621, 24100, 9704, 8659, 18587, 2070, 25568, 8385, 23697,
+ 26680, 1197, 15105, 22300, 24309, 9887, 5876, 300, 7498, 21323,
+ 550, 29483, 5837, 14724, 4982, 16013, 21743, 17287, 14456, 21929,
+ 3966, 23926, 12823, 9671, 11886, 8, 17535, 6010, 6360, 21374,
+ 7738, 26928, 30019, 32473, 15000, 6151, 16163, 30538, 17237, 19170,
+ 21919, 25578, 13686, 29629, 26519, 27051, 19828, 6973, 24806, 29582,
+ 32412, 2699, 15588, 19223, 31158, 18275, 25135, 5375, 1765, 5736,
+ 27564, 1576, 14030, 30651, 712, 25814, 12028, 20939, 12036, 10779,
+ 5507, 15983, 16048, 22419, 24548, 11826, 11510, 21842, 2353, 21997,
+ 10523, 27675, 29554, 6812, 8962, 12242, 30790, 28522, 242, 28212,
+ 27854, 23054, 25240, 30150, 7366, 4442, 5456, 18699, 245, 27153,
+ 7584, 4602, 13512, 1530, 31237, 27055, 28474, 31026, 755, 18529,
+ 758, 22982, 3095, 12692, 10688, 28033, 10975, 28816, 7953, 27139,
+ 17980, 30993, 19969, 31507, 21415, 16448, 5738, 823, 25954, 8674,
+ 27979, 19073, 28160, 9680, 23658, 4011, 23847, 14759, 9534, 12135,
+ 31125, 12992, 2827, 22000, 7265, 11363, 2127, 28389, 12675, 5687,
+ 29533, 18263, 8599, 1789, 22088, 5665, 2270, 10110, 32258, 24183,
+ 24454, 18882, 1221, 24770, 30507, 131, 23474, 3499, 29085, 19169,
+ 6073, 12150, 5348, 10328, 1464, 15762, 8321, 10478, 18919, 3694,
+ 2039, 19889, 3699, 23438, 13962, 19808, 1385, 19421, 16455, 4457,
+ 16854, 30789, 9284, 32531, 11309, 7805, 1065, 24829, 5608, 30242,
+ 29935, 1223, 12402, 23562, 19688, 24847, 27461, 18389, 4864, 22431,
+ 32079, 16324, 29506, 26596, 7579, 16079, 23710, 26019, 12077, 16625,
+ 11241, 2023, 25646, 27079, 2085, 25662, 7241, 31065, 21507, 10788,
+ 596, 824, 22694, 12992, 11571, 7113, 3498, 14542, 18425, 28640,
+ 8805, 19677, 1361, 31376, 11372, 22970, 25117, 19778, 8025, 19756,
+ 31580, 7685, 29132, 14561, 31569, 4133, 5040, 32681, 25058, 27391,
+ 6592, 25314, 11326, 13075, 16969, 1075, 8130, 22875, 14129, 12158,
+ 15390, 29916, 12600, 271, 6323, 14970, 24702, 15386, 12608, 10000,
+ 15942, 25956, 26046, 4032, 11257, 30272, 12680, 3208, 878, 15293,
+ 23999, 28950, 31848, 13854, 13037, 18398, 2912, 3210, 28136, 873,
+ 7557, 26885, 31738, 23024, 22018, 20639, 16958, 32553, 12415, 19435,
+ 29773, 12385, 11498, 29619, 15898, 18123, 26743, 13802, 17691, 17432,
+ 18405, 26338, 17578, 3399, 5892, 29376, 18858, 18367, 16756, 17196,
+ 20845, 3227, 2223, 11597, 20437, 26181, 23369, 31732, 24762, 19526,
+ 12663, 27159, 10380, 4444, 4815, 8578, 10298, 30669, 10574, 4553,
+ 2130, 24572, 1439, 13185, 8041, 17722, 30874, 2991, 14269, 31966,
+ 9740, 897, 22553, 27544, 13494, 26684, 5113, 9474, 16280, 10102,
+ 9967, 10616, 27759, 7045, 24389, 13866, 19324, 31799, 7140, 23407,
+ 25735, 18372, 24948, 19805, 5412, 14336, 19141, 8854, 9269, 6101,
+ 22638, 30052, 11952, 3313, 25524, 6921, 20898, 10684, 14509, 25936,
+ 13684, 23437, 7077, 8808, 24173, 2333, 15808, 20210, 26233, 30012,
+ 25825, 11865, 1065, 14786, 19147, 15714, 762, 28361, 30598, 13060,
+ 4314, 21017, 6917, 889, 1256, 740, 10757, 6549, 892, 9652,
+ 16952, 14935, 9063, 1185, 6563, 18110, 30844, 32711, 32068, 20445,
+ 10063, 25079, 8953, 12594, 26172, 28077, 21149, 9524, 4011, 13890,
+ 10868, 2091, 10643, 6499, 713, 15684, 1597, 27842, 13525, 27109,
+ 25163, 13323, 18659, 31550, 9208, 29466, 20402, 10785, 8097, 28779,
+ 27419, 28947, 1413, 31698, 18931, 10403, 23753, 3436, 6963, 15866,
+ 12223, 20693, 15446, 14260, 19815, 28827, 9987, 31982, 17462, 13811,
+ 25068, 4768, 31255, 20651, 30966, 17198, 1456, 23392, 16538, 25657,
+ 11494, 28657, 26763, 11963, 11427, 24627, 8601, 23891, 11734, 26343,
+ 23253, 1245, 3004, 25833, 23030, 23366, 20319, 32426, 13051, 24734,
+ 1116, 11743, 25362, 7791, 19176, 7035, 4793, 29006, 19221, 21979,
+ 17187, 4271, 27986, 14145, 27357, 18686, 31793, 4228, 17841, 7147,
+ 4974, 27654, 23499, 15109, 44, 31973, 1050, 4234, 30337, 3702,
+ 26105, 19069, 16437, 2031, 15887, 7162, 18631, 22627, 27251, 10439,
+ 10929, 24308, 532, 20267, 8685, 9028, 31577, 17411, 1976, 29228,
+ 9732, 13586, 15254, 12977, 31836, 26009, 7574, 1843, 3979, 31015,
+ 32215, 3816, 4933, 24755, 9547, 23433, 19626, 7656, 23483, 28491,
+ 26734, 20672, 3852, 22289, 31799, 17236, 32704, 13536, 14150, 26611,
+ 5824, 20115, 1626, 32113, 18520, 29904, 11985, 19905, 10371, 22074,
+ 9489, 15046, 5225, 4840, 8742, 3431, 5414, 9239, 15532, 15074,
+ 24525, 27675, 2288, 5218, 5804, 668, 1106, 5331, 12242, 4350,
+ 20462, 16629, 9423, 21281, 32379, 19887, 20411, 4171, 31090, 167,
+ 6522, 8290, 16755, 32527, 23869, 20831, 3558, 32450, 9548, 16639,
+ 4062, 3471, 9476, 32443, 23618, 25300, 5147, 2555, 16686, 28495,
+ 20268, 135, 2711, 7986, 24943, 4414, 31278, 629, 23495, 1802,
+ 30343, 20336, 7427, 19, 13691, 29609, 28509, 9523, 26059, 9963,
+ 8007, 30123, 7173, 13464, 28520, 31508, 1708, 28479, 3553, 31128,
+ 11667, 625, 28372, 28769, 16522, 5841, 12327, 32338, 14652, 31851,
+ 27269, 32501, 21592, 20295, 5030, 29621, 9711, 19005, 21969, 3406,
+ 19742, 15370, 159, 27009, 2796, 21156, 30465, 22796, 16501, 12491,
+ 16004, 16857, 6217, 481, 5076, 29046, 24335, 32763, 10367, 29637,
+ 20334, 8248, 28156, 16885, 21805, 22866, 4588, 23984, 2968, 14450,
+ 3999, 11414, 31526, 14409, 31450, 10219, 23130, 3676, 26584, 13452,
+ 21991, 25247, 5262, 14120, 9239, 9542, 14132, 14508, 26477, 30424,
+ 5632, 12031, 9354, 22149, 19509, 15856, 20301, 2745, 24668, 1133,
+ 13118, 30705, 4049, 18933, 15149, 22990, 29570, 8271, 23574, 4711,
+ 25076, 19837, 10056, 996, 12935, 4588, 18374, 10313, 17914, 7917,
+ 28398, 23439, 30769, 20841, 29784, 3065, 24374, 1231, 11521, 17573,
+ 31615, 4690, 15785, 18018, 15727, 20562, 27769, 8897, 1054, 9751,
+ 13801, 3439, 31069, 1989, 10465, 22465, 28405, 28300, 19998, 19089,
+ 8496, 8480, 7896, 21065, 667, 24681, 20130, 12605, 29961, 19579,
+ 27793, 11326, 5083, 5576, 8096, 25963, 29567, 20116, 595, 22859,
+ 31287, 28842, 24987, 12825, 13852, 27470, 25338, 25951, 21602, 19826,
+ 21991, 20423, 7645, 24621, 13428, 17197, 7364, 17768, 5934, 15096,
+ 20406, 28379, 8261, 10923, 3578, 312, 8685, 6839, 267, 30629,
+ 1027, 1940, 22356, 7024, 11508, 14095, 5176, 9214, 29147, 30694,
+ 8533, 4869, 20969, 32658, 1290, 8443, 266, 23140, 25142, 19919,
+ 1477, 8659, 9539, 27094, 28260, 27925, 612, 11016, 24918, 12268,
+ 10522, 8812, 3281, 31683, 20733, 9681, 14780, 22265, 953, 447,
+ 1483, 7805, 18519, 1965, 2284, 9627, 5054, 19572, 27106, 2069,
+ 8825, 11012, 9775, 25206, 8122, 24406, 4408, 25763, 15775, 19874,
+ 20132, 29363, 8885, 18897, 19461, 18432, 20667, 29493, 32186, 20606,
+ 26792, 30840, 25364, 11340, 28655, 22482, 5559, 4489, 31489, 28543,
+ 26691, 105, 24851, 29297, 22580, 32136, 23842, 5442, 22279, 18046,
+ 16437, 1900, 11935, 13491, 6371, 3260, 1254, 17013, 29716, 19204,
+ 17079, 26183, 6924, 8209, 25084, 14460, 29349, 5084, 26387, 5893,
+ 24539, 15108, 2423, 15240, 21902, 7548, 20380, 30642, 28548, 30081,
+ 8730, 3021, 16046, 23248, 6670, 19349, 10924, 11797, 3773, 1351,
+ 3218, 22694, 9851, 24316, 26349, 13425, 28364, 7733, 24321, 12340,
+ 16328, 3511, 23381, 1004, 28356, 30105, 27506, 2447, 5166, 22939,
+ 23783, 3581, 26809, 29113, 8592, 11828, 32186, 4352, 27416, 5316,
+ 21714, 28321, 8125, 11140, 6862, 1348, 3155, 5506, 2507, 31902,
+ 30604, 1344, 13982, 20806, 31350, 17181, 19827, 11972, 16965, 30737,
+ 435, 12267, 8019, 4253, 13612, 31082, 1381, 19458, 6764, 25245,
+ 24880, 19378, 22125, 8361, 26396, 14084, 25976, 10183, 16199, 18219,
+ 18243, 14048, 13005, 20329, 13917, 16731, 15943, 5504, 28363, 11059,
+ 11665, 3690, 18420, 2892, 9425, 21321, 9658, 26631, 15028, 25249,
+ 1258, 8724, 2043, 453, 9942, 391, 20535, 21135, 8256, 6446,
+ 10192, 29012, 20346, 29730, 15180, 12055, 32204, 16797, 7118, 15357,
+ 12310, 29451, 13533, 22017, 27318, 100, 20327, 20457, 27820, 18104,
+ 17926, 1145, 9724, 13580, 20097, 2534, 27988, 15204, 31894, 14734,
+ 14575, 12321, 25079, 24549, 24249, 8077, 28562, 10419, 8116, 14773,
+ 31765, 7037, 666, 21111, 5042, 15424, 16836, 10203, 29984, 9318,
+ 20554, 25255, 24546, 10226, 14956, 1325, 6091, 23294, 25905, 15464,
+ 16834, 2919, 29005, 18247, 32195, 711, 17736, 26697, 25126, 9379,
+ 733, 5450, 15396, 15590, 27553, 22941, 14743, 4750, 30949, 7770,
+ 24577, 4774, 10972, 19705, 29904, 10100, 21249, 32, 15072, 4083,
+ 23987, 14010, 10562, 19332, 24354, 15689, 32572, 28128, 26479, 16765,
+ 22928, 28497, 25103, 17413, 11521, 19746, 1137, 23717, 18964, 3667,
+ 4064, 1161, 19988, 146, 27306, 23257, 9560, 16743, 21634, 6029,
+ 713, 26543, 14883, 8323, 28830, 24907, 27702, 29902, 24170, 22809,
+ 15734, 25170, 20569, 14627, 19474, 14734, 5046, 7447, 31314, 29624,
+ 7345, 18680, 23166, 32527, 29024, 30738, 4604, 9581, 17923, 6195,
+ 30648, 16667, 11916, 17688, 29129, 13290, 2399, 6182, 22097, 21631,
+ 1878, 8283, 21412, 17903, 29960, 5763, 9133, 28044, 10571, 8623,
+ 3726, 31486, 15607, 16355, 135, 13973, 28653, 9999, 14105, 2525,
+ 24408, 12864, 18795, 30323, 28979, 12056, 4076, 28440, 6412, 8060,
+ 12090, 18180, 23047, 17292, 19011, 11132, 10789, 32728, 8106, 23463,
+ 6854, 29648, 5740, 4766, 27245, 21629, 32195, 22466, 25540, 24431,
+ 1098, 10578, 11744, 31223, 10850, 13629, 29125, 20630, 13269, 5172,
+ 31021, 2740, 23738, 15108, 10885, 26261, 21913, 5667, 1593, 20874,
+ 19151, 904, 2353, 20580, 31539, 7872, 6300, 19502, 8697, 4927,
+ 23276, 5916, 14295, 26868, 8737, 15806, 20327, 32544, 19275, 30841,
+ 4301, 10599, 14154, 20792, 6297, 9000, 16601, 20831, 15855, 19722,
+ 21451, 19457, 997, 26839, 2451, 6226, 14892, 18318, 28426, 20575,
+ 4339, 7603, 22381, 26620, 9224, 29162, 24741, 12286, 16704, 22980,
+ 3276, 6571, 28186, 30937, 5356, 20079, 28831, 30231, 22794, 28625,
+ 24460, 23385, 4451, 5028, 32179, 4923, 9461, 20610, 25759, 31021,
+ 18753, 28278, 17015, 12231, 20304, 4089, 12068, 12637, 16884, 26400,
+ 23734, 20178, 14672, 19219, 9988, 4273, 1946, 16833, 18067, 11897,
+ 8992, 20946, 10938, 4153, 29065, 12509, 16131, 3677, 22622, 8668,
+ 8147, 25544, 14025, 6109, 590, 1571, 11420, 28922, 21365, 22644,
+ 21140, 23946, 21137, 27634, 18400, 18329, 10965, 17176, 14557, 20118,
+ 20543, 19192, 17188, 11084, 9151, 32466, 23238, 4116, 8859, 27109,
+ 5334, 22856, 9490, 31621, 31528, 8698, 28736, 24942, 19801, 4326,
+ 8001, 23640, 21263, 29094, 10137, 17099, 9090, 28197, 31955, 9781,
+ 1596, 31830, 5993, 20026, 20765, 21542, 25316, 32331, 26529, 431,
+ 22340, 14714, 16230, 26542, 16802, 30860, 3560, 17975, 20, 1616,
+ 911, 6567, 13521, 30256, 14317, 26075, 13462, 26886, 11072, 16799,
+ 13384, 5169, 319, 13929, 31194, 16103, 22803, 18504, 5233, 10700,
+ 26275, 14871, 24518, 5316, 12564, 25078, 22220, 22278, 6800, 8699,
+ 31124, 15731, 5447, 22820, 19053, 8997, 10676, 24720, 9807, 30794,
+ 12834, 26863, 31866, 11059, 28526, 19512, 10586, 10152, 23310, 10138,
+ 30894, 24703, 23122, 20916, 4841, 5997, 14058, 264, 23000, 22299,
+ 169, 13997, 30854, 21372, 15497, 16709, 10845, 9311, 1262, 27695,
+ 32141, 3648, 32559, 12030, 5298, 19812, 19026, 28969, 11185, 5925,
+ 19223, 13827, 25570, 17802, 31033, 17646, 7029, 24858, 4592, 8652,
+ 21518, 31986, 21434, 27063, 27827, 6422, 10075, 26610, 13032, 32517,
+ 23074, 30495, 3864, 19600, 19823, 690, 20535, 8427, 16242, 15525,
+ 23206, 8197, 4405, 23406, 15959, 16405, 11741, 29742, 30769, 5493,
+ 30509, 17707, 25270, 4276, 23371, 1152, 6627, 25319, 30663, 1811,
+ 22103, 31807, 28121, 21448, 952, 22753, 19434, 30452, 5715, 4081,
+ 12374, 10773, 25602, 22768, 2417, 9152, 1107, 31561, 5832, 9178,
+ 31718, 23590, 4009, 4107, 14103, 7816, 4837, 13424, 6109, 2455,
+ 17364, 31888, 6898, 10551, 14490, 14482, 22581, 23771, 7593, 17069,
+ 25164, 18590, 12935, 6367, 18829, 23696, 978, 16098, 17951, 26189,
+ 1665, 31836, 19804, 24789, 30828, 19286, 5754, 30359, 10767, 2799,
+ 21099, 27087, 5514, 19025, 6913, 22290, 26349, 16357, 23894, 1575,
+ 22963, 16579, 17259, 15641, 3980, 19565, 24847, 18826, 17504, 188,
+ 10243, 13386, 912, 2586, 26459, 21289, 17023, 25586, 23079, 11529,
+ 1105, 32101, 2387, 25655, 27378, 5695, 1228, 6907, 22874, 26665,
+ 14308, 1645, 2832, 28704, 23800, 9099, 17645, 27685, 21584, 17033,
+ 803, 24886, 25158, 23656, 18558, 15742, 6315, 26314, 29417, 27337,
+ 28518, 6661, 14643, 25914, 20574, 23926, 13843, 10816, 6811, 19992,
+ 9322, 5062, 24744, 4948, 12489, 29610, 26171, 30235, 1075, 881,
+ 8471, 28211, 27684, 31801, 16690, 6606, 17361, 27374, 1043, 21345,
+ 690, 5313, 22399, 22963, 5182, 32726, 3924, 15925, 23798, 29757,
+ 12981, 3473, 4260, 2340, 9319, 26245, 15845, 4683, 10875, 29426,
+ 13029, 440, 6446, 30512, 8042, 4523, 9485, 27557, 6164, 19156,
+ 8285, 21654, 24291, 15044, 10169, 19516, 5369, 28322, 509, 29467,
+ 14753, 1567, 14179, 14991, 6801, 29355, 9196, 15784, 6508, 14058,
+ 2306, 7223, 27275, 14945, 25179, 3113, 12541, 1398, 544, 5396,
+ 7116, 31127, 14415, 10768, 26754, 22969, 2398, 5576, 28396, 14084,
+ 14369, 27857, 6686, 5580, 9965, 31290, 29367, 24260, 21502, 23140,
+ 7783, 28782, 29974, 14355, 30894, 25814, 30311, 24518, 10470, 24448,
+ 24755, 7492, 22915, 30623, 27314, 6008, 29850, 4743, 14772, 7806,
+ 2464, 16997, 5511, 8190, 16501, 32046, 5019, 13753, 32160, 16341,
+ 32100, 609, 7133, 29121, 30208, 20654, 24277, 7294, 8986, 10414,
+ 812, 19379, 23822, 20317, 4032, 10580, 10829, 25717, 19504, 10776,
+ 2564, 4743, 156, 24110, 20984, 1355, 25260, 14892, 9140, 6709,
+ 21460, 27720, 15591, 32584, 21718, 4554, 9992, 13359, 21128, 24769,
+ 2619, 8586, 12247, 6645, 10104, 14982, 12556, 22302, 15850, 23728,
+ 11342, 2387, 24469, 25099, 9064, 15301, 31036, 6495, 10957, 28333,
+ 4482, 6357, 16857, 7811, 847, 7873, 90, 19313, 14197, 29887,
+ 15695, 5383, 8596, 2305, 4848, 15920, 1083, 12775, 25582, 11621,
+ 16463, 20432, 17915, 15648, 13233, 16689, 30093, 28820, 27419, 23780,
+ 14047, 24731, 11083, 26306, 18489, 29936, 5476, 12915, 18802, 15774,
+ 27281, 26757, 15539, 184, 13035, 8636, 1149, 20555, 19357, 19625,
+ 750, 15505, 8261, 4478, 15936, 30311, 5022, 10273, 11922, 30209,
+ 23389, 21631, 6379, 31197, 21336, 32035, 7036, 29173, 3053, 4103,
+ 20261, 11065, 6050, 10666, 8763, 20284, 23561, 12898, 20617, 3118,
+ 27111, 26100, 7316, 30986, 8340, 31074, 11812, 2576, 8357, 21252,
+ 14847, 10614, 20937, 2266, 22264, 18523, 32753, 6433, 9256, 31740,
+ 21428, 4388, 9340, 31530, 10737, 5717, 29552, 4092, 3766, 1436,
+ 14105, 20929, 24416, 7407, 29545, 15160, 22532, 25379, 8879, 28932,
+ 4110, 16898, 14173, 19546, 10792, 1693, 27406, 32253, 15198, 15332,
+ 32455, 23916, 11647, 4979, 20605, 14425, 8390, 20655, 27096, 13918,
+ 4281, 27154, 27703, 9452, 16466, 21699, 32244, 16260, 12637, 11882,
+ 7401, 18473, 11041, 14658, 31283, 1045, 5186, 24176, 17205, 28843,
+ 9190, 10899, 31712, 17581, 11799, 30876, 20018, 4527, 3945, 16096,
+ 29437, 6603, 31708, 12907, 6122, 11671, 13571, 13463, 26301, 9812,
+ 27494, 16094, 4571, 20584, 20262, 16621, 2569, 23055, 5087, 9465,
+ 16758, 6733, 27602, 28246, 8188, 17447, 15940, 9798, 3235, 23058,
+ 7457, 2831, 12391, 30124, 15845, 13648, 22075, 14250, 31164, 10132,
+ 3149, 29713, 6376, 31784, 27276, 28330, 28004, 9514, 8808, 15279,
+ 199, 29411, 15320, 6347, 22890, 21591, 9122, 21058, 6861, 1561,
+ 28375, 2155, 1335, 9060, 30620, 26983, 6301, 19816, 14128, 13069,
+ 24261, 23778, 299, 4388, 8364, 20975, 1028, 11221, 2852, 30242,
+ 13014, 31327, 1729, 25812, 31844, 11789, 18166, 28091, 29530, 18790,
+ 21628, 1471, 19414, 14243, 5875, 14856, 21030, 30822, 8652, 22876,
+ 16084, 13224, 18534, 18344, 3039, 18931, 15735, 12252, 12108, 13522,
+ 16814, 2044, 24285, 19335, 9623, 7028, 16673, 16379, 8894, 4013,
+ 12205, 26619, 20503, 5853, 28328, 9888, 13725, 17699, 32141, 2575,
+ 17210, 15315, 25900, 29027, 12007, 7951, 9970, 20200, 32276, 2455,
+ 12651, 23178, 15946, 29409, 32261, 18573, 12559, 15213, 15383, 22654,
+ 28426, 21331, 11553, 20585, 18023, 12062, 5718, 14412, 22653, 32476,
+ 27479, 27084, 15022, 23414, 5698, 18471, 7823, 24126, 235, 13418,
+ 17737, 22215, 17257, 4580, 16960, 4857, 7125, 28378, 20722, 28004,
+ 4942, 9596, 16929, 5589, 29760, 2328, 17460, 18471, 30182, 29582,
+ 2779, 25948, 16654, 18180, 6642, 8941, 12829, 14298, 14248, 17501,
+ 31826, 29408, 18912, 4884, 4687, 29639, 8919, 2155, 30677, 8150,
+ 263, 24068, 24783, 30942, 17996, 30812, 16786, 31856, 10822, 24483,
+ 13411, 845, 27646, 15051, 22585, 13598, 18124, 223, 3269, 25702,
+ 11896, 21654, 12208, 26292, 5791, 15912, 16164, 15645, 18776, 14176,
+ 1421, 8425, 4376, 15858, 12961, 18573, 14803, 24592, 1438, 30938,
+ 11620, 30520, 27858, 13939, 12079, 1360, 15969, 11140, 31493, 26612,
+ 28227, 5553, 19272, 22031, 25996, 20557, 2639, 23464, 24304, 20173,
+ 13067, 18431, 27782, 7036, 9451, 16857, 2764, 11888, 28414, 30232,
+ 25836, 12476, 22104, 5262, 11837, 32743, 7094, 3859, 13581, 1437,
+ 17509, 20181, 4766, 14245, 27231, 21488, 7278, 21523, 22456, 29503,
+ 31419, 11711, 28984, 9841, 2119, 7413, 13386, 8799, 24409, 26734,
+ 19476, 10140, 14340, 14975, 488, 16718, 31659, 30353, 3291, 26173,
+ 12741, 721, 1203, 12330, 10718, 23081, 31751, 7522, 1758, 31342,
+ 1441, 4243, 3982, 731, 10535, 733, 26712, 5822, 2811, 7212,
+ 6735, 22641, 19295, 9670, 2927, 4236, 24797, 2848, 19493, 21849,
+ 29158, 23798, 24082, 18056, 29113, 2714, 22540, 12580, 1158, 17805,
+ 2917, 12230, 28371, 17228, 3696, 6921, 5152, 20844, 20546, 24125,
+ 18630, 28649, 6582, 1120, 31525, 26044, 8116, 4426, 30718, 939,
+ 2738, 31527, 19998, 2405, 6010, 22570, 5437, 24782, 13614, 5248,
+ 7205, 9112, 17546, 17539, 16919, 7955, 23658, 26417, 32618, 19014,
+ 14220, 11484, 24949, 25150, 12182, 5666, 32175, 8358, 26971, 32544,
+ 8213, 16536, 5722, 27363, 14540, 17843, 28551, 8991, 19720, 14702,
+ 19791, 36, 28460, 21163, 214, 27917, 563, 15248, 21123, 31803,
+ 19534, 27026, 18878, 8194, 7374, 15314, 8696, 23457, 2373, 21421,
+ 4332, 120, 1512, 23438, 16933, 19317, 23864, 12295, 11201, 30416,
+ 19170, 7969, 8308, 5112, 15843, 12784, 17104, 16845, 1519, 13418,
+ 15811, 4879, 28692, 28537, 26209, 14614, 5787, 18766, 10979, 18116,
+ 26671, 16377, 29424, 8121, 10817, 29238, 21788, 26565, 31402, 10890,
+ 17839, 1699, 5266, 8335, 8871, 5092, 23697, 25740, 16640, 16169,
+ 30741, 10569, 24370, 2197, 29700, 24610, 8444, 23938, 16034, 23385,
+ 30816, 28019, 30900, 27313, 8175, 19274, 25062, 9784, 2630, 11964,
+ 25706, 23396, 27353, 27137, 994, 20577, 15343, 26576, 13184, 20906,
+ 26094, 17802, 22379, 15831, 27609, 23990, 30053, 949, 16663, 22189,
+ 22700, 18076, 11382, 2454, 11549, 7421, 23663, 21909, 21919, 7483,
+ 4268, 13120, 447, 11452, 31943, 7251, 18072, 17727, 18517, 7076,
+ 16118, 9328, 20515, 6489, 30395, 6585, 3263, 14168, 9601, 26204,
+ 16954, 20991, 31872, 25535, 23853, 30998, 2994, 25606, 8442, 29953,
+ 566, 231, 2900, 11322, 19955, 19642, 4354, 31999, 24189, 6608,
+ 6111, 24392, 3900, 19462, 21030, 25340, 31947, 26778, 24300, 24164,
+ 18846, 22589, 21486, 24800, 5608, 3945, 5261, 15833, 11963, 4340,
+ 6679, 17398, 14449, 32486, 4424, 29843, 22604, 11656, 28945, 20335,
+ 8537, 27837, 28311, 1700, 18586, 31637, 29311, 11997, 25699, 23072,
+ 29545, 16323, 15109, 28032, 22970, 30904, 25770, 10818, 20639, 32200,
+ 17536, 14575, 10319, 16604, 7450, 18653, 11664, 2865, 17427, 1355,
+ 6780, 15113, 14580, 24749, 1157, 2465, 9047, 10821, 27575, 28002,
+ 31821, 8691, 20285, 27739, 26366, 32334, 27431, 29423, 31887, 6387,
+ 874, 715, 3913, 13598, 24616, 19996, 10487, 5239, 24370, 4862,
+ 18575, 20014, 16076, 19255, 8981, 7241, 1456, 1061, 27581, 4925,
+ 11349, 29429, 26448, 30652, 27504, 6422, 20176, 9935, 21436, 3309,
+ 17759, 17444, 4854, 15051, 25949, 8873, 2604, 12828, 10449, 7002,
+ 6456, 21217, 12554, 18006, 17288, 28512, 12678, 19001, 4640, 13849,
+ 530, 13734, 22241, 30717, 7219, 5923, 13579, 7899, 1989, 18218,
+ 4865, 26651, 31458, 6268, 22860, 14254, 12549, 25273, 8931, 5957,
+ 15727, 6958, 17065, 13761, 23754, 28654, 16952, 31467, 2573, 6436,
+ 15837, 870, 23199, 21671, 16867, 6370, 26047, 16335, 3349, 31377,
+ 15139, 904, 23678, 2527, 11487, 1700, 9331, 12126, 28809, 6774,
+ 23252, 3071, 23451, 21916, 13966, 19080, 16152, 4380, 2148, 9538,
+ 9843, 15283, 4336, 29682, 32172, 30569, 30692, 22027, 25276, 13673,
+ 18582, 19746, 9779, 17424, 6076, 23458, 16160, 836, 13939, 31681,
+ 13873, 13063, 5767, 691, 19483, 4171, 17390, 17437, 24380, 13320,
+ 6037, 2508, 21631, 26765, 1888, 13223, 1921, 26900, 14188, 5090,
+ 1522, 16280, 12439, 23413, 6717, 13547, 24642, 10957, 26987, 1795,
+ 17749, 6849, 10308, 22932, 28292, 20935, 11192, 5349, 11729, 31080,
+ 22654, 9948, 9554, 10225, 13819, 23130, 4405, 4716, 10341, 14543,
+ 29441, 6862, 5672, 10757, 542, 3698, 31881, 17984, 1432, 10438,
+ 14217, 3721, 31520, 11845, 268, 32583, 12116, 13221, 27450, 12559,
+ 11072, 25937, 23078, 31677, 6948, 25369, 16557, 20420, 4727, 1064,
+ 9378, 14786, 20781, 5943, 11816, 17496, 28214, 29441, 18014, 11320,
+ 2887, 27383, 2370, 6783, 30172, 31796, 3791, 22854, 22910, 18099,
+ 20329, 13939, 26433, 9920, 10107, 2261, 5778, 684, 15967, 2929,
+ 25391, 8389, 21630, 790, 11383, 6533, 15544, 25144, 6628, 14858,
+ 1286, 24315, 10454, 27334, 4701, 12173, 18322, 28280, 13270, 24761,
+ 8586, 3419, 28941, 31417, 223, 157, 6086, 26700, 26916, 12818,
+ 19671, 21513, 20325, 9258, 9282, 28659, 4967, 5665, 1185, 23373,
+ 7730, 14453, 22983, 6832, 18893, 1437, 23204, 22106, 30281, 4856,
+ 26217, 21193, 28672, 28164, 15597, 22409, 2847, 22992, 5711, 30794,
+ 6242, 180, 24030, 29749, 5919, 28223, 5173, 8064, 18566, 25969,
+ 7338, 2880, 2087, 26410, 31210, 24447, 3509, 31971, 15837, 7055,
+ 31753, 7068, 12496, 12445, 24937, 13077, 29650, 10889, 3339, 15681,
+ 8798, 23286, 24021, 25080, 14139, 15005, 28263, 748, 14497, 29926,
+ 16987, 17374, 28573, 20921, 22731, 25362, 11958, 29073, 18452, 30208,
+ 27601, 4051, 18138, 24140, 12626, 16223, 17997, 2808, 10884, 21860,
+ 426, 23001, 20283, 30328, 9988, 11591, 29368, 31208, 32068, 2585,
+ 14796, 5964, 11119, 20945, 15425, 4703, 1319, 27923, 21877, 22798,
+ 117, 31324, 26696, 18383, 14533, 21744, 6712, 2100, 9010, 2068,
+ 18891, 15808, 22532, 638, 17454, 29945, 5495, 7690, 32283, 2238,
+ 24511, 20398, 21503, 29147, 25160, 5040, 5469, 13531, 30274, 27158,
+ 24429, 25118, 29277, 30559, 2826, 23595, 10193, 7536, 12747, 22598,
+ 12450, 8401, 3695, 19782, 29474, 11801, 15486, 17569, 32439, 21415,
+ 6957, 16841, 9694, 17299, 22402, 13243, 31088, 29156, 25018, 9428,
+ 2341, 25348, 20968, 7399, 3414, 15985, 32734, 27022, 24071, 31156,
+ 21072, 16573, 23332, 12183, 2359, 29085, 10763, 30611, 1908, 6039,
+ 27723, 20872, 24502, 942, 21419, 31153, 10397, 20499, 14191, 14550,
+ 23584, 20979, 3798, 1219, 17964, 23956, 29927, 1274, 18061, 4256,
+ 6509, 20389, 27154, 5825, 17217, 29390, 7916, 7277, 18375, 7634,
+ 2136, 25604, 7099, 32531, 13694, 12568, 24878, 10734, 16280, 32267,
+ 5835, 6381, 4950, 12256, 19551, 8253, 27009, 15435, 153, 25698,
+ 13024, 30218, 3086, 10537, 31576, 29560, 15743, 3294, 2134, 17248,
+ 2911, 960, 13938, 25615, 32400, 10162, 23116, 12461, 14958, 12339,
+ 10426, 14541, 17934, 9872, 27174, 13890, 31431, 10840, 32049, 5428,
+ 15346, 23057, 27804, 17012, 23535, 13353, 7273, 13325, 21097, 1072,
+ 21053, 24604, 10202, 12356, 7433, 5601, 14929, 31436, 24553, 27925,
+ 16243, 3177, 1101, 16254, 10175, 23081, 5974, 24770, 18199, 15358,
+ 22147, 2169, 26236, 18287, 28556, 8837, 8986, 17038, 30606, 31142,
+ 16004, 17194, 23913, 28745, 17472, 20037, 23398, 15265, 10374, 3016,
+ 11294, 21753, 17477, 25206, 1687, 5449, 21095, 4127, 9647, 12039,
+ 21078, 4630, 24254, 31295, 29631, 29157, 2935, 18150, 28566, 19006,
+ 19215, 10604, 29274, 6197, 24226, 30096, 31642, 11437, 9426, 23416,
+ 22200, 21008, 30897, 23297, 4333, 31300, 30689, 340, 4237, 2266,
+ 29689, 9402, 12684, 3464, 4907, 4785, 2882, 729, 25636, 25663,
+ 17259, 25891, 26932, 27782, 4722, 13754, 24239, 30105, 23791, 15971,
+ 16531, 16270, 1646, 10507, 21354, 30164, 24946, 16313, 13426, 3783,
+ 24761, 26818, 13564, 18818, 28098, 13116, 1298, 15860, 2189, 1972,
+ 29020, 13111, 5282, 20772, 14405, 12316, 30548, 12831, 14937, 31243,
+ 27463, 6735, 2545, 30218, 11568, 20513, 7699, 8219, 26076, 17087,
+ 11412, 3275, 30068, 14399, 28543, 10504, 1023, 11289, 22971, 11315,
+ 31528, 29151, 32487, 28790, 19777, 28712, 12937, 9560, 11657, 1998,
+ 8808, 4238, 7594, 31577, 28726, 20756, 29830, 27322, 3698, 22653,
+ 16947, 14141, 25741, 3720, 13636, 25529, 32332, 21235, 25931, 17673,
+ 19053, 20884, 9884, 5824, 11405, 23717, 19283, 18457, 26185, 16736,
+ 30104, 5421, 7076, 19148, 24353, 16489, 30376, 26326, 14841, 62,
+ 11857, 8611, 3712, 29978, 29862, 27429, 15028, 15256, 4137, 23276,
+ 30382, 28404, 9329, 26175, 623, 12225, 28182, 15468, 24797, 734,
+ 30157, 15708, 17417, 7334, 32468, 15978, 3763, 27751, 13457, 4469,
+ 3856, 31765, 23414, 564, 22219, 30784, 2343, 15818, 21577, 29764,
+ 10207, 22683, 4401, 16064, 18704, 26205, 14892, 23113, 2889, 22642,
+ 21481, 28255, 5981, 5749, 16741, 17567, 30914, 1299, 32617, 9787,
+ 21815, 28444, 14676, 11688, 18345, 1241, 6938, 24726, 25176, 26017,
+ 1165, 9765, 7222, 26535, 475, 27990, 11663, 4630, 11608, 6079,
+ 8175, 32096, 24190, 31876, 5441, 3538, 18994, 6018, 2612, 15469,
+ 30793, 14541, 6115, 25073, 12875, 18525, 30900, 14394, 20343, 29188,
+ 21632, 1487, 519, 19875, 6133, 10169, 2485, 22430, 23353, 28049,
+ 28541, 19853, 7120, 31709, 11941, 17205, 19904, 10397, 28411, 950,
+ 2035, 1568, 13406, 4869, 20444, 4124, 10111, 25501, 18526, 12030,
+ 23529, 5234, 18409, 1407, 14143, 19239, 6630, 15480, 24005, 32384,
+ 28501, 16631, 18466, 17690, 17076, 10386, 26213, 31834, 13091, 12283,
+ 29765, 23459, 6855, 2005, 25261, 18380, 25708, 25542, 31352, 31441,
+ 25710, 32718, 7289, 21448, 14553, 4055, 17086, 25367, 29903, 19853,
+ 10005, 1765, 6954, 6255, 13008, 11214, 11363, 23590, 7110, 1499,
+ 19379, 12566, 21146, 21937, 16247, 27444, 9792, 3592, 20697, 2839,
+ 16572, 27999, 20141, 17745, 24877, 24558, 14233, 5119, 30475, 15837,
+ 20345, 1695, 685, 14771, 9217, 17442, 24334, 4881, 17572, 29506,
+ 22736, 24992, 12725, 32022, 13953, 3144, 18125, 24036, 5662, 16547,
+ 9324, 30774, 17365, 32433, 23779, 7728, 28175, 3277, 26737, 17696,
+ 23214, 26591, 9388, 5975, 403, 980, 25378, 22584, 12388, 28747,
+ 19265, 20110, 7052, 13713, 4980, 10531, 131, 32208, 21903, 4494,
+ 15695, 24195, 621, 24908, 331, 22061, 14551, 11538, 31527, 21067,
+ 936, 6754, 10288, 20871, 17199, 13149, 10449, 30254, 17877, 11480,
+ 15962, 7396, 21504, 21169, 22017, 19351, 13111, 3683, 17703, 3249,
+ 25734, 15321, 6876, 2706, 8740, 16512, 10916, 32573, 24659, 6304,
+ 13435, 19537, 21896, 20204, 19992, 20284, 19916, 4696, 29039, 17835,
+ 19810, 24106, 21625, 22084, 18090, 26708, 28215, 4504, 26437, 18945,
+ 19701, 32595, 16506, 5742, 8652, 2998, 20184, 21499, 9578, 26952,
+ 9501, 2946, 14870, 15048, 15959, 25063, 28398, 6501, 15177, 28656,
+ 18547, 19250, 3856, 19543, 29256, 15828, 24327, 31774, 15927, 6525,
+ 6631, 15651, 5237, 31, 2611, 24308, 14631, 19673, 26579, 7652,
+ 2852, 26550, 11518, 13407, 8189, 406, 12894, 5754, 24891, 19564,
+ 22127, 3022, 3815, 938, 13353, 7047, 19280, 22778, 11486, 32440,
+ 5128, 6447, 18789, 3314, 19504, 7547, 13944, 22292, 15349, 23778,
+ 24667, 25700, 10587, 12782, 29118, 17887, 28218, 10405, 14821, 29646,
+ 12165, 26808, 15878, 10650, 6610, 4093, 31219, 13281, 18199, 4383,
+ 5112, 25801, 12722, 27285, 2055, 8853, 22701, 18896, 3602, 17526,
+ 31039, 28345, 16313, 12707, 406, 25434, 16677, 30379, 8403, 23515,
+ 28980, 17674, 6231, 21169, 25814, 4347, 12861, 13586, 12727, 16782,
+ 295, 13228, 19486, 9978, 19774, 2966, 31765, 11060, 21108, 23431,
+ 11722, 28865, 13325, 22854, 8501, 21448, 18781, 31585, 15611, 363,
+ 10195, 27426, 2194, 6487, 3638, 21183, 4518, 3482, 5423, 23505,
+ 16572, 13494, 18696, 29191, 24854, 16883, 4275, 7708, 24534, 6137,
+ 1550, 3334, 1638, 10653, 9061, 6001, 13334, 23804, 27192, 23915,
+ 23303, 9414, 26431, 19041, 17481, 17373, 14252, 5450, 24384, 28447,
+ 29616, 4386, 8268, 16767, 8768, 24986, 12968, 13915, 6681, 26638,
+ 403, 7690, 29698, 31927, 23726, 16564, 29265, 18466, 15270, 9062,
+ 432, 20704, 25874, 9061, 14113, 4480, 31903, 23491, 28480, 10938,
+ 15466, 2353, 29384, 1517, 23981, 24596, 17497, 31692, 29854, 2267,
+ 31609, 21331, 17300, 13967, 20696, 11521, 18796, 2987, 16344, 11841,
+ 3883, 16687, 24908, 297, 30948, 17392, 25472, 31846, 7645, 15410,
+ 17275, 1911, 27629, 13176, 11136, 3866, 6696, 19611, 6875, 7684,
+ 11967, 16922, 15066, 28117, 7201, 7857, 1305, 1099, 14694, 25645,
+ 7938, 12470, 6638, 5246, 3733, 32172, 2117, 20750, 11365, 27389,
+ 10314, 1105, 30435, 1001, 1169, 18846, 10975, 9617, 2821, 1853,
+ 17740, 2476, 15570, 28353, 21060, 27003, 5506, 22423, 11596, 19711,
+ 28005, 10208, 5848, 23145, 23351, 16252, 17170, 14802, 22781, 6503,
+ 17879, 24876, 12336, 5961, 2, 23673, 28957, 11080, 29166, 26171,
+ 31116, 21537, 5942, 25643, 20128, 8055, 12223, 7213, 19966, 9835,
+ 6649, 13700, 31281, 14444, 8801, 23106, 26190, 10320, 27723, 3331,
+ 1235, 28580, 22494, 1755, 24021, 7233, 2400, 12685, 28763, 15392,
+ 30132, 4606, 17157, 15216, 6176, 14057, 26609, 26853, 13652, 32723,
+ 30686, 5202, 20392, 20546, 18578, 31610, 12454, 810, 25210, 31012,
+ 11208, 12968, 31121, 10861, 32386, 10226, 28034, 32354, 29059, 1935,
+ 5393, 25550, 7993, 3523, 22711, 2385, 915, 28494, 24716, 25522,
+ 14602, 12886, 22891, 28278, 1762, 5025, 5456, 23218, 9389, 19463,
+ 2820, 8221, 22290, 18983, 30973, 9321, 18892, 13402, 12159, 27860,
+ 19189, 18149, 17928, 3578, 19333, 25203, 16363, 19949, 18710, 24258,
+ 25659, 11399, 1258, 30108, 19690, 17919, 11310, 23049, 28978, 17339,
+ 21888, 20419, 12084, 20325, 30640, 22250, 6368, 15425, 15811, 16377,
+ 2068, 23230, 23614, 15353, 15880, 10827, 19361, 15604, 4585, 23915,
+ 3121, 15021, 29380, 25612, 22266, 12174, 16550, 28693, 24597, 25058,
+ 16642, 10302, 3623, 19780, 12882, 32036, 19242, 16471, 17153, 21661,
+ 21104, 696, 28553, 32584, 8164, 5937, 3033, 11369, 25748, 28208,
+ 31737, 20468, 9324, 7287, 24560, 12008, 24900, 27156, 14054, 1502,
+ 30494, 19860, 15750, 32226, 3496, 10100, 2982, 25473, 17161, 20952,
+ 13610, 21539, 29657, 22655, 29221, 21916, 17521, 27895, 4674, 3069,
+ 20326, 27405, 16227, 432, 7504, 392, 21383, 13764, 18896, 21271,
+ 17905, 25733, 31185, 9095, 29575, 15952, 1805, 25913, 18040, 165,
+ 1235, 15060, 289, 9598, 520, 16695, 12338, 7391, 11373, 13746,
+ 2060, 17583, 14623, 19573, 12654, 4806, 13924, 19272, 18769, 9543,
+ 10916, 15485, 6160, 11568, 9398, 20003, 17356, 26415, 8542, 12669,
+ 527, 5816, 27155, 3763, 3247, 14164, 20741, 24774, 24054, 22588,
+ 28254, 19913, 30719, 22054, 17096, 20303, 15203, 26463, 25392, 16160,
+ 4374, 11802, 4554, 7216, 27531, 17672, 26710, 7121, 25375, 31272,
+ 30625, 23335, 29108, 11233, 78, 17628, 4508, 31822, 10454, 32534,
+ 17338, 20185, 21710, 30118, 16611, 17419, 361, 21635, 23178, 10146,
+ 19261, 1654, 20125, 1252, 330, 3094, 4778, 21812, 26936, 16119,
+ 23110, 31971, 6368, 21791, 23727, 2632, 2318, 14521, 7600, 27411,
+ 17797, 2062, 15813, 3038, 24132, 20912, 5504, 5637, 32264, 24824,
+ 8235, 16312, 18962, 11955, 31151, 25166, 28458, 18969, 29621, 19164,
+ 32740, 19967, 1546, 30983, 2082, 13901, 7752, 16406, 31194, 10673,
+ 4787, 32332, 22298, 2965, 15457, 24180, 15689, 27215, 31902, 22461,
+ 13743, 7576, 12686, 24520, 28472, 10560, 24084, 768, 17780, 14368,
+ 2291, 22314, 14563, 17231, 5939, 31804, 15472, 14745, 9671, 8051,
+ 31803, 15148, 9836, 13472, 411, 15765, 17364, 22979, 22628, 11243,
+ 20740, 6362, 6501, 22346, 18427, 31739, 32309, 19331, 7060, 10145,
+ 25136, 23570, 24749, 28484, 21692, 32081, 4745, 6188, 8401, 15851,
+ 30323, 16006, 28088, 29842, 25252, 4280, 23826, 30197, 27751, 21746,
+ 18973, 26348, 16763, 27909, 3635, 32502, 12473, 19577, 28307, 20198,
+ 9718, 5337, 5988, 24537, 7467, 19538, 18423, 15979, 20692, 25213,
+ 5197, 17963, 10133, 30584, 24537, 16716, 9507, 6459, 30086, 12445,
+ 25186, 27433, 24828, 20411, 20683, 27622, 27935, 10628, 19729, 19817,
+ 27609, 20688, 17668, 4946, 11034, 4444, 29877, 27517, 15133, 11527,
+ 32475, 29911, 27116, 31041, 25717, 26736, 6182, 28864, 8113, 22738,
+ 19200, 3444, 26125, 31634, 8074, 32446, 21948, 12580, 820, 4061,
+ 4683, 16115, 21904, 21161, 5252, 28593, 22361, 25219, 12691, 3564,
+ 2741, 21388, 7527, 27875, 26807, 8725, 27739, 29591, 4136, 13911,
+ 22550, 24101, 20871, 20580, 19375, 10578, 15438, 28766, 31509, 23656,
+ 4471, 3815, 2479, 9537, 16191, 14808, 1087, 31393, 18986, 26934,
+ 12812, 14537, 18247, 8290, 320, 27720, 19381, 12175, 4751, 16149,
+ 30054, 10617, 10265, 15323, 28963, 24917, 31634, 23444, 8656, 1283,
+ 16288, 4441, 19698, 10123, 20612, 18552, 28782, 20423, 22525, 2248,
+ 9619, 24413, 26729, 13625, 13659, 26097, 21294, 6319, 16878, 13464,
+ 15960, 13585, 10600, 17807, 15748, 2204, 1500, 19501, 29180, 15742,
+ 28313, 278, 30243, 30624, 24236, 32434, 6164, 13507, 25766, 16861,
+ 10118, 29390, 32671, 8928, 23283, 4198, 19834, 23200, 4089, 7104,
+ 28267, 26646, 27392, 947, 16823, 27135, 6685, 24338, 24507, 16597,
+ 16182, 15928, 30000, 3325, 17767, 15076, 25517, 23874, 9637, 14920,
+ 19309, 8578, 24225, 5468, 25171, 13735, 9199, 7032, 15403, 6361,
+ 2152, 8994, 26675, 9459, 10189, 7461, 2010, 23091, 5037, 24035,
+ 17095, 4917, 1928, 4331, 15389, 13602, 10292, 2766, 27902, 12325,
+ 21120, 27951, 2126, 25630, 15640, 20762, 19385, 15771, 29096, 27543,
+ 25079, 7940, 24900, 24702, 14926, 27157, 6152, 14220, 31065, 15761,
+ 21499, 10167, 26377, 15157, 825, 11455, 32233, 27115, 27986, 6918,
+ 32678, 2113, 3053, 9633, 13006, 25369, 22193, 2735, 11736, 1186,
+ 1637, 23017, 21349, 20359, 4949, 2427, 25541, 23142, 29432, 19731,
+ 18365, 8067, 22737, 25399, 30855, 21694, 32403, 19675, 10523, 32706,
+ 14216, 9011, 5293, 6784, 21299, 32710, 5751, 23516, 4917, 10948,
+ 28344, 30885, 14445, 921, 22781, 28875, 27491, 22466, 22431, 15564,
+ 999, 7135, 22669, 28528, 29685, 15114, 5963, 8118, 23004, 28776,
+ 24635, 12046, 32159, 24317, 6428, 16328, 15772, 23493, 13008, 28621,
+ 11883, 7680, 26722, 11149, 29193, 18893, 28487, 11576, 2614, 2298,
+ 31972, 31793, 10779, 9755, 17745, 192, 19248, 24025, 22365, 7,
+ 2397, 23181, 31186, 5175, 2656, 3598, 28154, 29955, 29806, 24006,
+ 15201, 9301, 14365, 21772, 26845, 21312, 12673, 20910, 18124, 4919,
+ 25749, 24268, 11933, 10108, 22749, 12781, 23442, 2778, 22602, 32332,
+ 16579, 32151, 5470, 4723, 103, 12197, 31888, 29707, 26703, 23320,
+ 13554, 28147, 6067, 25309, 5137, 17551, 12849, 18856, 2333, 1123,
+ 17427, 5422, 17226, 7904, 15313, 29077, 6005, 18813, 7382, 10536,
+ 26891, 21258, 20359, 17488, 6695, 25409, 12930, 26047, 18170, 22687,
+ 20771, 14063, 20592, 14450, 25421, 30923, 31248, 25906, 31335, 3244,
+ 7973, 3860, 32676, 2438, 17179, 4829, 26504, 12644, 299, 15092,
+ 16040, 23313, 7995, 5820, 29617, 9240, 18431, 23584, 683, 32495,
+ 12389, 1904, 25983, 29040, 11312, 11627, 28087, 6024, 30178, 13213,
+ 27526, 15923, 11744, 25323, 17928, 10920, 21713, 2156, 26826, 25040,
+ 17735, 6266, 10893, 1021, 28833, 2057, 4423, 4313, 25392, 20536,
+ 5995, 10141, 21400, 20518, 22122, 6019, 16761, 263, 14970, 21629,
+ 26447, 12407, 9110, 9255, 919, 13581, 6086, 5882, 15668, 20788,
+ 27296, 8643, 10000, 14390, 32271, 27476, 9990, 27034, 83, 8826,
+ 17408, 22192, 19273, 28719, 8028, 1642, 18669, 23056, 7573, 11117,
+ 285, 10513, 543, 24680, 13472, 10351, 658, 32421, 10598, 20710,
+ 5387, 17118, 3089, 13349, 32207, 13393, 2741, 15487, 24626, 534,
+ 3292, 5347, 22200, 19121, 11470, 19726, 22137, 484, 22031, 3583,
+ 25034, 26823, 11560, 29355, 19993, 19482, 9386, 22771, 8473, 31961,
+ 25457, 16083, 18720, 14097, 24614, 32732, 13517, 27379, 22023, 1764,
+ 3565, 7206, 30443, 18428, 7071, 19298, 32384, 5794, 4023, 7739,
+ 2776, 11320, 17249, 14650, 24100, 29365, 9991, 50, 28095, 26523,
+ 26996, 12497, 25198, 11049, 6713, 2934, 28134, 4049, 19279, 32322,
+ 6542, 15852, 30207, 1650, 29319, 16301, 9983, 15340, 14058, 2387,
+ 13790, 15127, 26704, 20899, 2977, 24816, 26520, 20118, 15535, 3419,
+ 32228, 10831, 31210, 24502, 30437, 17487, 7455, 8628, 12377, 4844,
+ 21664, 21609, 17105, 14591, 12847, 5025, 10168, 9182, 8478, 17270,
+ 145, 17802, 1973, 15394, 25472, 16169, 6100, 26641, 20748, 4022,
+ 4825, 2107, 14115, 6903, 1220, 4784, 9566, 7343, 15002, 24436,
+ 5767, 23574, 30727, 6030, 29529, 13190, 12358, 6748, 12934, 16503,
+ 17990, 19753, 14847, 20397, 6149, 2305, 25967, 22960, 22848, 6852,
+ 22024, 9085, 335, 2426, 28547, 22395, 20555, 5862, 9826, 10928,
+ 12145, 11870, 889, 25141, 28875, 13786, 172, 19687, 12813, 30026,
+ 8954, 1376, 26301, 2093, 30139, 4134, 19862, 3423, 19237, 10785,
+ 21807, 2354, 26133, 23379, 13272, 11713, 28941, 8643, 14020, 32129,
+ 26232, 18618, 3182, 31769, 20022, 16434, 3637, 24948, 29780, 2188,
+ 19785, 788, 32027, 1665, 26315, 26537, 31309, 21339, 25392, 14562,
+ 26027, 23909, 9447, 1923, 9402, 27808, 10811, 5560, 31175, 24503,
+ 9850, 7080, 1577, 13621, 13911, 14926, 16838, 13558, 13197, 4228,
+ 3033, 19931, 27589, 9825, 14578, 31682, 16058, 8901, 16958, 18870,
+ 26523, 32562, 31240, 17506, 30129, 11742, 27008, 28876, 14401, 26118,
+ 15291, 6976, 8628, 2692, 23036, 4745, 26101, 24228, 7474, 9064,
+ 22555, 32052, 14529, 26686, 19272, 17882, 17029, 16652, 31440, 13483,
+ 31764, 1949, 15774, 22520, 16708, 21506, 2260, 22635, 16366, 25919,
+ 1458, 18259, 23793, 580, 16057, 10045, 27257, 26399, 10256, 25284,
+ 4993, 4719, 1830, 9642, 8342, 1820, 32153, 19495, 31198, 22085,
+ 15191, 23680, 2650, 1402, 7171, 16092, 26728, 9516, 13210, 10068,
+ 26508, 11105, 3670, 26185, 30575, 26284, 10194, 4858, 29736, 7517,
+ 23920, 17493, 19387, 11509, 24568, 19470, 7391, 15837, 26753, 10223,
+ 13061, 24407, 13461, 7535, 917, 8116, 3472, 13189, 4219, 29896,
+ 24393, 32446, 21474, 2203, 8692, 29582, 6463, 15969, 6983, 13027,
+ 26514, 940, 15068, 1280, 24809, 16865, 5591, 30345, 15141, 1000,
+ 17864, 19418, 13824, 9256, 11987, 16029, 12879, 5811, 28942, 14748,
+ 20101, 9149, 2346, 1747, 11385, 9811, 25686, 9162, 17513, 9034,
+ 27488, 12322, 26942, 19573, 18717, 10861, 25105, 17435, 28684, 28483,
+ 15599, 13479, 9014, 11922, 16089, 4258, 1624, 19253, 5391, 3807,
+ 31044, 22728, 11151, 14069, 17029, 11195, 19672, 4594, 19778, 12198,
+ 28403, 21326, 32357, 30684, 20916, 3614, 25851, 15939, 21054, 19082,
+ 18910, 17507, 6085, 3969, 25234, 19132, 32152, 13484, 11118, 4701,
+ 24158, 4256, 11516, 7346, 9375, 22359, 12450, 7582, 17543, 15585,
+ 10369, 21449, 743, 12375, 20125, 15164, 11645, 17169, 16190, 20011,
+ 10357, 4120, 4759, 18449, 29999, 14302, 14758, 7939, 5699, 17453,
+ 8795, 10045, 29891, 2142, 26364, 5378, 10944, 20939, 3272, 20643,
+ 22287, 31879, 5595, 20701, 24140, 16460, 27217, 28519, 15648, 18868,
+ 23726, 27596, 20416, 29612, 19838, 4215, 12982, 13606, 12856, 11788,
+ 8420, 5903, 872, 24831, 29382, 18049, 22029, 21855, 8951, 5945,
+ 9280, 31986, 31735, 2635, 2327, 27527, 21291, 11540, 29641, 19848,
+ 29989, 25713, 5651, 11471, 10022, 30766, 4570, 30650, 25057, 29378,
+ 10769, 32386, 10626, 10553, 31453, 23240, 9967, 32625, 31991, 30065,
+ 26190, 15497, 22611, 7860, 24263, 919, 18943, 27761, 10123, 17561,
+ 8525, 21189, 32277, 14767, 6196, 10971, 432, 17543, 2804, 7173,
+ 18489, 16408, 21241, 6923, 12326, 6803, 18690, 29635, 5063, 19350,
+ 12930, 4321, 16844, 31395, 7750, 30225, 24328, 27090, 29785, 8259,
+ 5492, 30914, 15653, 16454, 13431, 21461, 25562, 921, 9828, 9117,
+ 30740, 24446, 24389, 20625, 12984, 4687, 10455, 12037, 16926, 20245,
+ 28629, 10073, 8566, 18263, 30329, 11888, 32612, 1840, 4161, 8803,
+ 30702, 22436, 19183, 24439, 9624, 6964, 10451, 8525, 19917, 22704,
+ 20556, 1113, 11393, 26701, 21645, 15253, 8981, 30456, 31645, 20087,
+ 20091, 21481, 9633, 29472, 18586, 15482, 14686, 22742, 6388, 6714,
+ 14842, 30388, 6278, 26429, 27138, 12960, 19695, 11447, 8114, 29822,
+ 32469, 20425, 11888, 31139, 3973, 8347, 2457, 31885, 20953, 24491,
+ 1152, 1233, 27231, 11621, 21428, 29524, 31415, 6131, 13186, 7870,
+ 7229, 15190, 22459, 5164, 28137, 10166, 2232, 20518, 14707, 502,
+ 4506, 976, 29626, 4748, 25558, 14948, 7270, 13968, 5106, 29407,
+ 16588, 26386, 5001, 507, 9747, 19121, 19605, 20574, 24213, 1385,
+ 494, 18705, 20104, 15021, 6413, 3123, 25566, 30134, 12566, 14831,
+ 1385, 27674, 11030, 27051, 32067, 20128, 1928, 8578, 25197, 7251,
+ 15647, 25077, 17846, 11221, 27839, 6621, 9695, 24310, 5836, 5796,
+ 28412, 13445, 13736, 17589, 2333, 11367, 24951, 21553, 14894, 12773,
+ 24870, 5604, 24348, 74, 19627, 9335, 16442, 13742, 9358, 11751,
+ 1250, 2061, 680, 28982, 2655, 20636, 18475, 17504, 8714, 24924,
+ 27874, 13968, 31412, 22767, 21434, 8852, 14660, 26795, 18562, 17806,
+ 1185, 16621, 2799, 11757, 2259, 6063, 2787, 5788, 13669, 32093,
+ 14830, 633, 15117, 29669, 5654, 11273, 3215, 31758, 20947, 7530,
+ 26334, 3338, 15710, 1161, 9348, 10830, 21803, 6037, 24645, 2977,
+ 6580, 7603, 11007, 2931, 5241, 28659, 22741, 20337, 11845, 1666,
+ 10636, 24406, 15026, 26146, 20533, 7684, 23791, 472, 7693, 22739,
+ 10689, 25828, 21665, 24873, 10952, 14582, 25398, 25675, 9988, 31903,
+ 4967, 30066, 21656, 32262, 26896, 32290, 22477, 28124, 14699, 2231,
+ 13145, 7826, 15737, 6465, 3554, 17353, 9124, 2193, 28862, 17930,
+ 25762, 5524, 25597, 32439, 24476, 8416, 2985, 28737, 400, 18061,
+ 10828, 20124, 31732, 19014, 11443, 27632, 20124, 2463, 8946, 23954,
+ 10461, 26793, 19112, 27954, 26099, 27845, 3716, 10838, 10400, 31157,
+ 7944, 12295, 23062, 25849, 2189, 29385, 4119, 21336, 27272, 10961,
+ 7771, 5309, 13323, 11891, 22322, 29252, 2447, 20698, 16234, 8853,
+ 14320, 6395, 14707, 22641, 22713, 25803, 27585, 8074, 2978, 19632,
+ 26226, 31640, 26967, 23350, 19505, 32169, 4987, 27908, 602, 17336,
+ 1517, 19726, 11358, 5762, 3402, 24844, 30314, 6549, 1715, 31274,
+ 29507, 16810, 19664, 7681, 4469, 1332, 30228, 23494, 27564, 31545,
+ 18499, 449, 30818, 23649, 1330, 18177, 23738, 6733, 29903, 15695,
+ 26284, 297, 20576, 8032, 29283, 6021, 29456, 20303, 16099, 12384,
+ 29607, 6474, 30191, 25478, 2969, 3723, 27434, 24605, 28482, 3209,
+ 22140, 19834, 31600, 17520, 3511, 11833, 23586, 22223, 379, 31116,
+ 4239, 22417, 343, 24275, 28778, 20015, 2864, 26477, 5733, 1572,
+ 10727, 27342, 21492, 17312, 10038, 2258, 4691, 12416, 5339, 7761,
+ 17610, 5502, 28921, 26612, 20528, 13221, 27067, 18247, 2990, 21001,
+ 1082, 24079, 16069, 21428, 10913, 29661, 16530, 27107, 25999, 23011,
+ 7249, 13939, 17596, 16647, 24353, 29334, 15072, 13878, 29446, 28106,
+ 28880, 14587, 11060, 30988, 21482, 8272, 25995, 4680, 25524, 16820,
+ 25950, 25621, 704, 3709, 19320, 28063, 20179, 7024, 20321, 26340,
+ 17477, 18063, 7645, 13604, 12459, 28466, 182, 914, 14516, 29785,
+ 13243, 21584, 30033, 27969, 2825, 7578, 27673, 20533, 20105, 18242,
+ 26347, 31655, 28346, 7260, 28373, 21887, 30385, 1338, 28212, 29875,
+ 24414, 7579, 15901, 2328, 10256, 31519, 8956, 30072, 22587, 14334,
+ 31867, 20452, 20090, 5626, 11430, 15435, 208, 19858, 31308, 21836,
+ 4659, 23929, 29352, 5961, 24907, 28230, 3648, 445, 29815, 7789,
+ 7438, 25295, 26385, 19054, 15838, 295, 15347, 9548, 25847, 6144,
+ 14649, 13633, 13821, 22910, 12617, 2224, 13590, 27458, 23825, 14171,
+ 4940, 4413, 11152, 982, 6707, 31425, 10904, 12604, 31435, 26078,
+ 27858, 24864, 935, 3307, 4354, 3526, 591, 4707, 20108, 29843,
+ 21476, 24307, 11064, 1219, 26882, 9680, 15922, 9818, 16618, 846,
+ 9301, 27997, 8161, 27055, 2472, 3393, 1235, 20536, 27689, 8356,
+ 8764, 22667, 31690, 6459, 24137, 24112, 15290, 27660, 7738, 9333,
+ 18661, 19933, 24842, 5752, 27070, 5100, 27986, 19842, 19260, 3296,
+ 5739, 20886, 3874, 26112, 23762, 18506, 3972, 28835, 28113, 1494,
+ 31623, 23527, 18012, 13419, 12648, 13990, 32058, 1478, 31168, 19878,
+ 30821, 8964, 2054, 14864, 4530, 20152, 25685, 13348, 28340, 27963,
+ 8815, 32298, 4062, 26435, 2563, 31660, 23273, 6839, 5163, 18658,
+ 9333, 19906, 25145, 26222, 31987, 22567, 4531, 19786, 17602, 30420,
+ 4508, 32510, 19352, 32185, 23797, 26134, 32548, 23514, 16004, 6867,
+ 27890, 9635, 468, 24609, 7054, 6524, 13693, 27849, 32492, 21150,
+ 25253, 21736, 3079, 7717, 24007, 10144, 12233, 9830, 5300, 5389,
+ 11563, 26754, 32215, 12410, 9885, 10300, 3260, 8917, 22184, 22023,
+ 20436, 24929, 15314, 7011, 7026, 15531, 15298, 362, 26138, 23487,
+ 420, 26022, 14843, 30619, 7119, 12582, 24506, 27364, 7333, 1489,
+ 9841, 27096, 17083, 22010, 27896, 30340, 27707, 6708, 20579, 25911,
+ 22918, 6503, 9163, 1334, 797, 30499, 5458, 16817, 1729, 31797,
+ 9313, 20214, 28633, 19832, 19764, 14309, 24341, 1262, 3481, 24484,
+ 21841, 24847, 9972, 19348, 9660, 32353, 16775, 18819, 21305, 20297,
+ 21744, 17955, 23813, 17953, 31219, 26554, 16026, 25994, 2426, 16668,
+ 9940, 11012, 11482, 12503, 10835, 1980, 17240, 16557, 29984, 23460,
+ 16620, 6471, 16275, 9929, 27205, 24103, 2676, 25826, 4620, 1503,
+ 26208, 18212, 15213, 640, 19054, 16478, 17876, 20054, 15891, 5953,
+ 1524, 12498, 23107, 29439, 28686, 20424, 26073, 5657, 14192, 24795,
+ 4409, 15217, 1852, 3893, 5428, 18855, 14442, 27003, 14636, 20642,
+ 10512, 27647, 1144, 1389, 6369, 31544, 7945, 12357, 12020, 25200,
+ 9550, 16624, 3272, 10941, 29526, 32080, 4740, 24114, 11061, 32311,
+ 14467, 2902, 31400, 28285, 8719, 7381, 25596, 16464, 19821, 22902,
+ 3627, 19660, 1307, 8269, 24649, 4555, 30293, 13618, 27678, 511,
+ 4317, 12658, 27669, 6974, 5116, 27844, 22613, 14108, 27844, 29310,
+ 22317, 18879, 18841, 22280, 3253, 751, 1776, 401, 3506, 1389,
+ 22869, 15874, 31163, 10374, 22707, 11056, 154, 30695, 20688, 22870,
+ 22261, 26035, 31511, 11458, 24110, 25299, 1434, 22734, 903, 20878,
+ 2903, 1810, 6794, 1625, 25018, 32472, 13992, 19184, 24420, 24784,
+ 18464, 6053, 43, 19206, 34, 30456, 2658, 30992, 16436, 18281,
+ 6490, 13452, 6358, 20362, 12584, 10698, 7009, 22616, 16297, 29893,
+ 821, 16843, 11972, 31320, 31251, 17836, 27631, 25006, 31688, 23719,
+ 2293, 16891, 7436, 31137, 23030, 22633, 14761, 3916, 13487, 23126,
+ 19936, 5112, 13563, 14268, 32520, 30636, 10906, 25072, 6008, 16501,
+ 5170, 27280, 31143, 16638, 19347, 3766, 20114, 7521, 18239, 626,
+ 29534, 4669, 5418, 4216, 27199, 12809, 29374, 25109, 21144, 3239,
+ 9762, 872, 11364, 30012, 31932, 30670, 27348, 23104, 4853, 29342,
+ 6713, 25553, 18748, 2071, 7461, 19533, 2637, 27286, 17613, 10015,
+ 18099, 2060, 18610, 2521, 18827, 7088, 24961, 19332, 19084, 2033,
+ 2871, 20019, 24900, 3247, 12936, 1759, 15780, 11690, 20866, 14190,
+ 18879, 23867, 16238, 3861, 6351, 16194, 14327, 9440, 18297, 6239,
+ 23950, 143, 12626, 15717, 15116, 9636, 8097, 5899, 2201, 21690,
+ 21863, 3557, 14285, 30488, 7324, 29331, 2838, 26758, 14524, 13881,
+ 15450, 4960, 25218, 1839, 30429, 4840, 12531, 9721, 10340, 20448,
+ 5023, 1657, 28059, 19289, 16932, 4451, 7604, 3014, 17651, 6642,
+ 14673, 24660, 31575, 23513, 16548, 28286, 17075, 5501, 13524, 15835,
+ 8971, 4705, 18595, 13883, 9413, 14817, 1103, 17395, 13233, 30244,
+ 24757, 5749, 13128, 1868, 7612, 11556, 10289, 5871, 22513, 9830,
+ 6922, 8139, 8559, 1274, 6244, 32181, 8706, 24460, 29199, 14803,
+ 652, 11910, 9625, 26379, 10151, 11306, 3089, 8891, 32651, 31454,
+ 14096, 3499, 26419, 1478, 7931, 20800, 27323, 20376, 1666, 1266,
+ 25869, 9132, 14188, 2047, 17084, 23891, 31895, 9057, 27696, 14698,
+ 32058, 2046, 6916, 26159, 23918, 32032, 7852, 17747, 18413, 21284,
+ 21595, 5200, 17689, 28278, 22051, 28412, 832, 32445, 9567, 24670,
+ 29726, 13906, 21582, 30145, 25507, 5623, 29440, 2056, 27639, 8390,
+ 17270, 12097, 27324, 3175, 30981, 5245, 23443, 16774, 1787, 5598,
+ 15329, 16516, 17029, 28913, 23507, 15981, 23504, 26430, 16543, 3627,
+ 29295, 4382, 31757, 10745, 18685, 21197, 7479, 28954, 23555, 10176,
+ 7820, 28106, 24603, 14393, 29979, 14197, 27478, 27928, 9487, 17703,
+ 19932, 30196, 32629, 17476, 24018, 30058, 27974, 18297, 14977, 18357,
+ 27553, 25074, 19124, 6015, 7512, 717, 31329, 13559, 5550, 9423,
+ 31628, 25380, 16479, 9814, 3689, 3961, 2785, 23951, 5313, 10153,
+ 13034, 15593, 29846, 445, 24114, 7114, 3594, 2659, 24442, 30592,
+ 18557, 11657, 19661, 16506, 31478, 11562, 19206, 1976, 13252, 23144,
+ 12946, 8320, 9061, 25820, 29047, 2643, 11942, 13354, 20117, 14111,
+ 27660, 32728, 29228, 438, 4211, 6496, 22431, 26751, 3829, 7299,
+ 3192, 24683, 28685, 31201, 24747, 21547, 9212, 4039, 27679, 9121,
+ 21612, 17736, 3434, 14228, 31060, 23439, 17885, 32167, 13595, 26995,
+ 5824, 24716, 15360, 13644, 17374, 4213, 19129, 24837, 8005, 12235,
+ 28762, 7283, 16967, 14371, 12153, 20965, 22468, 11118, 14992, 253,
+ 23468, 25967, 20386, 15294, 29631, 8563, 30498, 31205, 17815, 2108,
+ 10768, 13949, 28137, 23102, 9061, 2990, 32008, 2574, 24753, 16598,
+ 7338, 23319, 5635, 32475, 17135, 22671, 6409, 7871, 5791, 14505,
+ 1912, 18036, 26803, 12, 11438, 18418, 26392, 31109, 27287, 30344,
+ 27823, 22008, 10701, 26223, 4760, 2205, 5379, 19109, 26288, 13160,
+ 9123, 25848, 27480, 14281, 14262, 15457, 17529, 16278, 21253, 3476,
+ 13765, 21062, 10109, 10709, 22079, 19039, 1752, 14349, 7421, 16177,
+ 30074, 3101, 11052, 14021, 25753, 2162, 30550, 13329, 22433, 15834,
+ 15840, 30061, 30935, 15766, 23255, 30539, 24892, 20912, 28908, 3874,
+ 6068, 3983, 444, 12971, 2919, 30920, 23381, 16208, 3432, 7735,
+ 32502, 21986, 3477, 31055, 25879, 7818, 7870, 28590, 17065, 2306,
+ 1545, 13556, 13215, 23812, 22932, 32470, 28333, 12035, 29277, 16238,
+ 26192, 3354, 13663, 22997, 31502, 30786, 30718, 1268, 8959, 32199,
+ 933, 20631, 10892, 1277, 31918, 195, 29303, 9519, 12418, 13130,
+ 20252, 6104, 3841, 924, 27894, 6933, 21284, 8416, 24164, 22619,
+ 7904, 2628, 13997, 9061, 3662, 26001, 22082, 9585, 1546, 9218,
+ 19524, 18604, 16601, 26966, 28998, 30699, 24718, 26916, 8020, 1691,
+ 1582, 11887, 11060, 21755, 13650, 378, 747, 1161, 1741, 24541,
+ 5508, 20665, 28303, 15065, 26636, 24557, 6345, 28649, 31713, 8354,
+ 8786, 12185, 27181, 1767, 12362, 18075, 22701, 15892, 11005, 32024,
+ 11191, 8888, 8201, 68, 6523, 6355, 4036, 2613, 649, 4678,
+ 10712, 15349, 13203, 22919, 15664, 24022, 29812, 29849, 24344, 31237,
+ 2162, 13372, 3487, 1378, 960, 17249, 20800, 2703, 6727, 19168,
+ 8642, 2887, 19367, 32109, 4701, 3058, 4216, 8137, 2334, 32118,
+ 27861, 24885, 1421, 31055, 3099, 6188, 14988, 994, 18926, 14161,
+ 32642, 18702, 19581, 3751, 23737, 1797, 5127, 11520, 14085, 7002,
+ 9119, 30136, 24231, 26203, 10028, 16034, 1392, 30880, 15027, 2627,
+ 24618, 16100, 14041, 12862, 30515, 8212, 9891, 5648, 27243, 16806,
+ 19073, 8701, 11344, 26156, 19595, 16970, 30824, 6697, 2570, 5805,
+ 2272, 8995, 5690, 31234, 20338, 25849, 23118, 12863, 13708, 12663,
+ 30389, 23722, 10158, 13864, 18844, 27210, 28691, 31851, 16052, 16539,
+ 9365, 12233, 19509, 21126, 11211, 7814, 16675, 17807, 7540, 10358,
+ 18640, 30545, 536, 4114, 18338, 30503, 13804, 25035, 29974, 18477,
+ 29431, 26015, 22277, 32615, 18035, 20201, 550, 4671, 30070, 7805,
+ 17365, 26933, 5329, 27380, 6418, 2770, 22584, 837, 5837, 29405,
+ 23716, 8086, 10081, 27090, 29174, 5201, 16734, 28816, 10205, 15225,
+ 31627, 5202, 8697, 2111, 8747, 16096, 30529, 30928, 12672, 22279,
+ 8354, 23154, 22926, 17734, 15080, 5071, 28449, 12490, 8162, 27024,
+ 28177, 2205, 6849, 28974, 28869, 11546, 15298, 9733, 16630, 19876,
+ 3853, 21675, 26037, 20119, 15068, 20607, 21168, 19327, 18655, 10117,
+ 7345, 2440, 7904, 18545, 22375, 28214, 27299, 20225, 105, 20054,
+ 1296, 27280, 7032, 10549, 4243, 4841, 25604, 9231, 22212, 32601,
+ 14322, 22986, 10563, 5128, 8093, 21220, 18918, 14728, 5915, 14763,
+ 7703, 21167, 31937, 7852, 12663, 17570, 18665, 24941, 19400, 17715,
+ 29426, 4447, 7689, 25453, 10121, 23310, 19170, 32364, 13351, 21915,
+ 20035, 7795, 19419, 17516, 2121, 25656, 2378, 8482, 28513, 642,
+ 20980, 459, 11695, 30198, 32441, 12121, 11697, 28462, 28059, 84,
+ 23071, 8972, 24773, 19403, 5398, 30030, 20173, 2192, 10870, 12642,
+ 2102, 27813, 16777, 17787, 22073, 8433, 4581, 13284, 30404, 23863,
+ 24467, 11925, 6596, 73, 624, 4356, 17312, 30841, 31956, 11325,
+ 14597, 4177, 25970, 6453, 22505, 29572, 10367, 1371, 458, 35,
+ 25623, 11633, 31543, 14356, 25564, 31386, 25746, 26305, 32736, 30132,
+ 12308, 20237, 25285, 1255, 14609, 30092, 31522, 10110, 24702, 23283,
+ 7209, 9206, 21168, 15053, 4487, 23637, 23142, 8816, 10892, 15550,
+ 25866, 29744, 140, 30785, 7220, 10962, 31877, 2039, 14448, 28996,
+ 24577, 8271, 28993, 25227, 21822, 4259, 11878, 1532, 19085, 16655,
+ 24155, 23471, 7416, 17026, 5667, 3377, 22055, 9493, 24133, 5753,
+ 389, 2204, 20757, 31517, 23710, 7035, 28212, 23494, 26315, 31676,
+ 18266, 32738, 5138, 11870, 27219, 10136, 10056, 8431, 11336, 14849,
+ 30584, 26973, 14912, 9109, 9353, 14345, 4838, 30947, 32538, 12317,
+ 19853, 12678, 10161, 6688, 21105, 3924, 10517, 9415, 26688, 1496,
+ 4600, 10254, 15065, 13827, 20953, 7816, 16211, 21022, 23849, 18675,
+ 6465, 32259, 23725, 12304, 25908, 32653, 27683, 30898, 3202, 21325,
+ 11304, 15892, 1606, 31102, 11097, 26223, 10664, 3899, 27321, 9676,
+ 30047, 2032, 339, 8983, 28788, 6927, 8992, 29558, 2120, 14852,
+ 3882, 24537, 4056, 8810, 10482, 10449, 17472, 24703, 16655, 15525,
+ 31358, 21973, 20761, 5027, 23161, 6219, 11973, 9908, 19266, 15676,
+ 31313, 13363, 29849, 25846, 19491, 18175, 31155, 6766, 26029, 13263,
+ 20794, 23346, 27027, 198, 24214, 23454, 24336, 27464, 12395, 23379,
+ 1174, 11, 2146, 7653, 13748, 31089, 4141, 23508, 26685, 22549,
+ 24517, 16318, 1191, 27043, 14582, 17362, 7601, 12782, 7198, 904,
+ 19272, 27196, 6706, 21903, 11436, 2788, 2049, 16903, 21967, 4892,
+ 30397, 10481, 11262, 780, 5559, 11492, 30146, 15399, 24938, 13825,
+ 8713, 15290, 17339, 8489, 2689, 25541, 2431, 28525, 13637, 17931,
+ 20798, 2501, 22971, 9573, 22326, 27909, 11452, 8539, 17059, 21006,
+ 14326, 16373, 22590, 9793, 16527, 18895, 13828, 26682, 267, 11372,
+ 31800, 15546, 14960, 22220, 1963, 20452, 24744, 17473, 8507, 22189,
+ 26150, 10622, 18074, 17550, 27341, 30705, 28753, 2427, 21005, 11091,
+ 30980, 27673, 1103, 5501, 2551, 21548, 24467, 7293, 12497, 6478,
+ 6999, 7913, 672, 10727, 9147, 29299, 28702, 7769, 12260, 12478,
+ 12083, 3195, 6046, 18032, 23994, 12105, 11333, 30857, 16776, 14042,
+ 6373, 21491, 18858, 21650, 3488, 15193, 13551, 22424, 14928, 1853,
+ 423, 28042, 23662, 27717, 2729, 23408, 25651, 7126, 30107, 17135,
+ 29948, 21220, 22125, 18368, 17651, 19209, 11303, 10592, 8172, 16852,
+ 6885, 9480, 4493, 2659, 1823, 13279, 31410, 23860, 30254, 31087,
+ 5647, 23096, 22540, 30293, 12312, 28969, 7772, 21309, 5661, 9246,
+ 17578, 22542, 186, 22621, 11763, 25442, 32110, 10608, 31592, 30265,
+ 7050, 29307, 16495, 10222, 24653, 460, 14315, 5738, 17997, 10932,
+ 24253, 9879, 19480, 10645, 6027, 10519, 22044, 3645, 15295, 14135,
+ 26564, 8306, 15827, 23582, 30692, 29390, 16589, 24139, 25687, 6094,
+ 18693, 15678, 18663, 11557, 27182, 14196, 15724, 12630, 5780, 27801,
+ 16184, 22401, 29603, 28666, 18867, 19837, 22441, 24377, 25155, 10280,
+ 21725, 20804, 7023, 27131, 30111, 12679, 21315, 22498, 3585, 23393,
+ 12534, 4170, 18055, 2517, 9674, 6267, 17451, 28547, 30004, 21544,
+ 4516, 2774, 2109, 6980, 11752, 2686, 4136, 25112, 25584, 22049,
+ 15445, 10131, 20411, 3917, 1893, 7649, 13461, 7858, 24479, 16703,
+ 2201, 8590, 11922, 20749, 22901, 19304, 1020, 24356, 28269, 4097,
+ 26603, 26987, 19363, 10632, 6178, 12709, 31381, 20237, 13502, 18317,
+ 15335, 12088, 8218, 31013, 1635, 827, 5615, 7499, 30526, 19973,
+ 15808, 27789, 6044, 7096, 15477, 23614, 6999, 21854, 2374, 12233,
+ 31996, 31960, 2522, 13382, 6935, 25878, 14768, 23115, 15025, 14990,
+ 24767, 8709, 4886, 28646, 7513, 3463, 18140, 25332, 17749, 3425,
+ 28192, 19945, 25197, 7029, 5651, 22729, 19941, 30726, 22966, 24351,
+ 12142, 15634, 30689, 15854, 25417, 15330, 2698, 15850, 2991, 22751,
+ 17220, 28136, 20849, 22951, 20742, 404, 6108, 22880, 21294, 2146,
+ 10207, 22349, 32197, 4295, 5744, 5022, 21253, 2984, 27179, 11917,
+ 5656, 1043, 17468, 15782, 23331, 32557, 4224, 19302, 22659, 6251,
+ 231, 29960, 23895, 11781, 22557, 6812, 4414, 12712, 18281, 21849,
+ 24930, 29036, 25557, 10292, 16053, 27909, 30351, 7858, 4474, 2877,
+ 11407, 19962, 1544, 17314, 27002, 27694, 5834, 4219, 16838, 29179,
+ 30603, 15617, 24608, 31343, 17904, 25548, 23050, 21771, 9030, 12684,
+ 14281, 32282, 7038, 16377, 13182, 28993, 32118, 7437, 29587, 2646,
+ 2171, 21104, 17496, 26741, 4875, 308, 5358, 1873, 3807, 26050,
+ 15205, 713, 3625, 22548, 17441, 14524, 11802, 7205, 20610, 15645,
+ 2727, 5798, 18628, 21578, 8077, 14835, 25891, 26521, 14994, 16197,
+ 21059, 10292, 25358, 41, 29904, 21544, 23211, 1073, 4193, 20920,
+ 7017, 5865, 21923, 5367, 30437, 31244, 7091, 918, 15066, 2040,
+ 18635, 19194, 32488, 23136, 11809, 23697, 32660, 18753, 23308, 1127,
+ 10897, 22039, 11113, 19956, 16446, 22352, 5437, 11065, 11887, 30721,
+ 31132, 4619, 2160, 24536, 31945, 942, 16455, 5970, 10654, 12965,
+ 1338, 31789, 25646, 15049, 27537, 23073, 28586, 8089, 16797, 31691,
+ 2945, 1233, 13817, 18410, 27595, 21822, 13072, 16077, 4328, 19408,
+ 5087, 27660, 16996, 4849, 5629, 8311, 12574, 28181, 11480, 2124,
+ 1194, 8594, 6721, 29101, 22515, 3251, 28715, 22352, 26917, 10759,
+ 24495, 889, 202, 27135, 31060, 24357, 21555, 7096, 17038, 16776,
+ 26393, 22550, 17540, 21434, 12420, 8978, 30742, 23726, 1772, 14165,
+ 13087, 2403, 6046, 12293, 31479, 1374, 28002, 1247, 24637, 30551,
+ 19035, 3206, 18387, 13875, 22830, 31002, 17705, 18994, 31079, 781,
+ 27071, 3690, 11032, 13874, 11749, 1652, 24002, 5399, 22214, 15461,
+ 9849, 1685, 32164, 15103, 8516, 16805, 7269, 30761, 451, 11125,
+ 17231, 17309, 5908, 23484, 23568, 3553, 18166, 15178, 7681, 7032,
+ 17455, 28899, 6059, 30809, 1068, 4173, 29067, 16288, 14312, 16296,
+ 19986, 2948, 19471, 18174, 27376, 8585, 13410, 15899, 26514, 12022,
+ 1629, 19615, 21737, 10634, 10007, 12369, 29294, 10347, 4203, 32182,
+ 15459, 18783, 29013, 20195, 12123, 30270, 11678, 21647, 25852, 7848,
+ 188, 32108, 28164, 14835, 18420, 10168, 3466, 9575, 14273, 4366,
+ 14727, 12974, 121, 30851, 1172, 31366, 9774, 9966, 21749, 18361,
+ 4050, 20871, 3287, 11855, 4511, 2740, 2006, 8962, 30390, 13599,
+ 4546, 9970, 19975, 11532, 15011, 23450, 32368, 7146, 11258, 4867,
+ 26153, 10791, 25418, 12343, 2399, 841, 30167, 27641, 5151, 24635,
+ 16814, 20915, 13174, 3044, 12261, 2224, 2519, 5630, 27684, 15755,
+ 17084, 10278, 13669, 16360, 2448, 12591, 11255, 10337, 26573, 23228,
+ 16585, 6852, 20066, 32014, 10725, 30843, 20055, 1306, 59, 5963,
+ 17587, 223, 27296, 20546, 32158, 17910, 31254, 31466, 4803, 26219,
+ 6990, 10435, 2296, 26571, 16747, 13552, 28961, 28798, 11785, 31793,
+ 4177, 24407, 31358, 20753, 21299, 362, 18015, 97, 4265, 23070,
+ 12103, 31204, 24498, 12675, 30163, 29004, 1169, 23781, 29681, 2917,
+ 14636, 30113, 18523, 27537, 21682, 29239, 23390, 13684, 5760, 21921,
+ 8416, 22256, 6214, 26851, 15265, 11860, 11109, 13028, 26049, 24784,
+ 9628, 8828, 17027, 29997, 24804, 7886, 32080, 1722, 29336, 29144,
+ 23039, 9354, 24025, 16712, 6739, 12508, 17713, 2449, 23749, 21723,
+ 24438, 20287, 22660, 23688, 13298, 31367, 6843, 3828, 25024, 4387,
+ 10514, 22194, 30329, 16989, 11639, 20108, 6161, 31081, 3870, 1653,
+ 1531, 27127, 7366, 5311, 13716, 19209, 11327, 18318, 3518, 13314,
+ 21289, 2701, 1483, 20480, 7422, 21727, 11166, 23404, 25171, 13145,
+ 21772, 8144, 9562, 17134, 136, 25064, 6060, 12138, 10496, 30203,
+ 11589, 2660, 4354, 28267, 24784, 3693, 18723, 6284, 3366, 8846,
+ 30113, 15282, 17, 12786, 5959, 20110, 10837, 11231, 23441, 5818,
+ 4337, 16363, 14353, 26258, 25506, 10860, 21777, 27974, 23721, 9520,
+ 2938, 19757, 19918, 20590, 31221, 27740, 32421, 10237, 30031, 13176,
+ 16400, 22724, 22562, 11976, 22789, 2674, 30130, 17806, 12433, 29039,
+ 13333, 31640, 22813, 15634, 4503, 28946, 24817, 13844, 6492, 5278,
+ 3062, 8516, 2887, 15271, 23232, 14973, 15131, 5361, 715, 23509,
+ 27360, 10613, 15365, 9496, 9353, 24429, 1933, 14197, 22227, 13227,
+ 21435, 22902, 14704, 7470, 8544, 5942, 15461, 20215, 3663, 13006,
+ 1713, 19481, 26908, 30992, 18479, 528, 12835, 20088, 25277, 23891,
+ 11724, 2143, 11934, 3117, 27662, 26226, 24093, 25544, 26930, 16483,
+ 17523, 7051, 11226, 15326, 1003, 21157, 1089, 7871, 26436, 5098,
+ 20676, 4482, 27223, 19423, 27554, 26106, 13818, 25872, 9728, 13894,
+ 4899, 32426, 29744, 28674, 6481, 28997, 12082, 8122, 7207, 5634,
+ 3963, 4260, 7258, 982, 17654, 5262, 16334, 14117, 20553, 2069,
+ 5372, 22419, 345, 26392, 9623, 4119, 16144, 1388, 7279, 11601,
+ 31838, 16337, 661, 30237, 32381, 14629, 22464, 29288, 22650, 30680,
+ 2543, 5186, 16369, 30624, 4176, 30517, 7960, 878, 11617, 10709,
+ 2046, 27552, 7253, 13721, 27925, 27768, 11705, 22761, 17135, 22733,
+ 5975, 10104, 28485, 23808, 31579, 1236, 10557, 28210, 27316, 11580,
+ 12012, 14772, 26301, 16561, 29722, 10431, 9757, 1103, 11846, 19558,
+ 8428, 19934, 25066, 17864, 10263, 19877, 21761, 32394, 3077, 10878,
+ 2757, 17797, 5754, 9264, 11453, 9147, 23484, 12280, 1271, 32144,
+ 9973, 17257, 28051, 21559, 1497, 16759, 22913, 15210, 14216, 15822,
+ 23178, 22366, 694, 2664, 18581, 30454, 14089, 17246, 28195, 7735,
+ 24002, 19710, 24093, 5372, 23968, 30751, 22223, 19946, 5633, 16561,
+ 22068, 14759, 13643, 23192, 17268, 23111, 20106, 187, 20907, 11015,
+ 29275, 14935, 32748, 12350, 20232, 2714, 23174, 17296, 7156, 15981,
+ 24965, 28773, 21562, 19601, 14460, 29849, 1169, 31725, 898, 14710,
+ 12403, 17446, 5499, 22751, 4734, 7281, 21401, 717, 15386, 11429,
+ 29218, 22272, 22620, 5269, 28275, 1774, 5674, 15772, 27205, 21504,
+ 32160, 27257, 19503, 15869, 13491, 31069, 18796, 30150, 30484, 3139,
+ 15583, 26693, 17751, 2944, 28500, 30112, 3925, 13979, 13577, 10418,
+ 24015, 14174, 1133, 699, 16212, 27437, 27175, 12118, 31844, 22167,
+ 32346, 13484, 22229, 30507, 16167, 29672, 22646, 26509, 29812, 3563,
+ 29939, 2505, 236, 64, 760, 11238, 17479, 3666, 20633, 23231,
+ 29388, 19164, 22258, 22286, 1556, 21922, 20746, 24778, 11024, 8543,
+ 14846, 19635, 20814, 22014, 30299, 6187, 16247, 8972, 11467, 28487,
+ 20765, 5742, 4596, 22822, 16819, 19279, 11165, 32385, 10461, 1373,
+ 20242, 16004, 3051, 3125, 24266, 1500, 10399, 23323, 2888, 7186,
+ 23863, 30959, 6975, 23319, 20903, 3164, 32505, 1312, 17959, 83,
+ 13049, 11443, 10989, 19640, 13792, 25346, 25916, 14171, 5517, 8313,
+ 26013, 8489, 22408, 7059, 29549, 13220, 16545, 497, 20887, 656,
+ 16340, 18349, 8355, 30191, 112, 236, 8688, 4144, 26489, 31154,
+ 16445, 25764, 74, 32763, 366, 21041, 7294, 5127, 17805, 22090,
+ 11025, 29429, 30480, 3102, 2755, 12179, 4186, 11280, 23485, 19829,
+ 6788, 8040, 5239, 4676, 2396, 31816, 24025, 345, 6318, 32225,
+ 31393, 13706, 3779, 19686, 15876, 3396, 2088, 11329, 21912, 23771,
+ 12464, 24070, 27249, 6941, 3516, 21669, 23946, 15405, 15802, 1123,
+ 9063, 11919, 20716, 26891, 761, 11903, 8043, 5088, 15298, 25479,
+ 16491, 21975, 22330, 31824, 1728, 23043, 10608, 15545, 9890, 17489,
+ 17652, 12838, 26797, 10357, 26101, 538, 3627, 27940, 6311, 1801,
+ 19094, 28548, 7911, 12135, 30297, 31457, 22818, 21253, 24279, 26785,
+ 13939, 29341, 22446, 31866, 28683, 5548, 28989, 20706, 5078, 14975,
+ 30820, 26567, 8796, 3217, 9098, 13185, 17381, 21780, 4325, 11269,
+ 22752, 22990, 31221, 17499, 27013, 7718, 16466, 21586, 14522, 14975,
+ 14248, 19058, 32307, 15812, 20736, 14898, 3038, 19780, 2881, 6763,
+ 25214, 30401, 19702, 18445, 31125, 26819, 2897, 8465, 16008, 1330,
+ 25200, 19374, 3838, 548, 736, 32208, 12937, 3316, 6240, 22726,
+ 6024, 9108, 3559, 11578, 22348, 6180, 21224, 15207, 17785, 29379,
+ 1492, 17286, 3759, 9637, 10209, 31369, 10858, 18277, 15882, 14092,
+ 9255, 18333, 854, 27273, 32713, 20917, 4190, 15051, 15674, 20984,
+ 7177, 20389, 16213, 20717, 14747, 10467, 6660, 6372, 14318, 4225,
+ 2981, 22991, 1534, 32027, 9651, 16211, 16556, 30885, 26786, 11551,
+ 19899, 24412, 22282, 5501, 10271, 2812, 17416, 7718, 16759, 15924,
+ 24802, 1883, 7384, 25687, 19945, 2353, 1740, 31060, 12964, 6957,
+ 3738, 11752, 8490, 23056, 9416, 7186, 18640, 32756, 735, 8136,
+ 15364, 8856, 16494, 10216, 19833, 11257, 14673, 4977, 18565, 16674,
+ 10547, 28403, 2247, 2884, 8274, 9796, 13580, 5897, 13698, 32373,
+ 8563, 15910, 6517, 27652, 7376, 20272, 28473, 6483, 11599, 26544,
+ 3586, 12633, 90, 13433, 4138, 17048, 4540, 3129, 21366, 20047,
+ 19974, 6223, 20123, 22512, 13361, 32732, 24577, 2260, 14982, 18717,
+ 31174, 15406, 31419, 25848, 20230, 1854, 26975, 6356, 26202, 4551,
+ 7288, 15022, 13726, 21186, 25962, 29545, 11000, 1364, 16922, 31590,
+ 18197, 27134, 26964, 1365, 11446, 10260, 30314, 19275, 18796, 25456,
+ 30750, 29204, 31647, 23143, 26306, 14026, 22997, 8188, 17822, 6822,
+ 32561, 18004, 29586, 279, 314, 3434, 28413, 29713, 29407, 27140,
+ 4317, 680, 6327, 30950, 823, 28125, 12941, 12869, 30393, 6072,
+ 32283, 29054, 23454, 26775, 22294, 9480, 8658, 7877, 6251, 15015,
+ 17494, 15438, 8905, 7139, 9191, 1810, 11359, 20153, 29914, 20249,
+ 15847, 3728, 17483, 28454, 227, 29039, 22646, 15247, 17190, 28012,
+ 28773, 21323, 21399, 21096, 9932, 1869, 7218, 3065, 31793, 19472,
+ 7503, 16296, 19535, 26996, 11815, 7005, 12989, 23752, 9876, 26647,
+ 8907, 8488, 22040, 13536, 13997, 21001, 27681, 11777, 31195, 23570,
+ 13707, 29810, 12983, 12334, 21351, 2452, 28528, 11487, 20219, 8994,
+ 23079, 12757, 12041, 31589, 6225, 4543, 29269, 29096, 14685, 22113,
+ 4961, 3820, 30870, 2790, 31099, 17117, 22090, 120, 31481, 27908,
+ 19500, 16655, 21700, 1597, 8439, 9350, 15123, 32364, 8020, 15348,
+ 26489, 8812, 13310, 1849, 18466, 7752, 14116, 10455, 13402, 28590,
+ 25871, 3076, 19022, 23712, 18948, 12541, 23063, 17005, 9580, 5020,
+ 500, 20704, 2098, 24621, 24535, 1463, 12909, 27262, 31780, 31830,
+ 29759, 6965, 20917, 26045, 5628, 18278, 5921, 15544, 2959, 9829,
+ 11582, 2645, 30490, 23001, 22244, 20123, 16093, 15378, 7668, 24953,
+ 14937, 26781, 2457, 24573, 15029, 13077, 2510, 31175, 29280, 59,
+ 15393, 12988, 32760, 13641, 28086, 27903, 8299, 12676, 32398, 20253,
+ 19548, 1553, 2569, 23175, 17608, 24585, 30890, 17990, 21225, 22736,
+ 24347, 29162, 16218, 8354, 20081, 1219, 17533, 14190, 31152, 3412,
+ 26, 10216, 21650, 13573, 10312, 30938, 3972, 23576, 1937, 18618,
+ 5362, 12766, 1105, 18306, 27588, 7467, 14175, 700, 9001, 2311,
+ 21999, 14300, 11155, 27046, 29367, 8403, 16643, 3483, 23121, 28385,
+ 19078, 3912, 3809, 26539, 21247, 31385, 9975, 22669, 32552, 31474,
+ 5047, 21553, 9428, 9573, 4663, 28257, 26487, 13097, 19496, 27161,
+ 32231, 16455, 27577, 3553, 1380, 25239, 9912, 4697, 1495, 11499,
+ 1274, 24342, 2903, 29322, 26110, 2476, 30961, 24288, 2509, 19212,
+ 30889, 13683, 8484, 24337, 11452, 19993, 10453, 597, 1576, 8553,
+ 5227, 585, 25710, 31087, 3085, 4997, 25239, 6820, 16805, 25180,
+ 30069, 31004, 8513, 4532, 16171, 19970, 24761, 7188, 15344, 8514,
+ 12946, 19199, 11279, 7045, 8226, 14465, 24370, 13410, 20213, 3847,
+ 17633, 4306, 13680, 31604, 26182, 9701, 692, 1392, 11571, 29620,
+ 15813, 16899, 7270, 27799, 24556, 5220, 23819, 23704, 28249, 28939,
+ 17794, 25895, 22285, 22285, 15715, 24847, 5367, 29609, 8895, 17576,
+ 24413, 9246, 5289, 20046, 26750, 18880, 18165, 6931, 28534, 9291,
+ 17216, 29617, 10593, 9847, 15153, 26051, 17859, 30925, 20477, 32052,
+ 4648, 7864, 29489, 12791, 263, 29151, 17580, 24056, 6124, 26546,
+ 4586, 20307, 2262, 21827, 23177, 19141, 31454, 9560, 32261, 4703,
+ 17946, 13502, 30407, 17538, 9921, 18656, 18014, 9991, 11152, 21656,
+ 30476, 12990, 25452, 32580, 22148, 29466, 3656, 8733, 19954, 3626,
+ 21833, 12228, 31548, 2251, 20008, 14878, 28551, 6941, 19929, 2658,
+ 14078, 10547, 20074, 32624, 3534, 13327, 27693, 9829, 26229, 22221,
+ 15897, 16748, 9533, 9246, 3438, 12503, 13571, 30712, 12440, 29294,
+ 22845, 4492, 3414, 11014, 24892, 2425, 1563, 28246, 8366, 30783,
+ 22197, 14599, 20838, 24822, 9260, 20746, 16992, 13376, 17389, 46,
+ 30719, 32636, 32295, 23794, 8602, 7228, 20342, 5527, 2103, 29689,
+ 28095, 29050, 23190, 11270, 5211, 31905, 31346, 19907, 23415, 4500,
+ 12035, 16147, 7866, 13678, 24775, 7952, 14121, 31283, 17026, 23293,
+ 3144, 23396, 2948, 3963, 16514, 18641, 10026, 2560, 31947, 21423,
+ 32167, 32390, 8068, 12778, 14852, 17792, 21151, 3005, 12646, 13842,
+ 19715, 18303, 20368, 28801, 17202, 18368, 11432, 11497, 19241, 20372,
+ 12350, 25134, 14216, 303, 25994, 22836, 11762, 10930, 25845, 83,
+ 31927, 21829, 30428, 4869, 29616, 19046, 21392, 27106, 17515, 896,
+ 9377, 1743, 11656, 14272, 11100, 12658, 30051, 31780, 12434, 14313,
+ 30708, 10709, 8603, 10171, 19443, 32438, 32411, 4878, 17215, 11325,
+ 32260, 13851, 19072, 18562, 2396, 4320, 27659, 21909, 30529, 18708,
+ 31239, 21269, 9898, 26720, 9166, 3582, 24431, 19148, 31382, 8899,
+ 7180, 20856, 10577, 26013, 8354, 11660, 25554, 9506, 830, 22385,
+ 20784, 31513, 2398, 1602, 30063, 8077, 32433, 15229, 24157, 29216,
+ 26911, 14079, 6075, 11682, 15881, 26415, 10909, 31202, 31954, 10617,
+ 11284, 20420, 21150, 28414, 7945, 25492, 11097, 6537, 11628, 2458,
+ 21500, 9413, 31887, 18671, 4619, 28590, 8396, 4239, 21602, 14918,
+ 29806, 17070, 24882, 11145, 21967, 2640, 9543, 29602, 4285, 12052,
+ 2188, 24159, 30498, 23376, 27600, 27107, 27876, 2147, 13258, 13723,
+ 27403, 1351, 1371, 23923, 15906, 19302, 5908, 5449, 991, 5551,
+ 15352, 6305, 11270, 28136, 2947, 17051, 138, 9286, 19179, 25123,
+ 30965, 25915, 31653, 7784, 23819, 24975, 13099, 32655, 31402, 15538,
+ 8189, 28584, 29429, 13649, 24549, 18401, 25266, 15399, 2944, 15865,
+ 27119, 27926, 6906, 17912, 22252, 7798, 2073, 15390, 30773, 31405,
+ 20861, 27417, 23055, 22527, 17190, 17019, 29461, 17064, 10294, 20842,
+ 1059, 27944, 18936, 22937, 12147, 31455, 24610, 3704, 2822, 22745,
+ 22103, 21672, 12870, 6379, 2800, 5554, 6889, 767, 27388, 31736,
+ 12568, 20652, 3973, 10988, 32465, 18186, 16406, 18303, 25226, 8900,
+ 32377, 25821, 6423, 2670, 32709, 10583, 7885, 31513, 13977, 16288,
+ 11240, 25381, 21154, 26685, 20522, 24407, 22883, 16183, 29125, 20011,
+ 15413, 2579, 13179, 11628, 3980, 8707, 1540, 30209, 18301, 20062,
+ 26800, 27146, 7549, 9038, 7501, 2348, 876, 14537, 21323, 7976,
+ 18386, 19906, 3614, 8371, 20328, 11168, 19172, 19074, 2010, 24047,
+ 10568, 13988, 30667, 4693, 7078, 23572, 4121, 13512, 25200, 11407,
+ 8803, 7167, 22224, 17571, 8393, 23078, 18574, 25097, 2803, 1494,
+ 29493, 5172, 11349, 3908, 20081, 23338, 4017, 30137, 15804, 10387,
+ 19421, 28994, 25401, 30479, 3526, 25768, 6624, 27597, 949, 11170,
+ 23260, 13914, 3537, 6474, 4657, 8886, 22502, 15054, 9890, 4525,
+ 16484, 12904, 14546, 19300, 12459, 16016, 23977, 24627, 19077, 16752,
+ 22521, 2994, 3828, 23704, 5474, 19991, 25135, 29939, 29299, 12223,
+ 4327, 13049, 2577, 25354, 15054, 21287, 5149, 14444, 18010, 23212,
+ 5969, 6337, 16838, 1126, 29291, 31201, 21851, 31244, 142, 373,
+ 10989, 11693, 23781, 18953, 28328, 26457, 2441, 32354, 19725, 23326,
+ 32165, 16145, 4663, 23350, 24280, 1608, 20067, 31358, 27098, 32237,
+ 9135, 13098, 20067, 31725, 8482, 26039, 584, 6355, 20205, 17442,
+ 20455, 5273, 20464, 32088, 9158, 32189, 15488, 15597, 23927, 20120,
+ 6760, 21264, 10175, 29932, 5677, 6335, 7159, 30652, 24983, 25655,
+ 13489, 12128, 23404, 8623, 21407, 17368, 25727, 25669, 24241, 25953,
+ 1513, 825, 14462, 29510, 19607, 5977, 6117, 1273, 32261, 27836,
+ 756, 2402, 2632, 15539, 28936, 28791, 24402, 17405, 22582, 4877,
+ 370, 2362, 10730, 19693, 3354, 26530, 718, 32043, 1509, 12791,
+ 4590, 24755, 5848, 440, 31513, 31525, 10217, 1688, 14474, 483,
+ 27837, 27183, 16328, 32104, 20662, 7150, 28106, 5339, 25645, 6488,
+ 32351, 14307, 12028, 1647, 4813, 6846, 3136, 10861, 3000, 14477,
+ 29533, 9397, 14918, 20466, 21058, 28169, 11393, 3549, 23790, 31229,
+ 6397, 23203, 30258, 3244, 11706, 32081, 5561, 6313, 17995, 2367,
+ 20295, 14649, 19768, 18920, 24382, 7359, 19618, 8440, 24678, 29559,
+ 29221, 2727, 3821, 13927, 2563, 15430, 15533, 23187, 13694, 4375,
+ 23214, 17521, 24709, 14690, 15340, 3996, 14995, 24517, 30042, 32460,
+ 14037, 14540, 32550, 10246, 22411, 12482, 31551, 12560, 18608, 11206,
+ 17685, 12328, 3549, 3105, 11936, 1269, 18283, 29398, 3747, 15806,
+ 21208, 28283, 1074, 23770, 19051, 3144, 4978, 4712, 10267, 32622,
+ 32672, 15936, 4014, 21161, 1620, 20009, 1054, 22553, 24583, 19532,
+ 3136, 19278, 10707, 12776, 2727, 22946, 7291, 21064, 19655, 1227,
+ 13483, 29170, 5462, 5040, 12417, 24098, 9720, 1404, 1611, 6262,
+ 3098, 15089, 14483, 27371, 13598, 18944, 11097, 30728, 3513, 12182,
+ 24223, 7001, 12442, 21432, 12843, 11807, 26701, 5074, 5768, 1094,
+ 2142, 18252, 20302, 13719, 25025, 29279, 10915, 1839, 22129, 6951,
+ 20994, 2352, 20568, 29945, 6203, 15542, 8047, 22006, 26811, 22029,
+ 806, 10976, 15374, 28449, 25350, 23853, 13730, 15925, 31381, 24410,
+ 20174, 9432, 31866, 21378, 13074, 11029, 28897, 47, 12705, 15083,
+ 21281, 1904, 26652, 12285, 12956, 5164, 2721, 3977, 23271, 29109,
+ 27908, 31902, 18220, 16800, 12636, 15498, 25804, 17365, 16322, 24466,
+ 26952, 25826, 27477, 25063, 16225, 1685, 26754, 22741, 20350, 14025,
+ 30850, 60, 10063, 18560, 28195, 15428, 17584, 818, 28620, 25421,
+ 2000, 23653, 6843, 25637, 4242, 28542, 27538, 7294, 2867, 10199,
+ 4114, 29599, 12334, 20753, 1574, 3417, 31580, 428, 11299, 10557,
+ 24160, 5076, 9806, 524, 29250, 8318, 15775, 16751, 27738, 12468,
+ 7108, 23528, 23152, 6445, 2153, 26889, 27169, 13345, 2999, 19428,
+ 16260, 27995, 6682, 16322, 7950, 21648, 11592, 7448, 28339, 10735,
+ 28287, 27318, 21070, 6393, 22029, 3906, 26435, 5523, 25622, 14053,
+ 25443, 3930, 22162, 16708, 6928, 28470, 149, 19378, 12961, 4914,
+ 9939, 11171, 32520, 15499, 1379, 28004, 22961, 9222, 25283, 11018,
+ 27566, 10375, 21533, 20393, 13330, 19424, 5832, 6854, 19866, 29159,
+ 8978, 30734, 14227, 5579, 23613, 32584, 9719, 27048, 455, 12424,
+ 7386, 5208, 17903, 16549, 23300, 397, 11636, 2542, 22496, 30748,
+ 7328, 29977, 22677, 27292, 13701, 28284, 24690, 13872, 27527, 15232,
+ 143, 17313, 28698, 17490, 19121, 16048, 23757, 9691, 27503, 22442,
+ 16008, 8179, 12179, 17212, 26129, 13265, 30915, 27785, 8661, 1734,
+ 25953, 3450, 17638, 23852, 12207, 8533, 8000, 16793, 2103, 26002,
+ 19280, 11352, 28522, 23786, 29879, 16153, 21127, 2224, 31819, 26855,
+ 28606, 19556, 7518, 1627, 17814, 12166, 30788, 21007, 4492, 29096,
+ 9743, 14678, 8700, 9415, 14749, 26922, 32581, 16859, 20949, 10086,
+ 12329, 27565, 8493, 19510, 7538, 21481, 3695, 28619, 22747, 30324,
+ 21182, 8275, 19245, 7935, 14548, 13352, 3497, 27869, 24973, 3143,
+ 29350, 18705, 12713, 23301, 379, 684, 19661, 17149, 27039, 1366,
+ 16844, 25165, 12559, 24106, 19493, 7682, 8688, 711, 20173, 16848,
+ 15222, 3747, 27694, 18439, 10756, 27299, 24431, 24002, 2709, 4841,
+ 31478, 30561, 32090, 28398, 28715, 2362, 19364, 28624, 17535, 14476,
+ 9477, 26861, 6062, 6324, 14258, 22192, 8000, 18596, 10284, 1963,
+ 31574, 1168, 11296, 23526, 18595, 32746, 19595, 3703, 5049, 7057,
+ 4897, 15699, 4486, 19526, 9968, 9060, 16670, 17759, 7233, 14556,
+ 23227, 15295, 31679, 11720, 12289, 21765, 17627, 29416, 24967, 5892,
+ 28526, 17598, 3476, 27508, 12448, 27877, 23590, 3046, 1802, 11684,
+ 3129, 27134, 21015, 3011, 26181, 26588, 30896, 27293, 14345, 29915,
+ 25368, 11895, 15751, 25214, 19476, 22800, 6992, 1447, 11600, 21625,
+ 19969, 30730, 19198, 24615, 13070, 3554, 8896, 21575, 3774, 21474,
+ 16840, 12113, 13175, 10607, 17981, 8672, 11836, 19212, 4065, 3265,
+ 7284, 24854, 25586, 9546, 3821, 26289, 2126, 13293, 7712, 32002,
+ 6618, 8461, 5047, 32415, 8739, 17423, 19788, 26435, 12358, 10421,
+ 15476, 25543, 30990, 16039, 10236, 7757, 16989, 10067, 4722, 6847,
+ 7629, 5623, 27111, 14200, 13974, 30204, 25844, 9792, 14003, 19334,
+ 12539, 29054, 1856, 585, 21935, 25001, 28711, 7838, 29143, 22272,
+ 23291, 1238, 13647, 27515, 15652, 19150, 15439, 28929, 27965, 18371,
+ 12271, 8155, 26554, 22120, 20459, 2409, 18126, 32054, 18852, 8979,
+ 29068, 28932, 104, 32131, 17996, 9687, 10995, 31761, 17488, 25083,
+ 27190, 8319, 30887, 1875, 15703, 16103, 12882, 1773, 30456, 11761,
+ 16806, 13017, 6076, 18249, 18161, 25148, 12807, 19537, 21600, 7072,
+ 15110, 787, 26400, 14734, 27888, 8057, 31684, 15711, 7819, 19648,
+ 16871, 17487, 13297, 27434, 13074, 21203, 3220, 22003, 4320, 27181,
+ 4736, 17799, 3679, 7229, 20192, 8690, 10426, 4506, 10180, 22936,
+ 29461, 13793, 11041, 4134, 22969, 32333, 2841, 14792, 8305, 32392,
+ 12157, 30365, 8243, 16321, 145, 17000, 2051, 3583, 20239, 19592,
+ 9493, 12213, 32110, 3114, 30258, 15254, 20067, 25789, 3676, 170,
+ 31913, 28326, 2741, 13474, 32766, 14389, 8093, 23657, 9070, 4824,
+ 283, 8955, 20691, 16527, 10878, 4730, 13725, 5536, 18756, 25471,
+ 9423, 25228, 20282, 22190, 23114, 14913, 28645, 19597, 846, 26769,
+ 3361, 3990, 12350, 11491, 22280, 1162, 5027, 3369, 8981, 13577,
+ 12916, 21778, 16009, 26720, 27029, 5504, 16398, 16034, 27805, 14396,
+ 7323, 506, 8668, 31721, 919, 8767, 32669, 27702, 17985, 3785,
+ 20136, 10840, 20047, 25219, 30219, 6584, 26581, 5698, 13338, 17640,
+ 25193, 11605, 26805, 3804, 19845, 4190, 21705, 1111, 21549, 2656,
+ 29465, 24995, 31697, 7192, 20031, 8325, 19060, 6545, 30701, 8816,
+ 6158, 17907, 1401, 19193, 3887, 24987, 13721, 7819, 8422, 24177,
+ 9067, 14684, 28641, 11894, 10936, 12959, 30421, 24733, 24953, 16380,
+ 28193, 32732, 19098, 11581, 13486, 26754, 9727, 31818, 16409, 1995,
+ 453, 16727, 22548, 14770, 28874, 3932, 8457, 14598, 2671, 2245,
+ 14849, 21952, 6044, 26731, 29125, 26004, 4357, 5828, 22338, 8902,
+ 21164, 8022, 10546, 27967, 10407, 6770, 26873, 8672, 6436, 24350,
+ 5325, 31766, 4010, 4435, 19738, 13743, 19874, 24681, 26917, 22764,
+ 17429, 2511, 16111, 30935, 15031, 29695, 8796, 17366, 26661, 30129,
+ 24468, 9345, 24427, 7503, 13482, 25777, 30409, 3242, 3708, 1753,
+ 2999, 15595, 3290, 18842, 18470, 16076, 4586, 2449, 19721, 19208,
+ 24778, 30068, 26132, 14095, 3960, 18525, 10947, 8703, 20463, 32357,
+ 12447, 28112, 21651, 14197, 12989, 22734, 21455, 15449, 21127, 19277,
+ 28413, 23062, 21950, 11672, 134, 1918, 1472, 23082, 5450, 2305,
+ 5127, 33, 5442, 1734, 10227, 2543, 24419, 18683, 31177, 23635,
+ 23750, 3689, 7931, 392, 20231, 12619, 27562, 5308, 24043, 3680,
+ 3433, 451, 10309, 25151, 17220, 27917, 23578, 4331, 22273, 22485,
+ 6659, 2983, 15269, 21660, 10195, 18699, 30010, 24534, 13946, 856,
+ 11728, 12515, 16169, 12553, 7106, 5952, 15287, 27562, 7482, 14335,
+ 15940, 14573, 11511, 16244, 11292, 27131, 5198, 23346, 8157, 1288,
+ 32367, 4150, 14045, 27946, 20714, 16737, 19910, 15467, 28018, 31276,
+ 28803, 1053, 16608, 20887, 352, 26477, 17275, 31074, 23404, 17467,
+ 20086, 19840, 29730, 24105, 27322, 30665, 16457, 16370, 31974, 31727,
+ 24601, 18174, 29332, 16307, 22175, 3379, 21727, 25432, 20579, 9485,
+ 25634, 32344, 15687, 23537, 8449, 5207, 16818, 30398, 26286, 22101,
+ 17134, 7334, 31333, 1063, 4815, 25660, 13369, 552, 32406, 14029,
+ 9491, 30508, 17684, 32244, 24056, 1717, 14355, 20329, 15498, 31594,
+ 3313, 2842, 24786, 30148, 8334, 8061, 12348, 29451, 12905, 26660,
+ 2531, 16513, 23301, 23186, 4111, 11997, 16786, 30029, 11004, 6650,
+ 21705, 9524, 10462, 6353, 2840, 5395, 7969, 27045, 28159, 7029,
+ 28917, 28285, 29882, 15033, 7946, 19927, 29216, 26472, 17560, 2971,
+ 6603, 2246, 26019, 11854, 24697, 26535, 29309, 17544, 15282, 32644,
+ 9356, 24232, 1195, 26062, 6221, 20678, 619, 15234, 18585, 20713,
+ 24364, 23806, 20264, 17786, 3332, 17427, 3667, 22521, 24004, 20571,
+ 10270, 8175, 21025, 27085, 26229, 31268, 25617, 12686, 30902, 24593,
+ 20600, 13578, 10864, 21400, 9220, 22340, 30571, 13043, 3925, 25706,
+ 8424, 2283, 18018, 941, 10281, 11594, 28440, 31568, 21044, 18834,
+ 25412, 31486, 6357, 5615, 18866, 24672, 11490, 25195, 19094, 10735,
+ 28098, 16481, 25388, 3079, 31280, 24628, 7324, 23613, 15933, 30528,
+ 10784, 18163, 8852, 16913, 12904, 810, 16642, 30419, 18494, 30871,
+ 16950, 15370, 22118, 3064, 18629, 30596, 712, 1448, 3441, 2443,
+ 19665, 18033, 4266, 18527, 27414, 16034, 1365, 20451, 11322, 23394,
+ 22733, 31126, 24338, 24132, 31783, 4293, 1544, 21276, 21179, 5887,
+ 22973, 6160, 27103, 11466, 24307, 11250, 24054, 29332, 5033, 14029,
+ 4266, 30188, 30599, 189, 5237, 32498, 29565, 19204, 29030, 21004,
+ 25768, 16219, 10018, 14811, 20085, 27014, 4137, 28014, 30728, 28459,
+ 2650, 9909, 30943, 31204, 2234, 32056, 30898, 1939, 29297, 22792,
+ 9886, 5366, 29461, 4598, 11139, 22139, 8235, 3844, 7083, 29525,
+ 6123, 31257, 11180, 30415, 32068, 23545, 11407, 27616, 29984, 13427,
+ 4913, 22272, 2281, 25309, 3818, 571, 4684, 29373, 29549, 20356,
+ 5181, 8393, 31215, 1355, 9531, 11282, 7564, 18770, 20181, 18300,
+ 5862, 15804, 1645, 16241, 15119, 29799, 9020, 10198, 16809, 11387,
+ 30102, 9790, 13899, 3651, 25455, 11358, 6439, 22844, 11807, 14018,
+ 29418, 14444, 17762, 25534, 24548, 12533, 19363, 30374, 22121, 24298,
+ 12154, 6977, 11383, 29793, 32371, 32124, 8344, 11978, 21777, 2396,
+ 27146, 13951, 4114, 26422, 5150, 7324, 8949, 2082, 10462, 27408,
+ 14266, 22189, 28402, 31476, 31721, 24526, 16069, 1308, 16085, 2076,
+ 13027, 8428, 17698, 8509, 14246, 9581, 30085, 29602, 15889, 8352,
+ 17099, 4209, 5628, 22803, 30493, 32707, 13169, 3505, 17538, 7952,
+ 25431, 26590, 16037, 17383, 13133, 21444, 8665, 30435, 4313, 13031,
+ 2906, 23258, 25538, 7424, 1749, 5207, 10170, 8968, 5419, 17739,
+ 18752, 18579, 4211, 28927, 18885, 10079, 4414, 23629, 28430, 28973,
+ 14622, 15888, 473, 17359, 1641, 21465, 24515, 899, 5434, 12004,
+ 25705, 12159, 29113, 19786, 28110, 25805, 24476, 21367, 32765, 857,
+ 15086, 31199, 19439, 10569, 22031, 749, 7598, 30860, 30973, 19772,
+ 30139, 23222, 26065, 22026, 20909, 14091, 1677, 16362, 26652, 20185,
+ 10260, 12728, 23485, 13324, 26234, 8658, 10702, 3580, 11902, 24965,
+ 22453, 8329, 30805, 31942, 9188, 18794, 8106, 16931, 15871, 26562,
+ 31970, 1785, 19009, 25076, 9124, 31718, 13340, 15801, 27289, 9601,
+ 5151, 32368, 8304, 19785, 11549, 15797, 4646, 32476, 17548, 12852,
+ 18052, 25962, 23083, 6335, 4841, 7528, 744, 13215, 27977, 20105,
+ 27392, 21544, 8054, 8682, 17256, 8849, 16286, 26764, 7788, 6146,
+ 4629, 1544, 32662, 24301, 14421, 29566, 8913, 3490, 20804, 28367,
+ 16078, 28446, 28341, 10764, 18087, 20004, 1072, 3886, 28354, 30352,
+ 13046, 27655, 30969, 24807, 5952, 6776, 3063, 15410, 31432, 30949,
+ 6629, 18957, 4234, 18150, 6727, 16635, 7628, 14911, 6944, 10492,
+ 13404, 24595, 27997, 26210, 25113, 7764, 28784, 26336, 31156, 27006,
+ 16700, 9444, 22712, 645, 20529, 29990, 20168, 20747, 8888, 21121,
+ 2600, 11735, 17361, 7171, 11648, 12675, 10234, 31040, 29404, 23412,
+ 2132, 22763, 32758, 9488, 30977, 15783, 20408, 21802, 16080, 19738,
+ 21757, 10177, 10268, 21827, 15000, 7659, 27889, 15374, 25751, 2572,
+ 23153, 3366, 5833, 11339, 19830, 6667, 25725, 29511, 16505, 24676,
+ 19853, 13573, 28851, 10902, 11419, 29742, 24193, 7829, 23195, 1399,
+ 11533, 12027, 11153, 10592, 9515, 8791, 10396, 28193, 24449, 9415,
+ 11060, 28129, 23019, 6089, 15792, 15658, 31774, 5198, 25867, 7578,
+ 20363, 21264, 14311, 18651, 28294, 28454, 26322, 26581, 28327, 14037,
+ 6601, 2593, 19056, 32426, 18170, 12737, 3633, 10949, 26318, 18191,
+ 19497, 25208, 10535, 2292, 7150, 8721, 4071, 19802, 10511, 7923,
+ 4785, 9700, 5367, 12780, 12275, 15580, 12308, 15298, 3876, 32365,
+ 20025, 14351, 6218, 25106, 14913, 29263, 9408, 26702, 3318, 4408,
+ 11574, 8350, 27441, 27722, 6393, 19372, 28482, 24486, 4725, 28101,
+ 16785, 4643, 1272, 25997, 9350, 24991, 10168, 23281, 30631, 27027,
+ 14872, 6750, 30208, 22506, 21799, 12336, 13256, 1044, 30313, 22638,
+ 8001, 31830, 10203, 5812, 2272, 32100, 26929, 2672, 30382, 2097,
+ 15970, 21329, 18158, 2566, 1894, 6653, 26112, 19154, 1342, 4355,
+ 7045, 5569, 12342, 528, 12996, 20495, 17255, 15205, 589, 29215,
+ 8575, 29064, 5851, 5831, 30405, 26938, 1407, 5358, 15447, 32170,
+ 10491, 22362, 182, 22248, 20076, 26307, 6533, 25756, 5421, 23084,
+ 8846, 28920, 1527, 8563, 28166, 24555, 9549, 24102, 18962, 28312,
+ 1303, 16024, 16266, 1798, 6541, 3892, 11772, 31769, 21846, 30226,
+ 26868, 16833, 20721, 3272, 14970, 30065, 341, 19587, 28381, 19155,
+ 16852, 86, 19887, 12474, 13637, 12753, 9233, 16984, 16994, 17366,
+ 17457, 22705, 12143, 12200, 7696, 20559, 8477, 6213, 21897, 22327,
+ 173, 10230, 31119, 22301, 3416, 27684, 16566, 20436, 7407, 9069,
+ 28404, 13832, 20415, 12791, 18601, 10799, 15287, 12292, 14046, 7101,
+ 21197, 18119, 202, 11415, 2205, 20343, 16027, 26827, 31571, 26785,
+ 26995, 9854, 9164, 30146, 11440, 8742, 20728, 15637, 23664, 11001,
+ 29315, 6058, 13652, 29604, 30388, 26552, 18821, 23361, 16277, 18740,
+ 16117, 17027, 29524, 12450, 17128, 16692, 11241, 27692, 22194, 20450,
+ 18937, 15089, 22978, 14805, 28410, 28319, 29919, 27460, 25241, 19268,
+ 19122, 28616, 26456, 6497, 4485, 13584, 17020, 7745, 31306, 26071,
+ 31526, 28296, 2271, 28947, 5312, 20239, 16784, 4463, 18586, 6127,
+ 20446, 26876, 725, 19932, 2686, 1315, 9857, 26037, 30885, 24287,
+ 23810, 26200, 15491, 11049, 29880, 23739, 1805, 4019, 4831, 22073,
+ 30976, 4056, 15539, 21801, 5411, 17875, 31704, 29621, 10188, 15408,
+ 8698, 10474, 18341, 31617, 28593, 25611, 21424, 8274, 8871, 29227,
+ 4745, 3423, 12028, 25082, 22252, 3588, 10217, 23008, 19830, 31988,
+ 7076, 5192, 22448, 17198, 26244, 30271, 6217, 17197, 16742, 29757,
+ 5283, 1119, 3919, 14658, 3986, 13017, 11859, 17445, 352, 18249,
+ 20405, 28457, 20756, 27436, 6991, 5586, 13043, 27969, 8756, 19703,
+ 20552, 23101, 25749, 24855, 7265, 3520, 28385, 3825, 31450, 20360,
+ 21040, 10830, 6942, 20709, 31714, 10018, 11562, 7788, 12419, 14547,
+ 21396, 23024, 11762, 31705, 30412, 20654, 14531, 23943, 23971, 16840,
+ 6369, 13864, 12041, 26869, 18808, 18766, 16667, 8566, 24594, 8295,
+ 22877, 13644, 28416, 29585, 16963, 11432, 26363, 5296, 23031, 12707,
+ 15371, 4285, 32342, 23599, 20904, 31585, 31291, 31309, 29215, 6338,
+ 22529, 10369, 21816, 22941, 15683, 20099, 31254, 23957, 13286, 21560,
+ 22622, 28618, 1114, 8928, 11420, 12718, 1308, 18065, 25570, 26644,
+ 896, 17380, 27314, 7818, 10669, 30190, 25373, 5353, 1513, 2162,
+ 1581, 11050, 5911, 25172, 13441, 16251, 637, 5201, 31287, 12946,
+ 22219, 8174, 2575, 1602, 89, 10926, 29644, 19020, 21169, 29064,
+ 6622, 19319, 19277, 4248, 10815, 14563, 29090, 29461, 7835, 13210,
+ 30813, 32643, 1971, 31848, 1004, 21546, 10243, 13293, 14912, 10182,
+ 8610, 24816, 32721, 8832, 15211, 12534, 1507, 17181, 346, 10003,
+ 3592, 9334, 17464, 11521, 1767, 14120, 15483, 14959, 26171, 17292,
+ 21608, 1691, 25631, 18410, 23930, 30755, 31624, 1769, 13575, 18201,
+ 21523, 23114, 7201, 1365, 30977, 7638, 18107, 271, 383, 18069,
+ 26124, 13741, 3627, 31297, 12857, 16089, 16341, 15098, 14126, 471,
+ 2946, 31547, 26828, 277, 4023, 11789, 16970, 3588, 20212, 10107,
+ 29909, 19751, 29566, 24901, 27002, 16490, 97, 30681, 6726, 19380,
+ 5046, 29566, 1708, 26559, 7714, 12755, 18214, 30504, 13215, 888,
+ 1055, 29122, 22911, 21003, 21521, 23088, 30126, 25174, 17643, 12723,
+ 17207, 1734, 5301, 24128, 28681, 22047, 23926, 14038, 18428, 14959,
+ 14422, 10766, 4367, 27713, 7168, 13044, 31987, 11794, 31306, 4117,
+ 21454, 23561, 24856, 28889, 15417, 9186, 8829, 3347, 17546, 31020,
+ 18468, 23255, 4441, 6580, 21999, 22156, 21821, 13889, 8157, 4417,
+ 30167, 4993, 14129, 31045, 530, 14148, 13009, 4337, 23976, 30184,
+ 22252, 1993, 17897, 29716, 24543, 27076, 5048, 28842, 29786, 22759,
+ 24278, 27382, 702, 1304, 26211, 31020, 3530, 22066, 25249, 25361,
+ 11383, 31829, 9212, 21752, 16672, 23168, 9031, 16112, 11238, 32609,
+ 26441, 13372, 31827, 8299, 25464, 24323, 26174, 19242, 13316, 23625,
+ 32238, 16595, 23319, 5150, 32642, 12320, 25436, 25109, 9615, 16730,
+ 3006, 8696, 21260, 10423, 24690, 29882, 5227, 13031, 25911, 20909,
+ 15369, 32746, 13532, 14325, 7624, 24612, 14851, 5181, 11770, 1971,
+ 25894, 11945, 1922, 3072, 983, 13579, 7477, 24468, 7500, 13657,
+ 6791, 16430, 30746, 7263, 14179, 19218, 11585, 3249, 858, 11171,
+ 27753, 8676, 27648, 6196, 21867, 29693, 659, 4380, 2835, 28458,
+ 17630, 5640, 25381, 21424, 27997, 17814, 22429, 29221, 3746, 6943,
+ 7483, 30687, 32247, 16083, 831, 24492, 20805, 7180, 114, 23235,
+ 29749, 12764, 4453, 17915, 6292, 20968, 19453, 32571, 1532, 16762,
+ 19503, 12082, 3249, 28881, 24073, 23368, 8137, 15548, 2290, 21460,
+ 23184, 28263, 24626, 21135, 29994, 28020, 15541, 23881, 27770, 22605,
+ 17419, 16602, 24899, 30393, 24756, 14428, 29325, 15022, 3995, 5271,
+ 5963, 17255, 9952, 30653, 15162, 5813, 31194, 31064, 8972, 1178,
+ 32349, 18048, 23494, 26900, 22328, 4689, 14695, 16439, 26626, 27292,
+ 10442, 16510, 22039, 17629, 22733, 28515, 6877, 22381, 32435, 25645,
+ 2892, 4857, 14791, 11530, 30893, 20531, 23106, 2653, 20129, 1479,
+ 3951, 29785, 21094, 6801, 16653, 7887, 26454, 10253, 6133, 28484,
+ 31920, 16655, 31229, 6471, 2203, 4276, 32027, 21762, 13416, 26008,
+ 5582, 25614, 7704, 32073, 1209, 22668, 21278, 9212, 18321, 21105,
+ 26726, 31871, 4410, 10017, 21397, 1135, 3373, 10048, 27027, 10411,
+ 29213, 30404, 9799, 32264, 10202, 11087, 8609, 29255, 1141, 9405,
+ 21982, 2372, 25765, 21496, 6919, 31343, 9065, 25620, 31675, 17024,
+ 13551, 31128, 18223, 32103, 26805, 31769, 1139, 7298, 5870, 7694,
+ 10999, 19731, 15655, 5855, 17485, 8945, 20010, 17215, 23344, 23422,
+ 14627, 8124, 23494, 19672, 27649, 20884, 18722, 21844, 21791, 12747,
+ 27661, 24360, 10276, 3706, 24326, 19559, 27176, 5738, 7047, 24371,
+ 2328, 8929, 27786, 29230, 603, 21436, 27212, 5425, 23733, 12734,
+ 25425, 25153, 31084, 19240, 22184, 7870, 170, 32394, 25456, 31966,
+ 27939, 26584, 20891, 4442, 31479, 9152, 6130, 20839, 32218, 23867,
+ 857, 11496, 25202, 22883, 25429, 6370, 24320, 30084, 24523, 7728,
+ 5955, 19317, 23563, 16504, 14234, 28713, 2828, 20829, 19304, 129,
+ 6393, 1014, 21180, 28772, 3565, 21631, 23346, 20498, 19964, 6223,
+ 8212, 31669, 23154, 18954, 30149, 26938, 14431, 26136, 1120, 2142,
+ 8275, 27478, 5532, 26892, 23398, 21515, 31219, 7142, 29051, 6941,
+ 18691, 290, 3270, 8581, 308, 31127, 13964, 2048, 19099, 11799,
+ 20778, 20743, 24862, 24832, 29529, 24322, 27097, 32270, 2224, 8889,
+ 14273, 23667, 23403, 3595, 17287, 26410, 27498, 7906, 23232, 8072,
+ 13949, 5734, 19010, 11796, 21982, 12401, 2001, 30104, 5375, 28483,
+ 7931, 23672, 25990, 20344, 25920, 16451, 21654, 30775, 14710, 18312,
+ 25937, 15275, 21100, 1515, 29851, 31671, 24782, 9847, 2592, 18149,
+ 2120, 4150, 15000, 16800, 29678, 14591, 32586, 12196, 2524, 6800,
+ 9934, 12722, 537, 32221, 17176, 2952, 25794, 4263, 14514, 1552,
+ 13156, 31055, 21321, 16856, 16809, 23789, 875, 3522, 311, 2973,
+ 10639, 5629, 17621, 18201, 4694, 32563, 16079, 22413, 2064, 16900,
+ 16028, 25254, 7554, 23220, 29119, 14572, 5607, 8480, 11243, 3411,
+ 3636, 23799, 31338, 19212, 19360, 27174, 1728, 32161, 21348, 404,
+ 3211, 32577, 12223, 31248, 26285, 24921, 1598, 5512, 30637, 17252,
+ 25402, 11899, 29019, 3075, 24226, 22960, 16307, 14416, 32251, 20521,
+ 6916, 13679, 30628, 13651, 1362, 30823, 15199, 3455, 14072, 18480,
+ 25613, 30869, 16017, 28174, 30393, 1287, 22553, 16413, 4824, 12037,
+ 16208, 14892, 30671, 24560, 351, 6350, 950, 528, 4542, 10927,
+ 3932, 31881, 9813, 19493, 19339, 11147, 7906, 16647, 909, 10442,
+ 31642, 24770, 26862, 30766, 10003, 18601, 19588, 27851, 5985, 2189,
+ 26797, 23059, 2688, 32142, 8408, 25930, 25074, 20272, 23111, 2875,
+ 25000, 17074, 21011, 11818, 22054, 22683, 5232, 16393, 26083, 26773,
+ 31026, 23791, 4590, 12158, 18832, 27077, 10711, 957, 29480, 2883,
+ 14029, 9170, 27716, 2331, 8708, 21297, 11612, 29043, 6746, 14673,
+ 25564, 4249, 32057, 14080, 16934, 4338, 18111, 9721, 4315, 22324,
+ 19740, 14008, 25943, 28373, 19260, 24717, 8570, 6852, 32423, 6128,
+ 8366, 24150, 23717, 16148, 13861, 4739, 8869, 1215, 24675, 23378,
+ 17887, 9560, 22013, 4498, 1593, 16962, 20384, 29899, 10343, 17256,
+ 13140, 14708, 6999, 30489, 1282, 18278, 3276, 25623, 16436, 15505,
+ 12617, 490, 32541, 2030, 17200, 19322, 4825, 12468, 32043, 24541,
+ 28918, 7631, 5067, 9582, 6706, 29070, 29295, 8991, 24198, 19868,
+ 16232, 1040, 8804, 4913, 27482, 31072, 2366, 29577, 20453, 28227,
+ 10567, 25750, 8581, 16980, 11389, 19954, 14519, 32301, 743, 535,
+ 30302, 13877, 2587, 22482, 18276, 4026, 19972, 30709, 2980, 7232,
+ 18146, 13133, 25608, 32536, 14482, 29907, 11246, 4404, 5904, 9254,
+ 8657, 30521, 5178, 3129, 805, 24022, 15063, 6729, 8066, 20565,
+ 15063, 2323, 9989, 23919, 19164, 19523, 14324, 32357, 17146, 20527,
+ 28576, 29772, 21691, 25029, 656, 4008, 1127, 21186, 8155, 5693,
+ 18306, 11814, 9174, 15138, 27797, 4324, 24047, 23831, 12338, 31453,
+ 28121, 32536, 9010, 11279, 31722, 12083, 17985, 25098, 20673, 20374,
+ 32413, 2468, 4139, 30188, 18458, 14574, 6984, 21738, 18538, 1383,
+ 24041, 25636, 10139, 2671, 2877, 14886, 20961, 13310, 3501, 19648,
+ 1686, 8597, 11780, 2977, 22655, 13685, 13779, 2343, 849, 9232,
+ 4372, 9590, 14963, 6077, 13069, 28616, 21766, 15535, 17015, 12804,
+ 31523, 18728, 20704, 23185, 14435, 21994, 8526, 14444, 6053, 6895,
+ 16933, 15736, 11275, 25689, 32330, 15126, 11078, 21420, 27017, 19702,
+ 32020, 16699, 3124, 26157, 25606, 20960, 29197, 13447, 9095, 5360,
+ 8294, 19998, 18202, 15982, 14215, 23851, 28387, 20863, 17232, 15901,
+ 17769, 20254, 32544, 17384, 666, 15633, 4341, 5792, 8208, 6428,
+ 32724, 24646, 8850, 3188, 26987, 15330, 7390, 29558, 15093, 6865,
+ 20389, 3481, 29022, 5217, 2776, 27042, 9383, 21403, 13346, 25111,
+ 25229, 5984, 5814, 15861, 7269, 30904, 24650, 18853, 11339, 27494,
+ 28515, 31789, 13691, 11456, 22228, 31908, 25599, 5309, 14977, 7144,
+ 20363, 32080, 26985, 5779, 1445, 13300, 22756, 13098, 32520, 10632,
+ 25896, 4248, 1099, 21598, 31506, 14555, 17854, 30863, 3876, 19454,
+ 10901, 19089, 1482, 22343, 6984, 8203, 28897, 11441, 19257, 8935,
+ 18041, 20124, 17816, 15017, 29914, 17348, 16771, 8192, 30662, 26480,
+ 370, 20123, 21246, 2540, 16851, 18750, 5640, 30008, 31473, 25621,
+ 19758, 10754, 31258, 2376, 970, 26834, 5633, 11215, 15297, 23429,
+ 609, 23688, 32334, 29436, 1763, 13703, 27137, 19733, 7490, 4013,
+ 25095, 14042, 15021, 13948, 17067, 7929, 18541, 3625, 16157, 3189,
+ 4039, 24563, 19570, 28058, 7460, 16564, 15853, 21302, 24175, 17846,
+ 30333, 27654, 191, 31687, 21382, 21615, 20790, 21648, 13540, 3694,
+ 9513, 32290, 17966, 13778, 3456, 22738, 27959, 17577, 22880, 32583,
+ 475, 31736, 11272, 5329, 13048, 17583, 10745, 19964, 15546, 7387,
+ 346, 26470, 21532, 25886, 20890, 32461, 27563, 8796, 13911, 620,
+ 13709, 1976, 31103, 10888, 1731, 23743, 12469, 12614, 32683, 5090,
+ 18934, 15551, 7625, 9514, 19324, 12118, 6854, 295, 19170, 21066,
+ 15545, 12330, 24458, 3719, 31654, 29108, 5180, 10178, 8260, 28717,
+ 7183, 11716, 16388, 23769, 20109, 6150, 14926, 2057, 12050, 16255,
+ 6926, 18830, 885, 10938, 1647, 19827, 15850, 24619, 4582, 6380,
+ 15911, 12995, 11891, 23433, 11718, 15554, 2084, 24751, 31723, 31949,
+ 32474, 13641, 15398, 18752, 7247, 21947, 27803, 3525, 11096, 30743,
+ 26464, 1830, 21608, 18068, 806, 29023, 25430, 7740, 10012, 23544,
+ 6752, 9700, 22032, 6289, 13935, 20833, 29911, 30655, 2205, 9465,
+ 20464, 18454, 18676, 19736, 9316, 19335, 1656, 24132, 12272, 5869,
+ 22632, 20819, 3174, 4066, 13506, 4060, 23121, 31959, 4101, 9451,
+ 32472, 23396, 10810, 26105, 30949, 28892, 11573, 10267, 4486, 18725,
+ 25, 21881, 27539, 6086, 29722, 30466, 13969, 12098, 11911, 1630,
+ 2262, 677, 29703, 7204, 9454, 25948, 14627, 20046, 11838, 32073,
+ 7172, 21226, 4327, 6935, 11134, 15122, 8429, 27851, 8014, 23069,
+ 13465, 16028, 26016, 11543, 15899, 15877, 10709, 22127, 10356, 29464,
+ 14466, 496, 31635, 25621, 25788, 17650, 3006, 5947, 21139, 20178,
+ 14388, 26334, 19164, 32159, 32017, 23482, 31796, 11030, 23665, 391,
+ 19777, 17873, 25304, 27086, 9275, 2747, 19154, 20730, 18347, 29383,
+ 982, 6578, 15475, 10466, 8304, 4710, 17679, 7206, 28576, 14632,
+ 26138, 592, 17789, 29118, 5140, 24180, 14109, 25077, 28258, 24559,
+ 19897, 26680, 11158, 11678, 29965, 24672, 6897, 29005, 10494, 10958,
+ 24358, 14194, 9855, 10679, 18017, 30492, 9141, 10432, 25480, 22054,
+ 21337, 25291, 19649, 32176, 14175, 6672, 9012, 4815, 1749, 30319,
+ 18450, 10116, 11021, 7684, 25302, 14315, 6142, 15357, 7371, 1973,
+ 1000, 27048, 13774, 29656, 16951, 11728, 22101, 3205, 17834, 1610,
+ 17072, 2907, 3508, 12235, 21391, 31194, 803, 8189, 22469, 7194,
+ 2047, 26065, 17227, 29629, 16053, 25622, 20360, 28450, 19572, 6731,
+ 28879, 6363, 6872, 28593, 17706, 23394, 23750, 13477, 24662, 11527,
+ 23191, 20013, 6414, 14381, 18808, 16337, 15245, 21430, 12816, 1964,
+ 17742, 24508, 10852, 194, 3606, 23170, 26360, 16276, 564, 16810,
+ 26423, 7410, 20999, 5032, 16661, 25361, 15042, 1398, 20467, 20701,
+ 19564, 16521, 19139, 26512, 20779, 15621, 1388, 13956, 14785, 3117,
+ 24944, 6469, 13143, 10013, 12748, 7147, 19066, 5563, 5664, 31143,
+ 16227, 491, 4367, 27035, 28539, 2818, 24041, 11759, 30750, 28030,
+ 18823, 6433, 30367, 21236, 4727, 32156, 2445, 24137, 5210, 15245,
+ 30517, 18469, 17033, 24818, 7528, 8101, 13823, 4083, 3711, 848,
+ 21107, 8054, 32667, 26189, 18116, 10734, 27698, 13779, 27802, 32371,
+ 4807, 29408, 19275, 10264, 12024, 5166, 16891, 32633, 5310, 17507,
+ 7432, 31379, 4337, 20615, 6821, 11993, 13066, 23228, 8900, 14724,
+ 25645, 9513, 13882, 554, 28519, 2360, 22813, 2962, 24372, 28417,
+ 31857, 18119, 21572, 22790, 11012, 7275, 14718, 22560, 32151, 8270,
+ 31046, 31673, 6718, 9023, 6139, 4668, 17162, 5922, 22468, 19914,
+ 14308, 31043, 18829, 8495, 28604, 14058, 28492, 26900, 27876, 16432,
+ 21385, 13685, 12470, 15632, 14877, 18262, 4733, 6337, 20026, 5810,
+ 32147, 22339, 29099, 29877, 23238, 26937, 4445, 7723, 10496, 29174,
+ 8991, 21047, 2344, 13274, 12454, 16712, 16707, 5855, 5076, 26697,
+ 31455, 32111, 18490, 11288, 16561, 23417, 30171, 18746, 32637, 17347,
+ 6450, 27597, 3638, 24450, 27767, 957, 359, 1064, 30239, 10555,
+ 19921, 23421, 24738, 9579, 32341, 20977, 32640, 29533, 277, 16176,
+ 9606, 19775, 20439, 31992, 12365, 6609, 30634, 24615, 27909, 19993,
+ 17355, 18457, 14960, 5975, 4041, 14384, 3121, 24891, 1256, 12212,
+ 13127, 3158, 18115, 13278, 4053, 26831, 21302, 16431, 4132, 18775,
+ 6523, 4358, 8426, 16990, 3219, 31858, 29389, 27015, 13544, 19781,
+ 14627, 10586, 1328, 21610, 17916, 32058, 30356, 9336, 10082, 10646,
+ 12306, 11142, 10719, 17507, 15648, 8002, 25664, 8649, 6034, 28477,
+ 12441, 31004, 2237, 12681, 13961, 22031, 9693, 15750, 27327, 10788,
+ 27572, 26873, 10173, 4711, 15732, 7006, 17372, 9564, 19167, 11136,
+ 18577, 23862, 8621, 15174, 12014, 29257, 28206, 1488, 17772, 14786,
+ 12080, 21442, 8935, 23702, 24867, 2528, 19178, 31416, 25723, 1500,
+ 26413, 3727, 9046, 15723, 14940, 9383, 14943, 21406, 12314, 15271,
+ 10482, 6256, 11846, 24707, 19585, 9884, 2941, 23282, 11062, 5041,
+ 20192, 32291, 20953, 26215, 7447, 29099, 18677, 18228, 30358, 1731,
+ 25910, 7963, 11038, 28080, 30486, 6341, 9863, 24450, 7608, 14290,
+ 31422, 4097, 16660, 31345, 19210, 31717, 30549, 14638, 31891, 26437,
+ 22911, 14604, 20516, 8274, 2901, 9172, 18736, 23109, 31354, 23212,
+ 1555, 13462, 6358, 22251, 28059, 17007, 5691, 3372, 21959, 9824,
+ 23881, 1698, 1998, 5716, 22415, 9387, 17763, 23492, 15602, 17063,
+ 13112, 9258, 29267, 10762, 19649, 13753, 15212, 3248, 17722, 23627,
+ 17403, 31089, 31211, 8859, 17443, 32502, 22955, 11188, 17423, 28874,
+ 26019, 16553, 17112, 692, 12116, 26247, 17577, 11845, 30684, 4232,
+ 3105, 5805, 21620, 17033, 760, 24275, 31806, 14270, 5606, 9636,
+ 9022, 24997, 1984, 7338, 1701, 21304, 32741, 27873, 3670, 27751,
+ 22488, 24007, 10147, 22981, 27694, 29363, 15703, 15490, 29867, 29287,
+ 28922, 3737, 10152, 3304, 31056, 5962, 11447, 5006, 18979, 971,
+ 8842, 30551, 26946, 30779, 15377, 384, 5322, 11479, 14563, 31319,
+ 7844, 27504, 15583, 12875, 8527, 285, 19219, 8517, 29152, 30765,
+ 26589, 4155, 29511, 11871, 9807, 258, 11987, 6998, 9432, 18531,
+ 22009, 23367, 15649, 3698, 4433, 20981, 27446, 10523, 16609, 31199,
+ 12262, 1278, 4510, 13239, 29292, 4221, 3120, 10775, 9551, 23826,
+ 246, 7536, 12934, 27366, 30026, 11331, 29408, 21152, 30214, 27539,
+ 13475, 16763, 29510, 25498, 5491, 31644, 2416, 17595, 13174, 22690,
+ 23410, 26808, 31158, 28286, 25163, 29733, 3015, 24197, 21965, 11292,
+ 5289, 30915, 4769, 21555, 31983, 10643, 8587, 10411, 19489, 25965,
+ 17391, 18666, 14688, 1790, 10645, 9771, 12104, 21374, 13225, 19061,
+ 18203, 6462, 26886, 3017, 32539, 7296, 32692, 32672, 12343, 18060,
+ 8110, 17045, 1770, 19200, 17129, 26718, 865, 14184, 22163, 10240,
+ 17628, 8462, 408, 6211, 9302, 25876, 13419, 4196, 25192, 11967,
+ 26115, 267, 27755, 14358, 8740, 22908, 31965, 30892, 19679, 19729,
+ 6917, 14010, 16220, 3304, 15834, 11888, 8663, 18905, 5666, 17293,
+ 9961, 4779, 17367, 28974, 3081, 25223, 31438, 27619, 850, 29612,
+ 23195, 10760, 27271, 10853, 32175, 18003, 29524, 11320, 963, 28841,
+ 8406, 30561, 7034, 24886, 15966, 3711, 20289, 444, 13170, 3212,
+ 6522, 16683, 22805, 13586, 987, 17779, 13385, 21660, 22032, 28566,
+ 14801, 1387, 6056, 26113, 32571, 11371, 26926, 6428, 32030, 16998,
+ 30870, 30240, 18081, 15734, 5340, 15401, 23100, 11968, 9447, 10124,
+ 28611, 26719, 1459, 26474, 26528, 16287, 5039, 4485, 16223, 16236,
+ 25444, 2131, 12145, 24330, 27992, 1873, 22057, 4358, 12594, 18842,
+ 5131, 15980, 5150, 32440, 32070, 570, 32371, 442, 1151, 14613,
+ 31892, 1670, 17104, 14651, 26388, 12657, 273, 18105, 22045, 19725,
+ 26198, 6110, 25618, 4674, 28600, 32239, 883, 13985, 5465, 1564,
+ 27649, 13556, 16546, 9907, 25379, 1050, 30671, 19604, 25481, 12306,
+ 25262, 23781, 26639, 2389, 3235, 32518, 24036, 24169, 2032, 17095,
+ 491, 29619, 22067, 30425, 11617, 11661, 14896, 17283, 21953, 8344,
+ 22225, 23958, 17380, 31827, 16235, 26019, 18029, 1005, 23875, 18283,
+ 25444, 2392, 20049, 11671, 19745, 7839, 8516, 23978, 7788, 29049,
+ 4806, 4147, 8674, 1310, 12288, 6471, 10395, 15961, 609, 29998,
+ 13321, 30175, 10395, 3421, 30499, 1247, 239, 18852, 29379, 32730,
+ 18603, 16809, 12621, 5045, 21745, 8853, 26002, 14605, 18617, 7437,
+ 28916, 12746, 27673, 28516, 5322, 1271, 2245, 24591, 21254, 27857,
+ 28626, 15449, 16917, 27421, 3263, 12120, 22534, 30655, 10677, 1311,
+ 28911, 32137, 18702, 11829, 5260, 6481, 14357, 5958, 16170, 20294,
+ 16140, 10521, 12739, 10884, 4724, 1218, 3435, 31461, 27016, 20505,
+ 15850, 9498, 24075, 9834, 30635, 14587, 31043, 366, 19669, 16924,
+ 4678, 11898, 7607, 1697, 24948, 9207, 26729, 10323, 27973, 19218,
+ 15280, 23539, 13381, 4532, 20771, 10958, 14428, 22709, 4748, 29329,
+ 20307, 4685, 3729, 5983, 23700, 9419, 8340, 7201, 22577, 25993,
+ 20439, 5405, 18216, 16415, 10724, 10443, 2278, 24023, 7212, 4835,
+ 7689, 24929, 4334, 23995, 19562, 2760, 21338, 17872, 17499, 22437,
+ 32503, 31650, 11053, 29587, 32322, 14278, 12022, 3298, 23704, 21814,
+ 1936, 24976, 28501, 26091, 2277, 6260, 6718, 30126, 10858, 15037,
+ 13084, 28459, 10218, 24987, 18602, 22343, 8069, 27708, 20657, 21171,
+ 20728, 20986, 370, 10689, 25119, 25811, 23108, 15991, 19640, 6169,
+ 8062, 10467, 22889, 8042, 19863, 28077, 19461, 31203, 18316, 755,
+ 9483, 15761, 17538, 5968, 7279, 14120, 16557, 20286, 14749, 12792,
+ 30064, 27807, 11452, 31772, 7366, 5270, 19759, 31477, 992, 10139,
+ 24930, 25559, 12560, 24527, 5059, 27905, 8421, 10636, 14606, 2771,
+ 24216, 27201, 19406, 3387, 31654, 10621, 16673, 12657, 10943, 20553,
+ 6843, 31716, 479, 29371, 23085, 28276, 10171, 22472, 14695, 28385,
+ 28766, 13146, 19580, 29059, 11540, 18082, 28838, 15420, 13191, 23216,
+ 11402, 21932, 24616, 18753, 26045, 29859, 6096, 2008, 3974, 988,
+ 3239, 26896, 14054, 3560, 19014, 2096, 4053, 9576, 19736, 4864,
+ 26575, 7551, 10502, 26075, 8591, 9863, 851, 11782, 7707, 8963,
+ 25540, 1600, 14080, 18645, 8453, 16794, 11743, 25266, 27720, 22665,
+ 13608, 17874, 16431, 11322, 30246, 20460, 14060, 5157, 14396, 353,
+ 2983, 27109, 3438, 1976, 19231, 1863, 10274, 19530, 30613, 27297,
+ 15912, 23358, 9190, 30053, 7417, 14008, 18935, 30965, 21308, 27214,
+ 24661, 1465, 5007, 29372, 29469, 12400, 13443, 19928, 17434, 16835,
+ 29160, 18120, 13870, 1056, 21324, 21106, 2035, 9157, 23486, 4148,
+ 8609, 21787, 26328, 17109, 31283, 13638, 22268, 21948, 22469, 6394,
+ 30941, 16992, 28481, 15760, 16449, 27136, 10042, 4185, 16902, 14228,
+ 536, 50, 3939, 7683, 29558, 3416, 22129, 18070, 9416, 2942,
+ 27626, 941, 27969, 18973, 8752, 23473, 244, 5900, 4497, 16457,
+ 6969, 20304, 13769, 17873, 10322, 29237, 1224, 28424, 12878, 27294,
+ 25270, 24840, 5422, 665, 5941, 4988, 15943, 13622, 10214, 20749,
+ 31463, 21146, 15406, 7197, 6715, 10831, 28218, 19384, 26224, 12254,
+ 11584, 29895, 14617, 19872, 5384, 29575, 11985, 22993, 24236, 10554,
+ 15905, 25062, 20124, 16925, 13732, 16416, 17380, 6041, 25960, 12130,
+ 19634, 701, 30616, 20800, 25618, 13036, 15448, 23128, 15613, 23763,
+ 27889, 22757, 16018, 21918, 10798, 18833, 5539, 28268, 14854, 28299,
+ 32627, 9216, 18554, 7386, 12734, 30393, 12225, 29681, 1018, 32452,
+ 2979, 13187, 15837, 4240, 7203, 9112, 12063, 1410, 15200, 17121,
+ 29825, 31979, 27325, 12104, 3598, 10551, 15168, 31948, 10913, 32103,
+ 5432, 28300, 19623, 20161, 8995, 17953, 11302, 16069, 25550, 7473,
+ 31231, 356, 10174, 32065, 26736, 21357, 32207, 10699, 7388, 13640,
+ 21275, 20625, 28367, 15846, 18973, 5168, 6205, 6648, 3351, 9464,
+ 15114, 2911, 8112, 23547, 24527, 31972, 29666, 3172, 20956, 32298,
+ 17939, 32523, 31865, 15328, 1154, 19526, 11634, 18491, 17893, 2049,
+ 24786, 18340, 4945, 29713, 31214, 21934, 2393, 11461, 3493, 13898,
+ 5242, 958, 8679, 10046, 19639, 32001, 1652, 26067, 13440, 8779,
+ 10982, 15566, 24280, 8357, 5618, 11938, 16567, 25655, 25067, 4068,
+ 12717, 9825, 25223, 9727, 24521, 8712, 22502, 7721, 15033, 25134,
+ 21200, 28822, 6706, 24262, 11839, 1003, 9107, 23494, 16925, 9461,
+ 12997, 15997, 13134, 9883, 19045, 19751, 1265, 15889, 20261, 3263,
+ 20195, 28495, 4719, 12564, 15749, 7618, 28748, 21279, 16064, 5441,
+ 1157, 24980, 70, 8002, 15112, 32695, 8986, 30798, 16268, 18033,
+ 18514, 14770, 4216, 7075, 23324, 2936, 14593, 5050, 15359, 12949,
+ 30355, 4484, 12643, 20324, 19827, 6210, 16724, 24659, 20642, 1022,
+ 22659, 23773, 8452, 7198, 25229, 31928, 26561, 13370, 14208, 32591,
+ 20460, 20267, 668, 1906, 17251, 30820, 1622, 24396, 28406, 18310,
+ 24995, 14486, 20939, 16942, 14962, 15627, 23552, 4113, 29050, 796,
+ 24723, 13644, 17207, 15076, 24191, 18165, 31279, 10078, 25896, 19958,
+ 5754, 14294, 6137, 19483, 3713, 21917, 5452, 5993, 3334, 14849,
+ 17546, 32690, 20581, 24700, 20371, 29286, 3865, 26924, 19296, 4268,
+ 1409, 32643, 21479, 27569, 4324, 6464, 7998, 23360, 31668, 8606,
+ 19460, 8852, 24335, 25803, 28413, 22378, 15755, 20379, 9212, 16218,
+ 15155, 22398, 9734, 5990, 5837, 7856, 12980, 31188, 18527, 10415,
+ 15577, 22073, 26865, 13042, 12901, 12247, 18323, 1496, 22921, 5672,
+ 20386, 20959, 2332, 3003, 9288, 27926, 16446, 20287, 5442, 1237,
+ 24891, 15070, 20710, 6059, 5042, 11724, 30564, 19352, 4598, 13343,
+ 29516, 29820, 26036, 24801, 15184, 24272, 22486, 3683, 24908, 12948,
+ 6056, 30933, 4739, 648, 23865, 26388, 27947, 23455, 2821, 21955,
+ 20269, 26801, 4816, 22685, 550, 32368, 8661, 9737, 26801, 9117,
+ 22560, 239, 4328, 27004, 3897, 29899, 20520, 10373, 29698, 6144,
+ 19477, 30044, 30690, 18542, 5342, 25091, 23843, 5702, 13507, 24399,
+ 25241, 20765, 22740, 21144, 21125, 27456, 30459, 13237, 30904, 10056,
+ 5436, 18215, 17404, 17390, 5692, 18581, 5807, 6688, 12032, 6521,
+ 2737, 24916, 27128, 18456, 11393, 3612, 23356, 695, 29090, 32506,
+ 27157, 19212, 28228, 27510, 21439, 32243, 3616, 18799, 19309, 866,
+ 21668, 7343, 23438, 15007, 26704, 25794, 27727, 30384, 28000, 7431,
+ 4961, 7956, 29611, 775, 4348, 18608, 31691, 5894, 7716, 23308,
+ 22398, 2776, 28715, 5567, 26956, 4854, 5495, 2600, 1898, 19921,
+ 3973, 23903, 1503, 13670, 20014, 26219, 11237, 20243, 28713, 31926,
+ 6290, 3497, 27858, 2750, 23223, 6594, 2857, 14604, 16393, 29781,
+ 18974, 17770, 8062, 10119, 7692, 23121, 8954, 31172, 10115, 31393,
+ 21547, 22287, 18250, 21908, 28849, 25750, 13220, 5877, 18819, 29322,
+ 29395, 1933, 12686, 16429, 24283, 4575, 16287, 17965, 5768, 32533,
+ 26498, 31536, 32690, 57, 11884, 18096, 16064, 22440, 32406, 5641,
+ 18283, 14020, 24107, 18384, 27333, 9194, 3428, 24935, 1657, 31908,
+ 20465, 17102, 14676, 26655, 26012, 19644, 16644, 19935, 30249, 11503,
+ 25888, 9393, 29824, 17600, 4969, 11745, 15630, 24058, 4432, 28846,
+ 29544, 8684, 26296, 2555, 25393, 1725, 26108, 9287, 26687, 9984,
+ 30004, 11231, 8697, 14216, 31924, 4946, 30211, 3966, 7894, 15398,
+ 9758, 30384, 7418, 22473, 32073, 11820, 3530, 21706, 22572, 26382,
+ 18627, 11337, 3255, 7062, 10993, 9133, 29959, 32382, 6393, 22165,
+ 8585, 29834, 25181, 7440, 30305, 19552, 27132, 8720, 14349, 10394,
+ 14296, 15900, 19269, 20506, 22556, 27206, 11302, 22685, 11102, 24413,
+ 24720, 24467, 3105, 13667, 27085, 17711, 28062, 5953, 31091, 7610,
+ 22468, 24250, 28043, 19756, 25725, 11422, 22514, 253, 8755, 20800,
+ 5376, 31801, 32659, 6441, 13672, 27091, 9360, 21006, 16223, 10555,
+ 23723, 7168, 2817, 18738, 30322, 23267, 15856, 9438, 15431, 23585,
+ 10814, 22297, 27235, 1184, 5261, 30735, 17947, 6897, 9588, 22792,
+ 14945, 458, 2597, 12930, 7565, 30390, 2125, 30851, 1118, 10507,
+ 2364, 18733, 17979, 15644, 24646, 10643, 5823, 4017, 20585, 1227,
+ 22645, 19892, 5424, 8517, 3296, 13357, 29398, 90, 1471, 3185,
+ 4527, 23592, 15246, 14485, 10436, 14238, 27984, 25641, 15293, 13523,
+ 28044, 11555, 28677, 9628, 16534, 22810, 15656, 2653, 28687, 27317,
+ 31872, 29471, 14255, 11106, 7184, 30435, 28482, 32075, 30896, 13622,
+ 22001, 2438, 9067, 5638, 8899, 7819, 5669, 15284, 32356, 21228,
+ 7040, 23402, 18980, 16448, 28161, 28591, 22594, 27232, 21103, 31033,
+ 31083, 9943, 12668, 16898, 894, 6291, 29864, 22174, 13714, 5089,
+ 10849, 10699, 7482, 32408, 13679, 5706, 24840, 147, 2959, 13037,
+ 5199, 6245, 18270, 11506, 30765, 26697, 4473, 7311, 19913, 20312,
+ 9443, 1998, 7642, 8959, 29351, 1947, 6505, 7343, 10430, 17179,
+ 30679, 20438, 8242, 13632, 30241, 15375, 30340, 28827, 23395, 20373,
+ 22092, 21873, 9883, 28158, 13087, 28176, 18864, 20262, 31925, 25955,
+ 5555, 19049, 3403, 19397, 15460, 25109, 22343, 7699, 2808, 8990,
+ 5659, 17157, 16921, 11540, 1643, 29374, 12079, 30291, 26994, 15521,
+ 27358, 8314, 22434, 8039, 24783, 28958, 9866, 26478, 1204, 17087,
+ 26109, 18260, 22662, 506, 14449, 24261, 10257, 2817, 2725, 9105,
+ 7603, 31561, 28295, 24834, 5217, 19330, 7508, 16748, 19178, 17868,
+ 25857, 5637, 23680, 11304, 1242, 20727, 8820, 9004, 15721, 26036,
+ 25409, 13564, 6041, 906, 29388, 117, 10011, 24183, 10218, 26795,
+ 19465, 31294, 19235, 22678, 14281, 11194, 25270, 28424, 14645, 17523,
+ 32732, 9954, 5112, 7279, 29009, 20360, 26427, 28235, 32529, 27026,
+ 26498, 14730, 4959, 15301, 28624, 7980, 29964, 13377, 11794, 27778,
+ 30454, 27131, 28346, 18498, 16591, 21102, 19371, 13783, 5408, 32654,
+ 16981, 25338, 14477, 31230, 29985, 29574, 24154, 2946, 7183, 16264,
+ 15918, 3511, 26781, 14230, 14103, 4354, 24812, 25443, 9167, 28614,
+ 30238, 11920, 17470, 8666, 23042, 30660, 24639, 25658, 22515, 5630,
+ 1959, 2300, 13565, 18474, 4996, 902, 23362, 17139, 19618, 1279,
+ 21660, 20697, 23380, 15619, 22660, 14467, 25712, 4763, 28979, 23894,
+ 30620, 26988, 31750, 20038, 13000, 18222, 2343, 14060, 16124, 28000,
+ 24170, 26329, 2644, 15162, 8565, 25387, 25417, 27620, 27940, 13918,
+ 22833, 1253, 22060, 29284, 1545, 2270, 8958, 6391, 9587, 17016,
+ 15086, 24110, 7419, 15259, 4244, 31054, 22942, 13537, 2930, 30691,
+ 9869, 12618, 13528, 18192, 24878, 27185, 11269, 26404, 11876, 16254,
+ 9615, 32109, 5392, 30750, 31237, 14417, 8664, 26288, 2002, 14746,
+ 30759, 18049, 27748, 31506, 29812, 25787, 22670, 24912, 17352, 27097,
+ 1067, 28881, 5242, 22366, 1285, 22859, 17469, 3527, 3317, 19261,
+ 12126, 28350, 21323, 19403, 1350, 28560, 11631, 31433, 17990, 12257,
+ 6857, 32534, 20116, 26783, 18399, 3371, 4752, 18228, 19645, 15347,
+ 28748, 2304, 10906, 7134, 14924, 27398, 19640, 17457, 24458, 16869,
+ 4236, 19104, 21693, 19979, 6431, 22814, 8923, 8229, 29108, 22004,
+ 16093, 8665, 17323, 21008, 3778, 5816, 9125, 12704, 16342, 10606,
+ 14825, 17120, 21044, 22844, 18951, 14128, 32138, 23465, 23995, 12906,
+ 21276, 18036, 5907, 25714, 16652, 5580, 28116, 24847, 23256, 25283,
+ 23579, 10745, 2852, 24065, 15936, 7987, 4794, 25269, 27135, 18842,
+ 30927, 13778, 16602, 13247, 20616, 17783, 16825, 17650, 30652, 31918,
+ 24020, 21151, 13052, 32602, 5330, 23518, 19152, 25195, 7218, 9029,
+ 3652, 13396, 5611, 6912, 24227, 27071, 6735, 22308, 10371, 639,
+ 6453, 31297, 28161, 31430, 22103, 20535, 17998, 23704, 1273, 2890,
+ 30315, 1407, 18124, 22392, 1840, 29825, 4625, 14345, 31891, 13391,
+ 17153, 25449, 4647, 13759, 23661, 4403, 8419, 11900, 15266, 28302,
+ 4645, 20476, 17295, 11452, 1014, 27315, 17194, 24048, 656, 20871,
+ 6927, 5216, 31518, 4483, 26218, 30620, 19394, 20943, 11032, 17438,
+ 5340, 28640, 21769, 26914, 12170, 11244, 233, 14520, 28011, 31137,
+ 23039, 24087, 1449, 18710, 3925, 3636, 21302, 23554, 9241, 9875,
+ 18517, 31532, 8003, 11869, 15197, 8226, 24184, 28084, 28857, 26414,
+ 4142, 3907, 1588, 23942, 6418, 25, 9076, 32707, 26790, 439,
+ 5059, 31892, 303, 8807, 11542, 4020, 14030, 4048, 10311, 2329,
+ 27117, 30664, 20134, 21615, 16604, 27497, 8368, 5316, 9404, 30823,
+ 23070, 10373, 1437, 27808, 30498, 10665, 10723, 30709, 7917, 15916,
+ 3310, 8281, 6004, 19647, 4346, 15399, 9844, 27070, 2115, 26297,
+ 947, 4194, 22893, 9014, 16522, 31800, 17188, 8619, 18592, 14033,
+ 768, 23134, 24568, 11707, 25515, 29535, 16942, 25777, 30277, 9311,
+ 18173, 6159, 31495, 3269, 12293, 25481, 15655, 12287, 971, 16667,
+ 26108, 3094, 6658, 29763, 2915, 32390, 15625, 13679, 32097, 27468,
+ 1204, 12721, 5898, 23104, 20047, 12986, 5793, 32421, 30176, 774,
+ 16640, 23807, 13485, 25172, 21562, 804, 18686, 7769, 3456, 1686,
+ 19236, 9141, 17985, 15632, 21434, 6950, 27797, 25439, 22315, 26364,
+ 23260, 9843, 23157, 5325, 21154, 17078, 25900, 5993, 7879, 11677,
+ 21697, 23824, 8412, 32124, 29956, 5603, 19919, 926, 488, 16025,
+ 24011, 19605, 30342, 17267, 13146, 31439, 19813, 20338, 15821, 12138,
+ 5625, 7111, 23261, 30025, 873, 21387, 31634, 25192, 22678, 24496,
+ 4196, 25452, 21848, 12088, 161, 25983, 2314, 20388, 12558, 21082,
+ 11850, 27056, 24017, 4771, 29690, 30269, 19342, 2682, 22410, 16271,
+ 5073, 17487, 29818, 696, 4268, 15862, 27930, 17748, 11169, 3069,
+ 20629, 13175, 5057, 18237, 8749, 6628, 7958, 30895, 26056, 20608,
+ 23359, 30593, 21932, 10502, 4442, 28009, 9607, 13819, 16679, 30010,
+ 30386, 32229, 22377, 1973, 25014, 28344, 9104, 10913, 14608, 9617,
+ 20630, 5662, 26929, 24230, 25895, 17462, 6601, 8573, 3844, 7861,
+ 29765, 32093, 15785, 16186, 13206, 27139, 20526, 30095, 24885, 8341,
+ 23147, 2102, 25444, 220, 17759, 25412, 16566, 22189, 20179, 10611,
+ 15569, 5032, 11322, 23410, 12915, 20774, 21724, 2431, 20147, 11884,
+ 14131, 17208, 4490, 24357, 23957, 14766, 14225, 32271, 17940, 18364,
+ 28940, 30708, 29091, 21655, 2600, 8924, 28282, 17573, 26753, 21889,
+ 25019, 27795, 487, 4867, 21589, 15010, 12386, 7901, 18216, 2625,
+ 1907, 3352, 21099, 21985, 3741, 8894, 21579, 15109, 1316, 6802,
+ 29397, 1176, 4885, 8702, 29974, 12164, 2950, 8781, 14209, 7552,
+ 9247, 10778, 16273, 27177, 17882, 2824, 12975, 5717, 23302, 32692,
+ 13397, 32164, 16018, 28136, 28532, 19032, 12424, 6418, 20243, 23398,
+ 29656, 22772, 10809, 20684, 31063, 10396, 26382, 12838, 15367, 8599,
+ 22845, 25468, 12953, 14178, 24476, 23647, 31280, 18209, 1295, 21812,
+ 7784, 20371, 10410, 24271, 8855, 25926, 28949, 6212, 12371, 14087,
+ 3893, 30457, 3892, 13981, 5128, 21760, 18906, 14775, 24017, 14756,
+ 9266, 10018, 24694, 4162, 18166, 1087, 19750, 16731, 17523, 30389,
+ 23870, 25062, 23183, 3683, 17518, 27883, 5642, 27545, 3608, 15181,
+ 15108, 5511, 27128, 11752, 5824, 5365, 11274, 15835, 7847, 10037,
+ 936, 26407, 144, 7510, 11763, 8570, 2110, 15259, 10101, 23365,
+ 32298, 11563, 8453, 11028, 25475, 24586, 15338, 11039, 12148, 23880,
+ 20803, 13084, 29093, 29049, 18598, 25688, 32260, 14693, 16903, 15366,
+ 1477, 26368, 5851, 8151, 16807, 21148, 30334, 6347, 4474, 11357,
+ 8658, 12358, 13534, 25069, 2602, 9062, 333, 3186, 22374, 24724,
+ 14684, 31421, 6495, 857, 26941, 11204, 10373, 17011, 27785, 19795,
+ 31174, 1065, 316, 4862, 27058, 3291, 3074, 31066, 17117, 31709,
+ 29105, 18797, 901, 2694, 10774, 28770, 9845, 16771, 28660, 32641,
+ 29481, 6257, 12874, 26719, 6451, 13228, 10965, 18770, 6878, 13409,
+ 15830, 24104, 19216, 20203, 1813, 26905, 25205, 7004, 14374, 10233,
+ 28633, 21593, 11243, 10675, 10198, 30764, 21338, 6130, 22448, 20,
+ 24448, 18721, 32637, 8671, 19654, 11926, 22409, 20411, 13172, 29450,
+ 17656, 27210, 371, 23885, 429, 22772, 343, 19255, 31595, 31873,
+ 21149, 22754, 11834, 12263, 14128, 2070, 32269, 19296, 23090, 31749,
+ 21409, 24000, 29690, 7481, 168, 4102, 28505, 14794, 12071, 26417,
+ 29730, 30164, 24605, 22613, 31465, 8232, 15717, 25325, 19978, 16194,
+ 17117, 9587, 7150, 27260, 712, 8238, 32393, 17281, 2417, 6732,
+ 7207, 9219, 9234, 23856, 17769, 21425, 3827, 14861, 13450, 23139,
+ 20182, 3508, 20967, 17048, 14739, 13994, 8639, 24611, 29184, 12670,
+ 16183, 28449, 23315, 20313, 2209, 7982, 17995, 15063, 24829, 24281,
+ 24907, 16149, 10944, 31573, 9929, 1292, 24533, 26737, 22182, 15133,
+ 27362, 17609, 14686, 23276, 9676, 28222, 12963, 370, 8573, 15013,
+ 26437, 3406, 6885, 10428, 31317, 30556, 16702, 7522, 9610, 6537,
+ 12693, 263, 12515, 22502, 19334, 20833, 3470, 24571, 17223, 31584,
+ 6153, 29277, 5352, 4453, 17799, 27267, 15576, 12719, 16533, 30933,
+ 22956, 12565, 14589, 17158, 6940, 24059, 27371, 24228, 8782, 28543,
+ 8526, 23021, 14168, 29939, 14209, 18149, 30720, 22928, 24107, 31909,
+ 25541, 20584, 10084, 758, 26916, 15517, 7705, 23582, 22548, 27089,
+ 27825, 8442, 24019, 10461, 22256, 9037, 28132, 9414, 2844, 2648,
+ 15449, 1005, 3679, 7595, 11598, 10629, 18541, 12858, 23990, 11082,
+ 29286, 28083, 10586, 20336, 27902, 21519, 21022, 9946, 16859, 21352,
+ 11398, 6029, 21567, 16906, 30074, 27492, 1254, 716, 13638, 14085,
+ 19762, 17313, 21477, 11539, 5509, 2666, 17023, 12710, 19182, 1038,
+ 24112, 16888, 30729, 18893, 28683, 1121, 25888, 4305, 28255, 5253,
+ 918, 30726, 25400, 24524, 10374, 26668, 7209, 9746, 23207, 14891,
+ 1865, 29344, 14195, 6054, 24956, 8539, 13192, 18898, 6644, 17468,
+ 14926, 27273, 3831, 32000, 28890, 11162, 2018, 7969, 8210, 10340,
+ 4206, 11780, 2578, 30115, 6450, 2932, 11983, 25481, 361, 27215,
+ 17402, 9745, 28150, 22911, 25640, 22416, 4517, 31532, 14639, 2444,
+ 19124, 15408, 9683, 22482, 14738, 8140, 12962, 12739, 13542, 29593,
+ 16924, 19951, 16083, 32705, 20503, 31717, 24442, 1902, 16482, 18504,
+ 2241, 11651, 169, 10022, 26451, 4491, 408, 6278, 17641, 14574,
+ 19267, 31552, 24519, 6251, 12486, 530, 23433, 20930, 26408, 32495,
+ 12063, 31153, 902, 30874, 13335, 31266, 9325, 15988, 15130, 25763,
+ 19079, 28307, 18874, 18710, 9338, 8723, 25963, 25770, 21005, 13233,
+ 4046, 15626, 25229, 21653, 22582, 31700, 4719, 25456, 9829, 7756,
+ 3126, 14791, 8854, 19794, 12439, 25487, 24257, 29073, 10715, 29945,
+ 9498, 22522, 20102, 29327, 4058, 31345, 5942, 32640, 20035, 16581,
+ 11213, 17976, 15070, 19942, 19410, 20276, 9992, 11602, 5653, 14869,
+ 32684, 29905, 29586, 3315, 12114, 11874, 10648, 3571, 24921, 7797,
+ 22315, 23324, 2688, 14938, 24998, 13414, 23212, 25338, 5285, 11284,
+ 31717, 14277, 31009, 12612, 17057, 5611, 10205, 10437, 13125, 6095,
+ 6913, 2088, 233, 10425, 17157, 10010, 26971, 202, 25297, 15089,
+ 4711, 7478, 30499, 12420, 19542, 2221, 11568, 22592, 23989, 2074,
+ 11406, 6264, 15448, 32656, 14417, 6653, 22430, 9089, 27509, 8943,
+ 22517, 18994, 5244, 5074, 30625, 29035, 29783, 15076, 22714, 19571,
+ 25738, 29102, 31860, 28220, 10380, 14554, 16292, 25562, 28268, 17988,
+ 127, 21305, 17082, 14676, 20900, 29200, 31653, 27018, 24157, 26897,
+ 24417, 858, 25633, 30563, 2508, 26427, 25950, 27217, 21840, 32507,
+ 31094, 15684, 19211, 32085, 24071, 30190, 24109, 15301, 11632, 4297,
+ 30370, 10907, 24209, 4544, 3826, 1871, 29138, 3371, 26981, 19732,
+ 28518, 15617, 8298, 5039, 6865, 30281, 5689, 20618, 32679, 4818,
+ 1976, 11780, 15255, 8996, 18075, 27916, 10665, 31926, 24272, 1262,
+ 21188, 30818, 11034, 30060, 18291, 29973, 7420, 32529, 18152, 29387,
+ 15320, 13762, 22338, 22971, 8024, 8598, 13067, 16846, 26893, 25064,
+ 12293, 20054, 342, 1706, 806, 29181, 7044, 5115, 1505, 12027,
+ 17723, 25596, 24743, 10125, 1307, 23264, 16046, 4770, 19616, 8515,
+ 28401, 26839, 16711, 22717, 5752, 23973, 8435, 32438, 22489, 30937,
+ 17806, 29052, 5119, 25669, 3059, 19346, 10282, 16822, 8716, 2380,
+ 19767, 7462, 55, 11416, 31778, 20274, 4591, 21279, 31689, 25550,
+ 20904, 29325, 31730, 22839, 23546, 12076, 24976, 19241, 15874, 184,
+ 10306, 24147, 774, 6511, 32029, 8, 17751, 17255, 30379, 20023,
+ 18044, 10276, 3635, 15261, 21132, 13930, 15931, 17465, 29404, 6736,
+ 27212, 17920, 13274, 31638, 29685, 20947, 569, 30264, 8466, 2222,
+ 25423, 323, 14159, 22818, 3259, 14312, 28903, 12549, 8010, 14543,
+ 11954, 30568, 2332, 4014, 2910, 25289, 21250, 23833, 13308, 32650,
+ 23851, 12444, 10687, 31394, 20224, 18695, 20737, 1171, 15948, 12041,
+ 29063, 24732, 20896, 24064, 3078, 29743, 25078, 28432, 10470, 27301,
+ 24468, 31346, 1093, 16689, 32307, 8975, 15167, 20242, 27745, 78,
+ 24173, 7693, 6692, 23082, 3499, 10011, 21216, 27527, 287, 18271,
+ 11898, 7878, 9079, 346, 7614, 30871, 8561, 24162, 5630, 9486,
+ 4769, 1104, 8188, 23290, 8047, 21370, 19979, 2418, 18527, 8417,
+ 23920, 944, 12949, 24747, 1806, 7971, 7576, 21715, 17219, 30655,
+ 26198, 5151, 1293, 20120, 15208, 32082, 12401, 13999, 26264, 27299,
+ 20509, 1035, 20384, 14703, 20044, 12556, 7221, 31275, 13546, 11773,
+ 4420, 23708, 14584, 20200, 6524, 11338, 5427, 19374, 5388, 28978,
+ 30704, 1622, 22190, 2235, 2123, 2982, 29156, 19179, 18048, 496,
+ 16001, 4059, 19353, 31279, 13676, 10600, 11338, 22355, 2721, 9516,
+ 793, 16344, 10360, 27309, 26049, 19869, 28714, 2515, 18905, 28660,
+ 25489, 19872, 7345, 13301, 7215, 26395, 4733, 26393, 13170, 17549,
+ 28853, 18436, 54, 26864, 22459, 14753, 19852, 22437, 20415, 11380,
+ 28346, 26725, 7392, 12844, 21635, 6010, 7827, 28536, 1960, 9775,
+ 15945, 24604, 11438, 8069, 12620, 8516, 29922, 5415, 4586, 13848,
+ 8347, 10400, 5078, 31376, 30399, 13516, 22475, 14474, 21896, 11148,
+ 8818, 4890, 16520, 31678, 31366, 15393, 4075, 4973, 29238, 10273,
+ 9469, 21060, 8139, 13391, 18412, 73, 2442, 29418, 4814, 7368,
+ 2268, 4556, 3557, 6540, 26796, 3903, 24866, 22101, 17169, 12561,
+ 16105, 28807, 25133, 29163, 27668, 15136, 10325, 22750, 2362, 29420,
+ 17265, 28479, 305, 764, 12198, 18613, 16593, 27988, 19763, 20880,
+ 7163, 11236, 3481, 22364, 986, 7610, 31743, 32694, 29289, 21621,
+ 9428, 8543, 12086, 22013, 8374, 13199, 20837, 9841, 18067, 18316,
+ 8951, 11873, 18702, 16506, 18765, 20798, 17188, 15733, 22247, 18446,
+ 30735, 27101, 10866, 5220, 19050, 10225, 16130, 8080, 11927, 18848,
+ 20892, 23059, 7262, 19355, 32759, 28502, 17366, 18095, 17539, 24987,
+ 2441, 2898, 29611, 8755, 3539, 7036, 7767, 31217, 17291, 30392,
+ 32182, 21984, 23013, 27770, 19514, 19505, 32151, 26803, 12260, 28023,
+ 13627, 28323, 6593, 13847, 23797, 13806, 16053, 13305, 1365, 7667,
+ 3447, 13444, 14719, 27481, 17885, 3786, 28809, 1002, 5466, 24063,
+ 11812, 7333, 23749, 16432, 5759, 3598, 859, 27953, 31080, 17097,
+ 31496, 14808, 6325, 29799, 23010, 23400, 11746, 10880, 11510, 32592,
+ 29435, 12290, 26696, 2838, 12988, 29384, 6165, 6286, 9208, 367,
+ 14171, 591, 5175, 7013, 20380, 5223, 9635, 1858, 17886, 13646,
+ 9253, 9052, 30966, 6937, 13771, 25749, 5382, 24816, 27245, 14200,
+ 16453, 4290, 28304, 30597, 1278, 30007, 25994, 28872, 7388, 18407,
+ 12007, 8113, 356, 4041, 6924, 8991, 26051, 17390, 21274, 5310,
+ 32202, 1647, 30741, 15251, 13879, 2980, 15686, 19669, 16950, 406,
+ 477, 12031, 8743, 2999, 11739, 29475, 1954, 9937, 22063, 30849,
+ 15032, 2365, 27679, 28248, 25724, 21333, 31722, 10236, 25283, 9259,
+ 16044, 30505, 2343, 26236, 897, 151, 29522, 27103, 13293, 16078,
+ 19577, 7234, 30588, 10044, 12326, 30615, 15013, 9605, 2107, 30667,
+ 7412, 24858, 3124, 11512, 2665, 269, 17836, 15835, 1051, 25124,
+ 15906, 28296, 23584, 29484, 14846, 32604, 26801, 11151, 9423, 30772,
+ 29322, 20521, 4823, 13276, 25232, 31320, 31689, 16331, 29366, 5458,
+ 4817, 25613, 26145, 17852, 24533, 26496, 3211, 28536, 32251, 25667,
+ 5349, 19902, 9067, 16492, 29504, 20846, 22102, 7929, 24045, 14756,
+ 29495, 23818, 9699, 6797, 26712, 28493, 28258, 18042, 19096, 13241,
+ 2006, 19763, 10093, 2943, 29182, 1422, 14373, 20797, 18765, 21824,
+ 23153, 32629, 9105, 10994, 29219, 6975, 8146, 24216, 6199, 14138,
+ 11645, 27646, 15120, 8904, 20162, 15267, 5125, 6523, 23098, 28107,
+ 5660, 1738, 32717, 23504, 14869, 12809, 5331, 17337, 19371, 26264,
+ 27513, 21005, 7190, 27738, 14694, 32234, 15828, 25704, 20895, 27473,
+ 11689, 24071, 13736, 18372, 3301, 14296, 16877, 21779, 20709, 8527,
+ 31072, 5747, 3036, 20582, 13410, 21456, 13012, 16275, 14055, 26468,
+ 1263, 2039, 29141, 2441, 30707, 11224, 29614, 3787, 19973, 25937,
+ 19567, 19522, 14517, 19784, 26808, 5663, 11579, 28321, 10284, 3204,
+ 19968, 6577, 13083, 10905, 3425, 3062, 21343, 19420, 28079, 16389,
+ 21635, 7096, 634, 31171, 12075, 9050, 5903, 25304, 943, 27072,
+ 7743, 19297, 10250, 23058, 20322, 25317, 19699, 25654, 5276, 32139,
+ 32329, 2975, 11871, 14730, 692, 22629, 12337, 6368, 24202, 24219,
+ 15024, 25415, 32239, 20445, 5843, 25701, 19009, 19240, 5746, 23107,
+ 11955, 24302, 24073, 10240, 20535, 29034, 31673, 8391, 31906, 818,
+ 28559, 32510, 5386, 11, 2313, 23488, 30579, 4608, 15830, 14990,
+ 11179, 10934, 24030, 32065, 22387, 14074, 18562, 21571, 15839, 12444,
+ 1829, 32511, 19968, 640, 28907, 28822, 1216, 29426, 15296, 11476,
+ 9740, 2106, 7837, 29026, 4409, 7024, 26886, 32573, 13472, 3474,
+ 13272, 6246, 25740, 21204, 3905, 1500, 6487, 18487, 21008, 14791,
+ 22735, 1885, 28207, 25078, 20190, 11420, 28269, 32395, 22891, 17233,
+ 385, 20725, 2939, 19575, 13900, 14111, 27548, 4984, 19807, 18151,
+ 29059, 17730, 17341, 15826, 1780, 32158, 31458, 6398, 4066, 16061,
+ 8708, 26968, 15832, 1812, 17560, 14350, 12951, 31083, 8728, 3912,
+ 13825, 19248, 13060, 31507, 821, 27920, 32551, 5789, 28924, 8649,
+ 10523, 31144, 31076, 30521, 21263, 6713, 25770, 21947, 16584, 30352,
+ 7005, 6580, 23270, 7005, 25537, 27497, 30569, 23089, 3698, 18708,
+ 2931, 17459, 22089, 30518, 10831, 15636, 30595, 19246, 30131, 14917,
+ 16928, 1035, 25410, 615, 11146, 9631, 31573, 259, 9079, 2516,
+ 29947, 635, 12304, 7236, 21311, 27712, 5459, 29699, 26537, 17734,
+ 2998, 16319, 24071, 8885, 18957, 14348, 13676, 19682, 26285, 3065,
+ 19066, 12413, 21458, 31719, 22237, 28684, 31550, 5787, 2584, 10647,
+ 15651, 19601, 8068, 17573, 22083, 19859, 5525, 23656, 29014, 25739,
+ 27232, 6709, 26540, 17814, 346, 5175, 29971, 601, 5731, 1123,
+ 25339, 6296, 25091, 27566, 28376, 20228, 21235, 30078, 28616, 21589,
+ 223, 12127, 32630, 21657, 15466, 26872, 10814, 30924, 24691, 20541,
+ 27282, 1192, 18582, 7654, 29596, 1726, 4342, 26143, 3876, 20166,
+ 826, 24961, 4789, 7732, 21718, 16961, 12283, 18188, 6796, 27047,
+ 9328, 11510, 5426, 4546, 3128, 23701, 15285, 16219, 23624, 11541,
+ 9822, 4135, 18382, 8195, 16212, 14656, 5325, 29538, 23651, 18902,
+ 9224, 6651, 9723, 1570, 12322, 3572, 28540, 28316, 2051, 12708,
+ 25776, 18286, 18558, 12966, 12441, 13352, 22832, 9004, 366, 15285,
+ 12459, 15766, 3552, 18574, 9172, 1604, 32673, 31021, 17545, 16296,
+ 26407, 21701, 4999, 25759, 7342, 14384, 2443, 7425, 12924, 3881,
+ 15288, 24694, 23656, 11707, 7993, 15244, 28829, 24057, 12327, 27399,
+ 26012, 30192, 32685, 16761, 29056, 2522, 28010, 2834, 11910, 3733,
+ 4118, 25528, 26828, 83, 4457, 13146, 31065, 24978, 312, 17538,
+ 21086, 9807, 25570, 10538, 8379, 24438, 32746, 25041, 9925, 15006,
+ 12005, 31438, 13383, 10739, 13719, 5091, 24519, 18547, 26457, 1557,
+ 25866, 20062, 6333, 7099, 19674, 10727, 9589, 3798, 16902, 4144,
+ 3441, 16800, 14251, 6773, 27976, 25960, 17586, 17288, 21977, 924,
+ 22682, 22909, 18226, 7464, 11639, 14246, 21169, 21502, 6971, 23746,
+ 10344, 21238, 12341, 12657, 5062, 26585, 13015, 4843, 11124, 952,
+ 28860, 30194, 14462, 5507, 32490, 13829, 6323, 29399, 20308, 25815,
+ 8270, 17174, 16291, 11775, 16086, 8381, 1333, 8945, 27458, 25842,
+ 6758, 813, 7009, 20829, 4367, 21686, 19065, 3129, 28237, 24774,
+ 21295, 8875, 29572, 26816, 8358, 1362, 30883, 10086, 31467, 13087,
+ 15273, 29260, 29329, 1639, 18792, 3980, 12184, 22582, 25480, 5052,
+ 10132, 28135, 2000, 23581, 32522, 25841, 31905, 30997, 6686, 4356,
+ 1731, 7392, 8299, 85, 11365, 25218, 30771, 6710, 10590, 256,
+ 31928, 3049, 30905, 16079, 29673, 30646, 6001, 14733, 1857, 6715,
+ 25721, 21999, 17389, 23044, 16895, 27643, 26157, 30043, 23538, 887,
+ 29692, 16993, 14274, 13473, 27379, 13662, 29031, 288, 1387, 8534,
+ 18852, 14651, 23266, 26333, 27021, 16713, 24480, 1323, 32583, 19304,
+ 1945, 16755, 6159, 22898, 4246, 22641, 23421, 6957, 14224, 28227,
+ 3082, 31938, 23900, 12409, 28881, 31089, 24206, 24175, 3218, 1666,
+ 8855, 11227, 17916, 10879, 9776, 12706, 25900, 5280, 1276, 24816,
+ 2673, 18567, 18024, 11399, 594, 12845, 29143, 23639, 6866, 13853,
+ 11772, 16207, 24050, 4576, 28550, 12148, 21880, 8376, 31491, 7216,
+ 15343, 22673, 15870, 3820, 16111, 4916, 17259, 24033, 13982, 30654,
+ 18246, 298, 30327, 6224, 11638, 15902, 6986, 6153, 24567, 7390,
+ 31364, 27953, 22584, 23594, 5809, 5047, 22466, 22393, 15679, 17374,
+ 5147, 4936, 12677, 307, 23018, 25522, 2308, 5570, 27483, 24897,
+ 7404, 19849, 7621, 8196, 13538, 1581, 31371, 23777, 20224, 26348,
+ 26432, 5421, 10525, 21715, 6414, 15482, 28495, 30513, 22360, 1200,
+ 13231, 24651, 20894, 27744, 4956, 11857, 3233, 1876, 11459, 14481,
+ 10952, 13675, 19229, 7403, 5059, 15268, 27448, 16773, 16238, 29560,
+ 32123, 7872, 10232, 1133, 2341, 25962, 10052, 23528, 5333, 21813,
+ 17295, 22338, 30799, 22375, 12116, 21535, 31613, 12756, 108, 6907,
+ 26292, 26121, 25210, 22534, 26681, 4299, 18566, 5682, 29444, 24000,
+ 25064, 28810, 31427, 25451, 22120, 28101, 12578, 31582, 3491, 14875,
+ 10314, 27306, 1457, 13143, 32423, 28315, 32004, 31534, 30703, 418,
+ 29587, 975, 10080, 27795, 18232, 19131, 3913, 30736, 28503, 13783,
+ 22987, 21061, 7105, 18111, 3809, 31959, 15064, 6238, 27550, 22294,
+ 10995, 23228, 16054, 6266, 6916, 16662, 28224, 20301, 24184, 5684,
+ 2746, 14245, 14430, 27383, 4942, 32405, 25036, 4914, 20307, 17828,
+ 20350, 25786, 24855, 31358, 31425, 27841, 30172, 22250, 12687, 3935,
+ 14112, 7420, 12796, 17778, 24866, 25484, 5329, 27816, 8865, 1767,
+ 19318, 24026, 10727, 4547, 13589, 15772, 774, 12921, 3836, 15122,
+ 11106, 4206, 17475, 12549, 32367, 5586, 24751, 23861, 24508, 398,
+ 10967, 8689, 17969, 21879, 10629, 1510, 3221, 29896, 6239, 26165,
+ 11090, 1743, 4039, 3784, 16253, 29158, 25599, 11493, 785, 677,
+ 32657, 20483, 6779, 4950, 15598, 27869, 23388, 18345, 853, 5830,
+ 28810, 12458, 10998, 25404, 32600, 27887, 27736, 11199, 12823, 6422,
+ 24312, 8676, 19420, 9327, 19251, 27045, 10628, 24053, 21349, 11771,
+ 21494, 19843, 14419, 25519, 1960, 11588, 15558, 11884, 21861, 5996,
+ 27769, 7194, 16461, 15397, 18997, 10855, 32029, 13260, 10555, 19110,
+ 14000, 16734, 13794, 22493, 31686, 6445, 29057, 13081, 14853, 32728,
+ 9615, 31237, 27197, 21881, 4617, 3003, 20976, 24864, 23316, 20442,
+ 32274, 28801, 31204, 29657, 23309, 8169, 13532, 4763, 3592, 24183,
+ 25335, 31299, 29545, 648, 32358, 1097, 26264, 627, 19067, 13262,
+ 14086, 9591, 4293, 3628, 28271, 16625, 14717, 25042, 19548, 21970,
+ 17184, 28495, 6891, 8785, 23902, 10412, 16594, 31709, 11059, 31487,
+ 13474, 1366, 28756, 22077, 13641, 5500, 11724, 26448, 27611, 25000,
+ 29159, 14441, 23186, 16570, 24399, 11160, 15635, 6738, 12149, 922,
+ 15858, 22083, 13362, 28402, 9593, 24644, 7343, 18747, 26021, 5097,
+ 386, 1724, 10098, 9426, 31769, 32317, 15704, 22307, 19804, 1305,
+ 7958, 7219, 22414, 4501, 21166, 26505, 28532, 22384, 26289, 20484,
+ 18618, 4795, 25020, 20825, 402, 29931, 19267, 16835, 4510, 26669,
+ 12685, 20469, 8208, 7417, 20736, 7508, 1296, 5610, 16543, 18531,
+ 31326, 9677, 18385, 31614, 16184, 5112, 16740, 21452, 13182, 23261,
+ 12241, 13423, 11796, 13534, 26306, 23037, 4744, 27491, 28113, 16948,
+ 27124, 7210, 147, 15337, 806, 26847, 20437, 13122, 24063, 17645,
+ 26661, 3621, 26137, 21907, 24981, 11504, 16556, 6202, 15547, 25451,
+ 12723, 17158, 4348, 32251, 23626, 5035, 28683, 10008, 25179, 130,
+ 8876, 16640, 10105, 32732, 8894, 1965, 15116, 22934, 30328, 3845,
+ 11695, 14061, 20723, 29010, 21974, 25748, 7144, 16881, 18356, 31492,
+ 20156, 6222, 1116, 24852, 14009, 18192, 9254, 23753, 5279, 5008,
+ 84, 9839, 13147, 400, 8181, 12776, 23574, 1834, 27658, 8773,
+ 19313, 15622, 28392, 7059, 3087, 24272, 8925, 26359, 23125, 12265,
+ 5142, 7422, 30061, 6237, 22976, 18990, 401, 3606, 10862, 16865,
+ 24454, 7759, 4027, 4947, 7526, 11083, 32048, 21753, 25763, 12870,
+ 20072, 14868, 2377, 11692, 28785, 9863, 7811, 26505, 14966, 13541,
+ 13409, 20544, 14747, 25295, 8920, 11649, 29737, 22397, 1547, 13685,
+ 26603, 30874, 20424, 27195, 18392, 16725, 4694, 18840, 15601, 4021,
+ 26734, 9450, 11885, 23596, 7815, 13662, 21780, 3952, 343, 16483,
+ 7657, 27270, 30102, 24671, 8203, 13599, 15621, 17824, 10717, 9768,
+ 3247, 917, 10597, 15005, 22638, 15934, 29682, 28318, 30642, 19425,
+ 12546, 3268, 1918, 7935, 27746, 1973, 11699, 3206, 5015, 4598,
+ 8593, 16968, 25213, 26625, 7547, 428, 814, 152, 7674, 29347,
+ 25893, 5976, 4613, 8926, 4004, 17809, 24704, 1343, 29522, 7509,
+ 26370, 1421, 32553, 31439, 21979, 1131, 31887, 32726, 3414, 20363,
+ 30403, 28098, 24635, 27167, 12667, 20863, 24472, 14736, 29388, 13792,
+ 5057, 27251, 9289, 20533, 18070, 8633, 3951, 23327, 17156, 20005,
+ 14657, 5027, 11727, 11780, 8495, 3198, 23438, 23832, 26428, 19384,
+ 18423, 32469, 7520, 26236, 4700, 22736, 18475, 3879, 9078, 29044,
+ 21164, 18847, 24674, 1782, 31121, 14822, 3817, 29324, 29071, 16623,
+ 20228, 19418, 19717, 23472, 19871, 24749, 25820, 30840, 5278, 21740,
+ 18609, 13955, 7198, 32460, 31286, 17356, 253, 21314, 30677, 19746,
+ 1180, 30398, 23191, 13438, 14819, 17942, 2885, 404, 902, 27584,
+ 21197, 16552, 18311, 21829, 18918, 17315, 31741, 7410, 27639, 31078,
+ 28947, 15313, 20789, 20318, 31827, 6104, 21516, 20824, 26917, 16991,
+ 9665, 31639, 21138, 31448, 5717, 29476, 19022, 18874, 5036, 6246,
+ 28918, 18366, 9199, 10226, 25494, 25934, 24366, 23972, 8814, 17978,
+ 11338, 19951, 21750, 1454, 17682, 26993, 3871, 30305, 17836, 24267,
+ 31708, 13070, 19255, 20143, 4321, 4904, 26030, 1595, 12202, 22474,
+ 24847, 13189, 22464, 9453, 10685, 18551, 20024, 6877, 20515, 32733,
+ 24188, 9198, 28571, 14524, 6222, 19050, 31886, 7141, 12041, 10959,
+ 15836, 16331, 24106, 22071, 30078, 16018, 30480, 14616, 31850, 29288,
+ 31744, 23085, 21942, 19480, 27756, 1460, 32001, 30684, 9845, 14554,
+ 29711, 17523, 430, 24948, 21427, 116, 1827, 17903, 25586, 16866,
+ 27290, 10634, 32613, 19456, 10520, 194, 17887, 1895, 28839, 18958,
+ 25168, 16469, 13655, 24269, 26601, 8008, 6019, 20605, 2689, 4044,
+ 32597, 9773, 13880, 2449, 4492, 3637, 19034, 28608, 24957, 22564,
+ 31622, 31375, 1112, 19194, 8463, 24340, 27053, 11160, 29090, 10582,
+ 7471, 1908, 29481, 31914, 21943, 6033, 8688, 11837, 30092, 20399,
+ 4870, 28141, 24545, 28095, 5607, 29021, 18335, 7577, 6487, 21832,
+ 23397, 1265, 22417, 10517, 29389, 19335, 3489, 22700, 8434, 29599,
+ 16911, 26761, 20527, 5809, 24253, 14350, 19241, 23137, 8722, 15902,
+ 22287, 12721, 11096, 29671, 17184, 15990, 9827, 25087, 4462, 26377,
+ 23156, 947, 7394, 29758, 8285, 29852, 24705, 19354, 997, 7283,
+ 17389, 6592, 5229, 19749, 4399, 301, 10452, 1834, 30643, 8485,
+ 6809, 22547, 16532, 2285, 15423, 1891, 6171, 27451, 3830, 1440,
+ 4226, 9707, 31607, 20906, 16893, 29171, 4656, 18507, 11259, 20377,
+ 5793, 4622, 15272, 740, 23046, 9045, 7095, 13392, 10550, 678,
+ 12640, 2501, 20939, 18758, 27300, 19402, 643, 4617, 16856, 27383,
+ 2790, 19048, 6753, 31144, 15913, 6612, 23229, 28153, 32083, 21322,
+ 26563, 16366, 11422, 9512, 25899, 14321, 6176, 31551, 24400, 386,
+ 2986, 18217, 16949, 22058, 8689, 8924, 16838, 21680, 3819, 384,
+ 5985, 22672, 27004, 25214, 14485, 26025, 14418, 15066, 27434, 31798,
+ 17934, 2242, 23137, 26879, 164, 17767, 4476, 26065, 26628, 10507,
+ 32641, 7723, 20474, 30043, 26684, 27706, 31058, 14848, 26243, 25095,
+ 17985, 18289, 25534, 29424, 3584, 17419, 10406, 20821, 21434, 5987,
+ 27468, 21651, 25768, 8155, 32349, 31542, 8571, 26227, 1445, 23914,
+ 30458, 17634, 21459, 9139, 18924, 12774, 21884, 21982, 23096, 10200,
+ 11618, 5688, 24907, 22915, 26101, 7421, 28602, 10550, 23578, 2067,
+ 20008, 5656, 18220, 21240, 25963, 5052, 576, 2810, 29162, 32757,
+ 31406, 5030, 1609, 10988, 26573, 3970, 8521, 9583, 12285, 16639,
+ 23273, 18828, 7915, 30633, 27858, 12639, 20752, 23969, 6641, 4136,
+ 30843, 14669, 14694, 8608, 24273, 30542, 26781, 9102, 18578, 4274,
+ 10426, 3477, 7581, 8555, 27451, 31568, 31479, 17152, 20952, 31905,
+ 4552, 32643, 9646, 16453, 30630, 28867, 18845, 19628, 19478, 24514,
+ 11247, 15112, 22352, 30826, 31546, 10405, 1603, 25979, 8839, 21112,
+ 26585, 26824, 20659, 3834, 3964, 17315, 3862, 6711, 217, 918,
+ 11107, 26657, 2276, 1876, 30927, 28971, 10268, 20462, 11382, 11539,
+ 29200, 29258, 22778, 12287, 1570, 15570, 19821, 7628, 1419, 25961,
+ 23409, 26531, 10911, 21411, 18589, 1997, 25938, 23349, 28451, 12232,
+ 8444, 31402, 20912, 7322, 5977, 29272, 9876, 1381, 21716, 18323,
+ 7715, 22588, 20997, 2080, 26715, 14645, 18040, 25068, 15815, 30655,
+ 6320, 25342, 28578, 28214, 3947, 30123, 17216, 32693, 10280, 27913,
+ 7338, 10284, 14055, 13734, 15497, 21170, 13104, 32377, 5445, 27164,
+ 22102, 28184, 31597, 22478, 28413, 14380, 13658, 25809, 3546, 10018,
+ 11791, 12582, 28602, 28196, 20324, 13658, 18630, 22344, 18276, 603,
+ 21765, 8711, 15603, 13194, 21026, 9712, 14260, 18193, 18032, 3485,
+ 16169, 20599, 14635, 15847, 29980, 14706, 16385, 15702, 12094, 1276,
+ 1488, 12251, 21519, 18600, 11954, 15042, 32509, 20535, 15671, 25826,
+ 12240, 8038, 23793, 18199, 2373, 17931, 13878, 8434, 25337, 14944,
+ 12065, 9646, 12937, 11679, 15834, 5478, 4088, 3791, 12311, 30342,
+ 22865, 12253, 3043, 896, 14733, 16622, 28063, 8384, 5814, 5620,
+ 1862, 28385, 11085, 27263, 9461, 19745, 20202, 6103, 23210, 24594,
+ 12834, 28999, 16203, 28819, 4525, 15035, 22763, 14079, 9416, 28046,
+ 7754, 26276, 19161, 16285, 12698, 3447, 15442, 8352, 14473, 7173,
+ 17111, 8634, 30075, 10669, 15523, 31566, 1559, 18701, 28456, 9493,
+ 27398, 186, 27893, 13421, 15607, 15412, 4829, 29940, 13031, 18713,
+ 24662, 28502, 23967, 13464, 12063, 21091, 15486, 7465, 3622, 29285,
+ 3960, 19579, 17320, 21168, 2655, 11694, 15002, 28026, 19809, 29635,
+ 24392, 11757, 18131, 1105, 12092, 20603, 25133, 31353, 97, 7538,
+ 10325, 22043, 17256, 12752, 13600, 11082, 17771, 19032, 9750, 26110,
+ 13520, 17637, 26229, 30217, 28017, 19455, 31865, 30541, 20473, 24748,
+ 15323, 10795, 10385, 13960, 407, 20543, 26813, 5656, 23795, 16714,
+ 14464, 14684, 18877, 19567, 8903, 22179, 24532, 14755, 24837, 19875,
+ 7146, 32607, 2586, 10953, 9607, 151, 10361, 29902, 13905, 26352,
+ 31626, 30859, 1676, 27950, 26701, 1806, 25309, 11755, 23873, 23021,
+ 20307, 19087, 11652, 4570, 23463, 32380, 10043, 888, 3267, 29321,
+ 26932, 18030, 32642, 25778, 15306, 15033, 10423, 30734, 28937, 30790,
+ 22128, 16641, 4115, 23744, 22140, 25010, 20418, 11175, 26154, 19135,
+ 9359, 29858, 20308, 29744, 26035, 13334, 22172, 8874, 19852, 25079,
+ 24310, 3301, 22849, 25310, 26215, 30048, 19369, 3932, 16396, 3156,
+ 22377, 17807, 12125, 11750, 13405, 14578, 18611, 20640, 9274, 29817,
+ 15112, 14370, 10865, 17118, 26366, 16405, 31574, 28981, 26403, 21345,
+ 26241, 8135, 28020, 25504, 16500, 5405, 6688, 29906, 3967, 18267,
+ 12174, 4434, 32737, 4048, 18336, 14857, 25392, 15562, 28218, 9953,
+ 16123, 30127, 17662, 27516, 11949, 9545, 5210, 21543, 7348, 24162,
+ 28101, 3849, 5859, 28305, 17221, 30112, 16917, 4947, 6197, 2671,
+ 12564, 1373, 12101, 32496, 8889, 20017, 22978, 21968, 27476, 7152,
+ 19480, 30043, 3405, 1903, 7061, 15926, 17676, 140, 18799, 31308,
+ 3095, 21699, 32521, 14346, 22394, 1020, 24434, 26063, 5484, 22439,
+ 4654, 16798, 11823, 28683, 27450, 28951, 3128, 15323, 21578, 21925,
+ 28560, 3595, 23381, 28920, 4218, 17889, 2643, 28086, 21846, 15695,
+ 27718, 8301, 8133, 29056, 25463, 5325, 29966, 6577, 13570, 31508,
+ 1473, 8258, 28052, 2505, 22682, 12813, 884, 10157, 7335, 22518,
+ 22976, 29167, 26285, 20163, 2298, 29343, 24009, 4399, 4291, 7013,
+ 6995, 18489, 22245, 22643, 16903, 5570, 6039, 20408, 4199, 27991,
+ 11005, 8278, 29275, 28492, 17391, 13911, 22043, 31242, 3067, 1691,
+ 18510, 26025, 16557, 18197, 7028, 7618, 13837, 30520, 7809, 3454,
+ 25194, 19627, 9930, 4595, 22358, 22596, 28965, 26289, 19442, 30516,
+ 7756, 16535, 7276, 25727, 20099, 2796, 25285, 32432, 8315, 31403,
+ 3288, 5578, 6005, 27677, 5016, 21889, 11434, 16045, 14233, 8106,
+ 4075, 8953, 26322, 27377, 23429, 3877, 12193, 31178, 16231, 19828,
+ 25871, 32170, 26503, 22809, 22614, 31350, 8577, 32074, 19360, 32316,
+ 1409, 27287, 530, 289, 9828, 13946, 4361, 410, 3354, 31023,
+ 22179, 12511, 847, 32197, 14722, 17309, 29002, 14454, 5580, 15083,
+ 21269, 30516, 31606, 14720, 2270, 132, 8643, 14627, 1693, 5263,
+ 13319, 13410, 9975, 1142, 23473, 6279, 9570, 21479, 11144, 5064,
+ 907, 6382, 20533, 5054, 24053, 3597, 10754, 2073, 29666, 2702,
+ 13281, 15761, 26230, 21784, 23472, 25888, 29466, 1153, 12219, 7022,
+ 11551, 25315, 1411, 1165, 31395, 1778, 32190, 20454, 22713, 6028,
+ 2462, 14451, 10948, 28050, 21846, 21807, 6436, 2039, 15323, 19915,
+ 17173, 1558, 10215, 18339, 18387, 7241, 1604, 7920, 27395, 14007,
+ 11591, 16447, 22606, 15981, 23963, 13858, 19023, 13489, 16447, 16165,
+ 6319, 6290, 1490, 3, 29070, 19140, 2831, 9754, 16933, 25515,
+ 9876, 3613, 4778, 12214, 999, 17161, 22900, 17902, 12218, 26970,
+ 2400, 27855, 14702, 27262, 24435, 16726, 3543, 29834, 13249, 21595,
+ 28479, 8748, 20877, 12833, 11949, 24288, 6833, 2092, 2663, 23399,
+ 31297, 23890, 21941, 9846, 27243, 4117, 19944, 15787, 4513, 3888,
+ 16539, 10948, 15099, 112, 26425, 275, 11734, 18885, 7103, 20269,
+ 10434, 12441, 19139, 22755, 923, 864, 18102, 11635, 15605, 369,
+ 24678, 28159, 30397, 29972, 26822, 22589, 9758, 13276, 32754, 26993,
+ 31394, 31031, 21870, 11672, 16538, 20291, 15790, 3814, 17087, 31203,
+ 16604, 14707, 28441, 6163, 1749, 26418, 17184, 28536, 17525, 10274,
+ 17186, 5691, 3604, 31432, 228, 28440, 13136, 18652, 30092, 11186,
+ 2061, 7235, 12990, 18730, 16059, 8253, 12038, 15087, 14296, 17120,
+ 12662, 14296, 27317, 2757, 8336, 23920, 19324, 29953, 14438, 7569,
+ 21106, 28502, 27647, 10804, 2170, 17067, 30205, 21383, 15579, 442,
+ 23677, 3136, 18498, 20489, 27711, 2097, 267, 5403, 28423, 10525,
+ 17596, 28647, 8514, 11723, 15058, 32393, 10989, 22360, 13505, 20024,
+ 8115, 30929, 20278, 1912, 19029, 9474, 14495, 10896, 18255, 28296,
+ 16621, 28735, 12985, 28206, 5784, 8875, 28011, 886, 21732, 666,
+ 15716, 885, 18276, 3300, 19821, 18916, 1724, 13353, 20473, 24693,
+ 21162, 25279, 18768, 12387, 19784, 22766, 17644, 29261, 31627, 15200,
+ 31267, 20548, 12048, 26067, 9223, 28195, 15640, 22033, 4235, 19486,
+ 9937, 17186, 10983, 14238, 5847, 13504, 1341, 15949, 22522, 12043,
+ 9596, 22380, 10562, 18046, 6533, 14189, 4912, 12322, 5772, 446,
+ 8775, 8705, 10177, 19683, 10955, 6110, 12336, 11463, 31177, 20515,
+ 17382, 14164, 5975, 5403, 7254, 14145, 32285, 9825, 11259, 299,
+ 27668, 22169, 5438, 7912, 12430, 12637, 2201, 17688, 7031, 15738,
+ 19965, 18172, 29146, 12125, 32113, 31884, 2982, 8136, 11005, 20163,
+ 32435, 6858, 2502, 24126, 31488, 6893, 19066, 30725, 15423, 17585,
+ 14574, 19625, 13459, 30265, 23814, 7567, 21656, 32581, 8918, 21643,
+ 5284, 5472, 19974, 14768, 9036, 22619, 15483, 15207, 23850, 31481,
+ 15411, 31935, 29150, 25580, 30833, 7684, 23123, 23296, 16923, 29587,
+ 1092, 5783, 14176, 7916, 22270, 15701, 3741, 15881, 30055, 12316,
+ 2178, 9455, 24895, 12347, 19825, 21890, 25510, 13794, 14886, 10653,
+ 24286, 2778, 24477, 25442, 27987, 32114, 14896, 6095, 29144, 16317,
+ 25601, 10130, 32052, 18170, 18071, 14879, 11485, 16212, 4044, 28415,
+ 26371, 26572, 28134, 14699, 6096, 27251, 22276, 6681, 21487, 1244,
+ 24508, 11094, 1099, 5329, 25858, 13141, 32537, 23877, 3403, 12487,
+ 12824, 6026, 25843, 5547, 16919, 9412, 6620, 9320, 17337, 29598,
+ 6745, 8985, 29045, 28219, 6986, 22824, 736, 1136, 18824, 2846,
+ 2351, 9776, 10883, 26809, 29943, 16967, 28713, 8512, 10552, 7499,
+ 17418, 4627, 16282, 5328, 19898, 17286, 25078, 8924, 30839, 10223,
+ 23832, 13723, 15372, 20734, 20676, 12115, 27893, 3917, 8438, 8857,
+ 22468, 12344, 3182, 7878, 11204, 19951, 3180, 8357, 30939, 26057,
+ 25017, 31598, 17589, 10460, 29414, 19960, 31518, 15050, 24536, 22570,
+ 15792, 21213, 28293, 17587, 22191, 29527, 13560, 15098, 21297, 11011,
+ 9371, 19800, 2178, 5392, 23221, 6022, 2246, 2847, 23090, 8529,
+ 19168, 15771, 4771, 22933, 2451, 9801, 22661, 15720, 7655, 2336,
+ 12998, 32662, 22735, 30554, 8581, 17486, 8200, 2251, 16922, 17690,
+ 21060, 16242, 29782, 28948, 13960, 18766, 25867, 23896, 31443, 5234,
+ 8655, 6581, 1536, 26972, 6654, 15784, 8429, 32643, 12542, 16778,
+ 15069, 16431, 17863, 30728, 19739, 11149, 21410, 15316, 8673, 5123,
+ 4144, 9626, 631, 9153, 10927, 24118, 4255, 24729, 4217, 24868,
+ 20273, 8720, 23245, 17207, 7683, 11701, 18898, 20878, 11531, 28081,
+ 28889, 7365, 10952, 30112, 30691, 17512, 12765, 18847, 5731, 5805,
+ 14848, 7078, 11077, 22626, 4114, 29465, 5678, 18724, 6543, 29337,
+ 13830, 14290, 26409, 12320, 12468, 15169, 23216, 21325, 26664, 25393,
+ 25653, 28156, 16543, 30080, 6767, 17178, 7202, 2974, 12894, 28600,
+ 12112, 9281, 6701, 10845, 4958, 32090, 15197, 3233, 14684, 19015,
+ 10272, 6903, 8890, 6730, 14339, 32459, 778, 826, 22480, 9933,
+ 12039, 25720, 4275, 16780, 31959, 22053, 2715, 17990, 31117, 6290,
+ 3555, 32766, 6130, 6136, 18482, 20176, 15493, 22634, 22688, 4994,
+ 19136, 24071, 26394, 31067, 6045, 25972, 19207, 4664, 25945, 138,
+ 1323, 30940, 19576, 27467, 4300, 28040, 13833, 11547, 20500, 8395,
+ 19243, 23085, 6071, 8348, 32208, 2363, 7638, 7078, 3777, 20858,
+ 20514, 28387, 13539, 25805, 21828, 12652, 18872, 6712, 15741, 12944,
+ 7976, 31896, 9865, 7715, 25218, 12690, 22218, 15128, 12478, 19658,
+ 5026, 30803, 16389, 25429, 14113, 15288, 17011, 29552, 18656, 10120,
+ 26139, 29810, 7724, 18925, 5707, 8959, 17767, 27347, 25106, 23935,
+ 16556, 27642, 11264, 9422, 21426, 28489, 1837, 5429, 26867, 14182,
+ 25980, 27546, 21005, 30339, 31521, 27379, 26472, 32635, 31585, 13825,
+ 19225, 3357, 4761, 28986, 21254, 5063, 16770, 16647, 24139, 20792,
+ 32179, 30767, 6621, 3743, 15208, 2707, 30829, 18679, 17537, 6173,
+ 24976, 13207, 206, 9203, 23580, 18693, 5001, 19440, 14293, 24076,
+ 29220, 5204, 31305, 27406, 22598, 7098, 4856, 32667, 15632, 19275,
+ 6840, 5185, 11684, 22322, 8792, 11942, 12520, 9039, 21636, 3029,
+ 6279, 24624, 28392, 17622, 25401, 29757, 22169, 8577, 5189, 1330,
+ 19376, 3475, 9284, 13779, 56, 25602, 28455, 27611, 5706, 1166,
+ 17275, 12853, 18806, 26521, 30444, 2926, 18277, 9272, 9224, 18539,
+ 31677, 7306, 30022, 14167, 21317, 17481, 8519, 16096, 14922, 13726,
+ 31835, 14755, 23105, 2106, 17223, 9700, 23213, 7842, 838, 32131,
+ 10563, 24010, 17229, 18987, 3404, 742, 21139, 18893, 2636, 2941,
+ 24657, 14157, 21985, 25535, 16582, 2939, 25837, 20248, 895, 19012,
+ 21495, 16133, 16085, 12330, 11983, 3111, 13495, 21489, 23409, 17814,
+ 13482, 4251, 11308, 2679, 24333, 19351, 23812, 8657, 11682, 27446,
+ 84, 17564, 25930, 4446, 7864, 19995, 21776, 28290, 3625, 18028,
+ 1641, 16593, 17514, 31582, 17082, 21422, 10404, 7042, 4635, 4961,
+ 10317, 1925, 5979, 2316, 4941, 19900, 27972, 21216, 868, 1025,
+ 26912, 27792, 21190, 29630, 26236, 23558, 26121, 19527, 43, 5718,
+ 19777, 20333, 23182, 12528, 106, 11344, 25363, 13081, 15110, 31860,
+ 10492, 7068, 15110, 5911, 13154, 28348, 26350, 11970, 30841, 24686,
+ 7989, 27935, 23061, 28357, 16106, 266, 19309, 174, 3998, 21226,
+ 1055, 23773, 13437, 21314, 25717, 3335, 20670, 6019, 28391, 338,
+ 27966, 14629, 31457, 2058, 24935, 10997, 1222, 28053, 17239, 30897,
+ 16180, 22697, 9022, 9426, 18826, 14012, 5640, 6313, 12199, 19644,
+ 21309, 23213, 5877, 16385, 27173, 32532, 15527, 11136, 21039, 1696,
+ 10558, 5441, 23187, 8124, 15698, 22547, 15671, 32199, 31631, 21886,
+ 22736, 15024, 13310, 1017, 22089, 30403, 29829, 11613, 15720, 10946,
+ 25266, 29082, 15535, 24632, 25268, 25000, 10368, 17418, 12202, 18113,
+ 30085, 18255, 18721, 27086, 12879, 16993, 22999, 28447, 17469, 20020,
+ 31685, 6750, 27552, 18407, 32093, 3782, 21276, 12953, 3089, 24464,
+ 11858, 27518, 26644, 1198, 11195, 25650, 1380, 1980, 15831, 22349,
+ 15880, 32052, 32648, 11063, 31126, 7649, 14264, 30526, 28153, 5270,
+ 16450, 24293, 23921, 21535, 21520, 14207, 30171, 2424, 2177, 11261,
+ 13619, 32317, 30221, 21253, 30551, 32610, 21547, 27460, 4366, 7204,
+ 3186, 12804, 7240, 20799, 2303, 2049, 22952, 29794, 16920, 22648,
+ 19263, 29664, 20238, 30338, 27803, 16040, 32360, 25760, 11264, 26743,
+ 14653, 14999, 2293, 24140, 13794, 7550, 31746, 16157, 15814, 32277,
+ 3001, 11464, 2713, 4440, 13043, 10572, 32436, 14164, 31836, 21561,
+ 15541, 17466, 30514, 7269, 25193, 24498, 26953, 14817, 27376, 28273,
+ 25171, 1067, 31771, 14862, 5214, 30885, 8985, 19217, 5534, 1350,
+ 17491, 10574, 28525, 27536, 17044, 30321, 7824, 20418, 8557, 5849,
+ 26812, 18510, 9944, 23722, 11096, 397, 16411, 26909, 1925, 18866,
+ 11759, 14363, 3932, 6397, 15330, 2571, 22646, 27185, 1786, 8168,
+ 6066, 30535, 6043, 32150, 10802, 11876, 21162, 9846, 12199, 29449,
+ 1523, 2104, 6607, 32649, 5064, 2032, 21820, 31425, 491, 25964,
+ 28502, 5635, 28591, 26821, 23971, 18259, 14169, 3637, 19014, 29654,
+ 16076, 9256, 2502, 7815, 15206, 3990, 7697, 28460, 27941, 10895,
+ 27329, 9609, 5390, 28952, 32413, 19667, 10959, 28725, 5731, 17255,
+ 5539, 11079, 15557, 27324, 27766, 27544, 11185, 5014, 330, 11829,
+ 21205, 31357, 15321, 9212, 10083, 26734, 1915, 30709, 8465, 19408,
+ 22603, 20454, 2149, 23977, 2949, 15137, 31279, 10002, 10035, 929,
+ 17495, 31465, 15625, 5461, 32728, 14277, 29837, 28604, 3085, 26159,
+ 123, 21938, 20268, 1807, 871, 12170, 24592, 9828, 10148, 21340,
+ 32059, 1592, 28261, 10144, 29979, 30164, 31266, 21500, 25484, 10544,
+ 22589, 29787, 26783, 9389, 3558, 575, 15513, 4358, 27708, 26712,
+ 17727, 2948, 28596, 29781, 4177, 18034, 11967, 6906, 22357, 3537,
+ 7079, 17011, 28821, 1101, 7610, 1768, 20843, 11375, 17835, 11601,
+ 1468, 4627, 8501, 14476, 16579, 10269, 29185, 21676, 27408, 11880,
+ 19402, 3221, 20944, 13311, 23999, 32198, 23374, 2448, 27433, 32373,
+ 25786, 14365, 14157, 27105, 11562, 20469, 26772, 1764, 29150, 9187,
+ 9961, 15559, 8136, 17573, 31075, 2651, 15947, 20639, 10020, 29509,
+ 30532, 27601, 8065, 22426, 24647, 29703, 11619, 27052, 26923, 17743,
+ 31212, 13859, 5064, 8880, 8798, 29263, 22783, 5913, 25913, 1212,
+ 24315, 25240, 10916, 31751, 25783, 18380, 27662, 26609, 1728, 19869,
+ 16149, 18610, 16701, 18730, 1959, 2192, 21292, 17411, 5479, 13231,
+ 26350, 4761, 12370, 25131, 9222, 12019, 22690, 2148, 3614, 11170,
+ 15858, 8601, 21834, 21238, 12708, 26809, 31633, 18034, 6272, 4981,
+ 29610, 12926, 8093, 17306, 7427, 27228, 14469, 8862, 16648, 93,
+ 8340, 23416, 30113, 11861, 30625, 26293, 2300, 8780, 10721, 23753,
+ 23182, 886, 12551, 17059, 17748, 17254, 28848, 1156, 32607, 3966,
+ 12799, 4880, 4751, 30378, 644, 22182, 21151, 5966, 31331, 27885,
+ 29793, 27004, 11698, 25775, 10827, 31083, 19746, 27627, 27187, 9764,
+ 14818, 9253, 16471, 14463, 4288, 4353, 21408, 26190, 28818, 21776,
+ 32552, 5592, 32724, 12522, 9465, 30089, 30098, 30845, 7704, 15335,
+ 10633, 29348, 27586, 9160, 28553, 22268, 3573, 30914, 16925, 24051,
+ 9010, 18404, 110, 5921, 13698, 2211, 17253, 31196, 22711, 21015,
+ 3600, 25606, 32244, 28776, 23879, 31530, 8303, 28291, 23183, 9159,
+ 12150, 26641, 13886, 748, 22960, 14249, 27872, 15877, 7590, 21828,
+ 31706, 27893, 17281, 30962, 18765, 29285, 9237, 21964, 17213, 11867,
+ 24863, 298, 31219, 16142, 29387, 23062, 14751, 17401, 11898, 1280,
+ 26434, 22318, 10945, 20403, 9419, 12525, 9397, 4487, 128, 10613,
+ 19046, 23512, 13216, 3354, 3753, 3768, 13383, 30360, 27163, 9697,
+ 7825, 9127, 11618, 20973, 14594, 30671, 18614, 12746, 6182, 8574,
+ 11425, 16488, 9588, 5464, 10242, 19124, 3448, 21454, 26456, 458,
+ 22834, 11506, 31037, 32102, 14009, 30345, 31793, 17052, 13603, 26722,
+ 22937, 8906, 30633, 4839, 12807, 1738, 9223, 9202, 24252, 31340,
+ 4130, 28130, 11372, 3107, 29421, 25837, 13121, 21758, 7309, 1720,
+ 28706, 15578, 31164, 24612, 820, 20183, 26219, 9579, 14241, 12808,
+ 5035, 4205, 14489, 6767, 1229, 31044, 6039, 17960, 26568, 23838,
+ 2022, 23268, 19676, 18252, 29539, 14233, 373, 20630, 19588, 3704,
+ 4690, 10450, 16793, 23328, 14566, 24245, 13650, 2321, 14335, 23016,
+ 8322, 24163, 27557, 15198, 16674, 32440, 4165, 6118, 15001, 6767,
+ 1295, 16636, 2875, 7706, 3484, 4069, 31503, 30258, 22228, 26363,
+ 26581, 15114, 17167, 23877, 4679, 22786, 16762, 18506, 20640, 2301,
+ 13501, 6183, 19035, 11541, 11482, 14816, 8509, 25997, 30808, 29684,
+ 11157, 29190, 20642, 28980, 9155, 13046, 9642, 28116, 28919, 24407,
+ 19665, 15043, 27963, 17052, 5899, 2872, 19636, 5865, 4670, 16526,
+ 2596, 20355, 31212, 10321, 31924, 26502, 6930, 24729, 31473, 2262,
+ 12112, 22166, 12052, 8023, 29513, 4973, 134, 11361, 31821, 19266,
+ 13987, 28270, 4406, 25238, 14527, 12566, 2703, 24020, 3942, 22846,
+ 32252, 28454, 2792, 396, 14549, 5773, 13077, 15134, 19989, 2097,
+ 25670, 18043, 15219, 19702, 15773, 22729, 27086, 20815, 17549, 16705,
+ 3278, 22103, 24988, 737, 9673, 31006, 6759, 13920, 11747, 17472,
+ 11495, 18535, 11130, 32701, 28660, 26622, 14017, 13060, 7431, 14661,
+ 12714, 3409, 26436, 8292, 14090, 10297, 952, 14532, 1272, 22660,
+ 1759, 19584, 26229, 314, 15209, 24598, 24659, 7424, 22077, 9827,
+ 9551, 29093, 11199, 28878, 5505, 8697, 19022, 28611, 19702, 4574,
+ 7697, 22371, 1435, 20641, 500, 15481, 20572, 32138, 25069, 15792,
+ 27022, 23217, 21124, 19716, 11402, 532, 16786, 11639, 27291, 28903,
+ 9289, 30981, 10523, 23851, 18036, 17113, 2776, 2434, 7936, 10689,
+ 26813, 2882, 19900, 28384, 23982, 14024, 9821, 25763, 18867, 9743,
+ 27845, 18934, 4185, 3457, 9861, 26039, 5717, 21260, 9632, 30314,
+ 17003, 7033, 12434, 18991, 1422, 16889, 27536, 4850, 11849, 28161,
+ 26386, 19170, 2909, 15192, 30607, 15652, 8620, 10351, 14983, 1736,
+ 31061, 16112, 27847, 9212, 17953, 10905, 30185, 23935, 28446, 12875,
+ 19738, 10841, 14729, 18270, 6944, 22986, 6897, 7992, 15771, 6528,
+ 30362, 2846, 3978, 11276, 18976, 585, 6930, 25495, 3420, 4669,
+ 6267, 13521, 18827, 10582, 24188, 30251, 11181, 28580, 10168, 8006,
+ 5676, 8697, 20872, 7339, 30142, 9023, 30715, 3004, 23948, 14351,
+ 4891, 29419, 11924, 8320, 31090, 18985, 20044, 1085, 27597, 26529,
+ 12424, 25819, 3648, 9383, 14493, 2665, 29290, 20203, 13767, 7752,
+ 5882, 14835, 32456, 26685, 114, 1224, 28882, 25028, 20268, 26607,
+ 21927, 5031, 30362, 8090, 29951, 29136, 31185, 17952, 21802, 10587,
+ 20809, 12971, 28406, 5360, 24030, 12336, 22739, 19280, 3355, 8357,
+ 11573, 31789, 4792, 24686, 12346, 3903, 23393, 32280, 30861, 14740,
+ 7354, 6729, 8074, 32040, 9887, 1015, 15523, 18101, 22960, 25817,
+ 12290, 7628, 26381, 4635, 111, 6949, 15710, 21846, 20597, 6452,
+ 18199, 16831, 11968, 21244, 24058, 27039, 17866, 25896, 6109, 2051,
+ 11959, 25944, 20653, 29364, 27517, 953, 5555, 26729, 19527, 27352,
+ 22038, 3900, 17436, 20920, 31905, 14171, 28859, 29730, 22215, 13824,
+ 22986, 25916, 27876, 27811, 11056, 28765, 12230, 20590, 28352, 31776,
+ 8044, 1521, 2327, 9143, 20237, 25879, 32199, 31362, 27229, 31064,
+ 16053, 11744, 8203, 21041, 2751, 31046, 5518, 14289, 8098, 8334,
+ 18465, 6166, 17179, 25745, 32524, 16311, 26445, 9719, 13094, 13251,
+ 28259, 10830, 3992, 16202, 20854, 14170, 28643, 2393, 11953, 30892,
+ 32549, 18220, 691, 25462, 23704, 24224, 4404, 3230, 26971, 3303,
+ 16620, 9489, 9077, 25983, 28336, 4186, 12823, 15717, 31711, 18803,
+ 1825, 22150, 7164, 2523, 14824, 24438, 9628, 26344, 32566, 7012,
+ 27267, 22879, 25235, 17998, 23306, 25410, 9411, 2417, 30916, 18409,
+ 25488, 5124, 23648, 2644, 28362, 11301, 21201, 9664, 28299, 19476,
+ 21933, 13432, 16063, 8095, 25299, 30958, 9188, 30173, 30545, 32010,
+ 15631, 31519, 12677, 15298, 22320, 20260, 24194, 2283, 1430, 19340,
+ 30388, 11087, 9142, 3727, 19912, 23807, 9256, 7663, 31174, 9707,
+ 20722, 13867, 13696, 17583, 24841, 6646, 16944, 6576, 1813, 30183,
+ 3165, 18536, 23925, 11378, 6142, 766, 21379, 7703, 30690, 13338,
+ 25, 16857, 21583, 31479, 32084, 8690, 17642, 11706, 12695, 4293,
+ 470, 22018, 10707, 10772, 12320, 23488, 26886, 29811, 19803, 21065,
+ 20738, 14077, 32391, 7081, 2160, 22341, 17976, 22074, 532, 21392,
+ 26100, 18550, 2387, 11585, 28380, 16138, 30706, 22420, 17806, 4395,
+ 31008, 32399, 7499, 16173, 32183, 14902, 11861, 24402, 17855, 511,
+ 11163, 19680, 9012, 29829, 15256, 19830, 23048, 18304, 30841, 8351,
+ 16748, 29685, 15230, 11688, 2636, 29354, 14242, 17327, 20248, 7389,
+ 10110, 8189, 20682, 1333, 4715, 11926, 1317, 23801, 27879, 14605,
+ 23098, 14720, 6202, 30621, 21297, 19945, 1369, 14454, 25158, 27916,
+ 32522, 4437, 9234, 26543, 24393, 20311, 24588, 6910, 13290, 6415,
+ 29263, 17205, 5761, 30422, 670, 26272, 15231, 13666, 11429, 27845,
+ 31901, 22171, 32129, 13792, 25214, 1193, 27267, 18063, 29071, 15186,
+ 9521, 23503, 15923, 7043, 28814, 31527, 3101, 7468, 23452, 21283,
+ 31996, 4945, 1310, 4, 4702, 13919, 19618, 2230, 1742, 10428,
+ 5311, 10242, 16960, 10657, 31388, 13829, 28080, 27180, 9905, 17889,
+ 27141, 14513, 6866, 19378, 11835, 30290, 8553, 24260, 20673, 2767,
+ 16899, 27651, 16416, 19103, 24334, 27826, 28382, 831, 24800, 30048,
+ 30370, 8650, 4604, 12568, 30360, 10186, 4241, 7385, 12567, 25165,
+ 31044, 5957, 11394, 5948, 12079, 6301, 23404, 7401, 25898, 9965,
+ 4095, 4071, 19529, 23172, 16030, 6942, 2982, 1703, 21449, 1566,
+ 25952, 23175, 8513, 32180, 11491, 3696, 9837, 19131, 29290, 28994,
+ 14333, 27445, 1987, 27173, 19149, 16795, 16978, 17017, 26124, 20081,
+ 7769, 19468, 157, 10268, 10103, 14224, 19901, 9464, 19054, 12108,
+ 15591, 27558, 29737, 2577, 12532, 23971, 8701, 10864, 12935, 4127,
+ 18223, 24106, 8616, 18188, 11190, 20968, 10927, 9845, 10307, 27948,
+ 612, 3601, 25471, 10888, 11620, 21272, 29843, 16398, 22215, 19541,
+ 3822, 11271, 31231, 25725, 6978, 31208, 25603, 9919, 25040, 21377,
+ 20398, 31132, 10726, 12920, 8545, 31737, 29350, 17910, 1520, 14450,
+ 10504, 24736, 30908, 8946, 32547, 713, 29980, 5248, 18600, 21733,
+ 22274, 14684, 175, 9793, 11995, 9547, 23734, 17394, 3254, 559,
+ 4326, 15372, 1705, 3290, 10649, 24852, 32368, 21540, 7706, 8631,
+ 27224, 28219, 171, 2235, 9564, 6203, 28621, 31031, 2701, 29695,
+ 11451, 31487, 24503, 22582, 31544, 11107, 21313, 26297, 11914, 9753,
+ 4437, 23836, 1991, 31351, 13377, 21378, 18767, 229, 5149, 23990,
+ 9114, 9363, 14766, 17016, 24372, 30055, 30859, 15637, 26629, 5690,
+ 29822, 32059, 7638, 23363, 5677, 22794, 3601, 11475, 13050, 25966,
+ 31432, 579, 27687, 26797, 21241, 2347, 2366, 23356, 17, 19669,
+ 20912, 27351, 11438, 29170, 10684, 13264, 26793, 23179, 30354, 9384,
+ 20052, 17978, 3513, 16348, 3328, 17049, 13230, 12289, 31939, 32763,
+ 28110, 25107, 8056, 24154, 11125, 6667, 13062, 18065, 2664, 13743,
+ 14566, 9163, 14960, 4526, 5855, 4412, 17480, 17644, 13588, 4111,
+ 14265, 9755, 15681, 22943, 1284, 20363, 24386, 8681, 1408, 5443,
+ 16085, 24130, 30596, 8528, 28320, 25669, 29063, 10845, 7286, 29968,
+ 4230, 30852, 21206, 2224, 26023, 11364, 29620, 28121, 26395, 31860,
+ 20604, 4570, 26696, 23702, 853, 1233, 23848, 17392, 28067, 3611,
+ 27884, 1271, 32719, 25871, 6118, 27596, 11850, 25068, 29861, 5836,
+ 14287, 15119, 18530, 15715, 8425, 8810, 32411, 22816, 2230, 22321,
+ 17405, 25871, 15082, 32726, 18567, 10051, 8982, 24632, 27885, 14514,
+ 1323, 16408, 24378, 16198, 7994, 5580, 27322, 3632, 6269, 18743,
+ 32535, 8320, 24987, 8952, 12994, 8690, 27176, 15330, 17556, 31243,
+ 20331, 172, 24758, 3429, 26725, 7658, 11454, 10568, 21262, 26684,
+ 24346, 19833, 26338, 5318, 26034, 18519, 12444, 21984, 24521, 22819,
+ 23362, 12302, 28452, 19616, 10849, 6962, 9327, 18396, 27034, 17408,
+ 2780, 13645, 30045, 435, 5901, 2079, 16629, 21502, 32052, 18893,
+ 32197, 32070, 12921, 9711, 18385, 3342, 7580, 26707, 31616, 28339,
+ 15067, 8526, 6304, 20569, 14102, 25684, 22186, 30245, 17969, 21703,
+ 20039, 19885, 14522, 29965, 23572, 21932, 5323, 27621, 8354, 11771,
+ 13874, 13307, 16834, 25532, 14800, 27066, 20735, 19928, 14399, 11105,
+ 31595, 3501, 5048, 16217, 26271, 2048, 23859, 29894, 24317, 27193,
+ 5327, 29276, 15160, 4047, 18805, 26483, 6423, 23553, 23480, 21342,
+ 22389, 23495, 26624, 22265, 29069, 17416, 7144, 17538, 8052, 8205,
+ 31460, 25002, 24551, 17462, 22055, 4075, 20295, 22763, 31684, 20251,
+ 28642, 4566, 24851, 20034, 18292, 25935, 19542, 32425, 30190, 22552,
+ 16796, 23859, 10613, 12619, 14054, 26096, 5038, 10896, 21385, 26096,
+ 17465, 28819, 16083, 8021, 3195, 1974, 16881, 29612, 20641, 26883,
+ 16656, 2174, 27105, 27492, 20419, 6689, 32259, 19734, 25765, 28884,
+ 28705, 29019, 28735, 11276, 20139, 9839, 23340, 22536, 25261, 1982,
+ 12154, 427, 17493, 20564, 29012, 15499, 6320, 12693, 27358, 20294,
+ 23732, 558, 28513, 31253, 24963, 22859, 22952, 2979, 24046, 27147,
+ 18858, 14367, 14648, 13104, 25961, 26255, 29469, 22300, 8473, 26728,
+ 19731, 12281, 21125, 20316, 6352, 29751, 5039, 21876, 20492, 32571,
+ 14518, 2910, 22920, 4693, 23805, 16648, 8015, 8691, 19338, 23662,
+ 23100, 789, 18092, 4784, 14012, 3329, 29409, 14183, 14037, 824,
+ 26870, 5689, 30056, 23464, 13168, 2731, 11955, 13603, 15147, 18999,
+ 12825, 4624, 26433, 5279, 8486, 11105, 29741, 16000, 8142, 28613,
+ 17969, 18986, 23029, 798, 15093, 687, 565, 21045, 15984, 19770,
+ 11739, 3756, 9995, 9378, 12850, 10037, 7428, 29503, 26373, 4098,
+ 4369, 16125, 29279, 28541, 1607, 23470, 405, 824, 13113, 6053,
+ 4998, 20775, 15972, 5760, 14370, 30989, 6603, 20037, 26921, 14900,
+ 16862, 23217, 24629, 353, 25504, 6860, 3579, 4871, 11785, 19649,
+ 5838, 9659, 21161, 7149, 30821, 232, 31119, 21814, 15581, 29636,
+ 11369, 13726, 24321, 14466, 31981, 1815, 17354, 6090, 27255, 32666,
+ 27938, 24678, 19187, 5747, 18925, 1854, 15101, 17375, 18250, 902,
+ 22855, 24280, 1814, 15158, 20795, 3376, 24499, 5050, 30946, 31197,
+ 2311, 31467, 1541, 17812, 6855, 31807, 7826, 26009, 16373, 13884,
+ 18496, 25813, 17319, 17459, 31606, 15145, 23307, 28714, 23914, 12034,
+ 20648, 16666, 25990, 29997, 29926, 14683, 29199, 749, 30673, 22876,
+ 4104, 17995, 4122, 14999, 31316, 14510, 4958, 22212, 5148, 32683,
+ 25515, 20301, 25200, 4126, 22081, 18691, 18737, 1914, 30613, 12303,
+ 3886, 12125, 20636, 30763, 28045, 24424, 4421, 11538, 11885, 12621,
+ 17480, 26420, 7881, 15145, 28702, 30895, 22431, 17429, 18768, 26235,
+ 8786, 9975, 23029, 484, 31822, 22431, 17014, 13886, 32234, 15887,
+ 30613, 24276, 10386, 23577, 8622, 14625, 24613, 28976, 316, 18243,
+ 5020, 4216, 31902, 13996, 22765, 23839, 15132, 7963, 46, 24816,
+ 28965, 11722, 25086, 12581, 16858, 4329, 27937, 21885, 22993, 14156,
+ 14186, 9615, 10002, 14433, 5598, 4190, 21094, 30820, 22, 557,
+ 24018, 23766, 17125, 23701, 3166, 9515, 17979, 13524, 30490, 15299,
+ 27209, 19560, 29539, 4891, 16358, 30685, 11875, 25413, 8242, 26595,
+ 8663, 23445, 26489, 2211, 17941, 7326, 22362, 27475, 9549, 3676,
+ 25640, 28168, 13327, 26291, 29072, 5580, 4877, 29720, 17020, 20209,
+ 7715, 143, 8248, 1957, 27796, 24789, 31955, 22726, 9879, 990,
+ 5321, 12535, 21522, 5762, 21470, 13811, 2213, 3955, 333, 20513,
+ 4330, 14194, 30498, 5225, 1275, 450, 26853, 71, 25653, 18653,
+ 32120, 15389, 7740, 17255, 16450, 22478, 11583, 17760, 11662, 13704,
+ 9598, 8605, 24109, 5857, 24073, 16249, 5731, 38, 5834, 14536,
+ 15361, 26095, 16325, 5132, 30670, 22775, 17823, 28396, 1579, 9259,
+ 1885, 11489, 31479, 4353, 22895, 32307, 31921, 17931, 14829, 21284,
+ 15068, 29644, 6688, 3946, 9128, 17354, 24900, 4579, 7374, 15844,
+ 3212, 25733, 17340, 6118, 4199, 10388, 30962, 9051, 24322, 4887,
+ 15020, 19875, 14350, 3468, 4801, 26181, 9667, 20187, 7115, 8070,
+ 19237, 137, 24968, 32058, 26502, 17454, 8320, 9690, 13132, 11561,
+ 10472, 18903, 31220, 658, 26823, 5422, 5463, 23920, 24919, 24381,
+ 11820, 30508, 2990, 3284, 26063, 15430, 28829, 22672, 19777, 30535,
+ 30681, 30052, 19823, 10231, 12888, 16249, 25783, 23247, 9214, 28472,
+ 23976, 5297, 20601, 677, 25353, 9943, 3946, 20718, 5405, 32522,
+ 27589, 31811, 1062, 18452, 4730, 13801, 13352, 28279, 5205, 2186,
+ 3567, 23903, 32546, 7376, 24915, 2006, 4630, 11314, 23739, 4663,
+ 4458, 5645, 7648, 12261, 32073, 19190, 16340, 2364, 12268, 591,
+ 2626, 15816, 9988, 28184, 9719, 22197, 31832, 24840, 31393, 15751,
+ 20911, 6876, 6615, 2828, 13296, 12016, 23386, 17038, 14728, 14604,
+ 3739, 19788, 24588, 21632, 25981, 18988, 27935, 2419, 31835, 1450,
+ 22167, 9336, 9037, 11796, 30171, 11362, 19623, 6137, 2703, 27226,
+ 17603, 9951, 20596, 14382, 5889, 11828, 11401, 2284, 17419, 24199,
+ 13687, 24496, 11614, 4856, 6955, 10426, 23046, 4845, 12741, 10435,
+ 30888, 7175, 9137, 30353, 17094, 18517, 3859, 13002, 9535, 9415,
+ 4713, 29190, 21013, 3045, 3180, 3367, 8051, 6336, 4918, 19437,
+ 22511, 17961, 26282, 7621, 24588, 3618, 25105, 21730, 21763, 7570,
+ 12545, 6031, 2243, 28733, 19331, 31684, 32566, 26866, 32116, 247,
+ 20678, 14854, 32044, 23604, 5664, 12802, 21854, 19056, 16695, 16537,
+ 9791, 23835, 1932, 18397, 491, 29940, 16814, 3506, 26628, 24353,
+ 25596, 24962, 9372, 18559, 29874, 18994, 5717, 31543, 8996, 20565,
+ 8134, 6802, 25668, 14496, 18465, 20750, 14442, 17054, 20243, 9393,
+ 32341, 16293, 14316, 26013, 30573, 5641, 4096, 27365, 24906, 1167,
+ 29773, 4511, 18554, 14885, 6750, 12858, 30847, 5584, 24687, 18,
+ 11544, 8933, 10449, 1858, 26818, 9596, 1168, 15545, 5245, 19234,
+ 29012, 21649, 19667, 21454, 11909, 21148, 23, 18199, 28082, 2367,
+ 16875, 2467, 25140, 31363, 30724, 26339, 29710, 20329, 17458, 25341,
+ 6680, 22910, 20378, 26890, 8029, 21168, 23366, 10626, 22465, 20320,
+ 14817, 15604, 2023, 5816, 5819, 24315, 1105, 21823, 11796, 21869,
+ 19401, 23978, 23190, 22485, 8448, 27638, 7203, 2852, 26486, 7859,
+ 31697, 26019, 18329, 6819, 28979, 3884, 24113, 3203, 11483, 4506,
+ 31483, 32041, 27676, 28030, 12948, 11215, 14869, 26388, 18329, 25263,
+ 16874, 8053, 12045, 31184, 5717, 19981, 13307, 31775, 4702, 11856,
+ 32348, 8897, 14182, 30121, 314, 6824, 11370, 26035, 5142, 18532,
+ 17030, 20140, 15240, 32316, 8888, 5671, 25893, 22654, 2279, 5632,
+ 6821, 13331, 12324, 26517, 28742, 29526, 21551, 28467, 12907, 1319,
+ 27709, 15311, 5769, 25146, 760, 3831, 29507, 29877, 20424, 8456,
+ 17364, 7675, 30033, 30112, 31406, 20162, 2365, 21590, 26464, 25964,
+ 18747, 14761, 13245, 18068, 8519, 21559, 15419, 25575, 26413, 25136,
+ 18329, 9525, 28488, 777, 25029, 26567, 24208, 20853, 24060, 2036,
+ 24020, 22929, 17459, 10479, 4675, 16222, 11702, 12003, 32561, 10613,
+ 21775, 8002, 13592, 17398, 23849, 23386, 29149, 28610, 5045, 26921,
+ 5717, 29162, 13005, 15986, 5384, 14183, 26071, 16912, 15925, 267,
+ 5549, 30603, 3350, 2999, 16379, 2281, 23140, 2255, 24040, 8902,
+ 6174, 31467, 7672, 22183, 31367, 19151, 30000, 30604, 12910, 10398,
+ 19324, 9412, 7345, 3402, 18255, 30469, 2820, 28751, 31881, 956,
+ 2543, 1441, 669, 10914, 18454, 6114, 13811, 24976, 701, 21209,
+ 10379, 29332, 7051, 4640, 1508, 24644, 15246, 2076, 28188, 25682,
+ 10112, 20786, 3160, 15457, 10569, 18232, 27750, 14615, 12996, 10538,
+ 21409, 17268, 7622, 27423, 8469, 19554, 11613, 17019, 30948, 23181,
+ 13397, 16997, 16105, 10868, 1281, 7292, 9370, 5313, 3640, 22981,
+ 20019, 11989, 18845, 8168, 21265, 22952, 24355, 22173, 7515, 13008,
+ 8657, 16737, 27880, 7135, 18883, 24941, 349, 19442, 3954, 13288,
+ 12182, 8071, 3125, 8284, 26184, 6799, 1031, 11111, 26084, 20677,
+ 31882, 16819, 12222, 10301, 17740, 12071, 28782, 10816, 21833, 5727,
+ 26998, 22103, 8626, 31834, 7718, 11174, 20973, 15475, 18365, 23675,
+ 29917, 30867, 21713, 24615, 7011, 22948, 30705, 22285, 31781, 13385,
+ 2440, 29944, 1166, 26060, 16644, 26034, 31510, 32088, 2360, 24530,
+ 5827, 1384, 29695, 22997, 12271, 383, 4387, 5488, 28237, 29722,
+ 11389, 29989, 6183, 226, 14173, 20501, 26345, 32551, 24876, 14357,
+ 1251, 4234, 9039, 26115, 6219, 4089, 17487, 16475, 32641, 27873,
+ 5687, 12293, 8855, 18078, 29758, 14193, 32273, 23607, 17318, 32742,
+ 19177, 9288, 31716, 20759, 26583, 8511, 31233, 9976, 26575, 17867,
+ 9024, 22991, 27082, 32146, 6913, 3214, 7625, 11811, 4069, 21856,
+ 6935, 17451, 25651, 21634, 27599, 8427, 13691, 11604, 29087, 31721,
+ 1913, 5552, 1995, 3302, 5691, 28538, 1653, 4625, 4998, 8312,
+ 2843, 1658, 21367, 7268, 10849, 7369, 11366, 21824, 28433, 21040,
+ 3599, 1514, 19040, 11678, 5108, 2800, 22899, 32566, 5885, 15781,
+ 9249, 13311, 610, 1397, 14587, 4573, 28618, 4981, 19081, 28608,
+ 20149, 31806, 12759, 15899, 6935, 9212, 31280, 29592, 26437, 12482,
+ 23082, 12810, 15637, 30497, 15843, 14242, 6721, 5368, 18057, 28775,
+ 3085, 11917, 25376, 15328, 11818, 477, 26239, 15123, 4313, 17457,
+ 16028, 15028, 19028, 32242, 12554, 3478, 14185, 22718, 16576, 27493,
+ 12136, 5051, 8476, 10135, 12095, 4652, 23080, 21664, 16356, 14402,
+ 539, 10085, 7155, 2612, 12323, 12020, 22681, 16786, 3169, 13426,
+ 5552, 19670, 8501, 22356, 31019, 27964, 20925, 14803, 31157, 26323,
+ 6552, 20889, 15509, 30420, 31216, 12481, 2773, 1075, 14263, 23294,
+ 8611, 15989, 20272, 31514, 25079, 7873, 16562, 3235, 9078, 32569,
+ 6825, 19937, 11927, 15499, 25821, 3594, 8708, 5570, 20727, 11193,
+ 18243, 15971, 21569, 22429, 6805, 22197, 3757, 28526, 2590, 15968,
+ 8985, 1318, 12359, 30009, 25809, 26221, 3425, 32349, 32341, 14421,
+ 1163, 31101, 30045, 31559, 8149, 26232, 12315, 2878, 24485, 18223,
+ 24512, 28722, 6490, 5013, 29761, 4824, 10544, 13317, 32091, 10632,
+ 31587, 30169, 7381, 29054, 12440, 11832, 28165, 2118, 24952, 32559,
+ 1685, 31090, 17822, 29443, 29831, 21646, 16819, 25030, 23927, 24406,
+ 8407, 21801, 8992, 14374, 32067, 24209, 12578, 31921, 7213, 4973,
+ 22531, 18678, 16620, 9158, 22899, 8816, 15197, 16151, 2516, 9101,
+ 13701, 15200, 11001, 31586, 1144, 12918, 25646, 5533, 121, 2461,
+ 31609, 32443, 10338, 5976, 13344, 22651, 5191, 23424, 30315, 29330,
+ 31574, 32148, 9387, 23456, 20737, 1360, 16763, 32355, 15712, 385,
+ 19270, 7978, 29904, 4375, 28938, 19853, 13025, 636, 1115, 7772,
+ 23663, 32036, 19626, 16853, 3342, 26982, 8135, 18970, 5036, 2698,
+ 25509, 13794, 8817, 32547, 23902, 4974, 13802, 7071, 29046, 20415,
+ 30567, 21276, 14692, 1542, 7841, 8829, 4686, 25436, 5792, 12733,
+ 2325, 29363, 27100, 8068, 18321, 25868, 14755, 11000, 26398, 10731,
+ 17594, 12246, 19543, 27656, 16711, 10433, 28705, 17992, 3566, 11226,
+ 14828, 17643, 32315, 5520, 20277, 1799, 17984, 21946, 31823, 5173,
+ 18815, 4835, 6756, 14986, 20746, 6116, 5815, 2249, 27880, 16313,
+ 32555, 14550, 1211, 21389, 14345, 7790, 23456, 3863, 16126, 28182,
+ 2903, 16169, 8035, 28753, 15012, 11910, 31681, 29974, 4852, 21749,
+ 20629, 7041, 14660, 31891, 21584, 16841, 20031, 20845, 6306, 12658,
+ 14758, 3918, 20728, 23492, 17653, 16854, 25156, 14971, 18756, 19148,
+ 8188, 10432, 29803, 8885, 23141, 18520, 26985, 1958, 8721, 18204,
+ 16391, 3670, 25766, 6313, 10168, 18807, 18146, 30808, 12740, 31559,
+ 24540, 18289, 1701, 1378, 14733, 7067, 2737, 2778, 14990, 4503,
+ 13818, 30857, 23843, 14382, 9075, 26534, 22393, 10088, 6996, 3735,
+ 6444, 6143, 7359, 13318, 16908, 3859, 10915, 22583, 30241, 29215,
+ 24545, 2201, 13037, 5932, 3757, 4507, 2544, 9541, 28471, 704,
+ 25714, 22826, 8587, 14582, 13436, 585, 1718, 25380, 14120, 19433,
+ 13611, 13570, 11290, 9897, 3173, 15405, 9807, 26153, 11213, 2939,
+ 23062, 26375, 20701, 12427, 3163, 20749, 24710, 10145, 1835, 18856,
+ 8143, 16817, 14197, 10908, 24512, 12474, 22542, 4343, 8318, 11862,
+ 19960, 22595, 28599, 28814, 6628, 22016, 1600, 24818, 757, 26962,
+ 26877, 18922, 24263, 13046, 4354, 28231, 6832, 2426, 24311, 16157,
+ 27206, 32174, 24001, 9173, 16161, 854, 6239, 2174, 28130, 4641,
+ 1809, 9828, 9331, 21215, 22464, 15076, 5521, 11502, 5530, 8318,
+ 32136, 18421, 29693, 32300, 25662, 21973, 16534, 242, 16499, 14557,
+ 16586, 21431, 24647, 23102, 32340, 18771, 15101, 17598, 18224, 27881,
+ 4094, 22448, 25784, 27767, 30497, 9763, 19982, 4523, 17961, 22106,
+ 22969, 15609, 28560, 5500, 12947, 5866, 16003, 29581, 5090, 27575,
+ 5165, 15261, 4293, 25878, 2616, 7231, 27346, 5716, 7825, 13373,
+ 15357, 3748, 19564, 22410, 30651, 26039, 13961, 8312, 1896, 30348,
+ 18101, 8491, 1510, 15498, 26259, 18766, 24200, 1740, 13724, 21508,
+ 21294, 30140, 24677, 21026, 11697, 30435, 32032, 9371, 8321, 13055,
+ 4454, 31548, 6796, 8790, 9524, 11161, 4706, 15179, 1843, 29767,
+ 3223, 28463, 9788, 75, 24937, 26969, 9243, 16083, 1443, 17529,
+ 1427, 25380, 23234, 10793, 9123, 8404, 19029, 4293, 16904, 30777,
+ 12458, 2941, 28419, 10017, 23206, 24744, 4188, 4547, 6901, 23131,
+ 16807, 14326, 14948, 1339, 26566, 2721, 18314, 20879, 7599, 13683,
+ 2478, 19098, 24176, 12500, 6885, 22567, 4208, 12315, 28027, 15973,
+ 22007, 16385, 16532, 20469, 18160, 10581, 18451, 1602, 30702, 27634,
+ 3003, 29713, 29294, 26095, 16788, 18009, 604, 31509, 10129, 18260,
+ 31960, 20630, 8303, 6102, 25657, 28923, 6112, 4830, 3410, 27743,
+ 29161, 3946, 10741, 18651, 2441, 29840, 23734, 22337, 667, 21451,
+ 14833, 16397, 29437, 32147, 23055, 23704, 9970, 17456, 24836, 12431,
+ 1221, 24783, 7964, 6052, 21424, 11990, 12024, 31619, 27131, 12661,
+ 13523, 9736, 1640, 6013, 8971, 943, 22735, 12662, 10204, 27212,
+ 32262, 3564, 10350, 14332, 29443, 12297, 27922, 24155, 17221, 5225,
+ 25288, 11767, 30320, 30761, 5638, 30213, 311, 5697, 19124, 19539,
+ 15742, 20244, 21883, 4478, 11712, 28230, 6719, 1381, 4015, 718,
+ 21482, 32733, 539, 32076, 2412, 8615, 16917, 2204, 21504, 4511,
+ 17236, 20651, 23216, 6709, 10200, 11145, 10011, 15137, 23244, 22720,
+ 14198, 851, 21169, 19173, 29137, 18217, 16057, 12140, 23707, 1765,
+ 9073, 10432, 16489, 6494, 10915, 28308, 5875, 28406, 10875, 18547,
+ 27487, 203, 10216, 5791, 4035, 16434, 22597, 23832, 19429, 6753,
+ 26169, 1275, 26949, 25707, 32220, 18445, 16477, 17266, 25627, 31384,
+ 11047, 25879, 7517, 10102, 224, 7222, 26471, 12907, 32524, 13777,
+ 2684, 29880, 17338, 6729, 17865, 2028, 15625, 3796, 23297, 13054,
+ 12779, 11051, 32069, 11673, 18473, 22403, 10054, 11703, 11175, 26303,
+ 7341, 29553, 15082, 8420, 6843, 18197, 23767, 20941, 31788, 7546,
+ 25533, 12320, 21602, 22160, 8598, 12416, 17855, 19003, 4490, 6404,
+ 5971, 5986, 15029, 26856, 19895, 26947, 12330, 26755, 19256, 9993,
+ 21048, 30073, 15160, 16800, 13548, 24370, 19666, 5064, 20438, 26507,
+ 189, 2152, 23312, 15307, 3699, 31525, 32125, 31192, 9362, 1844,
+ 12367, 5547, 2178, 14444, 31692, 13057, 22872, 21152, 29009, 18259,
+ 31226, 9003, 1687, 6153, 26244, 4300, 13877, 26859, 30955, 23989,
+ 2406, 28376, 24801, 20446, 28429, 23226, 21240, 13215, 1014, 4281,
+ 13065, 27774, 12383, 24495, 15831, 2118, 16055, 19676, 30192, 2137,
+ 20389, 18396, 22484, 21830, 20300, 23253, 6489, 4254, 20430, 10997,
+ 30798, 14596, 27918, 23836, 23647, 21636, 7611, 13013, 20536, 5414,
+ 5514, 29579, 5614, 11202, 7362, 30202, 23194, 15637, 254, 24035,
+ 19783, 11541, 814, 25092, 7438, 13442, 26336, 11847, 8831, 29886,
+ 1726, 13882, 14403, 32222, 4695, 3007, 1792, 31489, 22818, 3589,
+ 18557, 30944, 18111, 1206, 17927, 31399, 29825, 31602, 5651, 20740,
+ 29738, 29053, 23844, 26493, 14325, 12724, 5615, 31750, 15322, 26310,
+ 9405, 29907, 21517, 16288, 14866, 18539, 17608, 14377, 18572, 11262,
+ 1866, 23088, 4621, 31736, 24608, 2722, 4125, 4822, 10915, 14081,
+ 15241, 568, 32194, 30481, 30544, 25144, 3585, 30421, 8896, 11003,
+ 28866, 15545, 5853, 19589, 9411, 8209, 4866, 30930, 1001, 962,
+ 23755, 21538, 572, 10559, 5937, 32660, 24114, 12216, 5367, 12790,
+ 9776, 5006, 10822, 21212, 14158, 16905, 16788, 19439, 6491, 5453,
+ 14282, 1160, 23585, 19594, 17317, 15230, 23017, 21620, 27740, 13116,
+ 834, 29683, 21380, 25622, 6143, 12571, 22065, 10461, 29055, 606,
+ 18783, 6576, 16945, 8192, 21904, 2326, 28246, 2508, 13750, 22346,
+ 25097, 5382, 23890, 4054, 2173, 5792, 18910, 1379, 18567, 32176,
+ 873, 24528, 10844, 29218, 4225, 20609, 2715, 19370, 24917, 24826,
+ 32398, 29949, 30235, 4012, 19885, 3905, 17584, 12046, 9315, 27074,
+ 8574, 15088, 25621, 8678, 12195, 6157, 13409, 32611, 7248, 29151,
+ 14755, 24751, 10606, 10935, 5310, 19385, 19336, 4620, 4121, 30422,
+ 24293, 21779, 7655, 24062, 14324, 23953, 2988, 14392, 4846, 4846,
+ 3836, 24915, 9910, 12682, 3974, 3031, 24324, 11348, 21074, 20283,
+ 450, 19608, 27207, 26200, 17334, 1048, 4592, 12830, 4194, 9567,
+ 21120, 21638, 2344, 30290, 7187, 30663, 32690, 20744, 13110, 5581,
+ 28561, 18139, 6058, 21479, 15140, 31167, 18533, 18112, 12220, 8147,
+ 2266, 12944, 5373, 25910, 2938, 7059, 19336, 8220, 9595, 15035,
+ 16087, 2849, 28632, 10914, 11879, 31197, 31129, 24770, 4637, 15288,
+ 28500, 18152, 7651, 8447, 23540, 2278, 10386, 22072, 26297, 27272,
+ 31252, 2483, 12928, 14794, 17610, 3938, 16965, 12616, 20011, 30442,
+ 1766, 24310, 2734, 18426, 31273, 25361, 12522, 22748, 27393, 6998,
+ 2044, 29514, 24333, 3697, 29994, 15234, 11618, 11192, 3270, 3485,
+ 13962, 13081, 10836, 17692, 24012, 22865, 21487, 8900, 10158, 31839,
+ 27880, 17580, 8633, 31801, 31665, 25748, 30588, 3005, 1785, 20600,
+ 22740, 3562, 19993, 20837, 5482, 21328, 24751, 29836, 4476, 19397,
+ 22920, 27285, 30689, 90, 16580, 28981, 19783, 27022, 22836, 31491,
+ 18624, 30145, 23815, 2439, 5501, 21483, 28070, 28052, 25048, 22157,
+ 15068, 25048, 24472, 744, 9530, 13234, 6513, 8302, 24506, 28227,
+ 16843, 23670, 21666, 15304, 24261, 22067, 20907, 28967, 30584, 9959,
+ 16227, 30663, 9856, 14932, 26576, 2469, 13753, 2931, 4182, 29605,
+ 10054, 6505, 27354, 21030, 20440, 10423, 8744, 31704, 26156, 9393,
+ 1426, 3794, 11222, 13617, 6106, 21471, 4926, 23692, 1363, 27673,
+ 1768, 12741, 17730, 31930, 13816, 2817, 27274, 19758, 2549, 11323,
+ 26505, 2925, 10701, 20025, 18749, 10887, 11801, 4543, 11691, 3968,
+ 27299, 13058, 31105, 95, 28965, 4447, 4346, 2434, 12628, 24397,
+ 6146, 19764, 23069, 3729, 32155, 29058, 24623, 19633, 22143, 8266,
+ 19897, 9130, 19206, 19860, 16245, 4837, 7243, 14373, 13029, 13416,
+ 1162, 22610, 2525, 16970, 30413, 12563, 26433, 4201, 456, 14168,
+ 18704, 20063, 23041, 17312, 929, 9649, 20276, 16839, 557, 2122,
+ 12533, 4895, 28814, 17192, 26263, 22211, 12870, 10582, 15949, 3112,
+ 19139, 27418, 14223, 17397, 6882, 28015, 19647, 21269, 6065, 13749,
+ 13, 15370, 24185, 15784, 12184, 17028, 18940, 17295, 29909, 23858,
+ 27899, 27317, 4917, 31192, 5627, 16413, 14850, 18338, 16457, 30578,
+ 7562, 31672, 5692, 29757, 11136, 17426, 26810, 29531, 24223, 23694,
+ 16381, 26797, 30096, 31295, 27031, 25873, 4366, 264, 10164, 6289,
+ 32072, 14186, 26016, 17627, 10887, 27803, 5513, 13297, 6416, 17624,
+ 7045, 1826, 15436, 8187, 27095, 29241, 6438, 20048, 12910, 14068,
+ 9141, 1957, 20910, 29880, 8219, 22688, 22131, 8322, 2733, 31318,
+ 19283, 14625, 19284, 18456, 9508, 2979, 14386, 18320, 31422, 7181,
+ 11145, 30478, 27138, 1615, 12505, 22044, 19996, 27510, 3401, 23640,
+ 11012, 16164, 10056, 21123, 29259, 2365, 4468, 16853, 1300, 28644,
+ 15547, 28051, 5985, 7590, 5568, 2788, 22672, 22516, 4480, 10977,
+ 1317, 22999, 27957, 2795, 17865, 18143, 9595, 16193, 32659, 19037,
+ 26801, 27601, 31111, 14033, 2210, 32591, 31580, 14758, 12132, 9349,
+ 18819, 30493, 23425, 24042, 8804, 8840, 26453, 32629, 8427, 26296,
+ 8119, 31411, 10307, 12984, 11740, 12568, 15585, 16060, 22647, 16531,
+ 28357, 23892, 24613, 32356, 14588, 27877, 31497, 5170, 31338, 32090,
+ 13235, 29528, 27590, 32279, 12103, 4737, 14054, 2094, 7899, 10612,
+ 4925, 6358, 24608, 24369, 2978, 20505, 4421, 7740, 20818, 1996,
+ 7192, 825, 16441, 22212, 31855, 6585, 30829, 21575, 17862, 23380,
+ 12540, 12225, 11305, 9464, 10215, 28856, 5205, 5760, 21358, 29442,
+ 28442, 4232, 14478, 29494, 25603, 17536, 2761, 16224, 3897, 2816,
+ 31013, 24569, 22181, 29787, 19575, 19734, 6741, 18295, 15073, 991,
+ 17441, 25308, 5274, 4163, 31374, 13322, 11757, 24298, 31474, 14608,
+ 10885, 27499, 24281, 16474, 3559, 7872, 20648, 23243, 13632, 29175,
+ 29568, 13324, 7777, 10537, 613, 17699, 8200, 15024, 27296, 5447,
+ 30561, 13973, 25953, 31986, 20172, 16968, 21673, 7993, 8673, 31892,
+ 26471, 3417, 8881, 24017, 18658, 18578, 1103, 26716, 24406, 5688,
+ 20112, 15684, 24034, 23047, 7950, 26950, 11681, 27319, 31603, 32252,
+ 29208, 5328, 6388, 19281, 11472, 16320, 15643, 19768, 17475, 26922,
+ 7114, 8606, 29181, 27266, 22141, 6812, 23547, 15575, 207, 16626,
+ 23895, 12015, 20032, 23217, 16935, 16793, 19765, 18999, 31394, 7743,
+ 21312, 22880, 2436, 23483, 32418, 17659, 12724, 1387, 28942, 7291,
+ 10020, 6280, 10160, 18927, 18169, 27571, 5230, 22069, 6893, 13521,
+ 23662, 15722, 11249, 8473, 24536, 26532, 26646, 13163, 28381, 6628,
+ 8109, 23780, 20472, 29510, 23981, 943, 31603, 19067, 8022, 27678,
+ 12334, 32633, 12052, 14329, 17820, 5489, 9894, 28694, 24334, 10498,
+ 23679, 19497, 25652, 5804, 16493, 11486, 25312, 25991, 27512, 31781,
+ 15886, 18997, 26381, 26573, 20002, 22037, 28508, 10837, 22128, 9913,
+ 13566, 22015, 29697, 10651, 25051, 22053, 27028, 18443, 25931, 6864,
+ 27876, 3948, 19323, 8839, 22825, 10656, 9235, 22117, 27361, 14785,
+ 15381, 27759, 26832, 28946, 12040, 17444, 24134, 28725, 4951, 29013,
+ 19104, 18590, 17908, 26934, 27153, 12871, 6464, 1462, 31651, 18853,
+ 27439, 21260, 10360, 27100, 26279, 23442, 28758, 30511, 29738, 26071,
+ 16227, 11706, 7605, 22767, 4396, 18531, 27112, 15118, 17644, 5134,
+ 29286, 32342, 1804, 17168, 14719, 4076, 29670, 5350, 781, 23889,
+ 22478, 9768, 13467, 17392, 12371, 31928, 205, 7923, 21186, 9279,
+ 25084, 26459, 23532, 28378, 10272, 6736, 19753, 11792, 7667, 22965,
+ 31389, 30728, 2387, 31488, 11962, 19704, 2792, 30793, 9990, 12513,
+ 8456, 30624, 19999, 3450, 20951, 23716, 22268, 28777, 16563, 6226,
+ 7541, 31161, 13007, 11034, 28678, 3721, 18205, 3384, 9936, 9217,
+ 25970, 28993, 11232, 13963, 10469, 5372, 22708, 16703, 18808, 5236,
+ 19707, 18846, 18682, 29515, 8861, 21380, 26411, 20561, 8955, 20824,
+ 8482, 30549, 24952, 25734, 16364, 17724, 24376, 559, 14966, 4688,
+ 7208, 20511, 28332, 5850, 14654, 19967, 30179, 32242, 4098, 7883,
+ 6260, 6806, 25421, 1671, 9386, 29434, 3408, 28718, 11487, 5663,
+ 20185, 4076, 28897, 28583, 9170, 30092, 30363, 3560, 16650, 9012,
+ 5617, 3647, 7993, 31824, 31723, 9126, 14142, 8396, 26902, 27529,
+ 21418, 2182, 12071, 1238, 7042, 29443, 12770, 7508, 14913, 32609,
+ 28474, 26933, 18717, 140, 21178, 14574, 23947, 25013, 22563, 8518,
+ 24837, 12032, 16727, 27053, 5643, 5757, 25461, 13520, 28264, 30042,
+ 20294, 5994, 5814, 17751, 22744, 4445, 23332, 32377, 17000, 7425,
+ 18807, 16643, 3717, 18620, 13391, 23458, 15731, 3795, 31660, 488,
+ 31182, 24447, 16048, 18171, 30831, 4420, 23207, 12431, 3988, 11134,
+ 23364, 30225, 18746, 16189, 16429, 16421, 29902, 16978, 15291, 31827,
+ 31749, 8362, 20218, 6397, 32521, 30683, 26360, 15765, 31701, 12541,
+ 24380, 21261, 1250, 27835, 3476, 28814, 19203, 30121, 15124, 108,
+ 32397, 11481, 11867, 12634, 19388, 9385, 11032, 2010, 30290, 24030,
+ 2765, 9208, 22657, 23287, 21203, 3896, 18699, 32187, 27551, 9933,
+ 11432, 25365, 23875, 30219, 13992, 12577, 13623, 5407, 7385, 2951,
+ 31066, 24574, 17067, 8712, 19508, 6555, 8082, 3414, 9854, 20317,
+ 25772, 28201, 18916, 4304, 9636, 655, 20745, 20379, 2262, 9603,
+ 204, 31666, 17076, 27842, 16074, 12236, 24680, 22746, 20771, 536,
+ 9659, 19332, 19330, 19755, 565, 14387, 19799, 1341, 24965, 17133,
+ 30055, 28054, 23332, 16730, 11911, 16963, 1334, 21019, 14756, 10765,
+ 28337, 32348, 6407, 1196, 1216, 6573, 16599, 26935, 26474, 21517,
+ 12512, 26847, 29039, 12872, 23442, 27101, 30578, 24708, 32333, 11945,
+ 605, 4886, 20188, 23917, 2306, 27034, 8767, 7097, 27902, 2114,
+ 28845, 4728, 16099, 23406, 23257, 28195, 3478, 14717, 5237, 12084,
+ 17653, 22243, 22516, 24286, 24509, 16508, 18325, 31739, 28843, 20513,
+ 24477, 13382, 18146, 20344, 24035, 15818, 12685, 15632, 17042, 25754,
+ 9925, 26541, 20011, 8387, 20917, 21472, 8393, 18559, 19452, 8155,
+ 24233, 12971, 1618, 22916, 32233, 23931, 9327, 31432, 8592, 28013,
+ 20521, 50, 9679, 6267, 18396, 19900, 16775, 20885, 11278, 21989,
+ 24842, 18510, 20563, 14083, 7718, 4310, 4975, 17115, 31072, 2088,
+ 699, 9327, 14461, 18564, 19658, 6167, 3655, 16928, 18251, 27091,
+ 28557, 19483, 3121, 11744, 14700, 16818, 29202, 26505, 3277, 32694,
+ 25549, 4672, 815, 22077, 23408, 16621, 8359, 17049, 1113, 18310,
+ 10020, 1414, 18587, 8928, 12024, 27047, 19875, 4805, 10388, 20020,
+ 9243, 6726, 11155, 18925, 12046, 23122, 14075, 31314, 1613, 31368,
+ 18111, 21269, 22546, 5194, 25224, 464, 3556, 21523, 2484, 14836,
+ 14522, 17674, 8351, 32001, 2147, 31447, 17186, 13053, 21029, 3509,
+ 8282, 10015, 27301, 7368, 17323, 15563, 22278, 19122, 28420, 28867,
+ 6485, 26721, 27236, 31387, 7205, 16938, 27805, 8813, 374, 17180,
+ 344, 7887, 22748, 25230, 4185, 3842, 221, 4091, 27140, 25964,
+ 14234, 4368, 32032, 22088, 7858, 1538, 6620, 7837, 13923, 2085,
+ 26127, 14188, 5106, 5819, 26308, 18734, 22349, 17929, 17142, 29566,
+ 9200, 25777, 9112, 15634, 8453, 2875, 21721, 16367, 17615, 18933,
+ 3237, 26077, 28488, 26877, 31343, 18713, 6153, 28316, 1070, 3403,
+ 4971, 24533, 21669, 17591, 13036, 28478, 7912, 13751, 17620, 3599,
+ 15132, 5225, 14104, 4985, 126, 1189, 24958, 28217, 167, 30770,
+ 15106, 5228, 2062, 15673, 32376, 9637, 1998, 20729, 628, 29501,
+ 19625, 19133, 18535, 25322, 10061, 29451, 1802, 24467, 27095, 23327,
+ 13312, 19555, 24214, 2200, 20663, 11805, 7185, 2416, 32399, 32431,
+ 23115, 1073, 7742, 24329, 11589, 6246, 32371, 6959, 18629, 9040,
+ 23993, 13453, 12630, 15579, 17310, 26252, 32400, 208, 29973, 22882,
+ 4761, 30796, 2074, 30510, 27372, 14193, 23188, 5956, 28249, 859,
+ 28799, 29637, 23629, 5206, 32074, 7540, 16724, 18510, 7294, 25028,
+ 5340, 22919, 32161, 22326, 25660, 28046, 1882, 993, 12021, 4207,
+ 13782, 21074, 22583, 28712, 14441, 18583, 20903, 27742, 4729, 13719,
+ 25439, 20047, 17304, 18597, 13622, 15624, 15088, 18260, 32066, 16855,
+ 6628, 21900, 30620, 28932, 2548, 989, 2915, 2748, 10721, 6164,
+ 16644, 10318, 22034, 17420, 28088, 18842, 20535, 16071, 14414, 22213,
+ 2604, 29629, 23338, 27186, 6176, 15476, 18318, 30382, 3574, 22609,
+ 3608, 7659, 19435, 5806, 12428, 19248, 32378, 26413, 16596, 26190,
+ 21885, 17483, 28997, 13014, 13972, 11320, 31268, 12169, 28362, 7142,
+ 30825, 2576, 10102, 16479, 10690, 31470, 8800, 21085, 10715, 7602,
+ 293, 20500, 5341, 6513, 7133, 2387, 13109, 11635, 11002, 12747,
+ 4758, 30253, 18547, 28078, 12353, 32367, 3107, 3197, 6276, 28895,
+ 18284, 26139, 8064, 32166, 9247, 3621, 5936, 18537, 10912, 20870,
+ 9895, 29307, 29509, 12869, 9881, 5457, 1792, 21922, 10013, 16694,
+ 13118, 6242, 689, 21567, 21774, 15719, 8831, 15746, 24454, 27267,
+ 22495, 131, 8546, 26510, 28444, 3311, 3567, 21430, 24443, 16013,
+ 3368, 17687, 15481, 6513, 5918, 1676, 19541, 5747, 7837, 26564,
+ 26574, 5087, 3852, 21400, 1838, 15982, 24981, 8347, 8327, 1653,
+ 3462, 20467, 15165, 30045, 22519, 11880, 23748, 30547, 18094, 3003,
+ 12971, 27968, 14911, 31801, 7642, 6908, 29559, 22671, 792, 17855,
+ 2043, 28640, 1232, 5848, 2605, 8213, 2580, 5793, 26703, 18549,
+ 14050, 21426, 18155, 19061, 14758, 2645, 23154, 3281, 4609, 24634,
+ 1059, 13531, 13513, 2156, 13870, 2579, 12625, 25476, 25370, 14329,
+ 15338, 28701, 31844, 25119, 16809, 8071, 17513, 16002, 26987, 25280,
+ 30597, 10778, 9751, 927, 4221, 27568, 15907, 7763, 11290, 6384,
+ 27738, 20236, 20503, 20927, 32220, 26616, 6462, 17871, 4454, 17265,
+ 5325, 14448, 23507, 1653, 18718, 30377, 5603, 26454, 12679, 29575,
+ 30524, 19634, 12672, 32437, 25262, 22694, 17155, 18765, 10171, 13375,
+ 25657, 11502, 32087, 12081, 2130, 26895, 6636, 1996, 4020, 19090,
+ 3233, 28459, 2905, 29084, 15324, 7599, 20338, 10661, 11525, 2988,
+ 6481, 1995, 31118, 8801, 19589, 17260, 5424, 31022, 2887, 31987,
+ 18807, 29441, 11797, 26354, 2688, 20498, 24220, 1394, 2306, 2000,
+ 23003, 30599, 9611, 32538, 7558, 32551, 10508, 28339, 1192, 15163,
+ 26264, 3568, 6029, 18423, 10857, 21940, 4831, 14695, 6692, 28574,
+ 27151, 9291, 27229, 9601, 18678, 10533, 3422, 25877, 22717, 13712,
+ 16164, 11244, 19450, 28627, 4779, 28583, 30235, 182, 25708, 22121,
+ 29192, 12181, 22051, 21388, 7172, 1202, 14293, 31891, 25300, 26063,
+ 530, 10848, 13348, 24829, 17784, 15016, 2086, 6575, 13176, 1443,
+ 20604, 3090, 9309, 23560, 20056, 6817, 16009, 8504, 5090, 6644,
+ 8962, 21945, 13530, 20184, 17198, 9703, 27262, 4773, 17371, 20710,
+ 11950, 4556, 4482, 31707, 4686, 22704, 2509, 17756, 21228, 8887,
+ 24150, 11557, 29602, 8096, 5298, 9228, 23870, 8983, 18350, 22583,
+ 18849, 29318, 3544, 4492, 32357, 9519, 10562, 12905, 6851, 19064,
+ 25730, 12437, 31923, 19077, 16637, 6775, 340, 13580, 23142, 31878,
+ 9359, 29285, 9089, 15105, 17399, 2785, 24621, 13280, 2292, 30813,
+ 161, 15626, 15905, 13847, 16886, 21192, 5106, 704, 14310, 2682,
+ 6298, 2258, 9171, 7561, 26412, 24867, 15626, 8348, 20992, 9147,
+ 20042, 15119, 3160, 31458, 19584, 29345, 5955, 27774, 19157, 24428,
+ 30146, 19868, 28650, 23579, 27690, 5197, 20578, 1623, 20169, 31667,
+ 21154, 9090, 9164, 11867, 32724, 15784, 7264, 27341, 26162, 3250,
+ 10520, 22114, 28801, 32733, 11663, 29270, 22235, 31595, 5966, 26398,
+ 3250, 7833, 23536, 6652, 20498, 9680, 8836, 16592, 15910, 15647,
+ 7218, 26673, 4350, 22249, 20514, 8124, 27279, 23259, 24217, 16556,
+ 20732, 16673, 32613, 684, 16404, 28122, 16252, 21225, 29723, 24777,
+ 16864, 8554, 20941, 3405, 1989, 6308, 4000, 28307, 1014, 29513,
+ 1098, 11274, 32117, 25698, 16003, 25111, 1377, 17821, 18956, 25355,
+ 1053, 32744, 17904, 1106, 8623, 25150, 12298, 19436, 3430, 23233,
+ 2503, 4642, 26816, 17930, 14893, 27505, 22922, 18621, 20764, 28363,
+ 1865, 26464, 4052, 11263, 2009, 20589, 23224, 26229, 32596, 3237,
+ 30802, 26654, 30518, 2472, 16790, 171, 12478, 12995, 10091, 1277,
+ 30359, 3081, 12647, 25309, 12727, 933, 23002, 7406, 17800, 28014,
+ 27407, 17119, 30533, 23740, 16846, 14821, 25767, 20602, 6437, 26985,
+ 19906, 25981, 17257, 8190, 13865, 788, 29815, 17557, 8537, 13793,
+ 319, 10228, 28245, 11495, 14468, 2660, 5773, 3299, 14557, 10666,
+ 21508, 3552, 26624, 27449, 29362, 5894, 28479, 30374, 20776, 19635,
+ 24915, 21596, 21618, 17613, 27993, 25745, 21313, 21846, 17178, 17017,
+ 15434, 12608, 3215, 26553, 31721, 18307, 8357, 9246, 25866, 6254,
+ 21309, 15759, 8521, 30010, 1655, 19520, 27736, 24037, 24880, 10025,
+ 7841, 28990, 20169, 29879, 19245, 9020, 11306, 13249, 29893, 11667,
+ 17927, 20669, 7767, 28297, 3170, 6964, 15003, 10758, 8018, 12147,
+ 16117, 24811, 6402, 10372, 23966, 12965, 14588, 11868, 11007, 32002,
+ 21672, 13398, 12893, 11843, 12559, 31712, 15803, 32114, 10725, 12148,
+ 21756, 31990, 18887, 10699, 14409, 15204, 14273, 15693, 22962, 26264,
+ 7699, 4043, 6680, 9477, 28213, 24176, 19786, 6473, 9752, 15861,
+ 18798, 17412, 31407, 11029, 1443, 14315, 2990, 32577, 3044, 21528,
+ 1170, 7572, 16943, 30884, 20193, 27657, 20199, 27000, 14771, 27884,
+ 7288, 21344, 14961, 3214, 16441, 10082, 10973, 30525, 18582, 16461,
+ 10322, 2931, 13934, 1684, 30797, 15438, 9658, 1629, 5677, 30784,
+ 26992, 11222, 20023, 26632, 7847, 6600, 2525, 6625, 31483, 20078,
+ 12608, 27897, 23091, 2695, 17907, 20772, 20257, 11946, 6914, 11986,
+ 15306, 730, 20019, 2879, 13511, 7258, 26251, 15593, 13291, 21954,
+ 15380, 17479, 24102, 3411, 3294, 7352, 24745, 7560, 25412, 6586,
+ 10571, 17389, 12656, 9308, 32300, 27188, 17954, 27894, 14488, 1414,
+ 32428, 25879, 10030, 23, 23106, 5567, 23361, 24829, 21104, 9678,
+ 25982, 9794, 7404, 9405, 17871, 1336, 14990, 28044, 4736, 1292,
+ 30621, 13819, 6817, 10142, 16716, 7677, 1963, 5264, 29828, 21354,
+ 16998, 31390, 2532, 7668, 7945, 6957, 17159, 26460, 5283, 13350,
+ 15621, 5094, 955, 15364, 3132, 16138, 20531, 9260, 17744, 12396,
+ 21107, 5501, 6000, 7438, 25539, 23337, 23515, 2244, 2551, 28611,
+ 16035, 23529, 1618, 24729, 25777, 337, 19365, 31555, 13066, 8318,
+ 8119, 31100, 6993, 18455, 27625, 7985, 4492, 7317, 282, 32472,
+ 3883, 24384, 21193, 22531, 18246, 24922, 28025, 17461, 28710, 14234,
+ 11354, 9716, 17927, 16860, 29221, 3615, 11036, 23318, 26952, 2946,
+ 2260, 17806, 3907, 6312, 22108, 10058, 3922, 7152, 26725, 10952,
+ 12364, 11747, 28199, 6128, 22987, 6597, 16293, 31047, 29837, 19562,
+ 24883, 8549, 10778, 9548, 24630, 9385, 18343, 24026, 27948, 6955,
+ 18491, 31506, 22252, 16114, 18960, 32081, 19246, 14952, 29500, 17002,
+ 77, 15114, 2448, 19958, 11340, 7268, 16833, 27628, 27928, 16189,
+ 2501, 24946, 1548, 24847, 21120, 8178, 5818, 1978, 7328, 11887,
+ 12009, 21880, 19654, 15642, 25562, 22804, 2790, 5920, 19152, 11863,
+ 12528, 26311, 31950, 708, 3248, 32697, 1955, 21125, 30963, 9119,
+ 28708, 29092, 4587, 29938, 10681, 13694, 2260, 3086, 10011, 21109,
+ 23256, 25225, 26715, 16870, 28464, 2242, 10791, 17499, 24717, 22973,
+ 6729, 21505, 30134, 8494, 13680, 7004, 3442, 26579, 12851, 17465,
+ 424, 23047, 7507, 13028, 17861, 31893, 2880, 412, 17502, 9162,
+ 735, 20548, 16407, 24782, 1419, 15451, 15299, 22836, 22618, 5422,
+ 11724, 15567, 29345, 8268, 725, 19911, 13754, 571, 13215, 12013,
+ 20996, 8041, 29225, 27724, 32044, 2405, 12828, 29184, 23979, 19535,
+ 4197, 25932, 20368, 12430, 24100, 5094, 26240, 17600, 21189, 28053,
+ 20731, 17399, 10604, 15358, 224, 11298, 11671, 3259, 15668, 6345,
+ 31487, 430, 287, 13822, 29887, 31637, 19511, 24464, 14263, 21214,
+ 18434, 16513, 3123, 4796, 26293, 1722, 6856, 27258, 24386, 32510,
+ 26751, 18704, 10898, 11549, 24118, 22260, 26127, 13418, 24386, 16946,
+ 16230, 9326, 13145, 4287, 19851, 32222, 18352, 27914, 31485, 971,
+ 2912, 8405, 25931, 11545, 27406, 12867, 21975, 18994, 12235, 22322,
+ 14298, 13051, 17721, 13002, 12200, 4360, 10991, 4438, 14134, 6668,
+ 5407, 5715, 25561, 20115, 118, 4295, 14672, 4339, 15684, 27093,
+ 11781, 10367, 13789, 24973, 17552, 1279, 29759, 3593, 24189, 22109,
+ 10997, 20661, 11343, 19617, 17723, 13806, 24260, 5151, 16994, 29391,
+ 32091, 25071, 24694, 30023, 1556, 9374, 23071, 14959, 14967, 11555,
+ 15301, 24347, 15831, 25621, 5111, 7856, 26840, 24347, 782, 13365,
+ 30255, 27299, 28173, 20908, 27817, 23511, 22732, 8610, 27247, 16076,
+ 11094, 1797, 13704, 13565, 26255, 3894, 13727, 6137, 3098, 19039,
+ 15111, 13400, 15737, 32263, 14076, 12531, 22134, 26083, 18732, 30293,
+ 1730, 30447, 18038, 10860, 11997, 22718, 7409, 5252, 1077, 2318,
+ 14640, 32119, 16530, 23968, 20676, 24605, 24753, 22599, 13827, 32266,
+ 13871, 318, 6408, 11385, 20650, 15294, 23035, 28035, 546, 18640,
+ 20627, 10645, 677, 27745, 11480, 7456, 30507, 26772, 21806, 20114,
+ 24511, 17244, 25999, 8326, 12511, 2633, 13336, 21559, 7206, 2210,
+ 32455, 4155, 19496, 9141, 9859, 16238, 6046, 20843, 7004, 23596,
+ 28611, 23839, 24085, 31683, 3581, 28336, 15071, 11815, 9408, 2005,
+ 8552, 1512, 6063, 27569, 15892, 23650, 32517, 9384, 14474, 9780,
+ 31284, 7280, 15219, 27635, 5580, 31339, 10622, 15135, 18589, 15412,
+ 9128, 9045, 19488, 15480, 17594, 5063, 21523, 7175, 13843, 11498,
+ 26980, 16682, 423, 23150, 27728, 24888, 17736, 18803, 460, 18532,
+ 11045, 3834, 28708, 21465, 19344, 4761, 12002, 21001, 23556, 4468,
+ 11761, 15681, 20326, 19816, 6146, 1153, 19339, 15497, 5167, 22156,
+ 6139, 19663, 19166, 9019, 27124, 4108, 12777, 18198, 12722, 25633,
+ 25596, 5413, 19694, 27506, 1854, 13060, 17061, 27031, 1843, 31542,
+ 27674, 22613, 9697, 22971, 12062, 18636, 10289, 22245, 11663, 25841,
+ 8601, 17511, 3615, 9535, 8952, 16559, 16982, 3754, 20673, 1142,
+ 28123, 3285, 9308, 11925, 21231, 15492, 23753, 538, 26682, 14932,
+ 25223, 19099, 31690, 18858, 8884, 23242, 1881, 26601, 9589, 22858,
+ 6606, 8168, 25496, 20417, 31239, 12707, 8056, 12335, 26326, 25136,
+ 17697, 17534, 6217, 2037, 5557, 15450, 26159, 10009, 8719, 19778,
+ 14295, 12856, 22693, 6367, 8475, 17243, 10931, 19861, 20637, 24871,
+ 3222, 13657, 13137, 9300, 21877, 9922, 28988, 20833, 16935, 3170,
+ 10107, 14982, 8017, 30294, 902, 32235, 24271, 27164, 9142, 29719,
+ 7254, 25765, 24837, 25259, 21847, 17067, 26134, 18256, 22566, 837,
+ 14197, 20206, 11867, 6329, 4383, 19743, 1657, 15249, 15685, 18403,
+ 24781, 29681, 18509, 27541, 921, 19751, 13850, 31517, 31346, 26500,
+ 7309, 4200, 9447, 23658, 18251, 16661, 6243, 10407, 18625, 31601,
+ 22869, 4353, 7270, 12198, 12173, 13586, 15936, 6447, 6633, 17495,
+ 23466, 15503, 9522, 2435, 340, 27971, 10817, 16409, 27275, 28661,
+ 14182, 26681, 21947, 3314, 10506, 3258, 562, 9950, 13714, 12154,
+ 15142, 10663, 28807, 20466, 5114, 26039, 2292, 16398, 14781, 11118,
+ 18192, 15163, 32244, 15055, 3357, 29633, 32409, 23417, 24464, 2643,
+ 3939, 12505, 14450, 9188, 18504, 7839, 10758, 4541, 23873, 20846,
+ 5292, 16333, 9037, 16344, 29701, 23872, 26296, 14217, 1880, 29523,
+ 30365, 19138, 22837, 24166, 2474, 12810, 27224, 23890, 24611, 30240,
+ 975, 11006, 18217, 30259, 29792, 22061, 24893, 7765, 15653, 19354,
+ 22528, 25134, 29049, 17991, 23356, 20461, 19992, 6674, 4392, 20356,
+ 19329, 3209, 23528, 25109, 12191, 12287, 6228, 30119, 25257, 29920,
+ 14842, 8478, 2887, 25921, 26726, 23658, 13814, 16059, 417, 2302,
+ 2989, 24186, 9719, 24196, 23489, 13201, 12541, 4047, 32006, 11152,
+ 17363, 15377, 18999, 19801, 17575, 78, 15767, 30255, 30586, 15632,
+ 28633, 27920, 5159, 25693, 32317, 16453, 32161, 25574, 7165, 8503,
+ 32380, 32641, 21223, 12932, 11951, 12249, 14155, 31826, 26264, 22884,
+ 4887, 31460, 25408, 28566, 19521, 31595, 32737, 22613, 2661, 15134,
+ 10405, 9132, 24496, 31884, 27313, 27587, 30972, 1841, 17762, 28943,
+ 6460, 17736, 8406, 18118, 25627, 29665, 3503, 9110, 15328, 6451,
+ 12819, 10902, 13973, 13619, 2039, 16509, 28264, 24678, 20638, 16658,
+ 12625, 19699, 24924, 10467, 21493, 24060, 11680, 1850, 11211, 18734,
+ 12850, 19533, 29821, 30359, 9656, 18357, 9361, 4792, 4735, 27425,
+ 30024, 1756, 15736, 9548, 8646, 19368, 32385, 26924, 8564, 18930,
+ 28134, 13677, 24995, 15831, 2856, 12317, 17010, 20487, 16637, 10921,
+ 23281, 22884, 27287, 8712, 18566, 1228, 15913, 3894, 3472, 17202,
+ 16552, 7140, 17227, 17908, 9935, 3950, 8948, 29544, 18277, 2061,
+ 10797, 2488, 706, 21582, 24226, 25585, 17296, 194, 29933, 5462,
+ 31951, 28151, 24247, 20218, 18715, 680, 1056, 17294, 3890, 20017,
+ 11361, 32119, 20401, 12101, 22960, 23332, 30, 21219, 7269, 9630,
+ 5931, 8070, 8538, 30048, 11833, 24733, 32663, 22890, 23580, 17978,
+ 2351, 29841, 11550, 3342, 9061, 1305, 23622, 25237, 27155, 2693,
+ 12762, 22926, 8781, 32174, 11042, 686, 16449, 20243, 20335, 32149,
+ 1121, 8048, 22108, 5633, 29637, 26258, 852, 16706, 12234, 31849,
+ 23124, 4078, 28928, 14431, 4594, 26581, 10563, 6888, 26271, 6711,
+ 4391, 13658, 13097, 10805, 9370, 17408, 29316, 22406, 21188, 11881,
+ 3785, 16747, 25906, 25094, 8575, 13797, 25140, 15093, 2330, 293,
+ 28291, 28439, 30657, 20804, 29223, 12136, 24404, 564, 1176, 29584,
+ 24238, 26103, 25636, 9141, 5159, 23822, 31888, 5268, 31069, 21301,
+ 16642, 2512, 11317, 29773, 23839, 12937, 18716, 11674, 368, 21553,
+ 14995, 20270, 20234, 6043, 8682, 24997, 9838, 11349, 15691, 1043,
+ 23982, 13880, 28411, 26171, 8657, 14653, 18909, 13058, 1913, 30611,
+ 18232, 32547, 3779, 30190, 2489, 4131, 7791, 6689, 20924, 3976,
+ 14913, 6127, 1735, 32326, 30886, 8222, 31319, 31866, 31643, 1486,
+ 18400, 14682, 28875, 19977, 30223, 8044, 23799, 23963, 15698, 4343,
+ 13979, 14628, 6042, 18616, 5071, 2923, 32096, 13013, 28523, 26101,
+ 29670, 21015, 18798, 28631, 20671, 1363, 9889, 30408, 22161, 16681,
+ 13175, 5754, 3866, 4593, 3640, 27179, 1649, 31219, 31838, 31863,
+ 19342, 32726, 3904, 26992, 23053, 348, 31725, 26352, 20783, 7756,
+ 10843, 10030, 7202, 20399, 16321, 18832, 28546, 32574, 10305, 19904,
+ 16415, 13084, 25546, 15618, 5889, 8641, 6717, 32197, 26281, 16950,
+ 15054, 1399, 17818, 11400, 10926, 23710, 12824, 24183, 18151, 10533,
+ 17200, 14446, 15751, 13043, 27384, 18104, 512, 5827, 11800, 10992,
+ 24783, 6959, 29833, 14777, 30300, 23565, 22429, 8368, 3361, 16383,
+ 4416, 10399, 9999, 27718, 28797, 26612, 13869, 10967, 30532, 31089,
+ 18563, 30385, 1386, 2852, 11062, 8813, 13553, 22938, 18676, 19735,
+ 19338, 27472, 18322, 6460, 25944, 8298, 10484, 23108, 15607, 27303,
+ 29486, 11266, 13501, 16789, 9192, 10378, 1343, 9985, 29447, 12355,
+ 13591, 20402, 10378, 30781, 15845, 17495, 2481, 21188, 660, 3773,
+ 8549, 26165, 31455, 18245, 26580, 17936, 14355, 5782, 3420, 8783,
+ 10006, 32655, 27818, 246, 13224, 1407, 26659, 13804, 12521, 665,
+ 13954, 3337, 11035, 17058, 25283, 23152, 1706, 13805, 833, 25887,
+ 4201, 20617, 27675, 24516, 25375, 27065, 24795, 25554, 17986, 12196,
+ 2394, 8917, 27138, 846, 11742, 16899, 9354, 20679, 32390, 5139,
+ 5250, 14243, 27112, 9554, 19672, 6057, 18168, 19955, 28096, 21968,
+ 22060, 16038, 20217, 28007, 24029, 15213, 8018, 8595, 26097, 30891,
+ 7534, 25342, 22199, 20094, 19908, 15822, 32530, 13903, 20969, 25556,
+ 17882, 18088, 17682, 9990, 2687, 8517, 16853, 30768, 30959, 1901,
+ 29999, 15846, 21690, 2179, 25291, 6077, 32628, 32472, 16001, 25019,
+ 15964, 20163, 32542, 3083, 826, 7156, 3683, 6901, 15502, 26885,
+ 14928, 25358, 28902, 21842, 19362, 21932, 10640, 27915, 26010, 29085,
+ 28785, 16263, 4864, 11289, 25909, 12251, 9320, 26100, 11689, 13228,
+ 17332, 16664, 17764, 29761, 24794, 27187, 28845, 1500, 23527, 10925,
+ 22169, 10571, 4164, 22237, 1652, 19386, 9528, 27772, 27746, 14539,
+ 18351, 30042, 31046, 13033, 12602, 591, 483, 26073, 8278, 21109,
+ 6466, 26513, 9713, 31380, 27219, 15182, 27690, 8414, 21718, 2785,
+ 23129, 8413, 20860, 2633, 14927, 11177, 24906, 14727, 17119, 14430,
+ 3135, 30894, 11165, 22733, 13110, 8762, 11749, 18034, 14606, 8098,
+ 5919, 15271, 18183, 11313, 20546, 27926, 12399, 14865, 32407, 14196,
+ 14719, 11689, 8640, 21869, 17792, 25385, 21240, 12762, 12337, 12898,
+ 2460, 10810, 22125, 25820, 2283, 21856, 4617, 21026, 23306, 8809,
+ 11516, 5729, 32074, 25585, 4034, 5937, 8622, 7047, 12034, 19123,
+ 10664, 6493, 31854, 29916, 15908, 17476, 24298, 20240, 10439, 7640,
+ 30193, 19955, 21113, 22264, 11317, 31100, 2849, 2170, 23942, 2891,
+ 32431, 25628, 5109, 18236, 31584, 29117, 8249, 16956, 27965, 11469,
+ 4434, 2907, 13030, 5634, 20332, 27427, 12173, 3404, 24069, 11560,
+ 15941, 2060, 2386, 10209, 27261, 30593, 735, 30390, 4551, 29570,
+ 12663, 6746, 21215, 32115, 14403, 29531, 28136, 28530, 31029, 19192,
+ 31224, 27601, 5800, 24114, 5079, 24777, 14400, 7974, 27140, 29804,
+ 5912, 8345, 18937, 27868, 5404, 24533, 4784, 26811, 25523, 24756,
+ 12390, 31714, 32162, 20474, 1439, 1110, 30765, 8167, 25962, 19319,
+ 28542, 21261, 742, 18299, 4683, 26976, 31237, 4379, 4276, 9100,
+ 21904, 24972, 29290, 4235, 13932, 11441, 6166, 6518, 27, 11151,
+ 27641, 32667, 11909, 27393, 1487, 209, 14585, 12973, 17914, 5640,
+ 9839, 22582, 11228, 36, 14096, 21172, 27525, 5900, 18168, 8801,
+ 1678, 3837, 20026, 24724, 27716, 10277, 8740, 3060, 25866, 31853,
+ 23493, 25829, 19704, 24470, 1965, 28231, 25032, 1415, 756, 26208,
+ 10227, 25317, 10622, 19478, 11031, 31717, 14716, 17506, 7580, 5470,
+ 4150, 29697, 7063, 31779, 9225, 8557, 5358, 22159, 24491, 13067,
+ 8894, 13409, 17079, 23974, 19449, 20682, 27493, 5916, 32084, 15045,
+ 28056, 8535, 14432, 22439, 6943, 16767, 15862, 29687, 8500, 30574,
+ 14297, 22143, 8009, 18789, 9623, 2467, 6917, 30717, 4272, 20210,
+ 30089, 11872, 19450, 28923, 17911, 696, 16964, 26466, 15669, 23272,
+ 6202, 307, 30446, 2427, 9609, 2421, 23514, 14041, 2371, 6659,
+ 31040, 27329, 23940, 4247, 29113, 18931, 20054, 23080, 27446, 23597,
+ 6098, 2166, 7748, 28249, 12168, 26083, 27279, 25861, 7457, 31620,
+ 5285, 4883, 17987, 15736, 4349, 26802, 12725, 20856, 56, 3725,
+ 1476, 9136, 16550, 16706, 17893, 15821, 14604, 277, 5019, 5208,
+ 16549, 27110, 30363, 15938, 18534, 18272, 28719, 19136, 10630, 14708,
+ 24024, 10585, 15678, 32005, 28471, 22588, 8654, 11493, 13101, 19672,
+ 20672, 3841, 66, 19111, 27248, 16856, 15427, 7242, 23244, 24114,
+ 18223, 25307, 15193, 24846, 3413, 28543, 5751, 29148, 1206, 23354,
+ 28645, 22764, 6576, 20744, 13959, 14887, 20190, 15913, 871, 26621,
+ 5178, 23740, 18939, 25246, 6532, 19599, 23974, 22381, 8168, 11830,
+ 28800, 13489, 3803, 29786, 28506, 9614, 20550, 24404, 24317, 2613,
+ 14310, 22266, 7859, 16471, 31218, 5817, 13321, 20447, 29951, 24549,
+ 978, 20448, 21282, 9804, 7279, 6092, 18004, 27409, 30030, 4328,
+ 25626, 14776, 18353, 15356, 25701, 31613, 25777, 16207, 18358, 5354,
+ 11394, 4306, 10375, 424, 2808, 4252, 15335, 25238, 7498, 10134,
+ 17764, 12824, 25879, 15992, 557, 4786, 11430, 8436, 20344, 27605,
+ 114, 8496, 4130, 18680, 25062, 3962, 5525, 12011, 5989, 23096,
+ 4079, 23400, 15757, 27165, 18785, 8940, 32189, 3747, 12500, 24772,
+ 3540, 3765, 30675, 11627, 23868, 12715, 18341, 20243, 4904, 21628,
+ 20921, 6274, 16921, 24367, 16200, 10783, 29863, 11923, 17461, 18765,
+ 30590, 17968, 22840, 16887, 1191, 24189, 24891, 1644, 13321, 9044,
+ 15876, 366, 21807, 13986, 6165, 20101, 5707, 19299, 24016, 19610,
+ 7291, 27854, 15839, 16064, 29004, 17868, 8403, 28501, 27005, 31919,
+ 26123, 2378, 26885, 30497, 26584, 7103, 10326, 6746, 2782, 31699,
+ 24292, 23447, 23742, 30906, 30433, 13511, 1522, 5648, 11851, 20871,
+ 4856, 16492, 18729, 2128, 22706, 12345, 14610, 29679, 30733, 28353,
+ 24046, 16694, 17633, 12683, 17409, 1266, 5144, 32743, 805, 11805,
+ 13587, 22215, 9046, 26708, 6729, 16080, 10868, 651, 30001, 2225,
+ 14149, 11775, 18787, 9140, 19898, 10604, 15098, 17042, 14451, 11392,
+ 7228, 17036, 9092, 10128, 32381, 2231, 21626, 11147, 19008, 18840,
+ 9113, 3628, 8864, 28400, 6760, 7795, 6126, 4057, 23408, 32085,
+ 28060, 12050, 14144, 28339, 30553, 13208, 4788, 13961, 20862, 20342,
+ 631, 22120, 30889, 18653, 16327, 16166, 1191, 22903, 23160, 19156,
+ 2712, 6137, 19516, 4848, 27213, 8184, 20769, 30428, 2805, 27645,
+ 10587, 26255, 19193, 5595, 10308, 17803, 10020, 28992, 13473, 31246,
+ 23815, 13451, 7719, 31885, 3228, 9181, 27710, 31582, 7465, 29299,
+ 2564, 26293, 26983, 20019, 29589, 30929, 30436, 18820, 18570, 3703,
+ 15526, 5987, 26559, 25504, 15633, 19892, 30810, 2159, 30475, 8661,
+ 1032, 8805, 29277, 21369, 1674, 19928, 27484, 14772, 5745, 13217,
+ 25034, 9810, 2853, 10006, 3831, 4973, 17452, 24632, 1835, 20287,
+ 30121, 9773, 2632, 6708, 7715, 32240, 18348, 27459, 2440, 12615,
+ 6485, 20095, 1394, 16885, 31304, 4585, 10920, 7473, 15411, 13449,
+ 24552, 9048, 16465, 19389, 31204, 22495, 14222, 21200, 7306, 19851,
+ 11756, 6350, 16776, 8932, 25893, 16535, 2064, 8935, 17042, 1843,
+ 12760, 24059, 21579, 17509, 29030, 20262, 12688, 22915, 28042, 24961,
+ 14951, 644, 7724, 27113, 31367, 15707, 26183, 26872, 13173, 15236,
+ 3894, 10547, 20973, 4572, 2351, 3461, 21123, 6837, 5389, 9197,
+ 22922, 15914, 15186, 20595, 565, 5296, 13420, 9312, 10492, 6126,
+ 9783, 13742, 13633, 21967, 23236, 2750, 9780, 22997, 21593, 28233,
+ 26356, 16560, 25272, 16281, 11767, 10767, 7588, 4857, 27563, 31926,
+ 26786, 13930, 3165, 12496, 25597, 28311, 4443, 5255, 28428, 11,
+ 17749, 16083, 8119, 22690, 4105, 9359, 21304, 27965, 11552, 978,
+ 15391, 8122, 19026, 6524, 4505, 16676, 20689, 21775, 17393, 1062,
+ 24037, 32449, 23127, 29638, 11987, 975, 24033, 16976, 1028, 23827,
+ 30159, 1167, 16227, 17369, 6419, 11587, 16903, 10479, 30993, 23760,
+ 19730, 8699, 2467, 22836, 27097, 16657, 19040, 16955, 7493, 2693,
+ 13598, 22006, 27257, 31998, 30133, 22889, 26804, 24524, 20230, 31108,
+ 28793, 19324, 20796, 14421, 9198, 8361, 17746, 14971, 22147, 24853,
+ 29142, 2270, 6099, 7928, 7404, 6813, 26063, 30359, 28565, 15176,
+ 18969, 17945, 7729, 8528, 26286, 6038, 31299, 18619, 13768, 29042,
+ 20853, 26140, 259, 233, 15836, 1475, 21438, 21226, 19324, 11057,
+ 27844, 3881, 5903, 1231, 29484, 26992, 18946, 2015, 29309, 15669,
+ 6081, 2226, 25110, 1906, 8244, 8987, 15309, 12977, 23433, 1829,
+ 26071, 26982, 29493, 32257, 29672, 25218, 11317, 15170, 922, 23621,
+ 18074, 20045, 14355, 14676, 30276, 18442, 6370, 29707, 22766, 26848,
+ 22571, 23572, 3435, 27361, 17412, 21049, 20526, 15425, 26398, 30326,
+ 16656, 15885, 7336, 31827, 13902, 23321, 7024, 6513, 16593, 2875,
+ 15436, 16994, 17843, 5814, 32696, 10685, 20734, 11769, 5824, 13682,
+ 1463, 10634, 29473, 24156, 20251, 1597, 8875, 11797, 14120, 29097,
+ 31209, 20238, 1631, 31452, 20996, 25311, 4297, 15182, 24037, 4827,
+ 21560, 3092, 23194, 3816, 19407, 6998, 7931, 28302, 7364, 30211,
+ 20109, 10317, 101, 22979, 13222, 4916, 3929, 25390, 1234, 9903,
+ 21033, 27707, 6518, 27809, 15103, 12027, 20915, 22962, 27821, 135,
+ 13709, 32747, 29424, 14391, 3917, 20352, 20470, 5908, 1315, 23020,
+ 799, 17296, 30224, 19267, 27905, 11637, 7683, 3524, 13486, 28188,
+ 17731, 19374, 4665, 30943, 32524, 17238, 8822, 12240, 15229, 8565,
+ 10242, 12460, 12466, 21958, 23939, 28170, 24365, 5585, 15665, 26840,
+ 13690, 513, 24982, 7688, 5906, 8445, 25489, 31879, 19073, 9525,
+ 22945, 30575, 4804, 12475, 23648, 2173, 30709, 2901, 13390, 14021,
+ 810, 32464, 5328, 30116, 29082, 19863, 2169, 28663, 8961, 30596,
+ 29319, 5002, 18246, 16629, 18865, 28884, 3931, 12323, 28704, 17121,
+ 25958, 29871, 19643, 13199, 28702, 28030, 2471, 12285, 25975, 16583,
+ 7182, 24897, 28801, 14954, 31008, 7513, 11917, 25732, 7256, 25700,
+ 1939, 3648, 17153, 15891, 26064, 13552, 248, 2906, 4275, 860,
+ 4787, 8299, 12026, 23385, 4226, 15076, 13337, 7582, 26389, 10311,
+ 15579, 9172, 14655, 12460, 8011, 8428, 3833, 6578, 12757, 23477,
+ 30122, 21947, 3497, 30638, 30118, 13145, 20576, 16409, 244, 8451,
+ 8418, 10576, 16212, 22797, 31623, 31836, 23424, 2519, 2428, 24772,
+ 13747, 20036, 1897, 14499, 8040, 2669, 32592, 765, 1124, 151,
+ 22969, 14419, 9462, 12899, 2572, 21877, 17790, 25157, 23102, 2200,
+ 30508, 18743, 6575, 13480, 24074, 21679, 13139, 16096, 6205, 206,
+ 28433, 23191, 10888, 8922, 25192, 18269, 5649, 14318, 21592, 13638,
+ 31592, 3056, 6272, 17286, 28357, 19652, 9604, 19774, 24977, 23999,
+ 27313, 30870, 17704, 32607, 10468, 15372, 19166, 7993, 21159, 19980,
+ 25920, 25650, 14238, 12992, 28316, 19186, 32546, 23593, 6339, 26262,
+ 13867, 4207, 2573, 6565, 29811, 2677, 19358, 23366, 23768, 2225,
+ 27880, 23728, 32002, 15931, 113, 8929, 20551, 23075, 21974, 26771,
+ 27083, 6408, 5393, 23660, 2540, 5350, 7927, 3957, 8925, 18224,
+ 22276, 10189, 4240, 28959, 14939, 11167, 2010, 24137, 26633, 30801,
+ 210, 13685, 32394, 14846, 8314, 19374, 29326, 30503, 26017, 11670,
+ 17149, 1189, 7431, 21245, 11832, 30178, 24771, 12466, 19618, 23881,
+ 9954, 7321, 13407, 28923, 9041, 14334, 2651, 26564, 253, 21545,
+ 9358, 8781, 13880, 1331, 8575, 29843, 30815, 22296, 6407, 9111,
+ 4793, 22796, 19032, 27480, 9379, 29459, 27453, 8446, 2794, 14796,
+ 31908, 17752, 30841, 13453, 18521, 7048, 564, 18869, 27668, 6141,
+ 8739, 17726, 5558, 15266, 30163, 11666, 21712, 12117, 15353, 23200,
+ 9573, 13211, 21849, 814, 6129, 14482, 19686, 13425, 15017, 12839,
+ 11051, 26587, 10245, 31880, 6377, 11060, 24188, 25821, 5378, 3820,
+ 17806, 10803, 16789, 20144, 1032, 2744, 3179, 26683, 2948, 12590,
+ 13970, 5231, 32047, 5786, 32583, 22180, 19407, 11324, 30234, 5696,
+ 16132, 25028, 14412, 30343, 15309, 23491, 7548, 24757, 30287, 28256,
+ 6018, 29770, 28882, 12364, 18844, 20902, 27661, 14840, 6856, 29397,
+ 11427, 25861, 18288, 1708, 14829, 8188, 13900, 533, 31226, 10815,
+ 5253, 23463, 20180, 19519, 32022, 9594, 6405, 24560, 12152, 31033,
+ 17242, 15738, 6526, 27256, 15335, 24626, 14462, 29512, 32331, 22472,
+ 5553, 3849, 4918, 22977, 25052, 30592, 10536, 1832, 29744, 14378,
+ 10875, 14977, 12399, 3023, 29859, 29183, 6225, 14425, 5301, 10743,
+ 3110, 23783, 11558, 15251, 32444, 26142, 26837, 5067, 8323, 7359,
+ 8012, 22161, 17903, 639, 3651, 16972, 3358, 28947, 19558, 26504,
+ 1723, 12170, 22873, 2284, 26146, 29151, 28408, 14188, 31941, 30415,
+ 30691, 32448, 1230, 14312, 20282, 13844, 32518, 24547, 11685, 18689,
+ 10229, 31539, 26520, 3260, 18507, 5854, 24789, 30093, 25726, 16780,
+ 22834, 16515, 4021, 8925, 30364, 25959, 26085, 7424, 12380, 25838,
+ 28985, 11394, 32665, 18226, 32440, 31331, 31006, 24163, 9762, 21615,
+ 13406, 8634, 2330, 32715, 9141, 13487, 3466, 6607, 16881, 28268,
+ 5956, 31507, 14609, 30081, 1253, 20685, 26189, 17369, 29695, 24666,
+ 24406, 9965, 4215, 10522, 23774, 4151, 29483, 22657, 11867, 18922,
+ 21464, 17515, 6920, 25568, 4668, 24496, 21549, 27860, 23159, 23801,
+ 23713, 19409, 26807, 29650, 2445, 19946, 12308, 31744, 114, 15404,
+ 26809, 21268, 22126, 3537, 18757, 16448, 13499, 2742, 28529, 19050,
+ 9848, 29200, 15346, 13439, 29612, 31066, 9633, 5130, 11656, 14226,
+ 18393, 13829, 20460, 20644, 12320, 17902, 7213, 29991, 12042, 27422,
+ 4374, 2631, 12379, 20567, 9260, 3586, 24172, 18844, 8246, 2968,
+ 5328, 3141, 19709, 13372, 26166, 11602, 17489, 28688, 14737, 23040,
+ 6220, 31568, 17015, 32410, 11995, 25549, 22727, 20370, 30329, 31390,
+ 29583, 26832, 22590, 3602, 19245, 30538, 2841, 32745, 26292, 8405,
+ 11354, 3011, 6289, 7738, 16755, 20952, 11886, 15245, 1791, 31210,
+ 22614, 12986, 12547, 632, 2842, 5217, 116, 4149, 25076, 13028,
+ 20986, 20920, 17259, 17342, 2548, 19317, 19830, 11030, 444, 8172,
+ 19684, 9619, 23084, 10272, 17403, 17523, 22369, 28747, 17504, 28631,
+ 10686, 27856, 8247, 25441, 18484, 31601, 13962, 22785, 16321, 1218,
+ 24303, 22028, 7223, 20957, 14437, 20111, 20031, 27224, 24448, 4834,
+ 12957, 3700, 20422, 15232, 7862, 8599, 29784, 1813, 5711, 6397,
+ 11221, 24281, 3735, 17066, 17275, 29981, 25192, 30883, 11663, 12835,
+ 23498, 5213, 30463, 25395, 30393, 13942, 16455, 24555, 16680, 13987,
+ 15761, 6615, 31813, 20458, 544, 19010, 25343, 23825, 6894, 12875,
+ 14789, 14678, 15508, 8507, 2961, 6496, 2155, 13589, 14374, 28790,
+ 11505, 2415, 14230, 13807, 25966, 18561, 14086, 7913, 7383, 21116,
+ 29365, 8254, 14322, 28445, 28987, 19636, 19131, 15745, 1039, 25460,
+ 15623, 22075, 12620, 8894, 8807, 21412, 27317, 13018, 18767, 13426,
+ 13814, 15698, 17783, 19596, 10797, 1118, 31106, 14365, 26280, 3744,
+ 25566, 1255, 26352, 15121, 13035, 1499, 22535, 20796, 25695, 1254,
+ 21231, 25002, 29673, 18189, 8299, 2717, 23828, 5820, 27146, 29953,
+ 29807, 18523, 31840, 7583, 23531, 27939, 32407, 16020, 5764, 10288,
+ 17191, 27905, 32547, 22999, 5601, 16133, 9923, 5433, 11058, 3560,
+ 24019, 5144, 5286, 10393, 27868, 7402, 24235, 2651, 16484, 3884,
+ 15256, 27067, 3090, 2553, 24557, 13253, 10515, 24795, 29660, 18295,
+ 13243, 21217, 15881, 1398, 11376, 14322, 27535, 2048, 8132, 6240,
+ 6467, 5922, 6625, 25280, 572, 11563, 26922, 13306, 30611, 8032,
+ 29727, 26012, 1383, 16113, 9857, 22132, 26916, 1580, 14775, 8541,
+ 15621, 9713, 23665, 13913, 31960, 1894, 32139, 2528, 18434, 5611,
+ 15924, 20088, 1218, 25937, 20303, 27782, 18618, 2118, 15897, 11364,
+ 10923, 11028, 29709, 18099, 24960, 18060, 28165, 20211, 21646, 32572,
+ 28321, 11345, 282, 1257, 12268, 5311, 22811, 1593, 22589, 15946,
+ 32578, 3247, 13916, 15016, 1080, 21724, 2278, 12561, 2343, 30420,
+ 21747, 27217, 27515, 29408, 4085, 25370, 24042, 30322, 8420, 22686,
+ 4785, 27998, 31896, 861, 23329, 13126, 24950, 29756, 24667, 31062,
+ 30286, 18392, 22872, 13362, 20612, 9241, 25132, 9773, 9582, 13322,
+ 22667, 22972, 11006, 5608, 24972, 8234, 27553, 28537, 31917, 26765,
+ 4454, 7326, 18455, 760, 27747, 11308, 23076, 9202, 14421, 7928,
+ 21535, 15399, 25990, 7473, 4683, 30814, 26868, 5619, 7462, 32171,
+ 22447, 32024, 16366, 13798, 20867, 6994, 26725, 16475, 32471, 9335,
+ 13266, 23235, 9685, 2075, 19784, 22132, 6859, 12388, 298, 28116,
+ 4049, 8986, 10735, 3603, 1965, 14590, 23075, 26906, 28659, 24413,
+ 26542, 25534, 9841, 6116, 15449, 13370, 28105, 10934, 3982, 17628,
+ 5472, 16060, 27999, 12030, 22647, 19516, 11979, 25144, 14488, 7598,
+ 18236, 19412, 22324, 21195, 2899, 4738, 4746, 6630, 21736, 14925,
+ 27082, 4991, 10317, 17614, 27771, 5142, 16083, 8608, 14618, 14397,
+ 6800, 788, 20228, 32497, 1887, 27429, 14230, 24106, 11559, 1198,
+ 19090, 1457, 5985, 7386, 4548, 17458, 21972, 20700, 4070, 17042,
+ 6819, 17377, 28354, 2434, 31114, 28995, 22678, 1365, 11365, 28416,
+ 188, 31758, 242, 13418, 8074, 10686, 21463, 14624, 25976, 30477,
+ 15591, 60, 10624, 32278, 20641, 25550, 22219, 20856, 6905, 13450,
+ 23945, 14761, 14172, 445, 11041, 23694, 10734, 7558, 28042, 841,
+ 24086, 12610, 9720, 29267, 28220, 30280, 20156, 1994, 6353, 26327,
+ 6245, 5132, 1680, 31564, 556, 8324, 17924, 18328, 20879, 6340,
+ 8267, 3314, 11579, 2516, 11033, 5065, 24367, 27594, 15360, 25085,
+ 543, 10651, 8430, 8526, 7702, 23345, 16887, 18965, 30816, 26046,
+ 4180, 26162, 6823, 30287, 26284, 69, 21852, 2724, 16019, 4897,
+ 16729, 31807, 24401, 3453, 1220, 16827, 27108, 15853, 24374, 23135,
+ 26184, 15121, 16668, 6131, 13813, 7180, 29278, 15058, 4010, 5432,
+ 3135, 5185, 26729, 19737, 19077, 8959, 28098, 32143, 30681, 24094,
+ 30037, 13647, 31088, 8720, 1427, 19859, 15851, 29701, 23492, 26641,
+ 4988, 3957, 4942, 2346, 10571, 29176, 21044, 8805, 16408, 22878,
+ 7901, 8475, 20001, 26620, 17175, 21876, 6726, 25412, 24667, 17810,
+ 4715, 16537, 6483, 16651, 24862, 29793, 29849, 18589, 1657, 14171,
+ 23746, 7709, 30794, 13874, 24987, 4273, 3442, 24403, 7858, 22847,
+ 14475, 17148, 27416, 6949, 21966, 14742, 13926, 23851, 4147, 17477,
+ 14078, 3765, 8665, 23485, 19859, 27966, 29609, 8535, 16876, 24065,
+ 24631, 9828, 15588, 4089, 7656, 15809, 9142, 31244, 5210, 2988,
+ 14455, 2436, 8448, 18389, 9188, 5310, 3853, 26040, 19550, 26150,
+ 18068, 5931, 7731, 29539, 30445, 23859, 10527, 5326, 16474, 6940,
+ 14099, 20777, 8426, 24521, 16436, 4494, 10398, 22856, 24615, 20901,
+ 14539, 9897, 12428, 8218, 21183, 31761, 11464, 846, 14759, 19722,
+ 776, 5709, 27569, 28957, 30339, 29185, 13933, 30371, 14079, 13989,
+ 27257, 6104, 20886, 18811, 29277, 1585, 7866, 6850, 20660, 32752,
+ 20855, 2019, 18829, 25589, 3064, 11755, 15120, 14295, 7501, 16445,
+ 26981, 21555, 19563, 14217, 16849, 11076, 21620, 27896, 22818, 23988,
+ 30265, 30121, 10574, 4530, 17150, 21089, 21079, 16453, 1149, 18302,
+ 25201, 27872, 26157, 28973, 26983, 31542, 17347, 26589, 23355, 5967,
+ 16633, 2292, 1549, 25564, 3727, 14272, 7997, 25288, 144, 10928,
+ 11220, 19471, 22999, 6340, 18464, 18131, 28881, 23362, 4767, 14509,
+ 4485, 22443, 15903, 8001, 16593, 17901, 3874, 10261, 17654, 9946,
+ 18567, 31395, 5975, 32473, 19303, 26796, 9085, 10459, 28222, 30928,
+ 30559, 21905, 20299, 32604, 18656, 2781, 9785, 14691, 29850, 14214,
+ 22782, 7696, 23002, 12079, 22532, 23098, 14315, 8842, 1414, 10809,
+ 28824, 26569, 11326, 1528, 21484, 10069, 18749, 21324, 22844, 16579,
+ 11546, 4740, 26984, 31748, 14414, 14658, 7773, 23259, 14047, 12169,
+ 7134, 7828, 7996, 8982, 25989, 22004, 14440, 9460, 22020, 1900,
+ 27483, 17739, 7089, 19345, 17318, 8569, 24130, 27601, 25429, 6243,
+ 29140, 22878, 28185, 6413, 15155, 4207, 12199, 16233, 10581, 15272,
+ 347, 13165, 26663, 11222, 13089, 32360, 12429, 30688, 31637, 19094,
+ 22947, 22779, 13161, 16626, 3914, 5916, 24583, 31051, 20960, 6579,
+ 20856, 12442, 9038, 28822, 22405, 14739, 1352, 26939, 21020, 23418,
+ 11472, 1067, 8437, 4920, 3836, 24243, 13940, 27310, 11002, 25821,
+ 20946, 23113, 13649, 24479, 9336, 26839, 2153, 13137, 26283, 32153,
+ 32334, 25188, 8046, 6297, 6065, 10322, 9124, 25917, 5168, 16593,
+ 4214, 23325, 24535, 12108, 17652, 24850, 31206, 6803, 7935, 9871,
+ 14548, 4306, 32614, 10037, 3989, 18368, 22863, 3233, 14361, 11544,
+ 20697, 25225, 26389, 23373, 11519, 20743, 27909, 18042, 8384, 20788,
+ 26738, 13719, 12156, 4089, 28016, 23539, 12450, 29474, 18028, 9950,
+ 13960, 29876, 12836, 5030, 23706, 18561, 17143, 8646, 16567, 32761,
+ 17247, 13657, 11224, 8259, 17340, 32213, 11763, 24205, 13651, 13557,
+ 12575, 30368, 13974, 18935, 18424, 20407, 29862, 19720, 15173, 25489,
+ 17942, 12029, 6872, 7109, 25330, 10563, 21942, 6486, 24063, 25113,
+ 7544, 6791, 17221, 8444, 6385, 29424, 32715, 10083, 10769, 18898,
+ 30370, 429, 19209, 4776, 26404, 25688, 18096, 29694, 2174, 26995,
+ 20518, 4230, 32364, 16982, 15799, 26217, 2884, 12688, 27394, 14555,
+ 9014, 24865, 1626, 14322, 17618, 26858, 19820, 23224, 15050, 6497,
+ 32034, 8063, 11002, 24201, 30920, 9844, 5797, 20258, 27758, 23159,
+ 12290, 15388, 28301, 7210, 10487, 21586, 25837, 9032, 24356, 12405,
+ 12485, 2617, 2339, 23366, 26149, 14307, 18702, 10761, 4753, 7106,
+ 18498, 31030, 22254, 28731, 16483, 8561, 22691, 30509, 5537, 14524,
+ 19960, 25802, 26169, 29676, 10689, 27813, 13118, 15449, 10817, 9483,
+ 1689, 19930, 20297, 13463, 14927, 28913, 31648, 32257, 17666, 9538,
+ 17831, 15927, 12219, 20554, 15165, 20655, 6374, 17485, 7393, 3579,
+ 26782, 13200, 21526, 30878, 6699, 25545, 10508, 11294, 16073, 13780,
+ 31612, 16986, 7595, 21927, 724, 8990, 5440, 9864, 22932, 29173,
+ 8629, 16254, 22520, 3646, 11451, 3077, 471, 22914, 2698, 25861,
+ 3019, 14341, 18470, 13829, 15250, 32667, 12001, 668, 10164, 18621,
+ 8481, 24617, 6758, 21980, 13411, 14276, 7087, 1269, 11392, 25717,
+ 26313, 32614, 15407, 419, 20170, 7168, 11980, 32207, 22148, 10077,
+ 24408, 17794, 32681, 1652, 8384, 6787, 5427, 26474, 31586, 27470,
+ 29954, 29868, 25549, 16066, 7367, 15930, 20168, 2074, 32290, 19782,
+ 18071, 30494, 24071, 5629, 25977, 6298, 17254, 15269, 22901, 23312,
+ 14603, 23272, 21846, 19370, 26307, 20079, 4853, 8050, 17856, 8627,
+ 19126, 23749, 29758, 9744, 17493, 14597, 27751, 24092, 25827, 32399,
+ 8820, 13110, 24075, 3821, 19990, 10594, 25242, 21836, 25364, 1364,
+ 1087, 15664, 32053, 6346, 7822, 358, 17248, 10527, 29515, 26427,
+ 1538, 9245, 23526, 14827, 7344, 5908, 13378, 6748, 18190, 7208,
+ 25274, 30476, 5359, 12783, 8550, 16456, 6589, 12604, 27802, 11424,
+ 28444, 21813, 15024, 8599, 19146, 2476, 24840, 5279, 11209, 29612,
+ 19020, 30788, 25281, 26705, 25081, 2471, 31136, 17885, 22811, 4654,
+ 16003, 25353, 10328, 29050, 30169, 2201, 29487, 921, 30661, 10547,
+ 12418, 14205, 15557, 19313, 15442, 27053, 7570, 23093, 14027, 22331,
+ 19015, 20285, 21632, 15606, 15556, 27639, 1015, 30432, 10837, 29846,
+ 3176, 13283, 14479, 8549, 2498, 4543, 31099, 14939, 27119, 13639,
+ 29431, 4336, 20313, 13005, 13656, 19504, 31917, 23259, 17748, 15118,
+ 11743, 16164, 23840, 8442, 622, 953, 18645, 12470, 23785, 20608,
+ 25112, 10597, 23474, 30435, 28410, 18917, 20226, 8133, 26653, 3678,
+ 20525, 5562, 27161, 27675, 24103, 32631, 22045, 32665, 9031, 7815,
+ 26074, 24798, 18508, 26176, 13980, 4620, 30878, 32502, 4026, 15414,
+ 31702, 2414, 26673, 11890, 2175, 13973, 28556, 21296, 13342, 1906,
+ 7687, 4042, 9329, 18778, 4083, 16988, 26101, 8803, 12380, 20949,
+ 2986, 16923, 30442, 1102, 31770, 2681, 15621, 3995, 3992, 17683,
+ 28220, 6176, 25542, 14482, 6120, 4582, 2138, 12899, 7180, 14319,
+ 26913, 22704, 2944, 3526, 6468, 22671, 27471, 8025, 25546, 17529,
+ 26973, 29451, 17758, 14077, 17485, 25094, 13138, 3509, 27297, 19150,
+ 21477, 20602, 5411, 21020, 3009, 6356, 24708, 9705, 1224, 3508,
+ 10820, 30409, 4624, 18278, 13521, 7034, 5420, 12225, 22259, 4797,
+ 18606, 12961, 14951, 22372, 5097, 21143, 28107, 15021, 19452, 30174,
+ 19898, 14542, 1548, 32657, 2359, 31697, 24272, 2332, 17743, 162,
+ 23379, 20465, 9210, 4711, 18165, 11132, 12867, 4111, 12979, 8024,
+ 424, 12334, 31145, 24003, 28868, 14088, 28373, 20047, 26411, 21227,
+ 6174, 27867, 2198, 4803, 6805, 5314, 9024, 10984, 15354, 3154,
+ 23951, 31802, 7554, 25728, 26359, 4464, 5079, 217, 12316, 1709,
+ 16481, 23484, 28214, 3924, 20420, 23239, 28090, 3614, 426, 18319,
+ 30775, 29546, 24002, 16532, 20861, 21972, 14857, 13940, 4101, 30984,
+ 30280, 18782, 21645, 14041, 4317, 6858, 9475, 32397, 30911, 26471,
+ 28324, 24187, 16573, 32085, 29541, 19417, 6150, 25237, 9874, 7375,
+ 11246, 16318, 15541, 26831, 22255, 25329, 29369, 17193, 16622, 28430,
+ 20559, 986, 21696, 2856, 27025, 4773, 12013, 9783, 25573, 26726,
+ 27060, 8973, 16933, 15010, 27215, 140, 15357, 1378, 4984, 21013,
+ 9364, 26434, 299, 7235, 9326, 965, 12718, 27098, 19089, 24555,
+ 16335, 11514, 14566, 27910, 4717, 16537, 28643, 13769, 9529, 7728,
+ 32103, 24994, 20158, 7091, 4837, 586, 10143, 17863, 18117, 24474,
+ 30496, 10800, 1287, 13728, 18664, 9864, 29482, 6386, 4102, 3895,
+ 19276, 30018, 31537, 17055, 29330, 23091, 24148, 31895, 20170, 2667,
+ 21834, 32283, 8015, 233, 997, 23873, 23853, 24729, 5942, 4463,
+ 26246, 550, 27656, 4044, 31029, 5136, 32430, 3060, 16560, 254,
+ 2047, 12528, 31539, 4181, 27550, 26213, 31259, 29961, 23423, 30219,
+ 400, 16052, 21670, 9569, 19302, 24805, 22834, 6048, 12613, 17594,
+ 2971, 3053, 16904, 6321, 3896, 19410, 18020, 21179, 20996, 24047,
+ 30922, 6290, 9121, 20717, 29838, 589, 15773, 12980, 8264, 27442,
+ 8437, 2014, 6011, 17611, 27863, 22379, 22388, 8252, 4780, 7862,
+ 13173, 25043, 2902, 16807, 21523, 21217, 29110, 19243, 17885, 1480,
+ 9842, 4577, 23358, 16470, 24821, 5399, 26021, 24657, 20919, 9716,
+ 2530, 28243, 14782, 12534, 13268, 21208, 7013, 15264, 27969, 24982,
+ 26716, 27244, 7173, 12045, 20720, 8967, 27503, 25694, 6284, 7869,
+ 25832, 1376, 4992, 306, 31701, 23793, 12802, 18260, 4287, 906,
+ 15474, 8845, 12209, 13335, 9443, 5181, 3554, 25349, 4566, 23911,
+ 2708, 19356, 1608, 5803, 14140, 26511, 19184, 1140, 10979, 1233,
+ 31938, 31602, 9420, 28075, 25783, 26955, 16983, 22284, 31952, 21901,
+ 19493, 2336, 18009, 28392, 24189, 30243, 21867, 30874, 28911, 13176,
+ 13748, 11306, 311, 2293, 3194, 25433, 25956, 2690, 7134, 7766,
+ 2361, 28642, 2910, 14897, 6867, 7888, 6558, 27538, 27276, 6990,
+ 7016, 20907, 544, 21050, 27633, 13675, 14094, 29218, 12894, 18676,
+ 15425, 18009, 8326, 31568, 30448, 18506, 3834, 13407, 6851, 23309,
+ 6723, 3348, 20791, 25912, 9578, 22497, 28739, 15608, 26046, 3440,
+ 1084, 6752, 23505, 29076, 12534, 1024, 24004, 1151, 11820, 27066,
+ 5828, 5173, 25377, 25041, 8149, 577, 25992, 15427, 5582, 4518,
+ 24481, 24665, 20645, 20760, 8614, 10364, 8173, 30060, 25189, 12362,
+ 12445, 14414, 29486, 18665, 19, 3890, 27375, 1947, 89, 20109,
+ 3230, 8851, 20902, 3396, 27863, 4104, 13608, 23652, 6855, 7047,
+ 7424, 10005, 20552, 25997, 32143, 20169, 27981, 341, 17392, 22457,
+ 17025, 9455, 5573, 14738, 28459, 8082, 15927, 10347, 22101, 2611,
+ 27704, 27131, 28461, 26198, 9739, 2825, 29867, 7973, 5639, 2339,
+ 14452, 8383, 5272, 17555, 7423, 31186, 4998, 20111, 31478, 15212,
+ 20090, 26544, 30175, 2830, 25790, 17062, 1019, 6915, 16452, 24361,
+ 11630, 31983, 28138, 4402, 18081, 683, 19196, 2156, 10725, 8528,
+ 11258, 27621, 13401, 2706, 24732, 24074, 2573, 28752, 14612, 31954,
+ 25959, 9832, 28819, 12857, 30150, 5840, 8462, 26864, 4454, 15331,
+ 9282, 31059, 16004, 5368, 1526, 25243, 22466, 18745, 27520, 9301,
+ 20428, 27827, 5258, 19475, 22588, 7081, 22806, 2913, 28603, 24622,
+ 18624, 27130, 7017, 5619, 20291, 26684, 20352, 16477, 575, 9690,
+ 19252, 1754, 31802, 24785, 27613, 19318, 26852, 24733, 15191, 4009,
+ 9887, 8620, 15785, 7027, 8510, 21779, 16870, 6827, 18957, 2176,
+ 14929, 9365, 20754, 2671, 24516, 25010, 915, 24225, 9299, 17372,
+ 29657, 22218, 14636, 1170, 20019, 9099, 11201, 23952, 32573, 29087,
+ 24106, 12194, 3937, 26457, 24260, 3003, 22431, 5710, 25375, 21057,
+ 29578, 13647, 27159, 23724, 5267, 13978, 18752, 25935, 6794, 3664,
+ 10632, 8565, 5474, 15658, 14103, 16816, 5173, 29544, 2170, 19566,
+ 25991, 24587, 257, 1741, 11471, 68, 12901, 24497, 28980, 812,
+ 430, 4371, 2452, 5557, 4948, 27548, 2506, 10977, 17061, 114,
+ 5425, 5170, 10342, 7506, 14948, 32353, 29885, 20191, 15432, 9811,
+ 8271, 23865, 27725, 23112, 14501, 30418, 31216, 6998, 19412, 32125,
+ 23429, 29462, 14173, 10696, 13363, 20893, 24146, 30860, 23360, 1965,
+ 2746, 5826, 26766, 12589, 32311, 16280, 27238, 9175, 30182, 16581,
+ 10357, 13873, 9607, 6425, 6164, 29374, 28126, 25944, 26061, 2933,
+ 21080, 3912, 14362, 8562, 29170, 29449, 3951, 13548, 1879, 28325,
+ 26491, 20839, 13384, 4072, 32172, 18986, 7233, 21618, 24817, 6900,
+ 4698, 12298, 11971, 16619, 24171, 19765, 8550, 8149, 23923, 15367,
+ 21356, 18314, 315, 826, 23676, 11689, 29494, 18301, 11089, 12171,
+ 24236, 32014, 16645, 28789, 9751, 22411, 12688, 26642, 1998, 27654,
+ 3468, 13600, 30176, 14679, 6459, 2153, 9539, 2742, 29898, 15349,
+ 6190, 26761, 6615, 27262, 10179, 2938, 21042, 6948, 20721, 1485,
+ 3040, 21858, 18585, 5872, 11878, 12609, 6895, 23892, 21828, 14283,
+ 23076, 23164, 5055, 10179, 8258, 32084, 9699, 29331, 26711, 9923,
+ 13001, 1414, 725, 23683, 1046, 13111, 10553, 7729, 22212, 20810,
+ 29931, 4256, 10533, 24153, 15717, 29555, 10788, 17457, 8600, 5355,
+ 11727, 2623, 16523, 14333, 19218, 3141, 25926, 8360, 1733, 2385,
+ 10734, 14981, 12266, 7920, 22065, 3488, 20783, 1183, 31973, 30086,
+ 23483, 7042, 7403, 20127, 28454, 9817, 18778, 3518, 25289, 15791,
+ 7385, 30199, 29753, 21588, 31821, 24753, 16142, 24590, 27829, 19451,
+ 25065, 31372, 81, 8996, 29877, 3739, 7946, 30085, 13356, 26013,
+ 11790, 4002, 1693, 10550, 23227, 10866, 15853, 11592, 3262, 9466,
+ 15069, 5666, 17276, 31777, 21898, 12020, 25265, 29887, 12090, 1158,
+ 12886, 11255, 20821, 6186, 5577, 455, 15794, 16112, 15912, 4573,
+ 21524, 280, 23549, 11948, 12533, 3533, 5153, 4800, 27010, 5904,
+ 15322, 15438, 18662, 10738, 8263, 10000, 29387, 22278, 23806, 22607,
+ 3870, 16150, 1523, 28994, 25363, 22549, 10396, 15254, 31594, 32341,
+ 26706, 25678, 19440, 9722, 14843, 22733, 26696, 16559, 742, 31281,
+ 14827, 11159, 7926, 6883, 22382, 14726, 4611, 31340, 24836, 11634,
+ 26749, 13195, 1603, 14628, 2898, 20612, 6443, 21555, 2834, 31162,
+ 21092, 32563, 9810, 29312, 10951, 18218, 3918, 22573, 28192, 7491,
+ 13522, 22382, 27442, 22215, 4698, 19425, 25852, 26952, 19320, 32223,
+ 10555, 14112, 5750, 29337, 28720, 26, 14908, 614, 27043, 19054,
+ 9077, 10587, 6952, 22515, 21742, 17949, 29601, 31632, 14142, 15091,
+ 14340, 25331, 2988, 9503, 11615, 10374, 1613, 7791, 9241, 16799,
+ 21357, 15631, 18554, 7416, 3120, 17825, 23661, 1374, 24185, 17295,
+ 16005, 7341, 27659, 31648, 25151, 763, 9455, 27850, 7559, 32276,
+ 8469, 21320, 28541, 13607, 15678, 25068, 9336, 21694, 32536, 9653,
+ 31563, 12019, 1195, 18340, 12232, 11233, 757, 8396, 3715, 7770,
+ 6097, 21673, 30169, 20696, 29470, 26034, 26672, 24245, 6940, 30769,
+ 4991, 11678, 20505, 14163, 29202, 6981, 21326, 4219, 26759, 13142,
+ 5380, 14556, 1309, 429, 3579, 12615, 17454, 21702, 18443, 15425,
+ 32249, 1140, 23052, 31321, 24997, 4310, 23284, 8377, 8579, 11655,
+ 4159, 32250, 13460, 3350, 23444, 16701, 20811, 182, 11173, 14199,
+ 1427, 16438, 29783, 29452, 4116, 28211, 29219, 4512, 24242, 11404,
+ 15547, 5161, 22103, 21782, 27889, 32073, 18419, 10897, 22997, 10716,
+ 14017, 5595, 12574, 6093, 21451, 17252, 28364, 3885, 21168, 13538,
+ 30731, 24966, 31653, 6982, 23897, 13164, 7866, 3310, 2027, 1110,
+ 19551, 27676, 22093, 26796, 30502, 4519, 27722, 10785, 25290, 4080,
+ 14859, 16963, 1137, 8728, 32387, 25424, 14382, 7024, 18698, 844,
+ 28618, 27441, 15943, 7504, 16068, 2158, 9300, 7461, 26518, 23110,
+ 31261, 10514, 20026, 28766, 7689, 15857, 29677, 8079, 18397, 20872,
+ 24627, 22235, 23005, 28439, 6939, 16550, 19764, 558, 7364, 1058,
+ 15765, 17345, 22048, 15116, 22563, 32126, 14072, 28566, 12686, 5982,
+ 21808, 13988, 18303, 9083, 6477, 14906, 12599, 23585, 5172, 18485,
+ 17267, 18471, 25140, 14650, 11154, 31104, 16199, 17389, 17913, 6669,
+ 12437, 4195, 13239, 15029, 26426, 8153, 29541, 6328, 16457, 23718,
+ 336, 19776, 1553, 26222, 17115, 6970, 22175, 28313, 16670, 20323,
+ 21380, 14595, 30419, 26278, 32472, 5365, 13683, 28325, 27006, 25173,
+ 26012, 21654, 5802, 30489, 9910, 5712, 14497, 30977, 4566, 2469,
+ 10944, 32646, 9186, 11763, 19648, 4622, 4855, 15350, 9016, 22113,
+ 4871, 26592, 24931, 864, 19911, 2476, 16420, 27637, 4552, 8111,
+ 17991, 13894, 31971, 24432, 26122, 4910, 9691, 18617, 5084, 2541,
+ 2366, 28398, 14948, 11294, 15756, 27806, 12229, 17898, 12955, 13656,
+ 4129, 24188, 58, 14784, 8540, 7348, 2069, 4577, 9250, 25632,
+ 28377, 8645, 13867, 15912, 12440, 27715, 10685, 25480, 21614, 2073,
+ 30323, 31236, 869, 27451, 10046, 23126, 1686, 106, 27049, 29292,
+ 28817, 15111, 8801, 6096, 30207, 7466, 10996, 24168, 14726, 25583,
+ 7385, 18271, 3821, 19984, 19889, 23651, 31105, 12473, 24780, 2833,
+ 27063, 20119, 4591, 21677, 32274, 9523, 7508, 9751, 19271, 9342,
+ 26867, 27642, 28576, 1196, 21248, 14151, 30110, 11846, 18869, 1506,
+ 18914, 26747, 4177, 923, 18509, 16824, 21857, 22367, 9319, 26232,
+ 32318, 20655, 12541, 23132, 19415, 2386, 19215, 18302, 15536, 20295,
+ 27625, 22531, 20523, 27390, 9871, 19951, 3847, 5576, 5214, 19773,
+ 32038, 13451, 29937, 3120, 22675, 10938, 1346, 24036, 18883, 22916,
+ 21009, 19240, 26907, 8012, 2442, 11664, 15795, 27482, 4130, 197,
+ 6490, 14800, 23746, 24096, 30170, 3039, 24615, 22135, 14205, 12346,
+ 31625, 7735, 30927, 28619, 19066, 16307, 17318, 29350, 17426, 18364,
+ 23392, 28987, 30537, 8306, 31852, 1487, 26276, 3673, 13580, 12845,
+ 18196, 944, 15192, 28056, 9755, 15870, 25735, 20229, 15152, 25069,
+ 8554, 10119, 26725, 2395, 9273, 8459, 11847, 30639, 5010, 13637,
+ 5893, 26729, 28351, 4330, 23765, 11262, 1848, 14112, 20372, 1762,
+ 13160, 31027, 15788, 1766, 7860, 5769, 25659, 17092, 23226, 6360,
+ 10866, 14328, 5590, 16534, 11323, 15058, 6891, 5553, 22558, 11466,
+ 32352, 28801, 9317, 27923, 7272, 3835, 8062, 14195, 19591, 2599,
+ 24482, 25937, 28242, 16340, 5556, 17680, 13174, 1162, 18284, 31643,
+ 19195, 12736, 29876, 9281, 20938, 25679, 11346, 8900, 11373, 32551,
+ 21448, 23468, 11799, 17984, 9848, 18145, 12516, 9684, 12300, 4217,
+ 865, 31180, 17941, 15311, 20303, 27000, 17650, 31957, 23972, 11138,
+ 5108, 15275, 23507, 17957, 13504, 30320, 1613, 8090, 25076, 30040,
+ 23624, 29395, 269, 1278, 16575, 31852, 27528, 11004, 11450, 29663,
+ 21319, 2234, 22223, 9463, 17975, 24707, 29673, 15751, 5424, 28894,
+ 30024, 9051, 8732, 6683, 26569, 26223, 22876, 556, 22632, 9055,
+ 23143, 10934, 25091, 27167, 5044, 11624, 18529, 31980, 21979, 4748,
+ 17522, 31618, 8695, 30171, 26072, 20112, 14158, 28054, 11687, 26473,
+ 9268, 26578, 18025, 10236, 24108, 29204, 32102, 1798, 9553, 7965,
+ 24866, 17542, 14068, 32519, 10534, 17010, 4999, 23953, 19203, 21928,
+ 23481, 15032, 24725, 8999, 2275, 12679, 17285, 23935, 1187, 16687,
+ 529, 30342, 25542, 11354, 4368, 6477, 18540, 25277, 24368, 82,
+ 12134, 10476, 11651, 31735, 11491, 29299, 20794, 15667, 23628, 8738,
+ 17072, 14472, 1900, 9384, 7594, 13621, 18644, 6500, 30429, 23724,
+ 11646, 32119, 10928, 24134, 6576, 3358, 2372, 31542, 29987, 20287,
+ 945, 3772, 25189, 32577, 16019, 26267, 1404, 18721, 11718, 32716,
+ 7628, 3010, 7533, 31604, 30523, 5509, 19513, 24596, 30354, 3866,
+ 31464, 31487, 17702, 2198, 5387, 30226, 24505, 23749, 22285, 30111,
+ 3227, 24257, 5489, 21162, 32020, 1475, 2395, 17752, 7687, 2874,
+ 18002, 5028, 23503, 12058, 15684, 6228, 23917, 5751, 28874, 13867,
+ 31461, 30802, 16046, 2913, 29413, 3251, 25259, 31056, 9128, 29176,
+ 5747, 21616, 19226, 31852, 29431, 20613, 4669, 9243, 30434, 32023,
+ 26571, 1253, 22118, 26147, 28189, 9426, 30780, 11536, 75, 29861,
+ 17382, 11748, 4757, 16052, 9528, 1208, 29185, 30710, 26902, 1898,
+ 10054, 10078, 22399, 1937, 233, 22375, 11979, 28854, 2214, 17905,
+ 25648, 5825, 26641, 17995, 19851, 18609, 125, 2449, 6237, 31632,
+ 14877, 16696, 12820, 8614, 20073, 20455, 1421, 494, 4547, 31880,
+ 12758, 9158, 91, 23456, 7736, 8938, 4688, 25307, 3957, 32675,
+ 6936, 23276, 8782, 16188, 14369, 9107, 20296, 28854, 4792, 32255,
+ 23472, 27069, 31019, 20823, 23517, 20442, 4906, 7572, 10933, 16873,
+ 13683, 4241, 31347, 13774, 6319, 29029, 25255, 24164, 30614, 22000,
+ 3965, 11702, 22618, 22196, 30275, 18290, 1347, 13542, 13094, 30618,
+ 30870, 9925, 29756, 381, 16316, 15915, 5576, 23270, 6560, 7522,
+ 21433, 10131, 21593, 28216, 13427, 2280, 11785, 20310, 4306, 5605,
+ 15621, 11213, 23916, 3926, 9014, 12530, 6423, 9289, 4287, 22124,
+ 1196, 23237, 23007, 11403, 2058, 28857, 9241, 25820, 26717, 18739,
+ 28307, 18682, 13216, 14802, 31165, 5030, 1376, 19582, 21042, 24602,
+ 2243, 18774, 739, 9115, 23498, 7402, 12914, 25934, 14291, 28331,
+ 12252, 10316, 866, 31648, 12891, 15352, 12576, 2394, 20619, 26257,
+ 4132, 1321, 29387, 7683, 29042, 9104, 17638, 17155, 18113, 5111,
+ 27379, 4698, 7810, 7328, 32121, 16513, 8477, 13020, 4311, 29551,
+ 29566, 25471, 19427, 3759, 8912, 8081, 20946, 1461, 32136, 16710,
+ 856, 10354, 32166, 23856, 23311, 7718, 10295, 13236, 26909, 630,
+ 1567, 22203, 12818, 22718, 6677, 22441, 29967, 18856, 30703, 4499,
+ 7469, 24318, 24864, 25517, 25116, 12732, 2687, 28673, 23563, 15978,
+ 28490, 12903, 3784, 21416, 21866, 945, 12329, 20235, 26360, 23846,
+ 11690, 7207, 1281, 28722, 13655, 10733, 14214, 26203, 17901, 19000,
+ 24263, 23927, 2620, 12194, 2498, 29724, 975, 32156, 5622, 31321,
+ 18639, 7870, 31852, 6819, 22821, 21851, 28664, 3858, 20191, 14937,
+ 12477, 14030, 28117, 7743, 14575, 8132, 22156, 144, 9949, 22685,
+ 24666, 4440, 2094, 7920, 24267, 28932, 27242, 15798, 22084, 8822,
+ 21693, 12287, 25574, 25433, 3832, 23524, 23733, 24242, 23001, 31165,
+ 26618, 28088, 31884, 31636, 6374, 23270, 19313, 2265, 19319, 23374,
+ 3104, 25174, 18592, 12848, 23211, 16998, 30116, 13003, 29731, 3426,
+ 4803, 5235, 2653, 26205, 19736, 19684, 1269, 31761, 10178, 25814,
+ 21396, 8728, 66, 31442, 13679, 2656, 12836, 26691, 6672, 13017,
+ 7650, 15568, 32601, 23408, 5893, 1001, 28870, 6209, 32141, 2208,
+ 3058, 21512, 1683, 3003, 11869, 22233, 30765, 8199, 12396, 9490,
+ 23698, 8431, 20913, 19085, 28798, 30540, 14957, 26138, 20696, 8319,
+ 13907, 2348, 11155, 11198, 3215, 16338, 30674, 8619, 6407, 21737,
+ 31055, 2603, 2785, 9873, 4861, 1141, 27717, 7901, 11500, 9577,
+ 22372, 9423, 12653, 4132, 31929, 6531, 25976, 31953, 24206, 13738,
+ 8266, 8641, 26051, 23354, 9810, 12991, 13259, 12132, 11086, 27293,
+ 22007, 4295, 16306, 21267, 15863, 15843, 11593, 16074, 9118, 16336,
+ 1822, 10675, 13285, 27951, 28829, 29597, 12595, 6498, 24566, 10503,
+ 26843, 17400, 24514, 20018, 8678, 23659, 5097, 24699, 26900, 28174,
+ 1475, 488, 24093, 18497, 31613, 769, 26172, 30439, 24255, 16097,
+ 26606, 7962, 30347, 32140, 29688, 5149, 30825, 20611, 32679, 14481,
+ 13505, 7574, 5211, 32748, 25224, 19450, 6215, 9256, 19998, 18331,
+ 5234, 25528, 28535, 20147, 7169, 23488, 11130, 15772, 14521, 21125,
+ 17574, 19683, 192, 1571, 16123, 30109, 14755, 21374, 15128, 28670,
+ 11421, 18810, 3233, 39, 4119, 31855, 4067, 1344, 10859, 11735,
+ 699, 32455, 4589, 7242, 25779, 31783, 11820, 4013, 8815, 10893,
+ 24181, 30118, 4168, 29943, 27033, 8786, 30774, 27278, 6896, 2363,
+ 16115, 24373, 12446, 644, 25693, 31330, 32533, 28775, 25373, 10284,
+ 28124, 22754, 13190, 8358, 12686, 18348, 30143, 31084, 26405, 3182,
+ 1829, 30075, 29816, 10544, 1771, 1862, 20995, 1297, 3587, 14598,
+ 8679, 14140, 7746, 28497, 14385, 32279, 3263, 14830, 30815, 14014,
+ 27516, 9960, 11297, 26799, 13896, 19425, 14172, 14791, 18147, 31145,
+ 19828, 24173, 21604, 19983, 3019, 23053, 472, 6135, 7557, 9160,
+ 16428, 16813, 19599, 873, 1869, 13689, 9183, 15003, 10893, 28788,
+ 1789, 20058, 19529, 14233, 25282, 1192, 13512, 8991, 23391, 27265,
+ 4199, 29703, 7074, 30224, 22771, 26609, 10613, 6435, 28247, 32563,
+ 25512, 22493, 8823, 26924, 3312, 14250, 15451, 2774, 2095, 6776,
+ 13968, 21403, 10741, 23077, 15563, 21610, 17223, 14387, 11472, 19721,
+ 18848, 30147, 7826, 9133, 16438, 10177, 14236, 31432, 18046, 7004,
+ 19887, 22818, 28658, 24249, 7341, 6187, 18706, 16872, 5045, 3216,
+ 11689, 25623, 32144, 7436, 21585, 8453, 2124, 15233, 13113, 29370,
+ 28710, 29767, 8742, 7030, 20910, 1987, 23992, 11239, 26405, 16956,
+ 20463, 14750, 13610, 1515, 16877, 22980, 27286, 15185, 23294, 13321,
+ 30628, 7118, 4309, 16862, 8277, 2670, 27929, 3556, 3602, 28422,
+ 19488, 1956, 9363, 18304, 30970, 16256, 7681, 25459, 19121, 7913,
+ 12887, 32247, 9935, 28883, 19982, 10679, 3361, 20070, 7161, 17223,
+ 4283, 17399, 26222, 23992, 25148, 16950, 5030, 23914, 20307, 12201,
+ 16742, 13602, 23426, 11865, 17375, 31068, 22050, 27083, 3028, 15843,
+ 4520, 305, 14330, 29086, 8230, 25058, 21924, 11437, 14613, 9736,
+ 5279, 9397, 11345, 19352, 29275, 15223, 1637, 22408, 8268, 23464,
+ 18953, 14652, 10640, 6140, 25321, 577, 7122, 16517, 13736, 17981,
+ 14190, 25147, 28965, 14118, 27350, 25820, 1277, 20915, 7476, 15094,
+ 24913, 11792, 3153, 22593, 25545, 18646, 16821, 25139, 5592, 22586,
+ 25360, 20175, 8258, 389, 25048, 26046, 6108, 708, 20020, 22432,
+ 1939, 9408, 20761, 24484, 23472, 2352, 4530, 9046, 4699, 10542,
+ 2566, 17593, 21853, 6120, 3797, 23190, 24874, 23960, 3778, 17171,
+ 23838, 32438, 19640, 1159, 2311, 875, 6534, 12429, 25572, 4938,
+ 20684, 32088, 12268, 31035, 7451, 2374, 30674, 9143, 18264, 31927,
+ 31048, 30011, 5473, 32287, 6338, 30966, 31731, 11354, 17020, 20421,
+ 10188, 4928, 23742, 26978, 8716, 20090, 12127, 24025, 5089, 20116,
+ 25736, 31547, 28003, 29778, 1722, 23445, 29629, 30280, 8210, 5923,
+ 31374, 17573, 24268, 26306, 19599, 24400, 25351, 19108, 1909, 21046,
+ 6599, 2375, 28441, 19426, 18752, 6824, 31702, 590, 12882, 21428,
+ 10290, 23032, 27472, 26111, 16833, 825, 22533, 1976, 16711, 466,
+ 25337, 22493, 28189, 21192, 23536, 21163, 20694, 9331, 8116, 27225,
+ 14625, 21713, 27924, 6149, 23281, 10784, 2861, 30959, 18140, 31147,
+ 9448, 19429, 16833, 12516, 32196, 25342, 16302, 29875, 25558, 23947,
+ 1537, 19214, 782, 15947, 14541, 714, 32187, 12766, 22399, 19888,
+ 28241, 6524, 27841, 16596, 13930, 11751, 30110, 12066, 16140, 20126,
+ 17383, 4666, 3626, 20820, 24534, 30078, 21869, 26016, 11506, 5992,
+ 24116, 24822, 22066, 13602, 30425, 1750, 17765, 13392, 17718, 8515,
+ 10705, 7984, 8807, 32119, 21019, 9958, 25554, 8405, 23911, 8209,
+ 13669, 18975, 1983, 11682, 26911, 4841, 5561, 3566, 24530, 17742,
+ 9044, 15874, 28455, 14817, 23076, 26422, 26850, 20966, 21167, 19205,
+ 10087, 25027, 9494, 8475, 17277, 8113, 27896, 7088, 22355, 27319,
+ 17555, 1557, 29377, 32217, 31532, 12684, 9423, 25485, 2737, 9309,
+ 15995, 15726, 4254, 16166, 12983, 13364, 19997, 19571, 14258, 9188,
+ 29553, 11918, 3416, 22596, 14996, 8089, 3356, 28050, 5407, 14297,
+ 26357, 10613, 29035, 11861, 12198, 24628, 23286, 1952, 9283, 14886,
+ 31240, 9971, 18161, 28010, 13974, 30078, 14573, 16343, 614, 5120,
+ 30160, 25910, 3700, 19094, 21521, 3503, 28565, 10960, 28363, 14466,
+ 30298, 6154, 23744, 7928, 15927, 10746, 22687, 19352, 14308, 7557,
+ 16002, 12701, 13060, 18391, 699, 22696, 11013, 16306, 1488, 28851,
+ 23367, 12550, 27076, 25158, 24192, 3779, 19608, 12013, 23903, 5867,
+ 3090, 13801, 4207, 23787, 30397, 12582, 6463, 20011, 3633, 32365,
+ 30400, 25828, 16020, 2267, 6382, 32050, 12129, 26258, 22450, 106,
+ 4456, 32430, 20743, 23213, 3607, 19323, 29277, 28349, 15351, 3301,
+ 12602, 31760, 15481, 32559, 14119, 11043, 26355, 27112, 1226, 13329,
+ 9446, 6939, 20560, 21348, 25474, 8903, 8974, 299, 15980, 25230,
+ 31335, 7757, 18366, 17841, 28656, 3100, 4432, 13628, 11474, 25133,
+ 23350, 7294, 11376, 13928, 2953, 4540, 4682, 11099, 21355, 30503,
+ 5921, 14547, 9541, 10250, 20829, 25262, 24659, 1608, 23723, 20971,
+ 21859, 31750, 9450, 1027, 2265, 17829, 22600, 1148, 22007, 6131,
+ 17576, 25787, 22363, 30370, 9288, 26138, 14537, 20217, 7584, 2618,
+ 22059, 10953, 31373, 32155, 19414, 4003, 23214, 4201, 23567, 24136,
+ 25870, 12697, 19918, 18017, 15620, 8245, 10434, 8816, 15960, 18164,
+ 29332, 20487, 17575, 30222, 20848, 22584, 521, 28494, 14274, 31820,
+ 10480, 30825, 32061, 31415, 27988, 26510, 2338, 8268, 8461, 24126,
+ 29119, 31150, 28544, 9822, 13622, 14599, 31869, 25995, 28543, 9212,
+ 27240, 6829, 12720, 7648, 2967, 6607, 24188, 8743, 17148, 31278,
+ 12282, 17182, 22532, 10895, 19112, 218, 16830, 8150, 432, 3182,
+ 11584, 20949, 12394, 19298, 17223, 31330, 19745, 12128, 28957, 19116,
+ 6426, 13871, 14528, 2767, 4562, 9702, 19520, 22437, 1928, 22873,
+ 30825, 29407, 31995, 12504, 8866, 22869, 13429, 31513, 24085, 5019,
+ 3592, 27250, 23568, 29909, 6936, 27211, 15275, 15308, 2842, 26836,
+ 31916, 19009, 21914, 26867, 6567, 26241, 17795, 28801, 3434, 15161,
+ 18843, 9909, 18328, 2444, 11853, 14048, 21651, 16739, 9387, 19291,
+ 15519, 29700, 15027, 13502, 24133, 21735, 10449, 4435, 18422, 15556,
+ 6310, 2251, 21745, 25329, 18696, 28719, 4455, 16619, 13130, 27161,
+ 10716, 21555, 5565, 22307, 27088, 12891, 1910, 10912, 3487, 9056,
+ 31058, 30602, 27558, 13882, 18488, 18876, 14503, 946, 17566, 8033,
+ 27502, 4980, 21327, 5805, 949, 5989, 2923, 9163, 14406, 28982,
+ 30127, 25366, 20575, 13882, 20726, 23435, 11354, 9588, 0, 17790,
+ 16781, 17397, 1139, 10637, 3440, 4965, 11039, 27603, 17405, 5855,
+ 19846, 5982, 15709, 6658, 19612, 32226, 26304, 28228, 10443, 32686,
+ 14989, 4746, 23354, 4064, 955, 30966, 21583, 18645, 28798, 24320,
+ 17267, 9444, 14375, 27593, 3093, 12108, 22597, 2219, 3057, 16746,
+ 11537, 10261, 5778, 8240, 26889, 28310, 18965, 3538, 12250, 29239,
+ 8497, 9154, 22659, 1038, 26228, 2271, 6840, 14352, 27855, 22506,
+ 11140, 7975, 12629, 19001, 3379, 26501, 19008, 31407, 5743, 22327,
+ 18229, 21739, 29865, 21757, 26313, 1216, 11707, 29529, 17731, 31205,
+ 25803, 12774, 26787, 21486, 26226, 26859, 19940, 19067, 16413, 4912,
+ 23423, 26032, 26292, 27152, 23856, 6885, 12410, 2000, 27900, 8606,
+ 9781, 1071, 28019, 5309, 28558, 16190, 31027, 13302, 24250, 20082,
+ 27565, 22916, 24410, 16376, 26412, 30746, 19616, 10312, 31763, 13597,
+ 29364, 11773, 21861, 29456, 16214, 2020, 3723, 24656, 26052, 8531,
+ 5714, 24065, 31198, 22716, 17204, 21320, 18056, 3201, 31960, 16570,
+ 25424, 27146, 7900, 10261, 19793, 13078, 30929, 7214, 1878, 27982,
+ 3975, 3371, 1347, 12320, 907, 9458, 26289, 1226, 16623, 18402,
+ 17625, 3253, 23625, 3520, 6067, 25093, 16638, 18164, 30303, 26222,
+ 5313, 25077, 14019, 29769, 29782, 17666, 12406, 9703, 28060, 28691,
+ 9948, 10021, 23242, 31503, 7827, 17728, 761, 17471, 8718, 12523,
+ 9187, 25347, 14720, 9887, 18666, 12995, 6652, 28979, 4956, 2601,
+ 20442, 31404, 22517, 29325, 26716, 24406, 13733, 29617, 24210, 14100,
+ 2452, 18351, 20346, 2292, 25700, 2863, 14700, 7430, 25782, 15837,
+ 19125, 8303, 6895, 10011, 899, 20409, 23100, 29426, 12033, 7021,
+ 6867, 6991, 30658, 31460, 20860, 29036, 7011, 24922, 24656, 23436,
+ 364, 2372, 1217, 6891, 14712, 2531, 26331, 11765, 9366, 27418,
+ 11722, 8886, 19950, 11133, 15771, 28050, 13992, 27818, 583, 6198,
+ 6409, 14812, 27629, 23758, 26335, 7357, 95, 376, 1824, 29820,
+ 9696, 2041, 5838, 17184, 2860, 1456, 12573, 25884, 20665, 14280,
+ 728, 26403, 22333, 10161, 11521, 28221, 22384, 29648, 15032, 26139,
+ 10003, 4213, 11869, 27047, 20273, 5390, 27129, 6624, 22437, 27035,
+ 30426, 22245, 27612, 26722, 28798, 3919, 15580, 18404, 5811, 6596,
+ 17541, 24847, 19195, 19658, 19991, 9653, 32053, 18648, 26613, 23357,
+ 19322, 10419, 8873, 28057, 22854, 3064, 16679, 28280, 8664, 12276,
+ 15958, 5308, 18907, 2748, 19404, 20526, 13381, 7290, 11737, 17776,
+ 24192, 27398, 6344, 17972, 18376, 23478, 29537, 6572, 26580, 24438,
+ 8883, 10561, 30904, 9499, 17168, 25992, 6154, 17908, 29272, 30578,
+ 835, 8354, 3963, 4547, 29545, 22058, 4921, 30405, 23531, 7497,
+ 26156, 1597, 4301, 24584, 22537, 26526, 6148, 22415, 7203, 9341,
+ 10788, 6718, 28464, 18245, 9784, 20474, 19024, 21036, 31985, 197,
+ 18251, 8805, 22276, 12690, 6682, 5015, 31437, 17239, 17322, 30607,
+ 13624, 18531, 25052, 13874, 18913, 17394, 16592, 10677, 11898, 2047,
+ 4451, 2832, 5486, 9561, 26870, 687, 3011, 8697, 28274, 12651,
+ 11845, 27027, 22664, 17850, 14817, 11371, 8510, 28962, 31567, 8298,
+ 4775, 20980, 25076, 22641, 4337, 9526, 14854, 9709, 17830, 21729,
+ 20977, 14508, 4139, 13901, 3833, 28911, 24461, 3305, 13601, 6080,
+ 22908, 9519, 26188, 29061, 29336, 7127, 7331, 24278, 23532, 9547,
+ 9270, 32652, 27064, 26972, 22502, 3098, 22388, 18227, 9602, 22817,
+ 3345, 5514, 7472, 14654, 18818, 13084, 4111, 12583, 22139, 31577,
+ 538, 12790, 10617, 29535, 29520, 19908, 5634, 17190, 17426, 6778,
+ 29998, 20218, 14540, 14052, 26214, 1327, 24791, 9735, 3436, 13328,
+ 25758, 29877, 29083, 31768, 32512, 23902, 25201, 12901, 9718, 24105,
+ 1354, 18281, 9846, 30019, 28782, 1507, 14231, 30583, 30542, 15885,
+ 18677, 13568, 3083, 12567, 4183, 24731, 23096, 20693, 6799, 27872,
+ 32481, 10165, 25506, 21457, 460, 31987, 14889, 31924, 29694, 2320,
+ 29175, 13342, 22401, 20096, 10748, 27217, 13413, 27299, 10601, 11207,
+ 32517, 29430, 6165, 2063, 13196, 12939, 5664, 23256, 19127, 23478,
+ 30422, 11084, 27612, 522, 8918, 5535, 43, 28803, 25971, 29415,
+ 2868, 12293, 10586, 13102, 27817, 20997, 26741, 7621, 28517, 21382,
+ 21264, 27612, 18862, 11336, 29243, 29008, 29367, 24124, 18799, 18372,
+ 29033, 6458, 15220, 12275, 2147, 18166, 13953, 7492, 25408, 4913,
+ 27558, 8096, 10520, 17452, 5479, 8064, 6217, 30562, 4522, 8266,
+ 3959, 5750, 21203, 31965, 10193, 6251, 27693, 21098, 17558, 25363,
+ 15756, 3463, 15320, 24778, 560, 19838, 31873, 7780, 18157, 4587,
+ 21907, 1379, 2953, 26246, 17076, 1645, 4966, 317, 25065, 18430,
+ 10592, 1670, 30370, 11611, 23289, 26611, 7671, 18887, 28340, 4358,
+ 6193, 5112, 6590, 22088, 19340, 28108, 14547, 23189, 25659, 21561,
+ 4192, 24250, 13741, 19330, 22501, 12098, 16655, 23473, 5278, 9356,
+ 1298, 12609, 1890, 26913, 31470, 13851, 12747, 31301, 25767, 14020,
+ 13975, 5836, 20622, 26580, 6478, 4143, 30220, 24490, 8485, 12767,
+ 20379, 22622, 25379, 13017, 5653, 19959, 14210, 25979, 305, 19678,
+ 7768, 6550, 29002, 1171, 22391, 25796, 26211, 29343, 12689, 17660,
+ 26729, 14794, 21664, 20835, 17591, 31117, 2948, 28005, 17632, 14794,
+ 20718, 12805, 17064, 16059, 9086, 369, 15699, 22825, 25896, 30938,
+ 21539, 1758, 18908, 13442, 18972, 30556, 6502, 6679, 30474, 18639,
+ 18579, 7487, 18885, 4417, 11669, 12916, 16308, 2061, 21416, 25618,
+ 30096, 25494, 12790, 15790, 13674, 16184, 18872, 426, 9712, 7551,
+ 28575, 23814, 32492, 23191, 17522, 3449, 26381, 8964, 8440, 11713,
+ 24298, 17043, 31000, 7223, 23876, 24465, 31295, 12198, 139, 30266,
+ 26882, 11869, 31140, 10356, 517, 15235, 5098, 13758, 25115, 11947,
+ 32371, 12131, 14766, 2472, 14996, 15603, 20322, 163, 21415, 1267,
+ 5621, 18539, 17419, 3540, 22890, 7947, 11117, 11042, 18278, 17058,
+ 14918, 19198, 22234, 19055, 30373, 14286, 21218, 5676, 15919, 8755,
+ 3309, 18333, 10596, 1852, 31263, 31336, 13348, 18137, 16371, 11815,
+ 20337, 32402, 29733, 5820, 16502, 31864, 5071, 18148, 28872, 24156,
+ 30162, 26896, 5101, 12608, 15479, 31344, 17947, 9483, 2646, 15440,
+ 2113, 10369, 32375, 20391, 15692, 369, 15288, 12013, 3235, 13616,
+ 32622, 31278, 19955, 21831, 2895, 18781, 25138, 1129, 26256, 30954,
+ 7646, 18344, 14922, 9366, 10374, 30696, 19746, 17543, 30092, 26515,
+ 25129, 8343, 14889, 4238, 32513, 3570, 1201, 24172, 23874, 10976,
+ 22809, 26850, 2843, 3295, 30390, 12923, 32573, 5365, 11079, 16269,
+ 9204, 24132, 22326, 6508, 7575, 31455, 1819, 4573, 20515, 29404,
+ 18050, 23246, 26659, 14763, 4078, 17988, 27347, 3494, 32286, 17044,
+ 4484, 30184, 8846, 26326, 29762, 21091, 9537, 9111, 18357, 12845,
+ 4542, 27598, 12869, 25627, 30041, 27153, 31873, 30097, 12979, 5641,
+ 8386, 5016, 11908, 15908, 32267, 561, 14744, 22921, 12852, 7658,
+ 23576, 13905, 24392, 7086, 26123, 22516, 24619, 31457, 26908, 6657,
+ 12416, 23981, 32670, 27411, 3017, 15254, 1229, 13312, 2000, 8789,
+ 8791, 16211, 11847, 30947, 22299, 13565, 22955, 30932, 23344, 32327,
+ 22894, 20966, 1321, 9739, 8532, 11226, 5271, 2340, 2078, 31362,
+ 1488, 27427, 22886, 22556, 21231, 17219, 16074, 23006, 17948, 21920,
+ 17484, 4818, 16654, 27811, 31737, 14564, 7629, 18113, 1225, 8250,
+ 3261, 3173, 30919, 195, 5080, 25130, 1649, 14867, 4923, 27470,
+ 14690, 2414, 29412, 20580, 13870, 26146, 23994, 7752, 28046, 30746,
+ 11725, 4440, 2749, 23729, 28128, 8417, 8481, 11716, 5157, 24280,
+ 23854, 32523, 23111, 32715, 15496, 17833, 22189, 7958, 4455, 24065,
+ 15102, 4954, 21824, 9164, 23520, 26411, 3746, 20584, 26118, 18953,
+ 20062, 4979, 25705, 3474, 2026, 6553, 31701, 757, 18695, 30122,
+ 32680, 19626, 5282, 8176, 17367, 30817, 25848, 32703, 20529, 30008,
+ 6398, 13133, 22760, 14896, 20736, 2500, 8269, 12514, 32392, 25494,
+ 9691, 14446, 11137, 27921, 18039, 21685, 15516, 26419, 12790, 24008,
+ 13043, 29375, 23008, 17311, 12525, 4496, 15731, 14863, 18017, 21038,
+ 14059, 24822, 18430, 22943, 11777, 15545, 13802, 16256, 21426, 4848,
+ 30121, 28756, 19265, 32607, 25409, 2587, 25727, 21801, 32155, 26407,
+ 19274, 8256, 12845, 19243, 20564, 23328, 3030, 26261, 12070, 11453,
+ 18697, 9245, 30052, 17081, 7470, 29854, 28498, 7131, 8517, 3365,
+ 15767, 22205, 14285, 19272, 30785, 22724, 26596, 13242, 778, 24917,
+ 29615, 16156, 30425, 23878, 11772, 26901, 17548, 3731, 21286, 13732,
+ 29941, 23635, 26937, 8373, 10786, 24298, 27479, 11251, 17890, 31871,
+ 17499, 32478, 22916, 10673, 23739, 19741, 17122, 8837, 16307, 30485,
+ 6815, 12195, 7072, 6330, 22444, 19395, 8618, 31397, 19473, 15714,
+ 2213, 6504, 24298, 30905, 14137, 14110, 10159, 24047, 22849, 11078,
+ 20153, 10126, 25714, 25809, 22274, 7476, 20541, 21113, 13613, 24203,
+ 1270, 9557, 22470, 23162, 17973, 8618, 1226, 18077, 7293, 29189,
+ 12394, 10995, 539, 12422, 12556, 21975, 22353, 6783, 29843, 19506,
+ 25012, 8766, 6880, 2542, 23251, 21286, 6552, 9902, 21017, 15365,
+ 19752, 12988, 26101, 21409, 6919, 24642, 6199, 2964, 2363, 19646,
+ 16830, 1370, 28447, 32432, 26960, 7593, 9059, 27541, 457, 16896,
+ 19284, 6681, 21368, 17539, 12126, 13449, 5318, 8710, 14543, 8071,
+ 30232, 28264, 31965, 26881, 9463, 23330, 30955, 9060, 2671, 3103,
+ 25608, 268, 18612, 11983, 14777, 17408, 15372, 1911, 25080, 21980,
+ 744, 26827, 6780, 7182, 20820, 18878, 1339, 23621, 5010, 28057,
+ 46, 17703, 9218, 21066, 10836, 28483, 6214, 22783, 14841, 27206,
+ 27042, 23796, 2104, 10865, 31913, 11401, 30143, 27210, 19478, 6296,
+ 3282, 21650, 15096, 3589, 1171, 2680, 21010, 28055, 2432, 23052,
+ 27777, 5638, 28477, 14582, 6047, 21589, 12180, 22376, 10792, 11873,
+ 23226, 24401, 22171, 15291, 23763, 13268, 15587, 179, 15545, 17656,
+ 16183, 32693, 14329, 19361, 7743, 29913, 24607, 447, 8312, 28597,
+ 7476, 10949, 18649, 16246, 14724, 93, 24759, 25903, 23205, 22361,
+ 22758, 112, 2996, 4333, 17953, 27163, 15586, 11292, 31915, 29043,
+ 23599, 2929, 3895, 28534, 27510, 17135, 13574, 9325, 14250, 586,
+ 23375, 5057, 5471, 28504, 26083, 21008, 18060, 1218, 25361, 31104,
+ 28047, 18687, 14023, 14419, 12657, 29059, 251, 11708, 30572, 17971,
+ 17225, 2289, 21930, 22813, 2526, 7810, 9040, 26214, 7060, 26601,
+ 18875, 28803, 30046, 8546, 15113, 27820, 5351, 31229, 12764, 5006,
+ 22134, 2545, 7770, 10817, 27157, 819, 25721, 22393, 9202, 20551,
+ 20345, 22784, 11269, 5463, 24242, 11620, 20723, 18306, 20367, 1517,
+ 563, 20086, 2267, 5329, 13679, 25665, 19259, 2987, 15149, 10084,
+ 19196, 24106, 18094, 4905, 5903, 7430, 11542, 21047, 29010, 32057,
+ 8142, 8036, 31762, 24427, 26151, 10442, 24781, 27566, 23104, 10525,
+ 21564, 5483, 11561, 11068, 7056, 7068, 13896, 11269, 30461, 22844,
+ 20988, 3694, 5493, 31228, 4993, 5585, 30134, 26424, 19988, 23176,
+ 22662, 297, 14679, 27834, 10301, 30812, 13558, 6516, 31109, 23395,
+ 28555, 1532, 2398, 11466, 29887, 5474, 23653, 5453, 26290, 19543,
+ 25429, 1607, 26270, 10050, 18638, 24686, 28855, 5777, 19541, 29374,
+ 12117, 5453, 20125, 26035, 2388, 3570, 29444, 26299, 28603, 381,
+ 31329, 10219, 11933, 9414, 15101, 2033, 17725, 26640, 23007, 30282,
+ 2421, 7391, 10573, 26549, 6745, 11786, 20623, 28391, 26135, 7696,
+ 8438, 19840, 18210, 16303, 15389, 4414, 31887, 23731, 28527, 4464,
+ 447, 16141, 26857, 24750, 2366, 20516, 10529, 1736, 7915, 17008,
+ 22152, 5884, 13657, 31044, 21996, 30316, 8822, 8939, 19521, 26319,
+ 20330, 14583, 28064, 10598, 8130, 23254, 15760, 20017, 21454, 13990,
+ 9349, 868, 27207, 29770, 32422, 30997, 17717, 22206, 2003, 11575,
+ 5648, 1959, 18663, 13259, 21798, 16687, 27194, 20309, 18492, 18959,
+ 3947, 28045, 23672, 30701, 8284, 23640, 22399, 11241, 9085, 19190,
+ 9178, 32115, 3406, 27517, 15518, 1887, 10527, 18566, 31820, 2875,
+ 32538, 8998, 21238, 24288, 23428, 27936, 10147, 22599, 23360, 13144,
+ 26869, 11166, 8597, 3211, 4361, 28571, 6961, 24638, 8351, 15377,
+ 29293, 6644, 21883, 5825, 6354, 7332, 8203, 8818, 2524, 2666,
+ 7241, 17476, 11007, 13437, 4579, 13121, 27880, 18273, 16281, 9781,
+ 4613, 1886, 30183, 5055, 15943, 12592, 17637, 14505, 13351, 21248,
+ 16747, 22645, 25319, 12691, 9592, 27704, 10778, 3522, 20437, 13228,
+ 30310, 24106, 26357, 23680, 7049, 20772, 8992, 13298, 3994, 11000,
+ 977, 5792, 27537, 21581, 29788, 4763, 21770, 11492, 9171, 28606,
+ 13638, 30342, 5163, 4670, 24947, 27707, 9371, 27521, 6189, 22973,
+ 6981, 27956, 30788, 18220, 29208, 12952, 21696, 3331, 27381, 21532,
+ 2594, 25675, 12048, 6449, 14573, 18191, 32154, 31834, 2405, 13583,
+ 11677, 13698, 23703, 12472, 1831, 16019, 3737, 2132, 14250, 1604,
+ 11795, 16255, 26019, 17715, 19710, 11482, 10106, 10547, 20140, 8195,
+ 25001, 19175, 22281, 9156, 20513, 8592, 16160, 12426, 16105, 26915,
+ 13025, 25369, 13833, 11935, 23585, 2943, 7334, 30365, 16098, 10310,
+ 5998, 12840, 10965, 8686, 9783, 30160, 26141, 23195, 17634, 9978,
+ 30038, 26122, 4998, 4986, 9430, 32201, 18891, 10084, 14130, 1448,
+ 31123, 13598, 23812, 13419, 25824, 954, 23020, 13505, 27378, 6019,
+ 31445, 21114, 20655, 26838, 16762, 2036, 26696, 32052, 26920, 32726,
+ 23578, 5780, 10437, 24321, 8402, 27902, 22033, 27332, 21205, 9813,
+ 20012, 24399, 735, 117, 18265, 2667, 13801, 24958, 28673, 32360,
+ 7249, 17006, 32507, 29014, 17461, 10230, 6410, 7288, 19231, 7558,
+ 12199, 12277, 21224, 26283, 15617, 11985, 15830, 23194, 323, 18204,
+ 30216, 7693, 9493, 31337, 17428, 12109, 25957, 10882, 30958, 30864,
+ 11367, 24154, 28428, 23686, 15322, 21315, 9927, 28975, 19598, 11873,
+ 517, 23791, 18211, 25183, 25365, 2532, 31251, 7520, 13018, 9079,
+ 28915, 21305, 4652, 4657, 20725, 14301, 14971, 27089, 24242, 15896,
+ 20917, 32155, 4390, 28289, 13674, 3826, 22012, 10922, 303, 18985,
+ 27404, 12441, 21568, 1431, 28963, 29308, 6761, 30441, 7170, 5784,
+ 23590, 21180, 9129, 13187, 23049, 2668, 23253, 7315, 30556, 7206,
+ 3783, 21142, 14344, 10565, 5191, 27843, 21941, 18139, 9705, 3569,
+ 12339, 15501, 30607, 14855, 7448, 9637, 9007, 8116, 23211, 10338,
+ 21206, 10848, 10753, 14226, 19437, 28770, 21606, 4707, 16316, 20851,
+ 8191, 30327, 1324, 22882, 30637, 14390, 8145, 15114, 18995, 13672,
+ 14375, 30594, 25756, 22019, 26908, 1427, 19415, 3905, 1743, 3439,
+ 22949, 7414, 17048, 3231, 8373, 25889, 20552, 30270, 23564, 14785,
+ 28850, 9061, 28075, 27882, 1386, 10214, 12396, 27415, 4556, 24381,
+ 8494, 20418, 19776, 17859, 9009, 10290, 10941, 29221, 25539, 22677,
+ 31116, 17173, 8477, 22350, 847, 5439, 22664, 12944, 19265, 5503,
+ 8132, 5164, 21183, 849, 11689, 14247, 1800, 30601, 22031, 1680,
+ 15425, 836, 31980, 20240, 22972, 15134, 17596, 18627, 7033, 677,
+ 31782, 23494, 3309, 11278, 3804, 24082, 8451, 16423, 32195, 15112,
+ 2913, 653, 8788, 14668, 16108, 1567, 16706, 21207, 13710, 26034,
+ 12380, 21320, 25911, 29959, 5046, 12411, 1569, 32250, 30211, 20829,
+ 3673, 24059, 16454, 14079, 1659, 6082, 21674, 15337, 7100, 11583,
+ 20653, 23984, 4910, 21968, 14980, 17611, 576, 25783, 7611, 32418,
+ 28804, 29643, 23325, 7656, 18102, 9837, 12243, 13611, 12025, 6334,
+ 14288, 24489, 19043, 20240, 28524, 19558, 24508, 14746, 30798, 32635,
+ 26499, 8303, 9616, 15793, 6450, 2993, 4894, 22094, 24004, 31745,
+ 19551, 16175, 19315, 1851, 17944, 14103, 3782, 11616, 12173, 25159,
+ 25803, 31188, 24297, 5455, 2721, 17610, 23775, 16931, 17978, 10492,
+ 21394, 15217, 27743, 415, 25778, 16946, 2037, 1174, 10984, 4480,
+ 1662, 19686, 27253, 23719, 3555, 26986, 13590, 29566, 24432, 17352,
+ 1322, 248, 27680, 29603, 5142, 6134, 32283, 21010, 28649, 607,
+ 7037, 24913, 5180, 1651, 1625, 23735, 2653, 5724, 32254, 1256,
+ 21676, 7686, 9592, 31820, 10564, 25393, 13146, 18368, 16350, 11205,
+ 20155, 18315, 14067, 7781, 15743, 15507, 21537, 4422, 18392, 11729,
+ 9168, 15170, 29963, 16898, 15381, 31528, 1400, 24991, 9943, 10583,
+ 19925, 13584, 14128, 10123, 22458, 21277, 19989, 8950, 27490, 13221,
+ 21050, 15507, 26288, 14994, 24368, 2999, 1392, 28428, 28624, 12009,
+ 32480, 13037, 2013, 24307, 7278, 3701, 8421, 14393, 11716, 25664,
+ 24168, 11850, 32258, 8564, 19773, 23989, 11850, 15935, 12848, 12318,
+ 6530, 8833, 11248, 1680, 9557, 17093, 11305, 24085, 9339, 2422,
+ 3053, 8836, 11835, 24656, 16216, 9115, 3886, 28180, 27764, 24653,
+ 14149, 23680, 26970, 7261, 18701, 14974, 26010, 29740, 11826, 20124,
+ 17117, 25296, 21827, 28092, 24777, 28261, 31924, 10764, 24613, 28328,
+ 12073, 28217, 8510, 8642, 21746, 22752, 393, 865, 32465, 27718,
+ 7305, 6669, 19972, 26184, 5107, 11962, 7551, 21653, 8977, 8857,
+ 20602, 14618, 356, 22324, 27179, 21182, 22669, 23738, 21205, 24144,
+ 20846, 23191, 28161, 25533, 31884, 26184, 26123, 25479, 6583, 15470,
+ 20705, 30834, 750, 4129, 4616, 16769, 15997, 25734, 7648, 10272,
+ 31848, 9380, 552, 22179, 780, 28019, 22468, 29423, 20228, 15926,
+ 446, 29047, 27210, 779, 23948, 5227, 16030, 11713, 18577, 27435,
+ 26412, 20713, 7910, 26114, 17769, 28976, 5977, 21009, 23870, 236,
+ 8374, 20873, 15464, 14836, 9286, 9246, 28959, 18869, 20886, 21432,
+ 21493, 898, 22393, 6507, 10498, 3372, 11856, 3753, 23614, 14803,
+ 22409, 32438, 23854, 1787, 13926, 27741, 24003, 28642, 26112, 8162,
+ 30847, 2834, 12427, 20791, 473, 9778, 3035, 17010, 2275, 21537,
+ 16167, 24191, 19242, 8518, 5646, 12306, 8157, 25121, 17623, 17632,
+ 7730, 20518, 25085, 20751, 774, 26828, 6379, 9963, 6596, 17121,
+ 31236, 22234, 11399, 20000, 3046, 2962, 16259, 12549, 496, 30345,
+ 7073, 14560, 15362, 24749, 27753, 4137, 29571, 13142, 29989, 12051,
+ 14761, 3449, 8515, 14947, 10996, 14622, 29692, 17539, 31740, 5396,
+ 6963, 9426, 17261, 18147, 10656, 22847, 9552, 18690, 15405, 9750,
+ 17292, 10570, 3744, 26649, 6060, 2987, 17275, 19667, 6626, 17694,
+ 25376, 25897, 22860, 8922, 22073, 17970, 26999, 12747, 24407, 11337,
+ 18722, 6720, 22489, 21600, 9796, 25572, 13328, 32663, 9040, 13807,
+ 4769, 21773, 439, 26525, 23338, 5621, 21934, 29920, 12328, 22509,
+ 10035, 11089, 14360, 14732, 9290, 9069, 476, 17722, 18573, 23038,
+ 2145, 30277, 7651, 32215, 6527, 5169, 31376, 17860, 9248, 22607,
+ 24686, 25281, 12709, 4497, 24953, 25194, 3717, 15004, 11665, 5555,
+ 26167, 13855, 11644, 20441, 22099, 9571, 20267, 4505, 15604, 3364,
+ 26430, 29855, 18016, 15520, 19402, 27457, 32235, 10989, 3161, 10349,
+ 26136, 16015, 27442, 17376, 23554, 13130, 31707, 28313, 18938, 4661,
+ 2781, 19342, 28018, 28688, 12999, 16541, 13338, 26071, 17013, 21445,
+ 29768, 30615, 22674, 26774, 1181, 23937, 22620, 29158, 30438, 25405,
+ 7079, 27590, 31296, 20865, 1573, 12725, 10368, 5601, 24036, 1299,
+ 17105, 7401, 3352, 22488, 8607, 4713, 12571, 12165, 23476, 31760,
+ 6834, 13403, 26785, 25148, 9106, 16587, 16992, 31505, 32035, 1327,
+ 18999, 3017, 23683, 5047, 29919, 29770, 10190, 26790, 486, 6398,
+ 2205, 17086, 16978, 7903, 1996, 24568, 12935, 11729, 5761, 29305,
+ 27499, 11573, 10345, 25026, 11975, 11963, 17221, 11303, 4849, 31607,
+ 10150, 31874, 4520, 30520, 30452, 18472, 32319, 19989, 31413, 2332,
+ 9982, 8264, 28940, 26755, 9669, 8256, 640, 27992, 9202, 22257,
+ 17663, 865, 5509, 623, 28707, 28258, 12162, 17083, 9908, 32144,
+ 7575, 2268, 31085, 4936, 15103, 31794, 1795, 21761, 21158, 18952,
+ 23907, 6016, 10894, 4968, 59, 23371, 24177, 27955, 14525, 27999,
+ 19880, 9841, 4768, 37, 8267, 18661, 10855, 20643, 10138, 2020,
+ 12517, 11247, 7579, 4456, 18433, 26858, 2053, 30049, 7351, 10794,
+ 16989, 5963, 25183, 31800, 29535, 24069, 4914, 9212, 29087, 5601,
+ 6666, 12661, 23408, 14584, 18793, 10926, 26117, 4544, 17341, 25325,
+ 10198, 27616, 14562, 21037, 25157, 18242, 7401, 206, 3714, 16746,
+ 15384, 23436, 12716, 10503, 20529, 942, 15417, 28616, 31480, 28543,
+ 30871, 28273, 18927, 28418, 19731, 12078, 10084, 26850, 21755, 12839,
+ 23725, 25512, 5375, 24660, 2483, 12080, 20189, 8339, 13741, 16990,
+ 14398, 17144, 23854, 8461, 6362, 13924, 8546, 24136, 5091, 15449,
+ 31892, 3773, 8353, 3852, 8180, 16238, 30298, 11708, 24216, 17578,
+ 28532, 17219, 18880, 30012, 10205, 23275, 25182, 9698, 23211, 22402,
+ 982, 30977, 17152, 24753, 27650, 22166, 1073, 14985, 1145, 8304,
+ 23847, 15199, 20753, 30365, 11013, 21466, 10146, 8226, 32522, 23882,
+ 5389, 27631, 19386, 8763, 4989, 7697, 27960, 21835, 30189, 15658,
+ 4343, 27192, 11499, 21534, 16529, 1341, 18587, 31760, 5111, 29855,
+ 23550, 17037, 20171, 26755, 9588, 16390, 27914, 23810, 8320, 29316,
+ 25326, 27263, 25804, 12439, 5139, 28728, 30317, 18575, 17880, 19740,
+ 27495, 8175, 4360, 6877, 2676, 26399, 5818, 8005, 18177, 13665,
+ 31861, 26573, 15994, 8454, 29592, 17260, 6855, 10210, 20473, 3757,
+ 32279, 31741, 29133, 1540, 23516, 2187, 1736, 4706, 25366, 17183,
+ 26245, 17415, 24021, 7451, 3623, 28568, 10745, 10603, 32577, 8561,
+ 12093, 19059, 1523, 23356, 30324, 31813, 10838, 20418, 17938, 3864,
+ 20762, 4354, 26605, 26102, 20334, 25728, 31813, 3508, 30240, 12768,
+ 32258, 16423, 22534, 16307, 23614, 10133, 20380, 12945, 19715, 30314,
+ 2030, 616, 15702, 10028, 3257, 23059, 628, 30897, 9677, 5423,
+ 12379, 31376, 437, 20522, 14732, 15829, 29594, 16028, 15376, 32249,
+ 18533, 15323, 8121, 22033, 30500, 18890, 27050, 22085, 12463, 29169,
+ 26905, 3460, 4747, 15571, 8532, 23414, 270, 13179, 5378, 7858,
+ 27844, 8025, 22188, 4914, 1810, 31820, 636, 29955, 10777, 20736,
+ 1348, 15169, 30685, 24954, 21697, 32579, 29863, 28657, 32034, 25619,
+ 8360, 32736, 10180, 4641, 21726, 20313, 32576, 6968, 26428, 31388,
+ 5287, 23216, 23045, 32232, 10764, 9702, 6777, 2449, 1603, 24809,
+ 4787, 23635, 13801, 19318, 4818, 6118, 23972, 6695, 21847, 17362,
+ 428, 12263, 8910, 29317, 26251, 2985, 22705, 15523, 28449, 15962,
+ 22409, 1693, 7146, 32019, 7254, 17541, 3972, 9108, 2353, 12321,
+ 15467, 15086, 8496, 9534, 8200, 22655, 15242, 6214, 12010, 26915,
+ 29179, 23317, 22099, 15529, 20074, 9225, 14070, 25988, 31690, 2904,
+ 31999, 16579, 32318, 29351, 31060, 14916, 13952, 2776, 24602, 8484,
+ 13443, 27683, 20604, 8313, 7511, 29800, 2471, 12356, 10318, 24515,
+ 28953, 4769, 30557, 20322, 19996, 12609, 20164, 12947, 24205, 28442,
+ 28657, 17953, 10466, 16989, 7074, 7649, 12140, 10921, 32587, 27784,
+ 26840, 22398, 4535, 32191, 8700, 4852, 8945, 5754, 11473, 17581,
+ 9061, 12165, 187, 8456, 26179, 15967, 12305, 22679, 25380, 76,
+ 22233, 23508, 15088, 31654, 26323, 1807, 1023, 11124, 29882, 19115,
+ 8574, 2366, 27334, 9098, 10773, 26911, 17525, 30662, 8646, 23579,
+ 14219, 11170, 2841, 3251, 28247, 704, 4982, 18871, 14137, 8596,
+ 24274, 13148, 19809, 17176, 13966, 16014, 7897, 30401, 8091, 647,
+ 13254, 31410, 7139, 1185, 6891, 1585, 6884, 30312, 32622, 6231,
+ 23966, 6644, 19423, 7947, 20912, 16502, 32374, 2609, 10174, 5904,
+ 4764, 7966, 10517, 13802, 9133, 8271, 4242, 9602, 11517, 7515,
+ 27328, 20035, 2841, 32551, 16704, 1626, 8783, 9305, 5486, 12741,
+ 20080, 8719, 28225, 10412, 32724, 31952, 32115, 22517, 10655, 28099,
+ 8162, 20499, 25923, 2078, 15671, 13854, 28486, 21218, 19141, 19241,
+ 24902, 10950, 30132, 32208, 19770, 112, 14430, 14864, 7674, 18155,
+ 24313, 27484, 24834, 9814, 16247, 25836, 23922, 18137, 10410, 9305,
+ 7258, 18398, 19628, 8807, 17973, 14205, 10878, 9761, 31155, 7735,
+ 15087, 20012, 32700, 29416, 25791, 17493, 177, 2807, 31749, 20332,
+ 7925, 23248, 20686, 14165, 6828, 6804, 4359, 12124, 25282, 8974,
+ 413, 15049, 14127, 5866, 21218, 16308, 16506, 11297, 5171, 15387,
+ 16508, 10680, 2776, 20786, 16487, 28074, 28715, 6394, 24583, 3875,
+ 23292, 31253, 10823, 28910, 22581, 28121, 4854, 22577, 30394, 27811,
+ 459, 23384, 19091, 29806, 3751, 15695, 11085, 23972, 21275, 2292,
+ 12701, 29235, 29994, 204, 14407, 31460, 20304, 14068, 25662, 14057,
+ 22979, 24923, 30733, 29108, 14584, 15919, 30325, 11024, 5481, 7317,
+ 22616, 1386, 8342, 23965, 22998, 28271, 27465, 373, 8885, 13789,
+ 28959, 5341, 19974, 1682, 32068, 4826, 5381, 30186, 19582, 3759,
+ 8514, 7495, 4205, 14857, 18942, 29169, 14353, 7034, 16600, 20257,
+ 8588, 2344, 29097, 26200, 6441, 15303, 6572, 2549, 18846, 3524,
+ 23010, 1543, 398, 15043, 18612, 31584, 29266, 13132, 18139, 28907,
+ 19449, 22721, 7037, 3903, 23181, 13716, 7064, 14963, 2200, 1462,
+ 24740, 32308, 27367, 9043, 21108, 22, 14734, 11196, 2142, 27688,
+ 23085, 28837, 17819, 4043, 24433, 2448, 5360, 5828, 8669, 6537,
+ 18318, 7823, 21962, 7444, 23352, 5110, 17068, 21604, 2979, 3811,
+ 32664, 7629, 4898, 8307, 22787, 21628, 24195, 18251, 17357, 1894,
+ 14387, 32303, 382, 7294, 11945, 6353, 22991, 13355, 14850, 25318,
+ 3436, 24825, 25833, 13695, 26104, 1935, 31930, 30359, 1873, 31457,
+ 3303, 14056, 26134, 10406, 10650, 25092, 1895, 27149, 19868, 13472,
+ 28140, 19627, 20341, 27955, 22553, 26552, 12757, 27328, 13232, 4476,
+ 21298, 11759, 27271, 2308, 16563, 28771, 27787, 26649, 12365, 17992,
+ 6917, 29043, 26156, 32299, 31004, 3881, 2388, 13071, 17819, 5484,
+ 11144, 17597, 25077, 7541, 2154, 10843, 10887, 3260, 16357, 21312,
+ 9244, 7275, 4040, 2567, 8886, 29970, 20659, 3554, 19852, 12956,
+ 14903, 22065, 9295, 25730, 12857, 13396, 27057, 24126, 11159, 18365,
+ 5928, 27651, 22543, 30793, 15855, 16299, 12636, 27344, 31055, 10737,
+ 7585, 9211, 22044, 29664, 13067, 19797, 21378, 27787, 24242, 20645,
+ 24834, 32511, 29377, 15740, 32183, 25718, 24535, 11530, 23774, 18125,
+ 7597, 6197, 13205, 26424, 1784, 21485, 5091, 7477, 11409, 10169,
+ 30969, 16830, 25555, 12950, 26807, 23235, 5188, 4610, 20082, 6871,
+ 2168, 32596, 29429, 2346, 17971, 22350, 13765, 26039, 12750, 16373,
+ 27562, 7614, 220, 24736, 1642, 25717, 16397, 24656, 27096, 17403,
+ 28754, 7743, 4621, 14989, 32577, 22716, 28406, 14332, 7868, 13877,
+ 6415, 3934, 16333, 25750, 17261, 12548, 13525, 17106, 3842, 16557,
+ 16102, 18622, 8989, 23545, 2669, 8486, 12080, 9505, 24340, 10779,
+ 14806, 26084, 1766, 20362, 24852, 24261, 12468, 29715, 28639, 5747,
+ 20920, 23575, 27871, 15753, 19065, 20243, 1651, 31351, 21230, 25389,
+ 32757, 12736, 29158, 9997, 1087, 7783, 936, 7662, 366, 20131,
+ 5078, 16885, 29158, 22746, 3735, 193, 13974, 23757, 3316, 26179,
+ 26237, 9489, 16515, 27088, 14188, 31934, 16963, 4468, 25614, 3435,
+ 18632, 24458, 13095, 22873, 2456, 16009, 1049, 9710, 18900, 24353,
+ 1196, 27237, 25115, 15495, 29710, 5829, 14763, 15117, 5913, 18191,
+ 31945, 5365, 16853, 14012, 4708, 2439, 6718, 2150, 5365, 609,
+ 30791, 13766, 21161, 8975, 1822, 15326, 6338, 30427, 2994, 22391,
+ 20026, 12518, 29811, 26062, 8618, 12920, 5720, 15755, 20075, 19349,
+ 15143, 5106, 15611, 27089, 25841, 16989, 674, 10597, 27355, 32746,
+ 1109, 31873, 21285, 25457, 16602, 23780, 3684, 16825, 1581, 15275,
+ 30738, 15339, 5667, 9062, 16457, 4678, 32333, 16497, 8908, 3861,
+ 10015, 17282, 3911, 7646, 24145, 21118, 9944, 25309, 24710, 31633,
+ 13005, 26288, 9772, 24189, 30896, 10836, 30627, 50, 3969, 14160,
+ 3233, 31904, 6722, 48, 15061, 2761, 3001, 9525, 30666, 1818,
+ 22385, 29003, 12815, 30715, 13314, 9019, 17813, 16549, 21138, 22306,
+ 3928, 30259, 12188, 9250, 25665, 2812, 24816, 16983, 28491, 17441,
+ 1275, 19725, 15078, 11618, 14153, 30000, 27033, 32566, 11848, 14339,
+ 25066, 11034, 26191, 28181, 29058, 553, 32222, 18034, 11149, 10733,
+ 10024, 534, 1632, 21365, 21198, 935, 31838, 26791, 30702, 1891,
+ 13340, 9176, 7516, 5975, 29635, 17818, 2095, 4049, 25526, 23765,
+ 13184, 18457, 25717, 21786, 30062, 13148, 31682, 16179, 30053, 3561,
+ 7426, 2047, 22433, 27296, 20709, 4477, 16877, 13478, 73, 25126,
+ 7601, 31070, 26204, 24192, 15147, 3733, 28161, 16624, 14845, 26877,
+ 32374, 17359, 23272, 14045, 31539, 12737, 7895, 4870, 31509, 20546,
+ 22303, 25609, 31419, 22658, 2821, 15271, 3633, 29299, 22145, 19081,
+ 21963, 26144, 9793, 15410, 14932, 30528, 29937, 3889, 13416, 7947,
+ 28090, 15771, 8991, 6220, 6152, 18872, 30188, 29112, 28817, 765,
+ 11716, 6782, 5011, 5946, 31106, 7455, 23644, 17429, 29066, 31872,
+ 7696, 15543, 13996, 26430, 22951, 6085, 30796, 13633, 5429, 22930,
+ 9664, 25492, 14446, 28307, 20218, 627, 4713, 10771, 30823, 18854,
+ 27812, 7463, 26134, 18190, 20297, 23013, 8733, 23422, 23215, 30417,
+ 16953, 31180, 23076, 26264, 12468, 23591, 29674, 30721, 31884, 9130,
+ 6783, 4640, 29905, 5682, 8993, 205, 4943, 28269, 9618, 25940,
+ 31341, 29236, 2329, 8046, 2645, 17179, 25289, 17008, 20821, 7494,
+ 2309, 27331, 23429, 30846, 68, 1940, 9643, 16259, 9490, 27852,
+ 14171, 4516, 14168, 16707, 10339, 17038, 10972, 7472, 5478, 3170,
+ 24843, 27877, 18374, 10250, 12279, 27577, 5319, 16332, 23196, 19269,
+ 14322, 28703, 24167, 23251, 11448, 19134, 14841, 17171, 19288, 4092,
+ 4392, 10768, 11523, 4695, 21062, 21347, 6973, 30799, 16550, 4262,
+ 3718, 20601, 2141, 5676, 58, 11215, 16198, 2031, 5046, 12874,
+ 30537, 21194, 23228, 26035, 17884, 9705, 14617, 1718, 25801, 8317,
+ 11140, 20536, 20530, 1972, 30154, 31978, 1491, 6376, 31784, 19230,
+ 18824, 19479, 19448, 29402, 4879, 6803, 6033, 16939, 2318, 7674,
+ 10600, 21436, 11608, 7017, 4731, 5031, 7788, 20205, 6127, 1675,
+ 4671, 2874, 9207, 1759, 28219, 416, 15865, 27782, 8327, 17978,
+ 19948, 21155, 7817, 25705, 12037, 28590, 11433, 6016, 21906, 13256,
+ 21336, 31681, 3110, 8523, 9553, 19337, 3062, 5030, 15135, 31943,
+ 29827, 26728, 2016, 21170, 26233, 16026, 27464, 14268, 17879, 16466,
+ 9449, 29633, 26449, 10885, 3249, 4741, 11507, 1821, 13492, 3677,
+ 22022, 19787, 22571, 4908, 1591, 23583, 15293, 28049, 18422, 854,
+ 25342, 31327, 3613, 3699, 16182, 10830, 30930, 1553, 15203, 28144,
+ 25006, 7031, 18817, 7654, 29471, 29293, 21768, 13139, 20234, 15694,
+ 16055, 25745, 2229, 24415, 17808, 31267, 30181, 2399, 292, 28651,
+ 6979, 1119, 20752, 13981, 14340, 7892, 26056, 10612, 13513, 28651,
+ 18067, 3108, 31172, 25884, 30935, 9487, 28701, 19970, 11415, 18363,
+ 12948, 23146, 4666, 25476, 12647, 16042, 15758, 27278, 19830, 29236,
+ 14860, 9470, 11941, 15466, 13406, 17514, 22914, 948, 23838, 19341,
+ 18472, 4816, 26849, 7744, 2659, 18538, 20852, 19878, 12564, 25837,
+ 15461, 29862, 2263, 27288, 10949, 14494, 26596, 17364, 22061, 16981,
+ 4915, 9157, 24319, 17202, 32484, 21791, 12270, 23212, 28125, 27451,
+ 15041, 28674, 13493, 2410, 29267, 21548, 9169, 13449, 9695, 16401,
+ 23756, 25301, 8570, 762, 5916, 15873, 14305, 30023, 6131, 19334,
+ 6517, 865, 24932, 28475, 7300, 25839, 23751, 31781, 23242, 21581,
+ 1118, 18320, 18488, 23097, 20537, 29278, 9972, 464, 27222, 23712,
+ 31904, 2234, 28173, 30563, 27871, 24481, 13995, 26828, 7445, 3815,
+ 350, 13928, 1391, 21400, 26193, 27069, 21284, 2205, 27927, 25381,
+ 16378, 12339, 16461, 20188, 779, 12700, 17531, 28759, 16073, 7956,
+ 5692, 14295, 4160, 6151, 13215, 22079, 9115, 7041, 21708, 17186,
+ 29162, 24294, 14315, 26913, 3106, 31971, 25665, 27764, 5989, 4260,
+ 10396, 16326, 24196, 4424, 22770, 31558, 7363, 402, 3909, 10747,
+ 26076, 18401, 29641, 343, 20294, 16994, 20553, 14096, 16054, 27524,
+ 29383, 26923, 487, 8876, 9059, 19546, 5015, 27947, 12670, 5255,
+ 12754, 17261, 23582, 19377, 10610, 15986, 6548, 2807, 31463, 14722,
+ 605, 18930, 15412, 15389, 25415, 14408, 23610, 16434, 15060, 21886,
+ 11065, 10385, 9699, 15118, 19604, 31649, 32653, 19642, 30164, 13910,
+ 14414, 17183, 7920, 19294, 10341, 17549, 1996, 8859, 24957, 22,
+ 14079, 11478, 17292, 32485, 21977, 24498, 22780, 8146, 3493, 11742,
+ 15881, 28979, 18987, 20367, 5994, 23796, 1401, 28462, 23603, 23274,
+ 227, 3661, 30458, 7524, 3913, 14048, 568, 27651, 21656, 19626,
+ 9203, 8396, 7827, 4853, 19610, 31612, 15060, 14982, 23857, 16155,
+ 28173, 3024, 30893, 19924, 28820, 360, 1186, 14084, 5151, 26297,
+ 7451, 27537, 30412, 20217, 32713, 3197, 26468, 30812, 12897, 1979,
+ 24288, 28551, 26687, 30529, 13100, 1863, 27471, 30302, 26412, 30851,
+ 3117, 24910, 15357, 15983, 23947, 13068, 26493, 771, 16084, 30055,
+ 5133, 12204, 31246, 30552, 3477, 30273, 30981, 15763, 16329, 26168,
+ 21926, 24924, 27051, 25114, 18857, 20892, 10833, 2356, 16755, 10804,
+ 19177, 27024, 5690, 5521, 27130, 3619, 13162, 27776, 27629, 15688,
+ 11079, 2116, 21707, 31597, 32468, 31463, 28488, 9740, 7412, 8653,
+ 25857, 15070, 23760, 18063, 11266, 8011, 30584, 16902, 28043, 31780,
+ 17613, 21925, 18964, 404, 16286, 12044, 7822, 10068, 5393, 18907,
+ 12012, 15647, 17221, 9156, 23010, 24422, 2869, 30437, 14828, 9284,
+ 14816, 28244, 22419, 5300, 3239, 2299, 20716, 17922, 13558, 7846,
+ 6753, 10111, 16166, 15194, 15539, 22649, 24738, 17641, 13376, 6762,
+ 29001, 7875, 21890, 13168, 5140, 16399, 23257, 21757, 21241, 28666,
+ 32650, 23248, 12815, 7247, 19463, 30244, 32242, 32329, 30577, 6439,
+ 22889, 421, 603, 13997, 20038, 8698, 28369, 10790, 25998, 12877,
+ 14744, 23501, 2778, 17120, 30904, 29987, 16125, 6476, 17208, 14748,
+ 24039, 28367, 17961, 22424, 31690, 26855, 10982, 17812, 7547, 32,
+ 12953, 32674, 20506, 18730, 11009, 14614, 25589, 21550, 8307, 22147,
+ 20138, 5730, 28959, 17382, 30860, 4572, 9621, 31520, 31048, 12196,
+ 12936, 20138, 1993, 12, 2001, 19588, 8536, 21828, 4278, 19822,
+ 11272, 27689, 2413, 1115, 6225, 5982, 19932, 8739, 17915, 8350,
+ 1443, 24952, 12349, 21584, 20828, 3867, 9511, 27484, 23841, 25167,
+ 3133, 18238, 31823, 14735, 101, 13401, 12938, 3964, 16643, 9869,
+ 19970, 15385, 15970, 9227, 30452, 22074, 17750, 21096, 22643, 18746,
+ 3615, 23025, 18024, 29421, 12945, 4927, 1240, 24021, 20338, 13067,
+ 5221, 27545, 21796, 26691, 10264, 946, 19331, 8284, 10333, 6760,
+ 3345, 26091, 26447, 9213, 15697, 3439, 27190, 18472, 32368, 9329,
+ 27726, 27077, 10794, 22224, 32459, 22218, 4588, 15958, 27161, 13437,
+ 2614, 20622, 13416, 31716, 17732, 24282, 29032, 6781, 16621, 23744,
+ 16209, 2864, 19403, 24709, 5415, 31618, 26012, 4605, 17980, 20747,
+ 32488, 31649, 24310, 9002, 23525, 29154, 16082, 31991, 7831, 1213,
+ 5033, 31609, 15419, 12176, 6707, 7194, 25062, 15148, 18377, 20311,
+ 3178, 1579, 16751, 9148, 22393, 10116, 17425, 7440, 18445, 8028,
+ 25101, 3021, 5638, 2591, 14834, 30931, 14613, 2512, 2695, 31068,
+ 15578, 22941, 18448, 32563, 8265, 16311, 5836, 31009, 17490, 20832,
+ 20162, 22440, 11713, 15686, 27838, 18932, 7779, 4111, 5270, 18191,
+ 18794, 10037, 2225, 14164, 10002, 17940, 15050, 21030, 11141, 321,
+ 23026, 994, 25852, 29726, 468, 28689, 17704, 29867, 28477, 25571,
+ 6608, 14751, 24028, 19673, 30907, 9912, 29510, 1985, 8912, 13135,
+ 23356, 7143, 8828, 7983, 31025, 13962, 10580, 27047, 21255, 31373,
+ 28924, 16094, 6426, 30831, 9031, 20327, 28543, 25213, 3487, 17941,
+ 23694, 20806, 9128, 20497, 157, 11344, 5408, 27433, 31503, 2825,
+ 31498, 28267, 8334, 8704, 24587, 243, 26260, 4181, 10260, 29441,
+ 10288, 8559, 6977, 11599, 10247, 22252, 6145, 10913, 29593, 20190,
+ 12408, 12189, 3013, 23092, 14113, 13533, 30351, 22390, 32440, 14147,
+ 7714, 9654, 20823, 25228, 8465, 17347, 25311, 18984, 30690, 28575,
+ 17049, 9289, 5069, 23091, 4125, 15163, 23233, 17218, 30579, 2291,
+ 9384, 4508, 14457, 12522, 7660, 15252, 15748, 19500, 13114, 5043,
+ 1354, 15275, 27270, 19886, 25600, 29914, 19791, 20374, 24511, 31863,
+ 18468, 9039, 11308, 936, 9063, 7235, 2392, 23370, 31057, 1367,
+ 2533, 12678, 19766, 27423, 1131, 19877, 10250, 22093, 13337, 15909,
+ 24101, 2672, 19616, 11532, 25155, 7387, 1356, 20092, 18895, 30690,
+ 24436, 7560, 26209, 7757, 11285, 23366, 6277, 17158, 5306, 1061,
+ 16318, 2325, 11167, 12161, 27594, 32718, 18197, 3445, 13096, 12105,
+ 11304, 30449, 21208, 18707, 19584, 17420, 31586, 20771, 7045, 23707,
+ 28441, 21264, 16071, 14082, 21921, 30593, 7580, 14666, 26799, 3556,
+ 5131, 12404, 24080, 24163, 19688, 21005, 13037, 22547, 1857, 31747,
+ 15437, 28527, 19193, 9911, 8411, 16646, 20659, 15699, 8170, 19568,
+ 8433, 20574, 18870, 23430, 11901, 22158, 3308, 27091, 28681, 28637,
+ 15725, 8261, 15634, 24286, 30799, 14632, 29194, 11346, 2341, 24661,
+ 8117, 10487, 13441, 25511, 18900, 16800, 2999, 18351, 30977, 22922,
+ 11747, 5289, 9178, 7918, 6701, 28590, 13153, 3539, 30539, 21547,
+ 9891, 5414, 29768, 401, 6552, 4620, 9860, 29006, 13131, 5495,
+ 2301, 26877, 16186, 10232, 204, 31961, 30208, 32724, 2803, 5752,
+ 14641, 23897, 30549, 21430, 18054, 370, 21766, 20975, 9786, 29306,
+ 29637, 14705, 22707, 846, 7879, 7472, 1893, 20646, 29879, 700,
+ 15604, 10405, 250, 9841, 26776, 4270, 31287, 20461, 12486, 23930,
+ 18967, 19144, 22797, 4455, 16969, 22399, 16190, 29971, 8906, 10416,
+ 13263, 7722, 21859, 16525, 12673, 22652, 627, 17035, 14401, 9555,
+ 25326, 3418, 20300, 17667, 29606, 12570, 29335, 32450, 28105, 5580,
+ 28526, 6842, 10411, 26118, 29787, 16989, 18630, 4587, 22601, 15097,
+ 24576, 32347, 23785, 11916, 25388, 13415, 28757, 30425, 6354, 9480,
+ 12788, 7867, 25907, 21776, 16029, 3514, 6024, 1376, 2047, 4572,
+ 7307, 11100, 15168, 15293, 14904, 19868, 31460, 16610, 14549, 6372,
+ 28657, 22603, 7472, 16727, 30288, 17735, 22568, 999, 26743, 1165,
+ 3950, 23568, 20037, 20359, 25485, 16838, 29485, 27121, 22312, 940,
+ 10135, 28067, 15235, 4486, 12675, 2219, 17990, 19185, 12400, 24991,
+ 13437, 9810, 30844, 5682, 7906, 17420, 10444, 2052, 25439, 16886,
+ 302, 27583, 18383, 25356, 15101, 20063, 14853, 24420, 26950, 1233,
+ 20751, 28772, 9256, 14784, 29627, 27955, 897, 3500, 18523, 2925,
+ 11463, 32060, 20934, 6171, 30771, 469, 23967, 15586, 28965, 8299,
+ 10202, 9594, 13764, 23191, 22395, 6498, 31204, 13802, 14497, 24018,
+ 12590, 19842, 22468, 29682, 9338, 8666, 25147, 1865, 30336, 6886,
+ 28673, 8312, 23472, 28768, 6840, 28712, 2398, 27741, 1518, 17985,
+ 8226, 15395, 15520, 2396, 5503, 17214, 2044, 17020, 24770, 9425,
+ 9067, 4344, 28461, 30507, 29135, 6844, 9045, 21914, 6153, 19634,
+ 25545, 17540, 8383, 32634, 31988, 7091, 3420, 21601, 23109, 27377,
+ 30808, 24209, 23181, 3285, 11449, 27781, 17320, 23516, 22234, 1472,
+ 6495, 15803, 12907, 28863, 23437, 30964, 22969, 21804, 28545, 2216,
+ 6703, 20052, 14500, 25260, 29213, 475, 9307, 25567, 7097, 3758,
+ 11567, 22202, 18788, 26682, 6444, 18472, 30510, 29148, 30598, 7832,
+ 30107, 28312, 8579, 10065, 4520, 6413, 17044, 3590, 32265, 30632,
+ 11205, 29355, 25013, 16665, 30296, 4487, 12196, 25859, 14765, 12681,
+ 11223, 3320, 22630, 19679, 16794, 10660, 10440, 10181, 3846, 24648,
+ 31843, 18843, 18889, 27755, 19189, 3131, 24874, 18892, 1164, 13705,
+ 327, 15002, 20203, 20300, 23457, 32231, 12847, 12604, 22747, 19035,
+ 30898, 29019, 6079, 24869, 17968, 11913, 23938, 19767, 10792, 26963,
+ 23369, 8883, 12677, 24333, 27883, 21152, 15230, 6944, 13561, 26338,
+ 5563, 12964, 14844, 14953, 9145, 24114, 26877, 424, 5487, 26099,
+ 8523, 14153, 28978, 5117, 11640, 16671, 29910, 8416, 19877, 24924,
+ 4630, 20091, 14079, 18436, 2613, 9493, 11402, 22689, 27878, 1705,
+ 5406, 30777, 32362, 3200, 12975, 30589, 18680, 25349, 24273, 27971,
+ 23905, 6102, 28794, 5430, 1780, 3607, 12042, 1740, 30367, 3339,
+ 30346, 22649, 10584, 7397, 28977, 803, 3515, 9691, 2605, 6613,
+ 11509, 1405, 32160, 10679, 23264, 3653, 10728, 22078, 12655, 9583,
+ 1571, 1440, 23373, 29450, 25074, 12683, 29121, 22608, 21118, 12310,
+ 29141, 8243, 28857, 2296, 3255, 7736, 19687, 10999, 22367, 12168,
+ 15196, 5540, 7538, 21061, 24199, 19270, 23399, 18202, 4655, 7956,
+ 9192, 28950, 7165, 13223, 29819, 26554, 17723, 15790, 15713, 28496,
+ 16859, 24292, 8382, 19327, 2235, 11583, 11515, 8221, 295, 14954,
+ 5737, 21572, 10656, 12150, 13351, 11176, 7131, 20685, 17477, 2599,
+ 4621, 32359, 15145, 5538, 20838, 1088, 8754, 10764, 7643, 20233,
+ 18844, 21440, 6953, 22813, 20900, 17432, 16151, 25528, 20204, 29755,
+ 14587, 20579, 3616, 27190, 29311, 11955, 15066, 21583, 3493, 21043,
+ 28099, 28309, 1033, 1183, 26108, 26300, 19303, 10323, 29116, 12840,
+ 9052, 24322, 19002, 2632, 28785, 2219, 26317, 805, 18517, 11977,
+ 2897, 28731, 4970, 12235, 5582, 2951, 26499, 16067, 20308, 4833,
+ 32749, 2914, 17449, 20364, 30380, 9764, 26407, 15372, 8966, 29896,
+ 1119, 15415, 16710, 19203, 18178, 7055, 18362, 31605, 22146, 17871,
+ 3326, 29916, 20212, 28100, 9084, 16264, 6329, 5726, 3636, 28431,
+ 25437, 12807, 12985, 23617, 18367, 19507, 11388, 15198, 21874, 28985,
+ 25933, 25223, 3940, 18529, 5919, 21619, 7101, 5182, 6924, 25443,
+ 11018, 3390, 10649, 88, 23195, 19071, 28730, 2691, 5673, 11492,
+ 8217, 13053, 15549, 105, 23059, 18616, 3276, 18355, 7171, 182,
+ 7079, 26092, 4932, 3704, 23571, 6861, 30833, 8378, 30771, 1276,
+ 22639, 5725, 687, 7833, 28334, 32677, 17167, 26643, 29867, 16292,
+ 8552, 13633, 2746, 25078, 30011, 20654, 7682, 30895, 15258, 26932,
+ 28617, 5778, 30860, 32204, 8690, 14724, 18355, 15268, 27843, 14656,
+ 24620, 626, 25068, 3659, 4023, 777, 24773, 1323, 28952, 11305,
+ 8152, 12756, 25021, 22940, 28575, 14179, 31392, 31102, 6799, 14350,
+ 4207, 7133, 1621, 347, 32491, 8322, 31327, 18577, 17294, 30477,
+ 12190, 2924, 11120, 9544, 3466, 26901, 6251, 1973, 14439, 1873,
+ 8573, 105, 21703, 22521, 4719, 2077, 9297, 21162, 3764, 21891,
+ 24512, 30397, 23444, 3798, 29231, 10618, 5514, 14773, 31123, 17544,
+ 21738, 23857, 12425, 26792, 1478, 2597, 9554, 26788, 30483, 15814,
+ 25115, 24705, 25864, 21114, 27266, 19708, 711, 29422, 12887, 14133,
+ 18239, 17250, 29087, 18597, 337, 13640, 31199, 23381, 30513, 14606,
+ 28823, 23122, 5392, 16952, 4876, 1628, 28408, 20913, 26442, 29406,
+ 6647, 31331, 32362, 20259, 8319, 5125, 11281, 20422, 5645, 4148,
+ 22329, 19562, 3593, 9670, 18484, 26028, 31213, 18011, 6125, 18262,
+ 12970, 4660, 9330, 23253, 12616, 15945, 11951, 32238, 15052, 8341,
+ 1404, 4524, 862, 22197, 25051, 30109, 3243, 15025, 22650, 17214,
+ 17289, 6682, 1152, 23987, 8409, 25429, 20358, 10683, 20914, 15670,
+ 31458, 484, 10940, 15569, 20012, 15099, 27353, 11660, 3835, 19655,
+ 4363, 8057, 9712, 29431, 18834, 12259, 5366, 23128, 13908, 16423,
+ 8903, 11851, 5762, 3781, 24499, 6775, 4473, 26295, 26525, 5307,
+ 10470, 22786, 1350, 870, 5678, 13450, 6862, 5035, 5901, 12330,
+ 29559, 21583, 28029, 31492, 25261, 26789, 5849, 10006, 21571, 26556,
+ 32322, 8719, 12800, 15319, 11842, 12384, 16986, 5661, 17839, 7829,
+ 25729, 19090, 13266, 7398, 19871, 10310, 32713, 30985, 11102, 8653,
+ 7978, 10827, 20396, 23022, 8169, 25567, 18875, 26783, 10620, 8566,
+ 4171, 27698, 6460, 25104, 8491, 15049, 15887, 1297, 14845, 18447,
+ 30532, 32151, 3643, 4906, 15038, 20491, 7799, 12523, 18005, 3574,
+ 5351, 17992, 121, 17430, 19232, 1805, 19480, 3762, 23842, 3278,
+ 21442, 18474, 28053, 6688, 4108, 1490, 32594, 7689, 3378, 22272,
+ 2085, 2996, 13312, 31332, 8401, 23145, 6642, 32152, 30293, 16829,
+ 7322, 31480, 24686, 1542, 19522, 27060, 16733, 26898, 27091, 13348,
+ 4842, 4889, 31733, 2139, 17577, 2031, 16248, 5886, 20348, 31870,
+ 30451, 13399, 8793, 8308, 23978, 4005, 19534, 12345, 16821, 29878,
+ 1986, 25380, 2399, 19384, 2813, 2542, 10189, 19277, 16875, 29031,
+ 17632, 4317, 21788, 23911, 7259, 4912, 8720, 12296, 22601, 9020,
+ 2226, 4370, 27289, 28475, 12834, 10679, 10764, 15361, 13495, 18561,
+ 13905, 18573, 14661, 392, 26478, 4062, 1435, 7912, 19553, 23816,
+ 4176, 30066, 32007, 25990, 448, 29090, 17214, 24018, 18001, 28881,
+ 24390, 15411, 5627, 15020, 27502, 7638, 5383, 12005, 8940, 545,
+ 29206, 31529, 4108, 20548, 9574, 27985, 25997, 23313, 13649, 13788,
+ 1863, 22285, 9238, 11933, 1554, 30407, 27356, 31153, 4836, 8552,
+ 9716, 3252, 11577, 30604, 22111, 31796, 4280, 6736, 23696, 7014,
+ 9747, 26796, 4210, 17432, 31535, 9988, 6829, 23271, 1669, 17657,
+ 29478, 25522, 14792, 13701, 10436, 14927, 10183, 3399, 22138, 17276,
+ 16790, 23323, 27010, 10776, 28392, 28398, 7398, 31891, 1472, 721,
+ 20037, 16035, 25929, 31307, 4052, 17208, 14337, 11252, 7075, 25267,
+ 8477, 26943, 3106, 24914, 22826, 14488, 32227, 6639, 32240, 30127,
+ 32417, 16619, 6555, 19475, 28034, 21349, 9501, 16386, 12441, 1711,
+ 2510, 14720, 25519, 19458, 26197, 17830, 25667, 15472, 6860, 573,
+ 24271, 283, 24607, 26507, 16717, 2981, 28341, 25709, 14074, 13031,
+ 30803, 166, 4442, 2022, 31037, 31095, 17020, 30466, 9374, 3184,
+ 19583, 2417, 28713, 25733, 19029, 23276, 769, 23908, 30151, 6056,
+ 3030, 4358, 20153, 5768, 16977, 25476, 18352, 25489, 6067, 301,
+ 7057, 20126, 23225, 725, 12460, 21077, 21186, 11375, 11512, 26457,
+ 5683, 31199, 8096, 6081, 8219, 28169, 25535, 26314, 26899, 22574,
+ 8296, 24776, 1897, 888, 2538, 26467, 6781, 1235, 18514, 3583,
+ 1386, 6911, 10033, 6780, 15593, 21731, 29343, 32288, 11379, 29221,
+ 9599, 23249, 30374, 12791, 19717, 26760, 5354, 1076, 17782, 20226,
+ 6740, 20651, 13359, 18361, 7627, 18619, 25321, 7186, 3945, 30496,
+ 24635, 21464, 32035, 524, 2400, 10217, 2733, 21369, 24891, 3375,
+ 8344, 7102, 22680, 27602, 5822, 25185, 27573, 22188, 24031, 6445,
+ 14593, 22270, 27788, 25988, 29987, 8289, 29508, 5110, 24638, 16639,
+ 7134, 27154, 8308, 8706, 22566, 19067, 9641, 27725, 971, 24383,
+ 31369, 9578, 23929, 15973, 9932, 6340, 6978, 15557, 1720, 24855,
+ 7746, 25373, 15336, 9764, 2435, 14688, 6989, 25257, 16414, 23633,
+ 15474, 18064, 3747, 4433, 3588, 2407, 955, 19573, 5009, 16656,
+ 15372, 23772, 12432, 4282, 9565, 13120, 9378, 17424, 31995, 30410,
+ 7447, 10927, 3419, 23595, 32692, 18398, 28416, 29416, 21171, 10873,
+ 20639, 23797, 26124, 303, 2690, 9350, 8691, 16110, 298, 9250,
+ 7842, 25498, 6968, 13561, 26968, 15621, 20110, 6007, 6818, 13340,
+ 2225, 18969, 8665, 31326, 30321, 17024, 27116, 11155, 28365, 15556,
+ 15199, 14266, 1297, 5386, 32660, 10563, 1601, 24409, 18762, 7038,
+ 26042, 12713, 18019, 30036, 23831, 21565, 32490, 15413, 17234, 19507,
+ 1364, 4945, 24363, 29786, 31750, 15115, 14542, 6211, 5144, 9386,
+ 11952, 17819, 26969, 28242, 20922, 18359, 24467, 23348, 19625, 369,
+ 25872, 7169, 23221, 6451, 15964, 31652, 4464, 11089, 16205, 17456,
+ 498, 30364, 5441, 28695, 30003, 14132, 1703, 31646, 18360, 9117,
+ 19393, 27277, 10354, 16405, 25767, 22059, 16099, 31781, 4240, 5993,
+ 31874, 20087, 19021, 24926, 7521, 17127, 28182, 24563, 7181, 11996,
+ 27785, 12000, 7349, 32729, 12016, 15575, 5007, 22607, 4291, 28414,
+ 10872, 28342, 4718, 6307, 10715, 25307, 10579, 6956, 26835, 32124,
+ 20755, 16972, 2196, 3602, 16905, 12413, 32519, 23278, 28952, 28586,
+ 13492, 22407, 15527, 31275, 14821, 5395, 27369, 20471, 22280, 8532,
+ 23906, 27669, 31830, 18357, 7591, 11860, 21682, 26773, 10085, 3388,
+ 32724, 23267, 5028, 9284, 14246, 3051, 2381, 29254, 25838, 20847,
+ 5866, 23599, 26414, 8698, 22958, 18427, 5064, 10097, 5557, 25569,
+ 12390, 24555, 9100, 28106, 27801, 16578, 22260, 3848, 7873, 4075,
+ 17123, 8261, 18476, 26498, 32460, 27065, 9346, 6057, 20768, 13217,
+ 18528, 23187, 25365, 15084, 4931, 3804, 24998, 24119, 30888, 27676,
+ 12251, 5883, 25713, 26043, 3658, 4869, 16011, 12295, 23518, 551,
+ 20942, 7043, 21463, 27694, 6692, 14978, 27922, 8979, 15854, 1269,
+ 16011, 9590, 13987, 28290, 3360, 1351, 27834, 8918, 26264, 9927,
+ 19147, 23611, 28131, 27567, 3057, 2157, 15523, 7854, 18802, 12201,
+ 32236, 13081, 2978, 21000, 9800, 11487, 25092, 12043, 27903, 17595,
+ 18099, 11127, 27285, 7341, 20736, 18787, 147, 6314, 31581, 26255,
+ 28299, 12179, 122, 13559, 14422, 18532, 5037, 8616, 16800, 30638,
+ 30871, 7635, 17063, 12615, 15877, 32288, 31295, 16959, 8212, 25668,
+ 16666, 10007, 21913, 26326, 25158, 4654, 19647, 27486, 23799, 13948,
+ 6898, 26288, 29575, 10882, 9212, 30584, 11195, 30593, 15470, 3861,
+ 9288, 10475, 19266, 7339, 25493, 28695, 11966, 28275, 963, 12344,
+ 26780, 15702, 24555, 1680, 21863, 5819, 9894, 8929, 29480, 6301,
+ 30163, 1061, 31554, 13280, 25492, 28030, 21403, 26853, 6298, 10096,
+ 6908, 12892, 24483, 24910, 21691, 4697, 20032, 18162, 30615, 30122,
+ 27356, 7857, 25571, 24937, 29690, 911, 1255, 7885, 11454, 4014,
+ 8579, 22853, 21167, 2829, 8213, 25288, 8379, 29295, 16797, 4710,
+ 892, 27288, 6175, 28964, 25273, 29631, 15433, 10502, 9264, 28993,
+ 1622, 27245, 19346, 22931, 20018, 15267, 23504, 8826, 30431, 26293,
+ 23957, 15742, 18711, 31105, 12051, 14492, 24883, 3087, 259, 22331,
+ 13387, 16677, 9447, 14177, 28831, 13589, 4243, 22311, 15669, 20186,
+ 15083, 3690, 7364, 10083, 13806, 20676, 30673, 31535, 10740, 19386,
+ 4632, 23066, 5683, 13623, 28461, 2423, 31368, 24122, 27235, 19550,
+ 20085, 24011, 1517, 1607, 26982, 26675, 13635, 27608, 16440, 9836,
+ 9928, 13820, 7163, 8663, 20649, 2869, 11767, 6189, 17672, 4915,
+ 9454, 19384, 4442, 26789, 10145, 9155, 11533, 23887, 22677, 12623,
+ 15214, 17501, 18199, 27655, 9419, 14071, 29054, 15222, 19156, 1813,
+ 15536, 8312, 23623, 21653, 1256, 4846, 3021, 30859, 11190, 26550,
+ 11807, 15064, 18247, 21211, 876, 1534, 22246, 23048, 12287, 3378,
+ 8387, 19267, 10269, 6323, 7411, 3031, 4908, 27739, 4537, 21394,
+ 27163, 31859, 17668, 10289, 21757, 25804, 26424, 11545, 3063, 22027,
+ 6961, 6984, 16221, 27973, 16262, 30090, 19224, 10700, 23818, 19696,
+ 14667, 30024, 24217, 10622, 22582, 29193, 30225, 27428, 26458, 923,
+ 21150, 14064, 8157, 17819, 3131, 17537, 7217, 25802, 26741, 8127,
+ 25329, 3680, 23666, 13001, 6411, 27043, 28723, 11311, 7972, 20407,
+ 26390, 5474, 7736, 13752, 20895, 11624, 18305, 32006, 27767, 23508,
+ 19355, 7648, 28853, 20470, 19685, 24629, 14685, 8271, 20778, 5814,
+ 25126, 32327, 30337, 4144, 17281, 21027, 28529, 13081, 28630, 21297,
+ 2649, 30569, 5649, 28741, 18447, 12971, 27997, 7273, 17864, 27219,
+ 3631, 21457, 32312, 8274, 23687, 27917, 9722, 19944, 26483, 2690,
+ 10033, 185, 25044, 16411, 112, 20004, 6244, 16700, 2775, 4304,
+ 2296, 11000, 27519, 9351, 32515, 16003, 13337, 5192, 22876, 8170,
+ 30417, 28311, 23873, 27905, 20857, 13336, 15003, 16541, 13283, 5212,
+ 9603, 30212, 25998, 27899, 10502, 16546, 3717, 16099, 5925, 27646,
+ 18309, 3567, 14880, 22508, 30046, 24252, 10997, 1283, 29595, 18104,
+ 28963, 17745, 21093, 17019, 20403, 25934, 11173, 18011, 25465, 24847,
+ 21353, 15674, 30360, 31164, 26505, 27043, 11588, 16196, 650, 23830,
+ 28620, 25167, 5570, 31135, 13783, 25205, 11965, 12717, 5869, 27821,
+ 11232, 31266, 17466, 32264, 9292, 8871, 20367, 7839, 1798, 2114,
+ 25514, 18633, 13652, 22058, 20919, 20626, 7274, 18650, 6167, 24425,
+ 4677, 10084, 18015, 22553, 31192, 26376, 25252, 14075, 29286, 11525,
+ 13302, 17001, 5679, 8879, 5674, 8053, 3150, 20418, 15069, 7899,
+ 29154, 28406, 31669, 22069, 24172, 28883, 8682, 22894, 1912, 8391,
+ 18181, 10361, 18304, 8310, 13032, 9539, 3085, 11601, 23311, 9702,
+ 28447, 25706, 26389, 30495, 32719, 30854, 24186, 25346, 32307, 3700,
+ 25507, 4076, 3714, 13214, 8226, 19386, 10104, 8926, 17976, 5944,
+ 16380, 19347, 19352, 1500, 1, 20211, 16750, 17845, 30890, 26531,
+ 28064, 25502, 10161, 28549, 2388, 8119, 18953, 30673, 18610, 26134,
+ 16834, 10087, 4075, 16313, 4910, 21347, 31098, 20415, 15682, 1522,
+ 4522, 12504, 28990, 26469, 27480, 18171, 28049, 15748, 29178, 22871,
+ 32758, 29989, 7392, 2187, 29412, 27133, 26554, 29977, 27173, 24757,
+ 13403, 10776, 29380, 26432, 31164, 8234, 18989, 3949, 25668, 27822,
+ 8336, 14264, 19270, 28983, 23174, 22118, 8140, 7996, 5623, 31441,
+ 14483, 9233, 30267, 30976, 8022, 4373, 31615, 29562, 17231, 21550,
+ 26987, 14172, 13564, 5234, 258, 7850, 20255, 18215, 4553, 27875,
+ 28936, 4334, 9771, 23000, 11798, 18235, 20252, 16061, 5756, 9736,
+ 21245, 6529, 32065, 3531, 17343, 23131, 24459, 23973, 16460, 12198,
+ 20764, 15836, 25890, 17390, 4637, 28299, 12353, 8779, 12826, 28312,
+ 23624, 13549, 25679, 3815, 30427, 4601, 26914, 17869, 13895, 2708,
+ 12528, 22216, 21097, 12348, 7180, 8813, 25804, 17503, 31749, 12961,
+ 5137, 17958, 14888, 22284, 3732, 4754, 18246, 26059, 6220, 19147,
+ 14520, 29797, 12275, 29877, 13983, 7425, 3943, 2499, 8048, 9174,
+ 2897, 26640, 1201, 4322, 5636, 22956, 25853, 4575, 27048, 9779,
+ 18254, 14451, 7575, 25253, 7036, 26791, 11015, 29553, 1024, 2970,
+ 9450, 29907, 27902, 23159, 10002, 32096, 5251, 21924, 16537, 28384,
+ 26635, 15420, 23936, 18779, 23366, 6080, 29590, 13431, 7195, 12297,
+ 30363, 13057, 18414, 31617, 22438, 13513, 1566, 24467, 5060, 31411,
+ 11218, 21856, 5602, 267, 19702, 18100, 28653, 25625, 24192, 14136,
+ 12087, 29429, 19960, 3561, 20509, 25757, 12855, 4808, 5351, 25413,
+ 31087, 29907, 17391, 25070, 14443, 27701, 4358, 28730, 32536, 19642,
+ 13843, 127, 22085, 7301, 32509, 21530, 19111, 773, 19659, 518,
+ 10528, 9253, 21514, 19373, 20544, 15299, 6767, 13309, 15117, 3428,
+ 30654, 3263, 10495, 31782, 7658, 28196, 1871, 24310, 27774, 19617,
+ 32626, 25858, 4923, 8445, 20192, 7793, 18435, 22185, 19481, 32082,
+ 5110, 29775, 15594, 25299, 31706, 12973, 25068, 3252, 1984, 30116,
+ 23375, 30459, 28132, 23436, 19157, 1512, 25814, 22219, 22305, 3115,
+ 24791, 1446, 29746, 341, 16518, 15447, 5419, 31885, 11452, 30047,
+ 11093, 18308, 12212, 7197, 5734, 7595, 18287, 26016, 27140, 27555,
+ 30550, 11194, 11397, 8948, 7458, 32341, 29433, 30211, 3321, 24330,
+ 32362, 4158, 14553, 23280, 15970, 7834, 26426, 30386, 23726, 15423,
+ 15599, 8421, 13922, 6017, 7758, 7832, 26141, 25363, 11152, 9772,
+ 17294, 26487, 23675, 7270, 31799, 18617, 32574, 10178, 10609, 21597,
+ 7836, 3594, 1969, 27542, 4940, 4136, 13065, 23993, 17568, 14393,
+ 3314, 18160, 23654, 19938, 12104, 18227, 29196, 25831, 4246, 9588,
+ 28935, 14841, 15764, 13082, 15988, 20944, 19438, 945, 25088, 3706,
+ 27207, 19680, 13830, 12019, 12670, 667, 25336, 27893, 6960, 921,
+ 10752, 11537, 16766, 27145, 17127, 29951, 19472, 21633, 20789, 7219,
+ 11865, 15159, 13466, 27312, 6941, 9587, 14476, 6689, 20785, 21316,
+ 26418, 27942, 9603, 12147, 897, 20716, 28250, 7605, 28325, 15616,
+ 13278, 31012, 31906, 17765, 18906, 22256, 31803, 4836, 14017, 24914,
+ 30227, 13731, 3055, 24258, 26386, 1529, 4914, 14698, 31242, 1921,
+ 30089, 6874, 1178, 621, 16171, 28669, 19283, 18205, 25803, 26956,
+ 20762, 20465, 11803, 19265, 13773, 13659, 10639, 8975, 26666, 10296,
+ 3427, 13200, 12012, 26208, 10719, 11903, 19766, 23931, 20698, 3559,
+ 17973, 28695, 22141, 8667, 1026, 4344, 3913, 9832, 26053, 10415,
+ 28507, 30152, 31008, 31087, 12015, 10968, 25291, 29979, 6180, 18381,
+ 14971, 14755, 25087, 13602, 24073, 10129, 15537, 11476, 32720, 18143,
+ 29469, 26066, 29783, 28172, 17813, 5039, 816, 24431, 25060, 3739,
+ 16159, 20682, 7314, 14225, 10623, 4386, 20323, 27858, 9442, 16590,
+ 289, 8849, 31480, 20431, 15003, 29680, 31154, 13919, 11502, 16427,
+ 27558, 7116, 3331, 10259, 28598, 24455, 18521, 32703, 29676, 14456,
+ 30469, 2174, 22441, 24213, 12023, 1807, 30975, 29363, 7294, 2581,
+ 12635, 6300, 1039, 29893, 1383, 30561, 4418, 8674, 3118, 5106,
+ 5917, 13035, 20866, 14827, 9621, 24467, 14234, 26289, 6226, 22897,
+ 7168, 27326, 691, 6137, 17323, 13625, 7442, 8363, 21095, 32202,
+ 5961, 8074, 20862, 16556, 29812, 25552, 2449, 16644, 21497, 5344,
+ 13255, 1393, 19398, 13180, 17962, 740, 14298, 15160, 24397, 27058,
+ 8967, 30766, 5426, 18663, 11510, 25844, 11116, 31710, 4459, 9419,
+ 29825, 5646, 13514, 28185, 25234, 16679, 23003, 31002, 2878, 16734,
+ 25802, 18130, 8899, 5124, 20338, 21574, 12902, 23646, 13018, 3563,
+ 3606, 4785, 2560, 5983, 19788, 10652, 4566, 15191, 19253, 7594,
+ 27275, 6105, 29203, 9000, 24075, 23211, 21985, 26164, 28617, 8715,
+ 25141, 4375, 6588, 21920, 8043, 3285, 23207, 2993, 21248, 12290,
+ 31134, 20117, 32572, 20438, 8902, 22122, 1556, 26500, 16732, 2826,
+ 29518, 18888, 15097, 25147, 12774, 4287, 28692, 28198, 12465, 16380,
+ 9672, 12299, 14912, 19672, 15575, 818, 1031, 265, 23024, 13349,
+ 14526, 27511, 25389, 6172, 520, 21323, 30432, 14521, 21843, 24904,
+ 16271, 26613, 2047, 29534, 18749, 20571, 28354, 20092, 15339, 21876,
+ 3147, 8871, 8031, 22658, 4901, 5449, 3108, 13680, 16095, 17867,
+ 28114, 3082, 18538, 101, 14992, 10602, 31170, 4917, 17366, 9650,
+ 9424, 31119, 1144, 2561, 400, 20885, 4064, 4767, 14191, 20487,
+ 1690, 24955, 5623, 9820, 13335, 13528, 16557, 3857, 14762, 30275,
+ 21050, 29761, 27351, 13768, 15050, 25718, 16077, 25957, 23986, 18879,
+ 31537, 26815, 12885, 5890, 31773, 19732, 27720, 24468, 15721, 15729,
+ 28340, 3335, 2345, 1829, 3836, 10051, 28534, 17013, 27296, 25304,
+ 27506, 29585, 21602, 27027, 22918, 14279, 7335, 4432, 8942, 21239,
+ 14623, 29966, 17016, 12615, 4008, 9289, 1672, 12567, 26736, 23684,
+ 13408, 18744, 19290, 293, 28830, 24408, 19620, 17797, 4358, 25281,
+ 3270, 15688, 15234, 32580, 28573, 18154, 30311, 31855, 20168, 1179,
+ 3578, 7431, 11091, 22349, 29491, 4786, 8850, 4107, 30657, 23027,
+ 10832, 19340, 2893, 4699, 22570, 11272, 24067, 9982, 14389, 25930,
+ 3151, 23333, 30439, 20231, 14308, 3906, 25140, 29038, 12803, 21033,
+ 1527, 16384, 6906, 4732, 26516, 30370, 6891, 1127, 9435, 19696,
+ 6094, 3982, 31280, 29653, 3257, 22852, 29673, 4440, 26207, 16126,
+ 20216, 11961, 2264, 21767, 19658, 19645, 25248, 15733, 32367, 4678,
+ 12513, 27483, 19194, 18726, 22773, 9792, 13611, 7477, 31526, 25040,
+ 9291, 20898, 8889, 15826, 13400, 24710, 14124, 16986, 20834, 14527,
+ 4795, 11328, 8757, 3579, 25129, 24016, 1592, 28435, 12732, 18371,
+ 10901, 5787, 19338, 24175, 31386, 10679, 19187, 28474, 28512, 22831,
+ 2415, 27220, 682, 6342, 18570, 29862, 18703, 24776, 15660, 22021,
+ 30556, 11747, 24606, 6060, 22324, 13111, 10186, 26345, 28409, 29360,
+ 3906, 4118, 24816, 12180, 3716, 9675, 17823, 28504, 26621, 10322,
+ 1402, 31928, 28491, 16731, 30143, 8455, 11591, 26609, 15519, 1987,
+ 1347, 173, 16542, 108, 16272, 20010, 10044, 4758, 7492, 17848,
+ 9941, 6206, 22841, 7253, 12230, 21082, 14937, 8153, 12497, 11187,
+ 6937, 12400, 31427, 7671, 2628, 28237, 1875, 27914, 26874, 28573,
+ 10062, 11422, 10744, 4794, 23537, 17411, 5658, 16546, 24470, 25664,
+ 14877, 13223, 8596, 9314, 25002, 5736, 14688, 14356, 17296, 3839,
+ 5368, 29808, 17234, 2684, 26241, 5909, 27617, 23699, 5422, 890,
+ 1962, 1937, 13669, 27266, 31187, 16532, 19485, 4176, 15554, 1020,
+ 24971, 9308, 10720, 19997, 9981, 24518, 28316, 19510, 13318, 24043,
+ 21170, 6567, 7899, 25399, 13229, 23902, 29693, 1594, 22954, 23443,
+ 20760, 28413, 2400, 20405, 10027, 8342, 30557, 8868, 26602, 250,
+ 146, 20768, 8801, 4883, 19474, 5762, 21209, 5906, 14871, 12201,
+ 27135, 1287, 17478, 19000, 20291, 5550, 13108, 29695, 25215, 19852,
+ 19752, 7862, 16601, 15931, 25123, 3057, 20714, 29187, 22813, 13648,
+ 23072, 13738, 8850, 1270, 11104, 13452, 13373, 29245, 5360, 6894,
+ 29220, 22184, 14741, 12943, 10452, 3866, 31480, 11648, 31982, 15685,
+ 1358, 4918, 29666, 15716, 15928, 990, 31227, 9261, 6888, 17904,
+ 2460, 22785, 8582, 20999, 22473, 8295, 6610, 20720, 10728, 10936,
+ 12554, 16384, 14537, 31516, 5390, 12203, 17637, 15028, 19138, 20563,
+ 16355, 19481, 17332, 16734, 12129, 13062, 30463, 22155, 11504, 9297,
+ 367, 18310, 10080, 21024, 4325, 32186, 18751, 18521, 7933, 29798,
+ 10396, 27994, 16111, 24307, 9232, 31467, 691, 2437, 4352, 880,
+ 15209, 10192, 7964, 22372, 6391, 1581, 5419, 24322, 27892, 20716,
+ 19211, 15429, 5317, 26092, 1267, 18707, 20229, 25706, 5116, 17845,
+ 43, 28439, 24544, 19339, 10854, 21613, 15873, 22526, 7372, 4418,
+ 14765, 949, 7604, 24990, 12704, 14860, 5216, 21450, 28362, 1218,
+ 30176, 4521, 6227, 16369, 31026, 21579, 10461, 19012, 22190, 13760,
+ 18697, 1380, 5794, 21802, 13116, 15027, 13113, 278, 1187, 14397,
+ 4513, 23565, 8052, 14828, 5740, 12133, 631, 29435, 22839, 24669,
+ 14790, 19372, 15242, 15210, 19665, 10046, 26368, 2507, 19876, 17945,
+ 30376, 9571, 28013, 6221, 20394, 32456, 14904, 5178, 27950, 18840,
+ 27134, 26000, 9081, 17164, 22238, 2171, 7769, 18127, 4266, 9495,
+ 7876, 9744, 10149, 16170, 15292, 29910, 5259, 3602, 10869, 16787,
+ 25042, 4348, 20922, 27389, 31280, 13143, 11405, 2073, 16477, 5513,
+ 16398, 5784, 21530, 19936, 10398, 25447, 10354, 13771, 579, 24962,
+ 20288, 5962, 12366, 25353, 7665, 20131, 18492, 26773, 3979, 13399,
+ 9179, 31436, 2030, 25428, 24238, 16947, 23643, 12140, 17041, 20804,
+ 17714, 24582, 26528, 21697, 7424, 787, 2902, 7751, 4280, 27716,
+ 25330, 15654, 9537, 13434, 27935, 6512, 13873, 19839, 1747, 17744,
+ 20953, 32243, 18296, 30877, 5761, 22921, 26698, 27311, 29940, 2419,
+ 15104, 32370, 31808, 31002, 29614, 29880, 4791, 15123, 18922, 6356,
+ 16441, 14926, 13614, 7012, 28086, 2961, 18557, 3950, 15854, 29477,
+ 29001, 15791, 25467, 29392, 7573, 16943, 6162, 29699, 3415, 10265,
+ 6406, 25171, 21280, 30666, 19725, 18989, 18430, 27432, 30535, 20422,
+ 30370, 15413, 7036, 4690, 16830, 16868, 30630, 20342, 18865, 20267,
+ 13999, 23295, 21862, 2137, 16507, 16084, 17017, 8874, 19241, 5929,
+ 16540, 16920, 4502, 32502, 23610, 26997, 21283, 8360, 7258, 12471,
+ 185, 16150, 14277, 13715, 15114, 19126, 9579, 31309, 1561, 22289,
+ 3075, 9934, 22012, 1140, 21746, 24567, 22752, 12777, 26222, 10549,
+ 8783, 2917, 18659, 1109, 7086, 18499, 15253, 17306, 24074, 11761,
+ 31880, 16909, 22804, 10986, 18333, 30229, 27497, 7652, 20733, 4679,
+ 20503, 7498, 16058, 10367, 1373, 21228, 26036, 816, 4275, 16374,
+ 19898, 10488, 17418, 32030, 16626, 15992, 26709, 19234, 27259, 14946,
+ 29000, 1906, 18512, 8147, 7776, 22825, 29808, 13028, 11555, 10818,
+ 2364, 23420, 169, 16649, 9504, 10856, 25179, 3535, 20853, 13485,
+ 16379, 226, 20646, 14620, 2789, 31933, 6034, 17448, 7316, 14459,
+ 30258, 17909, 17511, 9874, 13180, 20145, 25253, 13245, 8327, 25895,
+ 13504, 29242, 26351, 11153, 14038, 1334, 5755, 18094, 15997, 24710,
+ 13821, 15125, 12992, 12439, 23418, 13513, 1381, 32424, 3979, 27917,
+ 20850, 25910, 3, 8826, 17135, 26808, 17874, 22350, 11244, 18573,
+ 16938, 18951, 27334, 23603, 22240, 23601, 1447, 20665, 32276, 23420,
+ 8012, 23159, 1300, 24849, 10507, 12028, 28286, 15142, 30228, 23368,
+ 16293, 5328, 5111, 19004, 15670, 20505, 3174, 3918, 23324, 18003,
+ 29756, 18817, 25504, 25260, 27583, 12949, 6613, 19202, 29730, 11898,
+ 23347, 2808, 15951, 28427, 1154, 30025, 22243, 32761, 7674, 12124,
+ 21369, 20229, 4776, 6937, 25899, 1139, 30483, 4860, 29782, 16315,
+ 8992, 11367, 10654, 3201, 9011, 29757, 2098, 9159, 17559, 22956,
+ 32081, 19810, 16672, 15178, 2318, 30122, 19982, 19044, 25680, 19318,
+ 4661, 14482, 18460, 31304, 18267, 25487, 14871, 21700, 2786, 29512,
+ 582, 871, 8615, 7731, 11801, 2933, 13097, 2018, 17576, 16947,
+ 16366, 28120, 4156, 87, 22306, 5787, 8465, 10685, 20354, 14091,
+ 27994, 23899, 1912, 16881, 12934, 24951, 28807, 21979, 31682, 8215,
+ 27114, 15656, 29119, 18362, 11896, 13407, 22453, 25669, 22987, 27333,
+ 22952, 1088, 18593, 28974, 4074, 15938, 22658, 2835, 23521, 10922,
+ 19108, 5605, 522, 9616, 19979, 31393, 9534, 27900, 29940, 23973,
+ 1844, 28501, 6516, 194, 12872, 24092, 30045, 2962, 28794, 22746,
+ 29025, 11787, 13242, 17494, 28538, 20821, 21347, 8716, 5257, 19161,
+ 17157, 31707, 21821, 17819, 9831, 14334, 18998, 21961, 26316, 26941,
+ 3946, 27284, 11638, 28516, 13000, 4670, 26473, 31733, 30236, 17524,
+ 13937, 20250, 26675, 9951, 29542, 16605, 6463, 32758, 9647, 27291,
+ 28284, 19478, 5125, 1206, 22804, 10452, 21113, 19595, 29761, 2706,
+ 29113, 1700, 20145, 28752, 13199, 28974, 25390, 2501, 26794, 15021,
+ 1150, 942, 23457, 20718, 16520, 28263, 27957, 7229, 32441, 29368,
+ 17879, 31449, 23974, 18673, 16490, 4261, 5107, 9785, 29257, 16160,
+ 22643, 5155, 29836, 22935, 5520, 26242, 21127, 27034, 27630, 17279,
+ 16788, 6060, 18507, 29160, 1555, 3134, 4266, 25035, 10670, 23775,
+ 11440, 9028, 26338, 22957, 27982, 16275, 28090, 20239, 6048, 10353,
+ 26078, 4006, 5909, 12709, 20941, 23168, 6865, 18642, 14183, 29071,
+ 8783, 24467, 12718, 29786, 15691, 15305, 20429, 21235, 735, 8756,
+ 25946, 27945, 1004, 3905, 12248, 12798, 15547, 29219, 30080, 21340,
+ 18916, 7717, 321, 25091, 25711, 26175, 8197, 26054, 26938, 5863,
+ 822, 17911, 28570, 16937, 11392, 5664, 13125, 4602, 18137, 6899,
+ 21872, 5322, 4287, 7044, 14644, 14424, 15297, 21174, 32566, 26314,
+ 25921, 5363, 25735, 31229, 3192, 32289, 2249, 31002, 10683, 15313,
+ 24468, 21610, 19196, 18361, 20760, 4971, 22931, 9828, 19971, 10531,
+ 27967, 32296, 23205, 25268, 20583, 6745, 21841, 9265, 6566, 11964,
+ 31751, 26544, 32391, 28478, 30033, 12960, 17293, 20454, 24683, 30045,
+ 28023, 265, 12454, 2306, 6081, 31677, 22542, 16255, 5230, 12943,
+ 1355, 14827, 14597, 14969, 30917, 31003, 31962, 14, 13580, 23667,
+ 19598, 23800, 3702, 764, 14041, 8612, 24074, 17079, 22151, 26428,
+ 23452, 10801, 7617, 15830, 25402, 16472, 26254, 2795, 10695, 30349,
+ 27802, 11274, 9446, 250, 5173, 12749, 10778, 2342, 8862, 18189,
+ 2347, 28358, 19330, 6226, 9675, 2775, 14272, 20365, 21625, 10473,
+ 26991, 30730, 32422, 10942, 8482, 24224, 21014, 2579, 10346, 16939,
+ 32650, 11454, 9629, 26684, 19612, 16121, 23766, 27150, 31978, 2046,
+ 573, 19900, 22134, 27860, 393, 16306, 17741, 5480, 24259, 97,
+ 25191, 26591, 5196, 23096, 25039, 20011, 4641, 13263, 11267, 31196,
+ 16990, 4709, 9886, 6713, 14081, 8332, 28724, 14480, 25841, 3363,
+ 4990, 11978, 4159, 22149, 30135, 27714, 19883, 22016, 1093, 31960,
+ 15722, 8073, 26012, 1601, 25382, 2477, 12640, 12193, 16199, 29131,
+ 29641, 10075, 3441, 4225, 76, 15143, 19533, 29284, 22392, 13926,
+ 29325, 26868, 9246, 31411, 29994, 1999, 5044, 1723, 752, 548,
+ 3579, 24398, 6461, 31851, 4064, 3766, 22022, 9811, 11680, 11847,
+ 11034, 12540, 48, 11831, 22187, 30055, 476, 20400, 17674, 24363,
+ 7726, 1316, 16306, 28521, 30993, 11489, 3464, 27649, 12598, 23013,
+ 26721, 3846, 8631, 7923, 27589, 19056, 26363, 4070, 24819, 29713,
+ 10969, 27974, 3108, 28107, 31744, 11801, 24340, 7679, 13462, 23547,
+ 13503, 19528, 13343, 30065, 31336, 13930, 28833, 19067, 27104, 29061,
+ 8965, 1896, 14597, 27535, 4801, 25070, 25225, 8448, 17588, 7290,
+ 27637, 23247, 4433, 21445, 19693, 2206, 26112, 19112, 23477, 2866,
+ 13761, 10289, 25332, 805, 23827, 23542, 17592, 30687, 32020, 7337,
+ 20155, 27330, 4585, 13549, 9189, 10917, 18528, 4712, 24337, 31620,
+ 22228, 19226, 21268, 26229, 23890, 3309, 3067, 17886, 4345, 11149,
+ 30101, 25062, 13991, 16505, 19250, 12585, 12498, 4443, 13481, 4528,
+ 9395, 12437, 13472, 3616, 31402, 3100, 19463, 817, 15838, 24201,
+ 30438, 14690, 7972, 13933, 26201, 18156, 7970, 2021, 7128, 19956,
+ 9140, 31855, 18876, 27396, 31886, 29948, 7423, 26556, 6947, 29255,
+ 21572, 1477, 454, 22372, 18455, 30215, 11791, 15004, 18549, 20508,
+ 641, 14456, 29583, 7684, 29545, 32028, 27083, 20506, 31497, 30678,
+ 780, 11590, 6390, 27895, 26931, 4981, 24767, 23010, 15334, 7238,
+ 23503, 24418, 8592, 31238, 17045, 9793, 27048, 8415, 20706, 29206,
+ 9271, 4172, 14738, 22110, 21140, 20688, 32110, 16846, 5490, 31208,
+ 10577, 21480, 31773, 21566, 16266, 12493, 22785, 27679, 20610, 18258,
+ 16236, 10287, 1695, 15701, 3733, 14428, 10599, 30290, 11740, 28944,
+ 23529, 26673, 24147, 26283, 6744, 12898, 17790, 23856, 15098, 11052,
+ 5463, 24638, 30272, 22338, 30101, 5955, 14903, 32664, 4654, 10732,
+ 19743, 22900, 29467, 18656, 856, 29896, 347, 11949, 3206, 25791,
+ 23866, 11522, 7149, 22166, 27091, 6688, 28701, 2733, 12756, 12939,
+ 32212, 25566, 2433, 17157, 16928, 269, 4604, 11964, 32708, 5376,
+ 451, 9667, 27613, 28785, 22138, 8127, 3525, 29282, 21483, 28387,
+ 22072, 21169, 29771, 32542, 12725, 31468, 11710, 5522, 6695, 24934,
+ 12574, 9289, 27589, 6795, 1528, 1571, 311, 5232, 10200, 14099,
+ 23290, 12463, 2247, 23691, 22021, 12401, 7441, 12853, 13741, 9932,
+ 21580, 12004, 1222, 25936, 9109, 30154, 4619, 5852, 1309, 26603,
+ 3008, 31926, 4325, 27089, 32405, 475, 4805, 12674, 15310, 6292,
+ 16819, 12463, 27297, 5706, 31810, 28462, 18655, 411, 11881, 27051,
+ 24279, 1710, 17542, 18586, 10872, 1475, 20386, 879, 1461, 28686,
+ 16119, 17426, 19502, 26309, 21167, 7821, 1036, 20600, 11247, 28936,
+ 3628, 22689, 7700, 32760, 8577, 3452, 9533, 8851, 5555, 4120,
+ 9737, 4999, 16652, 2734, 23202, 14827, 28053, 24883, 4346, 32374,
+ 10620, 20521, 7764, 239, 30393, 28090, 11271, 16868, 7665, 16647,
+ 16766, 5279, 10395, 25534, 12164, 27990, 18017, 25066, 16574, 24482,
+ 8649, 19472, 21369, 24882, 26644, 12151, 16551, 9409, 2151, 26823,
+ 13347, 8517, 28200, 1238, 23101, 6506, 15019, 9150, 1650, 14142,
+ 16910, 4659, 14203, 4142, 20321, 3347, 7306, 9521, 29706, 25407,
+ 32720, 13123, 26216, 27050, 14914, 26645, 13239, 30127, 5277, 20227,
+ 18740, 20904, 14759, 2630, 6273, 24508, 7608, 11371, 23370, 24312,
+ 32634, 17923, 14889, 1697, 26093, 31645, 23239, 27593, 16302, 14321,
+ 6469, 25889, 1912, 20062, 28890, 24846, 4587, 8599, 22461, 25087,
+ 26764, 8857, 4677, 5373, 22030, 15328, 16718, 13956, 2000, 31962,
+ 12256, 14737, 26790, 6556, 9227, 25852, 6364, 4820, 14101, 23304,
+ 10104, 6654, 30936, 16185, 28864, 1499, 25189, 28261, 17916, 27423,
+ 23533, 32014, 17021, 11626, 23010, 28655, 29150, 7290, 21849, 25301,
+ 11146, 29087, 9139, 4528, 18302, 16751, 29052, 30698, 4177, 13754,
+ 25747, 31223, 5745, 9153, 10635, 19758, 18607, 21154, 28754, 4567,
+ 30206, 1559, 7184, 21381, 7287, 8544, 10834, 25510, 10657, 30334,
+ 5480, 16984, 4080, 5538, 13835, 2430, 21899, 12517, 26692, 3603,
+ 82, 26681, 30601, 11199, 800, 4512, 5672, 28328, 4173, 20892,
+ 25577, 3979, 30072, 6118, 18414, 30219, 25731, 21602, 8671, 13641,
+ 19934, 30803, 5700, 14004, 12297, 6092, 31282, 1827, 84, 16231,
+ 8746, 31265, 4330, 21048, 6206, 6023, 6157, 1028, 32117, 1873,
+ 15523, 17327, 6769, 28586, 19442, 10740, 25423, 31049, 31912, 16473,
+ 29391, 28160, 25374, 13409, 16565, 9618, 31453, 19203, 5999, 13510,
+ 26978, 10331, 3319, 4793, 24094, 16288, 763, 10360, 13249, 32598,
+ 29244, 32462, 14008, 3524, 1332, 32347, 13556, 10665, 17915, 30182,
+ 15086, 811, 25451, 23285, 8680, 8464, 20867, 30874, 21365, 9776,
+ 18697, 143, 26171, 2858, 27251, 12933, 30712, 8279, 2056, 3514,
+ 26819, 27644, 23363, 16586, 23445, 14532, 10616, 19399, 8199, 26733,
+ 7097, 2187, 26973, 24257, 19963, 3405, 30404, 6344, 22901, 7539,
+ 4312, 17468, 24137, 7335, 105, 27453, 20582, 14381, 25215, 2118,
+ 2989, 14964, 32155, 5728, 29523, 15595, 31808, 29077, 8326, 11285,
+ 12466, 7080, 25683, 20960, 17918, 14595, 8391, 23091, 570, 23025,
+ 15700, 1478, 32270, 25613, 14967, 32566, 30068, 12283, 10392, 1625,
+ 5563, 12117, 1586, 26063, 27858, 12008, 18739, 26329, 24003, 2337,
+ 6054, 14190, 15998, 23746, 29583, 30348, 728, 7129, 24086, 23245,
+ 6355, 1779, 13800, 10042, 23072, 26765, 21723, 25187, 14050, 9419,
+ 12497, 944, 32181, 29037, 990, 2802, 25839, 18942, 16301, 13885,
+ 14630, 29774, 20511, 18938, 21746, 10531, 28982, 7992, 17907, 13612,
+ 7218, 27715, 17174, 9782, 20473, 31608, 22549, 22690, 14524, 17495,
+ 27197, 30999, 31448, 6874, 31348, 20084, 9466, 26885, 18554, 24585,
+ 3463, 9919, 15215, 19462, 7995, 992, 13206, 25139, 22800, 30859,
+ 10584, 22242, 1377, 12222, 15756, 8739, 27727, 39, 7925, 24374,
+ 1380, 26426, 26892, 16454, 27766, 14976, 24576, 27220, 7630, 818,
+ 11772, 19825, 15754, 14342, 1448, 19760, 28224, 18761, 19954, 19803,
+ 31460, 13102, 15118, 30437, 22508, 2662, 30907, 18720, 16305, 14064,
+ 18889, 19248, 28185, 20787, 16600, 29120, 16243, 21834, 30306, 3315,
+ 13986, 8351, 24572, 21149, 11902, 28091, 11480, 22708, 14967, 16988,
+ 19343, 5121, 31356, 968, 32029, 12059, 26139, 9570, 6445, 19862,
+ 21225, 9595, 26520, 3960, 14884, 19562, 13096, 26860, 407, 25055,
+ 31137, 8763, 19390, 19572, 23810, 5111, 4907, 20357, 14856, 29562,
+ 5416, 23362, 2036, 17295, 20382, 8962, 25998, 15726, 5685, 28123,
+ 30570, 17902, 701, 21871, 31594, 17142, 17613, 26376, 13700, 25908,
+ 5289, 23272, 6597, 14866, 19817, 21978, 22422, 6630, 29272, 26893,
+ 10815, 18025, 9115, 17442, 4777, 19819, 17939, 19844, 24168, 965,
+ 25220, 5368, 8184, 11406, 32758, 21621, 31815, 8338, 32091, 29493,
+ 29044, 2559, 11891, 16140, 31447, 2146, 16365, 20473, 13889, 20690,
+ 9935, 18939, 28293, 7787, 7959, 28965, 12087, 1791, 32162, 17397,
+ 17843, 2055, 22862, 4066, 21345, 24544, 20316, 13364, 21816, 1844,
+ 26392, 1816, 17537, 24246, 22715, 4340, 13534, 25874, 15248, 4600,
+ 5002, 2339, 24406, 1526, 27618, 27751, 21734, 6771, 21797, 10673,
+ 27157, 19198, 28024, 29726, 7388, 6080, 1581, 8778, 18870, 2645,
+ 25924, 31172, 6474, 31962, 16434, 20159, 29002, 22343, 21474, 19466,
+ 27803, 14079, 15866, 30530, 7862, 13478, 31583, 17734, 9806, 15411,
+ 12283, 21227, 21299, 11078, 7102, 5617, 25462, 10683, 24802, 6710,
+ 7118, 28799, 32628, 7978, 16186, 29346, 10768, 10627, 10728, 7342,
+ 22508, 23858, 4950, 7736, 14359, 13205, 15287, 29108, 27139, 25070,
+ 2200, 5774, 8002, 1044, 21699, 12662, 2701, 24424, 30563, 1787,
+ 16394, 21003, 18026, 1115, 27343, 16974, 6192, 19097, 31650, 8810,
+ 2140, 28625, 13570, 23666, 1032, 27337, 14444, 14981, 24864, 23752,
+ 30935, 8008, 1291, 11691, 13953, 8851, 24206, 11829, 26605, 26219,
+ 14061, 13479, 13356, 14385, 7763, 26512, 25181, 21016, 30579, 10983,
+ 25200, 20701, 26224, 25431, 21295, 12722, 9978, 986, 10622, 27771,
+ 3515, 6537, 23777, 32316, 14577, 18867, 15680, 30674, 13404, 30252,
+ 21991, 25826, 5210, 31719, 465, 7952, 19537, 16327, 5414, 24945,
+ 17485, 32179, 16386, 12354, 29162, 3561, 3704, 26842, 30837, 5268,
+ 10711, 3549, 5198, 20384, 16171, 9139, 21904, 30413, 12039, 12600,
+ 28148, 25090, 27266, 14517, 5619, 27109, 8576, 15632, 19755, 13992,
+ 9779, 10047, 31236, 28965, 10721, 8194, 11411, 2606, 14055, 12754,
+ 2239, 3102, 3070, 18196, 7074, 10932, 15549, 22675, 8242, 1314,
+ 15199, 24621, 30496, 20064, 12231, 25549, 22016, 20422, 16321, 11417,
+ 29099, 31194, 11403, 32364, 10209, 30567, 27028, 25478, 27699, 30415,
+ 4227, 24706, 31776, 7585, 22139, 9353, 7807, 23150, 26269, 2502,
+ 29213, 2265, 17871, 31257, 4006, 7150, 9148, 3088, 713, 17077,
+ 15644, 27667, 24215, 15110, 13110, 26078, 28972, 18078, 31907, 8757,
+ 23186, 30323, 21332, 27858, 2786, 16453, 17367, 5795, 27564, 4726,
+ 16853, 18482, 14489, 23067, 26080, 22629, 19279, 12115, 14443, 31591,
+ 24213, 7128, 11802, 24038, 3256, 12243, 14653, 127, 3373, 22773,
+ 5271, 26486, 30071, 12227, 11107, 29355, 332, 12081, 17049, 29129,
+ 9715, 2675, 18285, 18625, 29936, 5392, 26392, 14455, 4579, 28984,
+ 21468, 8122, 16302, 30807, 23362, 18554, 18646, 4586, 12711, 5429,
+ 18220, 27794, 5878, 8883, 3756, 19814, 14519, 12787, 16293, 27022,
+ 30025, 28261, 17434, 32270, 25707, 25690, 15464, 6623, 18690, 15288,
+ 7978, 20036, 20502, 2802, 4186, 14683, 16669, 22071, 13241, 7922,
+ 892, 3818, 32368, 925, 7499, 10067, 19447, 32261, 3928, 3732,
+ 14902, 12931, 12911, 10462, 4330, 11502, 31193, 6116, 14411, 3249,
+ 16163, 26512, 748, 14112, 31521, 29429, 20194, 1036, 4145, 5510,
+ 16936, 6292, 2500, 31877, 9794, 25663, 29979, 11454, 10017, 29768,
+ 14159, 4212, 31047, 4409, 1172, 8604, 11051, 23227, 23742, 1097,
+ 9695, 21933, 12549, 9576, 8432, 8307, 5893, 12717, 3470, 16785,
+ 11529, 30925, 15596, 17528, 5000, 4334, 17898, 6303, 8176, 20059,
+ 28146, 26326, 11427, 25469, 6431, 20696, 10815, 15623, 1445, 20255,
+ 22051, 28272, 22125, 8444, 14895, 17062, 12543, 742, 22986, 17665,
+ 29349, 7955, 12330, 22133, 16589, 27717, 25552, 8973, 30896, 28391,
+ 21329, 2964, 16945, 4184, 24412, 22421, 18952, 135, 5625, 17287,
+ 26399, 21952, 8975, 16193, 12092, 24261, 10793, 28852, 16097, 23329,
+ 28025, 20184, 14449, 3513, 26142, 26855, 16019, 23972, 12706, 11722,
+ 28123, 31036, 30919, 18384, 6568, 12149, 13187, 24742, 20552, 29550,
+ 28233, 24964, 27235, 15942, 29834, 932, 10646, 17201, 1148, 17656,
+ 10846, 10699, 28698, 5404, 11576, 17068, 20332, 20106, 31494, 27196,
+ 10248, 20493, 26805, 3528, 11737, 19064, 15901, 1750, 287, 5783,
+ 1064, 16566, 3511, 10086, 32311, 23642, 28573, 27777, 21185, 18024,
+ 175, 14556, 10045, 29580, 29619, 436, 13123, 14099, 8348, 2501,
+ 3822, 26550, 26121, 19646, 16516, 18099, 17423, 16114, 19801, 23843,
+ 5176, 13648, 20976, 17287, 715, 2453, 25956, 1956, 11598, 20160,
+ 19462, 9361, 2634, 10694, 15688, 16654, 32334, 8840, 16602, 10263,
+ 16950, 258, 26386, 12217, 32429, 2757, 24721, 549, 16625, 13479,
+ 14628, 32003, 11479, 7353, 14824, 6920, 4110, 24697, 14002, 7115,
+ 15015, 9033, 19117, 24020, 16597, 22816, 18501, 7926, 2546, 10624,
+ 24644, 5856, 20675, 32424, 17467, 8174, 30973, 5386, 18468, 25157,
+ 24072, 7935, 18245, 13598, 32514, 20666, 20568, 10850, 11271, 26746,
+ 23784, 30840, 6320, 1796, 6142, 13914, 30681, 27729, 30717, 7663,
+ 1192, 27780, 12235, 18581, 7371, 12575, 15153, 6652, 20480, 6773,
+ 2693, 19771, 2267, 21859, 4486, 22557, 12996, 31035, 15751, 6332,
+ 319, 16897, 5840, 338, 15472, 15066, 4417, 13899, 14046, 27841,
+ 20536, 21151, 20599, 25980, 25013, 18014, 10964, 10958, 13500, 909,
+ 29375, 28143, 20219, 27952, 25330, 4921, 1453, 15528, 25634, 25124,
+ 15806, 20799, 28220, 29044, 30512, 7682, 3823, 9137, 10173, 10703,
+ 14698, 18392, 10430, 21934, 17255, 12880, 15435, 23908, 13160, 25119,
+ 28068, 17990, 17472, 1630, 20687, 12364, 16854, 30698, 25987, 15718,
+ 8998, 31581, 8517, 787, 1416, 24381, 25809, 14895, 27957, 19059,
+ 24763, 8460, 28423, 20222, 11606, 17349, 10112, 5352, 6613, 7887,
+ 8974, 12665, 30384, 20433, 7053, 32428, 24394, 18614, 12046, 1759,
+ 18128, 14592, 29655, 22734, 19556, 8543, 3499, 22466, 6779, 17794,
+ 10315, 23558, 21891, 28717, 31548, 14235, 24010, 15756, 15051, 29484,
+ 26779, 24519, 6735, 22340, 13482, 4566, 17326, 5567, 23985, 11415,
+ 26658, 10111, 4956, 4637, 20029, 12896, 14179, 25419, 299, 2925,
+ 9973, 13218, 1336, 10580, 13149, 12120, 13713, 6935, 3552, 26538,
+ 12111, 22277, 10980, 14707, 28081, 30185, 24664, 508, 31657, 11905,
+ 17231, 5654, 24219, 9521, 2286, 12134, 7777, 25593, 28297, 17409,
+ 3730, 3749, 27913, 31801, 15620, 10051, 15249, 15030, 10639, 30426,
+ 25953, 27336, 11028, 28249, 30458, 2299, 9662, 5070, 1666, 6636,
+ 30344, 20440, 7019, 860, 14336, 12127, 14672, 31619, 17482, 28034,
+ 4639, 678, 6247, 22993, 9085, 6892, 31928, 28349, 17254, 12910,
+ 5821, 11340, 24596, 29581, 18467, 2834, 30499, 28552, 32510, 7004,
+ 2034, 22350, 23379, 9390, 1356, 13968, 19929, 22896, 2632, 25883,
+ 5120, 29412, 22125, 8805, 13619, 18779, 21786, 3941, 25946, 15529,
+ 13349, 31400, 28836, 214, 19907, 12962, 5251, 8982, 27048, 21058,
+ 27128, 23291, 6511, 15305, 17680, 31722, 13371, 13787, 11695, 6860,
+ 13727, 24278, 21900, 15365, 955, 27236, 12157, 7594, 24744, 23884,
+ 3061, 29166, 2839, 15246, 24266, 7646, 21044, 23726, 4668, 20559,
+ 8401, 23120, 2868, 1300, 17344, 19717, 17097, 18548, 28544, 19301,
+ 6408, 20187, 18717, 24414, 17653, 13519, 30289, 26059, 1485, 31526,
+ 30959, 3144, 31118, 4982, 22913, 24901, 15545, 4302, 25904, 10842,
+ 14167, 20643, 741, 29914, 15162, 12301, 25518, 5291, 22405, 8500,
+ 4707, 1365, 1391, 13572, 9865, 24920, 4675, 27945, 7798, 25539,
+ 27307, 27191, 9398, 10242, 11055, 18984, 17582, 7160, 6649, 19212,
+ 21119, 22606, 28123, 1532, 2606, 21258, 1683, 22096, 10753, 8291,
+ 31309, 16658, 3116, 13779, 7273, 28850, 940, 25455, 24959, 6394,
+ 116, 30580, 17568, 22341, 16071, 16418, 4575, 25324, 1509, 24525,
+ 14864, 8706, 14825, 10033, 5072, 30273, 17650, 27142, 11718, 22083,
+ 7041, 468, 5672, 1782, 24610, 29449, 15232, 2378, 27215, 26697,
+ 19120, 4140, 13457, 30725, 11827, 4792, 30184, 26703, 4775, 20138,
+ 27245, 25836, 5256, 20246, 3894, 23467, 31551, 19290, 21882, 29430,
+ 9563, 29264, 4341, 20135, 2590, 30152, 9614, 5917, 29755, 27189,
+ 14392, 30350, 23006, 20134, 26390, 158, 30189, 20728, 19682, 14385,
+ 1677, 8778, 21391, 10110, 21737, 28594, 6701, 15974, 27183, 21294,
+ 29198, 27395, 5594, 20702, 14119, 8323, 10551, 13424, 1976, 16439,
+ 3106, 25307, 7984, 6375, 3857, 29776, 22603, 28777, 7765, 10861,
+ 6781, 19313, 15004, 5813, 13971, 26539, 23225, 1341, 30360, 7175,
+ 6824, 32679, 25845, 4949, 23500, 31828, 3805, 5393, 14972, 3542,
+ 17896, 20608, 31934, 9892, 9470, 24060, 24146, 17682, 23671, 27275,
+ 24051, 7040, 2432, 16823, 28633, 2257, 7361, 10650, 14722, 29983,
+ 5181, 17721, 15026, 26284, 3193, 28947, 1977, 25372, 27872, 19961,
+ 30964, 28898, 13158, 28191, 29590, 19705, 9068, 22644, 12200, 10452,
+ 23523, 22063, 8015, 1175, 6325, 16042, 23374, 31111, 9056, 13684,
+ 14539, 2239, 14052, 3746, 27734, 16934, 23264, 19813, 24103, 22429,
+ 31224, 28898, 5031, 28797, 14201, 829, 21043, 20800, 18496, 7927,
+ 24348, 11134, 21208, 24187, 242, 10780, 6882, 27123, 9730, 3520,
+ 31674, 5984, 21533, 28039, 30295, 20714, 17819, 28667, 22131, 13684,
+ 22432, 4159, 13036, 10100, 11678, 17293, 19819, 15874, 11803, 4835,
+ 5443, 19503, 15541, 31992, 20892, 29335, 21859, 13429, 14032, 28474,
+ 27901, 3682, 27413, 8071, 15103, 13534, 15965, 26810, 20618, 29204,
+ 6522, 31336, 8363, 10090, 26758, 8024, 24032, 17659, 1154, 4245,
+ 20696, 21832, 24637, 32449, 3195, 28970, 31863, 17836, 9002, 12300,
+ 26439, 32294, 16712, 26710, 19130, 25105, 20729, 21548, 20157, 14010,
+ 2857, 28249, 21053, 12649, 6609, 7046, 16268, 2614, 12149, 29616,
+ 7, 12575, 14322, 16345, 21238, 22872, 1654, 32765, 2995, 20194,
+ 9424, 3399, 31503, 19039, 10218, 11397, 2033, 14117, 11667, 9434,
+ 15168, 8081, 26498, 11954, 17155, 13213, 22424, 20219, 12487, 7605,
+ 8550, 29331, 30529, 6599, 5359, 24060, 27445, 666, 22191, 17751,
+ 19351, 18784, 18652, 8336, 5359, 2958, 6635, 4054, 9218, 15083,
+ 7254, 25678, 27566, 3047, 19357, 8456, 16918, 7727, 8843, 2098,
+ 2303, 4990, 9914, 2187, 13690, 2230, 19801, 7963, 31428, 9519,
+ 7469, 290, 7274, 13391, 12758, 8782, 11184, 32091, 1108, 27440,
+ 13364, 19852, 7369, 13297, 7119, 26726, 4480, 22337, 14780, 21061,
+ 30511, 29073, 26876, 10553, 9849, 8322, 6648, 19, 31415, 22173,
+ 10089, 28608, 28152, 5956, 29301, 21206, 13894, 12008, 2586, 24429,
+ 18476, 15229, 25040, 4912, 25205, 6443, 23402, 9652, 1845, 1863,
+ 10302, 29960, 1550, 6529, 17797, 8333, 31660, 18783, 6149, 17927,
+ 27282, 15338, 27373, 5365, 20761, 4007, 22016, 11294, 24757, 18120,
+ 20213, 30061, 14971, 8612, 27166, 29694, 21728, 32101, 3657, 14457,
+ 28356, 2816, 8164, 28575, 13231, 29291, 26468, 16162, 30042, 13834,
+ 14055, 25786, 7793, 27242, 4887, 19317, 17047, 5681, 25426, 2895,
+ 28587, 20053, 27913, 1794, 9289, 25229, 7782, 7199, 3988, 11781,
+ 27698, 6494, 32307, 24662, 18165, 28466, 6298, 21173, 27487, 20129,
+ 22155, 15722, 4582, 10835, 19420, 24965, 16817, 19945, 12922, 31436,
+ 19125, 32656, 21934, 3575, 11038, 24533, 17055, 26400, 25584, 31675,
+ 25113, 23669, 238, 17674, 24460, 10544, 22459, 25835, 344, 29897,
+ 16959, 7346, 22087, 23145, 22604, 10491, 23643, 1187, 27777, 23288,
+ 1227, 12639, 20591, 23561, 14664, 12822, 9211, 20365, 18052, 15429,
+ 13315, 18169, 20469, 7707, 11333, 15399, 12503, 11125, 8316, 1520,
+ 28272, 30477, 12491, 31484, 8087, 11246, 19807, 14041, 28023, 6956,
+ 23889, 13643, 4497, 20945, 19657, 14307, 29952, 19226, 18025, 10707,
+ 21761, 4836, 7145, 30209, 4274, 27745, 8702, 858, 1050, 20751,
+ 897, 19305, 5226, 23531, 20429, 16168, 20866, 29922, 18537, 28182,
+ 20663, 20616, 12775, 9097, 9428, 6156, 11275, 28230, 5982, 19820,
+ 21808, 17999, 1821, 16357, 15592, 17660, 4055, 9390, 27107, 9037,
+ 24415, 10213, 30482, 29311, 23503, 2506, 3083, 17117, 32529, 7211,
+ 13488, 11481, 2980, 13343, 23563, 28763, 32412, 25591, 28285, 7769,
+ 25323, 4466, 26392, 168, 27104, 15408, 19529, 13330, 27885, 2153,
+ 24506, 10408, 15533, 25055, 1398, 31833, 24869, 19217, 9807, 25540,
+ 12107, 11442, 4477, 5451, 22468, 14681, 8583, 27241, 21234, 14714,
+ 10343, 11077, 20014, 21397, 26345, 14471, 32338, 9389, 4948, 1898,
+ 31611, 15612, 13132, 9234, 2573, 21733, 19703, 11809, 29943, 20010,
+ 13151, 901, 23864, 21855, 29207, 3475, 8866, 14239, 7202, 25690,
+ 18909, 16509, 528, 15409, 944, 13373, 4970, 20883, 14716, 14917,
+ 28496, 18221, 17161, 19406, 26721, 10804, 10629, 31455, 32731, 4348,
+ 7114, 9596, 7171, 1991, 30688, 26907, 32200, 16347, 3523, 27223,
+ 14755, 13527, 32614, 17640, 14273, 15430, 25079, 14291, 32612, 13173,
+ 1125, 25054, 20871, 16258, 32544, 8775, 22209, 21430, 28960, 29109,
+ 25707, 29204, 3624, 18287, 7429, 23090, 25164, 24268, 28630, 6728,
+ 28337, 28907, 15315, 13959, 916, 13987, 6594, 23212, 31629, 18109,
+ 4511, 18900, 15381, 9313, 16191, 146, 8007, 4559, 10803, 15679,
+ 10979, 31568, 21743, 25233, 14488, 3691, 18220, 26735, 29571, 20827,
+ 6026, 20228, 20211, 20161, 14458, 18451, 23151, 10647, 3163, 2698,
+ 5882, 11621, 1251, 1113, 12693, 11959, 20929, 24196, 18182, 20430,
+ 25216, 1911, 5336, 32150, 16303, 14235, 15267, 14552, 32575, 9254,
+ 30349, 32689, 22572, 21559, 27665, 27459, 6496, 19490, 31743, 21930,
+ 2004, 776, 11972, 7217, 26616, 22188, 10732, 20934, 13909, 29057,
+ 19941, 30124, 21360, 22280, 24838, 624, 9970, 2648, 27599, 26910,
+ 32263, 766, 10867, 19636, 10500, 25608, 14227, 4567, 7244, 10589,
+ 21581, 5829, 6260, 16208, 29045, 10123, 7589, 14452, 24098, 632,
+ 11842, 5553, 16237, 209, 9419, 21655, 13685, 14278, 8450, 14323,
+ 20903, 9637, 20556, 32416, 16956, 16206, 5465, 31904, 22274, 29159,
+ 21255, 19051, 17248, 27857, 24196, 32391, 16788, 18394, 23731, 9561,
+ 31552, 22964, 3794, 27451, 23333, 21158, 21081, 11471, 11310, 28545,
+ 22565, 24978, 10672, 22742, 22229, 5300, 25840, 614, 15477, 24615,
+ 9190, 7898, 9050, 7670, 7488, 31668, 3660, 17368, 13738, 22918,
+ 12267, 7429, 8781, 5217, 16715, 22088, 5269, 12433, 11234, 4181,
+ 21304, 8071, 2724, 27742, 25716, 20759, 18028, 18145, 11672, 25828,
+ 20894, 5316, 11205, 4120, 18186, 5795, 10742, 2904, 28692, 22121,
+ 6206, 7415, 30226, 8989, 26705, 4969, 17142, 32511, 4934, 17403,
+ 21805, 13268, 11419, 25026, 2759, 382, 9850, 16593, 10199, 6863,
+ 11066, 22959, 7197, 25759, 12329, 8457, 19426, 11036, 9609, 1955,
+ 24612, 16738, 26584, 13972, 25075, 16204, 22101, 23475, 9499, 20873,
+ 12991, 6733, 17923, 20466, 11872, 29721, 16085, 3610, 18506, 15981,
+ 22495, 6695, 24801, 30641, 30522, 24033, 9881, 4373, 5033, 22025,
+ 16385, 127, 20163, 21484, 22273, 11975, 31317, 32056, 26975, 5671,
+ 3330, 32269, 648, 9453, 18988, 8535, 17038, 14451, 8472, 17244,
+ 22125, 17489, 1868, 21137, 17810, 31185, 21052, 21170, 14494, 932,
+ 21542, 5649, 7527, 10707, 16443, 8495, 19519, 29176, 6655, 27785,
+ 4730, 4013, 13298, 30900, 17962, 14661, 368, 26796, 18221, 13498,
+ 16342, 5738, 4458, 12519, 15078, 21940, 17495, 16119, 12397, 22841,
+ 17343, 30, 5922, 28125, 21954, 23431, 19666, 82, 25117, 20621,
+ 28602, 8424, 13995, 14637, 26421, 31142, 29996, 4283, 24471, 27289,
+ 3654, 4821, 15704, 16492, 28105, 18070, 19317, 14649, 15415, 18955,
+ 10515, 19359, 22916, 29163, 14949, 25621, 29978, 4482, 8401, 3197,
+ 26400, 32495, 32334, 12797, 12028, 10127, 2065, 32010, 15126, 18617,
+ 11368, 28613, 24031, 8364, 20454, 16011, 5139, 11205, 26048, 5831,
+ 59, 16886, 26487, 18443, 16245, 10355, 28599, 864, 31607, 27566,
+ 31872, 9434, 24018, 5510, 7299, 15215, 18548, 5051, 3023, 17160,
+ 30577, 25254, 940, 17625, 28675, 20519, 16839, 20974, 24783, 27358,
+ 2704, 3079, 22377, 29086, 10977, 12454, 28443, 22302, 15584, 23142,
+ 23778, 11762, 13350, 27790, 31930, 4282, 29985, 23782, 17435, 23194,
+ 31670, 20426, 15812, 17386, 21803, 14972, 29367, 14126, 28997, 32703,
+ 25733, 29256, 3757, 15009, 31947, 18412, 18072, 11160, 5629, 5461,
+ 31655, 31696, 354, 16438, 12300, 19140, 11872, 20724, 1775, 14860,
+ 22266, 32018, 29968, 27509, 21911, 13805, 25773, 9559, 2053, 4009,
+ 20646, 4387, 25533, 5227, 6879, 18492, 8041, 22472, 8678, 8968,
+ 5539, 24190, 22998, 32326, 17664, 11874, 27771, 27298, 4429, 6810,
+ 9398, 31366, 10776, 8204, 10531, 8756, 14963, 26134, 18938, 24082,
+ 17908, 14208, 26163, 4932, 22272, 1967, 11246, 24192, 25161, 22555,
+ 14353, 17694, 918, 4611, 22835, 31855, 30659, 10335, 31161, 15184,
+ 30728, 5654, 30014, 18943, 23166, 3185, 23865, 17453, 7134, 26063,
+ 28889, 16724, 13964, 12443, 19508, 22346, 27349, 26236, 4769, 11031,
+ 23669, 9163, 6242, 1028, 10589, 29514, 20359, 5364, 23987, 531,
+ 31758, 28663, 26905, 20430, 29519, 22557, 31026, 12071, 27288, 25992,
+ 23906, 10880, 6420, 12229, 22486, 8418, 12529, 29277, 32709, 12090,
+ 29633, 24486, 6389, 14786, 26145, 5599, 1152, 10685, 26265, 27260,
+ 11992, 13159, 11204, 32703, 7945, 14380, 28081, 22664, 2878, 6424,
+ 16008, 24174, 5767, 3471, 22129, 3598, 7129, 21054, 22193, 15779,
+ 10839, 17489, 18454, 12760, 5839, 15590, 22678, 29914, 18056, 16578,
+ 7219, 9136, 5947, 22595, 21794, 9679, 2143, 9110, 1835, 745,
+ 2473, 32554, 23123, 19207, 4820, 19557, 4281, 17623, 26782, 12949,
+ 5054, 22087, 13075, 27689, 23656, 23378, 18701, 29729, 15113, 24346,
+ 21756, 10179, 16923, 27448, 14051, 12432, 22639, 24912, 18339, 19062,
+ 13959, 4840, 24956, 14919, 21312, 2938, 20945, 2154, 947, 16583,
+ 6187, 21457, 21086, 7535, 5761, 20778, 20863, 6591, 5815, 19034,
+ 27841, 22218, 18788, 12839, 32282, 28603, 8664, 8244, 10740, 30057,
+ 13150, 18739, 18059, 18476, 29630, 18262, 21142, 17392, 1798, 18182,
+ 16169, 29319, 30858, 27608, 4314, 14404, 1322, 445, 7203, 11973,
+ 23251, 20089, 24839, 8720, 29001, 5974, 18936, 25570, 24611, 12057,
+ 20985, 26947, 22039, 8245, 22016, 26206, 5495, 18239, 5534, 23696,
+ 6652, 29090, 9953, 20159, 19395, 21652, 24954, 4077, 25493, 28744,
+ 1307, 24588, 25707, 13157, 7971, 19220, 20017, 29368, 29565, 32340,
+ 28107, 2341, 27845, 2053, 28246, 13284, 22445, 13605, 4016, 32490,
+ 28064, 387, 9786, 21924, 29349, 19990, 18396, 3051, 27269, 20882,
+ 19018, 29493, 10544, 30525, 30342, 20488, 16989, 8191, 5543, 17333,
+ 7281, 31161, 15064, 32322, 10914, 24792, 28323, 19624, 4700, 42,
+ 8048, 22335, 16355, 8944, 31560, 9334, 11835, 27956, 5855, 13255,
+ 26181, 28253, 1490, 17642, 31018, 16896, 18477, 8009, 31228, 13049,
+ 12592, 28085, 15003, 5307, 11091, 599, 20438, 18148, 32135, 5865,
+ 8403, 5909, 30143, 23846, 1457, 29952, 7343, 29566, 14699, 11458,
+ 22227, 4623, 8960, 7028, 5812, 977, 14801, 4604, 1127, 16400,
+ 2378, 23081, 15958, 14368, 6084, 4608, 5955, 11596, 13482, 20816,
+ 30089, 8975, 29147, 19853, 14245, 16775, 19536, 28634, 16886, 15398,
+ 18431, 4456, 6593, 4267, 767, 20991, 12664, 12880, 1004, 15578,
+ 19004, 30021, 18317, 12216, 3744, 20062, 20916, 14384, 19120, 15113,
+ 17766, 23365, 25906, 25986, 18492, 31546, 32299, 22858, 13577, 20392,
+ 22181, 23509, 25021, 9165, 26032, 15746, 31882, 20263, 16039, 14033,
+ 17477, 7233, 11444, 9681, 8206, 4558, 10134, 16343, 23091, 20980,
+ 1442, 2933, 594, 1002, 3848, 13994, 15038, 31685, 22104, 7511,
+ 29988, 5263, 31301, 5106, 25199, 28826, 13480, 19070, 6632, 5139,
+ 23240, 23483, 15266, 3546, 13016, 23706, 4629, 8849, 17089, 32755,
+ 30473, 11764, 31778, 8826, 32694, 11880, 27029, 21232, 13353, 11990,
+ 16693, 10902, 21993, 697, 93, 2535, 31195, 2166, 29874, 3462,
+ 31075, 26093, 22115, 20342, 32460, 29517, 22447, 18569, 12522, 18476,
+ 19880, 26139, 16893, 7895, 22071, 10239, 26073, 486, 8033, 23226,
+ 29508, 30740, 13256, 16879, 13472, 8782, 28789, 18203, 11210, 10,
+ 2004, 131, 19777, 19930, 13824, 9322, 30347, 12865, 2625, 15494,
+ 9172, 11461, 27092, 11701, 10457, 31557, 12266, 26605, 28932, 27021,
+ 3826, 21105, 2776, 16168, 5915, 18507, 656, 16245, 1557, 14582,
+ 20483, 28670, 17432, 16731, 23499, 6404, 12840, 20735, 24486, 13407,
+ 11671, 12154, 9756, 16005, 27851, 30251, 28003, 7656, 6466, 21034,
+ 29055, 5253, 19154, 8830, 25005, 28601, 18486, 18064, 17666, 27223,
+ 12486, 12512, 4688, 29945, 29574, 4599, 32585, 22675, 14178, 12189,
+ 19175, 26446, 6328, 15435, 1803, 12179, 24599, 17123, 9572, 25957,
+ 5703, 31391, 19346, 30197, 6537, 5959, 12939, 31088, 6175, 27048,
+ 5438, 30492, 5135, 25665, 29303, 12195, 21541, 22591, 9731, 25007,
+ 26167, 32428, 7444, 15542, 5804, 8675, 10727, 30232, 319, 31559,
+ 15011, 13415, 7937, 6452, 30597, 17669, 30109, 24886, 3130, 20469,
+ 19424, 633, 8332, 32235, 1913, 27777, 17473, 17573, 6141, 7707,
+ 21056, 19838, 4910, 24724, 3830, 10817, 26236, 17192, 1528, 19515,
+ 16844, 27325, 27370, 29076, 8057, 2514, 415, 31967, 3480, 5298,
+ 20865, 27375, 7297, 1517, 10292, 23276, 5771, 18184, 12150, 23719,
+ 25878, 4468, 6730, 31019, 18127, 23485, 11605, 10645, 15151, 9988,
+ 9864, 12325, 18245, 16559, 18431, 1940, 30646, 19551, 2601, 23720,
+ 17410, 10786, 14634, 17927, 14088, 3307, 381, 11849, 205, 21823,
+ 12254, 9296, 21881, 1072, 10343, 1500, 15778, 23183, 22777, 14426,
+ 15309, 30814, 10973, 25597, 27442, 4228, 14251, 25872, 31680, 1220,
+ 17771, 26507, 12129, 32240, 19963, 24804, 15487, 21594, 5553, 23591,
+ 14791, 23692, 5440, 19529, 30509, 27705, 15072, 22714, 26672, 11123,
+ 18089, 22585, 863, 1565, 17984, 28140, 15132, 20900, 29622, 31920,
+ 29600, 31466, 31661, 25774, 6719, 20611, 28349, 16175, 16877, 15652,
+ 25110, 3249, 26882, 1624, 870, 2361, 19514, 25461, 9213, 6892,
+ 27392, 207, 32559, 3801, 8428, 17195, 16377, 6170, 30858, 24439,
+ 2536, 17691, 7005, 6840, 2359, 24377, 803, 17987, 20023, 26767,
+ 20571, 19504, 30708, 11276, 27141, 24588, 29206, 5065, 19113, 10190,
+ 18949, 14746, 7834, 28940, 24401, 26084, 6012, 18031, 29520, 28846,
+ 6404, 31077, 23561, 14586, 8959, 29717, 24144, 9813, 7318, 26520,
+ 29491, 26797, 25808, 10854, 31893, 27235, 19544, 23310, 11545, 10401,
+ 23681, 6955, 10050, 26094, 3975, 30355, 6104, 27391, 24088, 19153,
+ 20365, 18896, 17938, 17110, 8160, 22260, 11919, 15083, 32578, 19754,
+ 19743, 8426, 14455, 20272, 28756, 9390, 10560, 15324, 21380, 19656,
+ 21559, 2152, 24522, 17267, 18938, 5390, 32334, 28619, 11659, 12244,
+ 24518, 12089, 22519, 14762, 23869, 17202, 24374, 8626, 22035, 18209,
+ 1107, 10975, 12102, 17057, 19661, 12225, 22511, 11248, 19260, 22687,
+ 30480, 28320, 23351, 30663, 9868, 19088, 21622, 34, 24439, 7963,
+ 31028, 18955, 31632, 30351, 9175, 6753, 28684, 26081, 30675, 8155,
+ 9622, 5279, 6604, 23196, 4499, 293, 13051, 8712, 29866, 21780,
+ 17362, 15573, 25220, 24064, 2531, 16229, 30416, 32361, 31998, 9299,
+ 23435, 10989, 10137, 21324, 1150, 18363, 24181, 2592, 17416, 31307,
+ 7039, 23576, 7453, 17229, 32757, 15243, 30351, 29919, 16841, 16812,
+ 5004, 22786, 2122, 10406, 30057, 7247, 31745, 11243, 2717, 20710,
+ 3545, 17096, 20241, 7592, 14724, 26942, 16791, 28070, 18201, 27405,
+ 21175, 13272, 20482, 25873, 12466, 5907, 2837, 28881, 5313, 6709,
+ 9217, 11862, 30110, 5283, 8684, 8249, 17221, 3829, 8538, 3584,
+ 4092, 22511, 25937, 24747, 19089, 26035, 955, 11657, 28131, 22326,
+ 12555, 25424, 18851, 10737, 28451, 19821, 18524, 30681, 9077, 24985,
+ 22193, 20880, 22633, 2989, 20455, 2269, 11775, 27575, 5027, 32602,
+ 15798, 14925, 10484, 19820, 30124, 18209, 4755, 21880, 12038, 17878,
+ 14442, 5972, 914, 23826, 2644, 22524, 9899, 11221, 16420, 29063,
+ 17758, 14601, 23272, 24409, 12747, 346, 19311, 23193, 24013, 5959,
+ 25096, 6886, 26845, 2425, 27533, 3909, 17715, 852, 8096, 9054,
+ 14383, 23501, 17461, 25833, 14840, 1659, 10833, 7523, 30819, 6896,
+ 26640, 13317, 278, 26185, 29677, 27638, 22253, 15108, 1342, 21184,
+ 30364, 29458, 24062, 29441, 3734, 22573, 25039, 8035, 28206, 26220,
+ 7743, 27085, 28668, 7445, 10315, 6875, 25475, 20914, 29474, 15756,
+ 14864, 14695, 1067, 4923, 31461, 7298, 10312, 977, 17047, 26708,
+ 3677, 24120, 20917, 4928, 27404, 32019, 28330, 1809, 2499, 9132,
+ 7909, 1424, 28409, 10029, 31543, 15191, 28596, 14356, 9084, 29920,
+ 25167, 24545, 5501, 10721, 19578, 1809, 27413, 21212, 12930, 5968,
+ 17299, 15601, 27603, 3563, 23648, 20472, 8379, 4740, 7394, 31436,
+ 21872, 26121, 6559, 14825, 9813, 15847, 21158, 27706, 6521, 24442,
+ 12587, 27180, 10592, 4040, 2161, 4871, 27911, 11120, 7661, 17534,
+ 290, 31453, 31912, 28805, 5800, 5823, 6117, 17762, 19089, 28860,
+ 260, 7175, 10975, 21602, 13478, 8351, 3291, 29793, 17170, 26983,
+ 6305, 22519, 22487, 28607, 11742, 15531, 25779, 8065, 1497, 16446,
+ 29620, 28817, 14000, 26335, 25757, 16053, 31716, 20894, 6539, 21415,
+ 26648, 14627, 22232, 22377, 25622, 160, 23104, 6873, 7955, 29956,
+};
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
new file mode 100644
index 00000000000..bf14f0b19d3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
@@ -0,0 +1,987 @@
+/** @file
+ Unit tests of the MtrrLib instance of the MtrrLib class
+
+ Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "MtrrLibUnitTest.h"
+
+MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] = {
+ CacheUncacheable, CacheWriteCombining, CacheWriteThrough, CacheWriteProtected, CacheWriteBack
+ };
+
+UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR];
+MSR_IA32_MTRR_PHYSBASE_REGISTER mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR];
+MSR_IA32_MTRR_PHYSMASK_REGISTER mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR];
+MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr;
+MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr;
+CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx;
+CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax;
+
+BOOLEAN mRandomInput;
+UINTN mNumberIndex = 0;
+extern UINTN mNumbers[];
+extern UINTN mNumberCount;
+
+/**
+ Return a random number between 0 and RAND_MAX.
+
+ If mRandomInput is TRUE, the routine directly calls rand().
+ Otherwise, the routine returns the pre-generated numbers.
+
+ @return a number between 0 and RAND_MAX.
+**/
+UINTN
+Rand (
+ VOID
+ )
+{
+ if (mRandomInput) {
+ return rand ();
+ } else {
+ DEBUG ((DEBUG_INFO, "random: %d\n", mNumberIndex));
+ return mNumbers[mNumberIndex++ % (mNumberCount - 1)];
+ }
+}
+
+CHAR8 mContentTemplate[] = {
+ "/** @file\n"
+ " Pre-generated random number used by MtrrLib test.\n"
+ "\n"
+ " Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>\n"
+ " SPDX-License-Identifier: BSD-2-Clause-Patent\n"
+ "**/\n"
+ "UINTN mNumberCount = %d;\n"
+ "UINTN mNumbers[] = {"
+};
+
+/**
+ Generate Count random numbers in FilePath.
+
+ @param FilePath The file path to put the generated random numbers.
+ @param Count Count of random numbers.
+**/
+VOID
+GenerateRandomNumbers (
+ CHAR8 *FilePath,
+ UINTN Count
+ )
+{
+ FILE *File;
+ UINTN Index;
+
+ File = fopen (FilePath, "w");
+ fprintf (File, mContentTemplate, Count);
+ for (Index = 0; Index < Count; Index++) {
+ if (Index % 10 == 0) {
+ fprintf (File, "\n ");
+ }
+ fprintf (File, " %d,", rand ());
+ }
+ fprintf (File, "\n};\n");
+ fclose (File);
+}
+
+/**
+ Retrieves CPUID information.
+
+ Executes the CPUID instruction with EAX set to the value specified by Index.
+ This function always returns Index.
+ If Eax is not NULL, then the value of EAX after CPUID is returned in Eax.
+ If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx.
+ If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx.
+ If Edx is not NULL, then the value of EDX after CPUID is returned in Edx.
+ This function is only available on IA-32 and x64.
+
+ @param Index The 32-bit value to load into EAX prior to invoking the CPUID
+ instruction.
+ @param Eax The pointer to the 32-bit EAX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ebx The pointer to the 32-bit EBX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Ecx The pointer to the 32-bit ECX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+ @param Edx The pointer to the 32-bit EDX value returned by the CPUID
+ instruction. This is an optional parameter that may be NULL.
+
+ @return Index.
+
+**/
+UINT32
+EFIAPI
+UnitTestMtrrLibAsmCpuid (
+ IN UINT32 Index,
+ OUT UINT32 *Eax, OPTIONAL
+ OUT UINT32 *Ebx, OPTIONAL
+ OUT UINT32 *Ecx, OPTIONAL
+ OUT UINT32 *Edx OPTIONAL
+ )
+{
+ switch (Index) {
+ case CPUID_VERSION_INFO:
+ if (Edx != NULL) {
+ *Edx = mCpuidVersionInfoEdx.Uint32;
+ }
+ return Index;
+ break;
+ case CPUID_EXTENDED_FUNCTION:
+ if (Eax != NULL) {
+ *Eax = CPUID_VIR_PHY_ADDRESS_SIZE;
+ }
+ return Index;
+ break;
+ case CPUID_VIR_PHY_ADDRESS_SIZE:
+ if (Eax != NULL) {
+ *Eax = mCpuidVirPhyAddressSizeEax.Uint32;
+ }
+ return Index;
+ break;
+ }
+
+ //
+ // Should never fall through to here
+ //
+ ASSERT(FALSE);
+ return Index;
+}
+
+/**
+ Returns a 64-bit Machine Specific Register(MSR).
+
+ Reads and returns the 64-bit MSR specified by Index. No parameter checking is
+ performed on Index, and some Index values may cause CPU exceptions. The
+ caller must either guarantee that Index is valid, or the caller must set up
+ exception handlers to catch the exceptions. This function is only available
+ on IA-32 and x64.
+
+ @param MsrIndex The 32-bit MSR index to read.
+
+ @return The value of the MSR identified by MsrIndex.
+
+**/
+UINT64
+EFIAPI
+UnitTestMtrrLibAsmReadMsr64(
+ IN UINT32 MsrIndex
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
+ if (MsrIndex == mFixedMtrrsIndex[Index]) {
+ return mFixedMtrrsValue[Index];
+ }
+ }
+
+ if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
+ (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) {
+ if (MsrIndex % 2 == 0) {
+ Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
+ return mVariableMtrrsPhysBase[Index].Uint64;
+ } else {
+ Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
+ return mVariableMtrrsPhysMask[Index].Uint64;
+ }
+ }
+
+ if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
+ return mDefTypeMsr.Uint64;
+ }
+
+ if (MsrIndex == MSR_IA32_MTRRCAP) {
+ return mMtrrCapMsr.Uint64;
+ }
+
+ //
+ // Should never fall through to here
+ //
+ ASSERT(FALSE);
+ return 0;
+}
+
+/**
+ Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
+ value.
+
+ Writes the 64-bit value specified by Value to the MSR specified by Index. The
+ 64-bit value written to the MSR is returned. No parameter checking is
+ performed on Index or Value, and some of these may cause CPU exceptions. The
+ caller must either guarantee that Index and Value are valid, or the caller
+ must establish proper exception handlers. This function is only available on
+ IA-32 and x64.
+
+ @param MsrIndex The 32-bit MSR index to write.
+ @param Value The 64-bit value to write to the MSR.
+
+ @return Value
+
+**/
+UINT64
+EFIAPI
+UnitTestMtrrLibAsmWriteMsr64(
+ IN UINT32 MsrIndex,
+ IN UINT64 Value
+ )
+{
+ UINT32 Index;
+
+ for (Index = 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) {
+ if (MsrIndex == mFixedMtrrsIndex[Index]) {
+ mFixedMtrrsValue[Index] = Value;
+ return Value;
+ }
+ }
+
+ if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) &&
+ (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 + (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) {
+ if (MsrIndex % 2 == 0) {
+ Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1;
+ mVariableMtrrsPhysBase[Index].Uint64 = Value;
+ return Value;
+ } else {
+ Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1;
+ mVariableMtrrsPhysMask[Index].Uint64 = Value;
+ return Value;
+ }
+ }
+
+ if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) {
+ mDefTypeMsr.Uint64 = Value;
+ return Value;
+ }
+
+ if (MsrIndex == MSR_IA32_MTRRCAP) {
+ mMtrrCapMsr.Uint64 = Value;
+ return Value;
+ }
+
+ //
+ // Should never fall through to here
+ //
+ ASSERT(FALSE);
+ return 0;
+}
+
+/**
+ Initialize the MTRR registers.
+
+ @param SystemParameter System parameter that controls the MTRR registers initialization.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+InitializeMtrrRegs (
+ IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter
+ )
+{
+ UINT32 Index;
+
+ SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), SystemParameter->DefaultCacheType);
+
+ for (Index = 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Index++) {
+ mVariableMtrrsPhysBase[Index].Uint64 = 0;
+ mVariableMtrrsPhysBase[Index].Bits.Type = SystemParameter->DefaultCacheType;
+ mVariableMtrrsPhysBase[Index].Bits.Reserved1 = 0;
+
+ mVariableMtrrsPhysMask[Index].Uint64 = 0;
+ mVariableMtrrsPhysMask[Index].Bits.V = 0;
+ mVariableMtrrsPhysMask[Index].Bits.Reserved1 = 0;
+ }
+
+ mDefTypeMsr.Bits.E = 1;
+ mDefTypeMsr.Bits.FE = 1;
+ mDefTypeMsr.Bits.Type = SystemParameter->DefaultCacheType;
+ mDefTypeMsr.Bits.Reserved1 = 0;
+ mDefTypeMsr.Bits.Reserved2 = 0;
+ mDefTypeMsr.Bits.Reserved3 = 0;
+
+ mMtrrCapMsr.Bits.SMRR = 0;
+ mMtrrCapMsr.Bits.WC = 0;
+ mMtrrCapMsr.Bits.VCNT = SystemParameter->VariableMtrrCount;
+ mMtrrCapMsr.Bits.FIX = SystemParameter->FixedMtrrSupported;
+ mMtrrCapMsr.Bits.Reserved1 = 0;
+ mMtrrCapMsr.Bits.Reserved2 = 0;
+ mMtrrCapMsr.Bits.Reserved3 = 0;
+
+ mCpuidVersionInfoEdx.Bits.MTRR = SystemParameter->MtrrSupported;
+ mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits = SystemParameter->PhysicalAddressBits;
+
+ //
+ // Hook BaseLib functions used by MtrrLib that require some emulation.
+ //
+ gUnitTestHostBaseLib.X86->AsmCpuid = UnitTestMtrrLibAsmCpuid;
+ gUnitTestHostBaseLib.X86->AsmReadMsr64 = UnitTestMtrrLibAsmReadMsr64;
+ gUnitTestHostBaseLib.X86->AsmWriteMsr64 = UnitTestMtrrLibAsmWriteMsr64;
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Initialize the MTRR registers.
+
+ @param Context System parameter that controls the MTRR registers initialization.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+InitializeSystem (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ return InitializeMtrrRegs ((MTRR_LIB_SYSTEM_PARAMETER *) Context);
+}
+
+/**
+ Collect the test result.
+
+ @param DefaultType Default memory type.
+ @param PhysicalAddressBits Physical address bits.
+ @param VariableMtrrCount Count of variable MTRRs.
+ @param Mtrrs MTRR settings to collect from.
+ @param Ranges Return the memory ranges.
+ @param RangeCount Return the count of memory ranges.
+ @param MtrrCount Return the count of variable MTRRs being used.
+**/
+VOID
+CollectTestResult (
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,
+ IN UINT32 PhysicalAddressBits,
+ IN UINT32 VariableMtrrCount,
+ IN MTRR_SETTINGS *Mtrrs,
+ OUT MTRR_MEMORY_RANGE *Ranges,
+ IN OUT UINTN *RangeCount,
+ OUT UINT32 *MtrrCount
+ )
+{
+ UINTN Index;
+ UINT64 MtrrValidBitsMask;
+ UINT64 MtrrValidAddressMask;
+ MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];
+
+ ASSERT (Mtrrs != NULL);
+ ASSERT (VariableMtrrCount <= ARRAY_SIZE (Mtrrs->Variables.Mtrr));
+
+ MtrrValidBitsMask = (1ull << PhysicalAddressBits) - 1;
+ MtrrValidAddressMask = MtrrValidBitsMask & ~0xFFFull;
+
+ *MtrrCount = 0;
+ for (Index = 0; Index < VariableMtrrCount; Index++) {
+ if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs->Variables.Mtrr[Index].Mask)->Bits.V == 1) {
+ RawMemoryRanges[*MtrrCount].BaseAddress = Mtrrs->Variables.Mtrr[Index].Base & MtrrValidAddressMask;
+ RawMemoryRanges[*MtrrCount].Type =
+ ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs->Variables.Mtrr[Index].Base)->Bits.Type;
+ RawMemoryRanges[*MtrrCount].Length =
+ ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
+ (*MtrrCount)++;
+ }
+ }
+
+ GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, RawMemoryRanges, *MtrrCount, Ranges, RangeCount);
+}
+
+/**
+ Return a 32bit random number.
+
+ @param Start Start of the random number range.
+ @param Limit Limit of the random number range.
+ @return 32bit random number
+**/
+UINT32
+Random32 (
+ UINT32 Start,
+ UINT32 Limit
+ )
+{
+ return (UINT32) (((double) Rand () / RAND_MAX) * (Limit - Start)) + Start;
+}
+
+/**
+ Return a 64bit random number.
+
+ @param Start Start of the random number range.
+ @param Limit Limit of the random number range.
+ @return 64bit random number
+**/
+UINT64
+Random64 (
+ UINT64 Start,
+ UINT64 Limit
+ )
+{
+ return (UINT64) (((double) Rand () / RAND_MAX) * (Limit - Start)) + Start;
+}
+
+/**
+ Generate random MTRR BASE/MASK for a specified type.
+
+ @param PhysicalAddressBits Physical address bits.
+ @param CacheType Cache type.
+ @param MtrrPair Return the random MTRR.
+ @param MtrrMemoryRange Return the random memory range.
+**/
+VOID
+GenerateRandomMtrrPair (
+ IN UINT32 PhysicalAddressBits,
+ IN MTRR_MEMORY_CACHE_TYPE CacheType,
+ OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL
+ OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL
+ )
+{
+ MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase;
+ MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask;
+ UINT32 SizeShift;
+ UINT32 BaseShift;
+ UINT64 RandomBoundary;
+ UINT64 MaxPhysicalAddress;
+ UINT64 RangeSize;
+ UINT64 RangeBase;
+ UINT64 PhysBasePhyMaskValidBitsMask;
+
+ MaxPhysicalAddress = 1ull << PhysicalAddressBits;
+ do {
+ SizeShift = Random32 (12, PhysicalAddressBits - 1);
+ RangeSize = 1ull << SizeShift;
+
+ BaseShift = Random32 (SizeShift, PhysicalAddressBits - 1);
+ RandomBoundary = Random64 (0, 1ull << (PhysicalAddressBits - BaseShift));
+ RangeBase = RandomBoundary << BaseShift;
+ } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1);
+
+ PhysBasePhyMaskValidBitsMask = (MaxPhysicalAddress - 1) & 0xfffffffffffff000ULL;
+
+ PhysBase.Uint64 = 0;
+ PhysBase.Bits.Type = CacheType;
+ PhysBase.Uint64 |= RangeBase & PhysBasePhyMaskValidBitsMask;
+ PhysMask.Uint64 = 0;
+ PhysMask.Bits.V = 1;
+ PhysMask.Uint64 |= ((~RangeSize) + 1) & PhysBasePhyMaskValidBitsMask;
+
+ if (MtrrPair != NULL) {
+ MtrrPair->Base = PhysBase.Uint64;
+ MtrrPair->Mask = PhysMask.Uint64;
+ }
+
+ if (MtrrMemoryRange != NULL) {
+ MtrrMemoryRange->BaseAddress = RangeBase;
+ MtrrMemoryRange->Length = RangeSize;
+ MtrrMemoryRange->Type = CacheType;
+ }
+}
+
+
+/**
+ Check whether the Range overlaps with any one in Ranges.
+
+ @param Range The memory range to check.
+ @param Ranges The memory ranges.
+ @param Count Count of memory ranges.
+
+ @return TRUE when overlap exists.
+**/
+BOOLEAN
+RangesOverlap (
+ IN MTRR_MEMORY_RANGE *Range,
+ IN MTRR_MEMORY_RANGE *Ranges,
+ IN UINTN Count
+ )
+{
+ while (Count-- != 0) {
+ //
+ // Two ranges overlap when:
+ // 1. range#2.base is in the middle of range#1
+ // 2. range#1.base is in the middle of range#2
+ //
+ if ((Range->BaseAddress <= Ranges[Count].BaseAddress && Ranges[Count].BaseAddress < Range->BaseAddress + Range->Length)
+ || (Ranges[Count].BaseAddress <= Range->BaseAddress && Range->BaseAddress < Ranges[Count].BaseAddress + Ranges[Count].Length)) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ Generate random MTRRs.
+
+ @param PhysicalAddressBits Physical address bits.
+ @param RawMemoryRanges Return the randomly generated MTRRs.
+ @param UcCount Count of Uncacheable MTRRs.
+ @param WtCount Count of Write Through MTRRs.
+ @param WbCount Count of Write Back MTRRs.
+ @param WpCount Count of Write Protected MTRRs.
+ @param WcCount Count of Write Combine MTRRs.
+**/
+VOID
+GenerateValidAndConfigurableMtrrPairs (
+ IN UINT32 PhysicalAddressBits,
+ IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges,
+ IN UINT32 UcCount,
+ IN UINT32 WtCount,
+ IN UINT32 WbCount,
+ IN UINT32 WpCount,
+ IN UINT32 WcCount
+ )
+{
+ UINT32 Index;
+
+ //
+ // 1. Generate UC, WT, WB in order.
+ //
+ for (Index = 0; Index < UcCount; Index++) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheUncacheable, NULL, &RawMemoryRanges[Index]);
+ }
+
+ for (Index = UcCount; Index < UcCount + WtCount; Index++) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, NULL, &RawMemoryRanges[Index]);
+ }
+
+ for (Index = UcCount + WtCount; Index < UcCount + WtCount + WbCount; Index++) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, &RawMemoryRanges[Index]);
+ }
+
+ //
+ // 2. Generate WP MTRR and DO NOT overlap with WT, WB.
+ //
+ for (Index = UcCount + WtCount + WbCount; Index < UcCount + WtCount + WbCount + WpCount; Index++) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
+ while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount)) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, NULL, &RawMemoryRanges[Index]);
+ }
+ }
+
+ //
+ // 3. Generate WC MTRR and DO NOT overlap with WT, WB, WP.
+ //
+ for (Index = UcCount + WtCount + WbCount + WpCount; Index < UcCount + WtCount + WbCount + WpCount + WcCount; Index++) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NULL, &RawMemoryRanges[Index]);
+ while (RangesOverlap (&RawMemoryRanges[Index], &RawMemoryRanges[UcCount], WtCount + WbCount + WpCount)) {
+ GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, NULL, &RawMemoryRanges[Index]);
+ }
+ }
+}
+
+/**
+ Return a random memory cache type.
+**/
+MTRR_MEMORY_CACHE_TYPE
+GenerateRandomCacheType (
+ VOID
+ )
+{
+ return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE (mMemoryCacheTypes) - 1)];
+}
+
+/**
+ Compare function used by qsort().
+**/
+
+/**
+ Compare function used by qsort().
+
+ @param Left Left operand to compare.
+ @param Right Right operand to compare.
+
+ @retval 0 Left == Right
+ @retval -1 Left < Right
+ @retval 1 Left > Right
+**/
+INT32
+CompareFuncUint64 (
+ CONST VOID * Left,
+ CONST VOID * Right
+ )
+{
+ INT64 Delta;
+ Delta = (*(UINT64*)Left - *(UINT64*)Right);
+ if (Delta > 0) {
+ return 1;
+ } else if (Delta == 0) {
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/**
+ Determin the memory cache type for the Range.
+
+ @param DefaultType Default cache type.
+ @param Range The memory range to determin the cache type.
+ @param Ranges The entire memory ranges.
+ @param RangeCount Count of the entire memory ranges.
+**/
+VOID
+DetermineMemoryCacheType (
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,
+ IN OUT MTRR_MEMORY_RANGE *Range,
+ IN MTRR_MEMORY_RANGE *Ranges,
+ IN UINT32 RangeCount
+ )
+{
+ UINT32 Index;
+ Range->Type = CacheInvalid;
+ for (Index = 0; Index < RangeCount; Index++) {
+ if (RangesOverlap (Range, &Ranges[Index], 1)) {
+ if (Ranges[Index].Type < Range->Type) {
+ Range->Type = Ranges[Index].Type;
+ }
+ }
+ }
+
+ if (Range->Type == CacheInvalid) {
+ Range->Type = DefaultType;
+ }
+}
+
+/**
+ Get the index of the element that does NOT equals to Array[Index].
+
+ @param Index Current element.
+ @param Array Array to scan.
+ @param Count Count of the array.
+
+ @return Next element that doesn't equal to current one.
+**/
+UINT32
+GetNextDifferentElementInSortedArray (
+ IN UINT32 Index,
+ IN UINT64 *Array,
+ IN UINT32 Count
+ )
+{
+ UINT64 CurrentElement;
+ CurrentElement = Array[Index];
+ while (CurrentElement == Array[Index] && Index < Count) {
+ Index++;
+ }
+ return Index;
+}
+
+/**
+ Remove the duplicates from the array.
+
+ @param Array The array to operate on.
+ @param Count Count of the array.
+**/
+VOID
+RemoveDuplicatesInSortedArray (
+ IN OUT UINT64 *Array,
+ IN OUT UINT32 *Count
+ )
+{
+ UINT32 Index;
+ UINT32 NewCount;
+
+ Index = 0;
+ NewCount = 0;
+ while (Index < *Count) {
+ Array[NewCount] = Array[Index];
+ NewCount++;
+ Index = GetNextDifferentElementInSortedArray (Index, Array, *Count);
+ }
+ *Count = NewCount;
+}
+
+/**
+ Return TRUE when Address is in the Range.
+
+ @param Address The address to check.
+ @param Range The range to check.
+ @return TRUE when Address is in the Range.
+**/
+BOOLEAN
+AddressInRange (
+ IN UINT64 Address,
+ IN MTRR_MEMORY_RANGE Range
+ )
+{
+ return (Address >= Range.BaseAddress) && (Address <= Range.BaseAddress + Range.Length - 1);
+}
+
+/**
+ Get the overlap bit flag.
+
+ @param RawMemoryRanges Raw memory ranges.
+ @param RawMemoryRangeCount Count of raw memory ranges.
+ @param Address The address to check.
+**/
+UINT64
+GetOverlapBitFlag (
+ IN MTRR_MEMORY_RANGE *RawMemoryRanges,
+ IN UINT32 RawMemoryRangeCount,
+ IN UINT64 Address
+ )
+{
+ UINT64 OverlapBitFlag;
+ UINT32 Index;
+ OverlapBitFlag = 0;
+ for (Index = 0; Index < RawMemoryRangeCount; Index++) {
+ if (AddressInRange (Address, RawMemoryRanges[Index])) {
+ OverlapBitFlag |= (1ull << Index);
+ }
+ }
+
+ return OverlapBitFlag;
+}
+
+/**
+ Return the relationship between flags.
+
+ @param Flag1 Flag 1
+ @param Flag2 Flag 2
+
+ @retval 0 Flag1 == Flag2
+ @retval 1 Flag1 is a subset of Flag2
+ @retval 2 Flag2 is a subset of Flag1
+ @retval 3 No subset relations between Flag1 and Flag2.
+**/
+UINT32
+CheckOverlapBitFlagsRelation (
+ IN UINT64 Flag1,
+ IN UINT64 Flag2
+ )
+{
+ if (Flag1 == Flag2) return 0;
+ if ((Flag1 | Flag2) == Flag2) return 1;
+ if ((Flag1 | Flag2) == Flag1) return 2;
+ return 3;
+}
+
+/**
+ Return TRUE when the Endpoint is in any of the Ranges.
+
+ @param Endpoint The endpoint to check.
+ @param Ranges The memory ranges.
+ @param RangeCount Count of memory ranges.
+
+ @retval TRUE Endpoint is in one of the range.
+ @retval FALSE Endpoint is not in any of the ranges.
+**/
+BOOLEAN
+IsEndpointInRanges (
+ IN UINT64 Endpoint,
+ IN MTRR_MEMORY_RANGE *Ranges,
+ IN UINTN RangeCount
+ )
+{
+ UINT32 Index;
+ for (Index = 0; Index < RangeCount; Index++) {
+ if (AddressInRange (Endpoint, Ranges[Index])) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+/**
+ Compact adjacent ranges of the same type.
+
+ @param DefaultType Default memory type.
+ @param PhysicalAddressBits Physical address bits.
+ @param EffectiveMtrrMemoryRanges Memory ranges to compact.
+ @param EffectiveMtrrMemoryRangesCount Return the new count of memory ranges.
+**/
+VOID
+CompactAndExtendEffectiveMtrrMemoryRanges (
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,
+ IN UINT32 PhysicalAddressBits,
+ IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges,
+ IN OUT UINTN *EffectiveMtrrMemoryRangesCount
+ )
+{
+ UINT64 MaxAddress;
+ UINTN NewRangesCountAtMost;
+ MTRR_MEMORY_RANGE *NewRanges;
+ UINTN NewRangesCountActual;
+ MTRR_MEMORY_RANGE *CurrentRangeInNewRanges;
+ MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges;
+
+ MTRR_MEMORY_RANGE *OldRanges;
+ MTRR_MEMORY_RANGE OldLastRange;
+ UINTN OldRangesIndex;
+
+ NewRangesCountActual = 0;
+ NewRangesCountAtMost = *EffectiveMtrrMemoryRangesCount + 2; // At most with 2 more range entries.
+ NewRanges = (MTRR_MEMORY_RANGE *) calloc (NewRangesCountAtMost, sizeof (MTRR_MEMORY_RANGE));
+ OldRanges = *EffectiveMtrrMemoryRanges;
+ if (OldRanges[0].BaseAddress > 0) {
+ NewRanges[NewRangesCountActual].BaseAddress = 0;
+ NewRanges[NewRangesCountActual].Length = OldRanges[0].BaseAddress;
+ NewRanges[NewRangesCountActual].Type = DefaultType;
+ NewRangesCountActual++;
+ }
+
+ OldRangesIndex = 0;
+ while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) {
+ CurrentRangeTypeInOldRanges = OldRanges[OldRangesIndex].Type;
+ CurrentRangeInNewRanges = NULL;
+ if (NewRangesCountActual > 0) // We need to check CurrentNewRange first before generate a new NewRange.
+ {
+ CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
+ }
+ if (CurrentRangeInNewRanges != NULL && CurrentRangeInNewRanges->Type == CurrentRangeTypeInOldRanges) {
+ CurrentRangeInNewRanges->Length += OldRanges[OldRangesIndex].Length;
+ } else {
+ NewRanges[NewRangesCountActual].BaseAddress = OldRanges[OldRangesIndex].BaseAddress;
+ NewRanges[NewRangesCountActual].Length += OldRanges[OldRangesIndex].Length;
+ NewRanges[NewRangesCountActual].Type = CurrentRangeTypeInOldRanges;
+ while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && OldRanges[OldRangesIndex + 1].Type == CurrentRangeTypeInOldRanges)
+ {
+ OldRangesIndex++;
+ NewRanges[NewRangesCountActual].Length += OldRanges[OldRangesIndex].Length;
+ }
+ NewRangesCountActual++;
+ }
+
+ OldRangesIndex++;
+ }
+
+ MaxAddress = (1ull << PhysicalAddressBits) - 1;
+ OldLastRange = OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1];
+ CurrentRangeInNewRanges = &NewRanges[NewRangesCountActual - 1];
+ if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) {
+ if (CurrentRangeInNewRanges->Type == DefaultType) {
+ CurrentRangeInNewRanges->Length = MaxAddress - CurrentRangeInNewRanges->BaseAddress + 1;
+ } else {
+ NewRanges[NewRangesCountActual].BaseAddress = OldLastRange.BaseAddress + OldLastRange.Length;
+ NewRanges[NewRangesCountActual].Length = MaxAddress - NewRanges[NewRangesCountActual].BaseAddress + 1;
+ NewRanges[NewRangesCountActual].Type = DefaultType;
+ NewRangesCountActual++;
+ }
+ }
+
+ free (*EffectiveMtrrMemoryRanges);
+ *EffectiveMtrrMemoryRanges = NewRanges;
+ *EffectiveMtrrMemoryRangesCount = NewRangesCountActual;
+}
+
+/**
+ Collect all the endpoints in the raw memory ranges.
+
+ @param Endpoints Return the collected endpoints.
+ @param EndPointCount Return the count of endpoints.
+ @param RawMemoryRanges Raw memory ranges.
+ @param RawMemoryRangeCount Count of raw memory ranges.
+**/
+VOID
+CollectEndpoints (
+ IN OUT UINT64 *Endpoints,
+ IN OUT UINT32 *EndPointCount,
+ IN MTRR_MEMORY_RANGE *RawMemoryRanges,
+ IN UINT32 RawMemoryRangeCount
+ )
+{
+ UINT32 Index;
+ UINT32 RawRangeIndex;
+
+ ASSERT ((RawMemoryRangeCount << 1) == *EndPointCount);
+
+ for (Index = 0; Index < *EndPointCount; Index += 2) {
+ RawRangeIndex = Index >> 1;
+ Endpoints[Index] = RawMemoryRanges[RawRangeIndex].BaseAddress;
+ Endpoints[Index + 1] = RawMemoryRanges[RawRangeIndex].BaseAddress + RawMemoryRanges[RawRangeIndex].Length - 1;
+ }
+
+ qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint64);
+ RemoveDuplicatesInSortedArray (Endpoints, EndPointCount);
+}
+
+/**
+ Convert the MTRR BASE/MASK array to memory ranges.
+
+ @param DefaultType Default memory type.
+ @param PhysicalAddressBits Physical address bits.
+ @param RawMemoryRanges Raw memory ranges.
+ @param RawMemoryRangeCount Count of raw memory ranges.
+ @param MemoryRanges Memory ranges.
+ @param MemoryRangeCount Count of memory ranges.
+**/
+VOID
+GetEffectiveMemoryRanges (
+ IN MTRR_MEMORY_CACHE_TYPE DefaultType,
+ IN UINT32 PhysicalAddressBits,
+ IN MTRR_MEMORY_RANGE *RawMemoryRanges,
+ IN UINT32 RawMemoryRangeCount,
+ OUT MTRR_MEMORY_RANGE *MemoryRanges,
+ OUT UINTN *MemoryRangeCount
+ )
+{
+ UINTN Index;
+ UINT32 AllEndPointsCount;
+ UINT64 *AllEndPointsInclusive;
+ UINT32 AllRangePiecesCountMax;
+ MTRR_MEMORY_RANGE *AllRangePieces;
+ UINTN AllRangePiecesCountActual;
+ UINT64 OverlapBitFlag1;
+ UINT64 OverlapBitFlag2;
+ INT32 OverlapFlagRelation;
+
+ if (RawMemoryRangeCount == 0) {
+ MemoryRanges[0].BaseAddress = 0;
+ MemoryRanges[0].Length = (1ull << PhysicalAddressBits);
+ MemoryRanges[0].Type = DefaultType;
+ *MemoryRangeCount = 1;
+ return;
+ }
+
+ AllEndPointsCount = RawMemoryRangeCount << 1;
+ AllEndPointsInclusive = calloc (AllEndPointsCount, sizeof (UINT64));
+ AllRangePiecesCountMax = RawMemoryRangeCount * 3 + 1;
+ AllRangePieces = calloc (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE));
+ CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, RawMemoryRanges, RawMemoryRangeCount);
+
+ for (Index = 0, AllRangePiecesCountActual = 0; Index < AllEndPointsCount - 1; Index++) {
+ OverlapBitFlag1 = GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[Index]);
+ OverlapBitFlag2 = GetOverlapBitFlag (RawMemoryRanges, RawMemoryRangeCount, AllEndPointsInclusive[Index + 1]);
+ OverlapFlagRelation = CheckOverlapBitFlagsRelation (OverlapBitFlag1, OverlapBitFlag2);
+ switch (OverlapFlagRelation) {
+ case 0: // [1, 2]
+ AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
+ AllRangePieces[AllRangePiecesCountActual].Length = AllEndPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1;
+ AllRangePiecesCountActual++;
+ break;
+ case 1: // [1, 2)
+ AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
+ AllRangePieces[AllRangePiecesCountActual].Length = (AllEndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1;
+ AllRangePiecesCountActual++;
+ break;
+ case 2: // (1, 2]
+ AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index] + 1;
+ AllRangePieces[AllRangePiecesCountActual].Length = AllEndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1;
+ AllRangePiecesCountActual++;
+
+ if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual)) {
+ AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
+ AllRangePieces[AllRangePiecesCountActual].Length = 1;
+ AllRangePiecesCountActual++;
+ }
+ break;
+ case 3: // (1, 2)
+ AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index] + 1;
+ AllRangePieces[AllRangePiecesCountActual].Length = (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Index] + 1) + 1;
+ if (AllRangePieces[AllRangePiecesCountActual].Length == 0) // Only in case 3 can exists Length=0, we should skip such "segment".
+ break;
+ AllRangePiecesCountActual++;
+ if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangePieces, AllRangePiecesCountActual)) {
+ AllRangePieces[AllRangePiecesCountActual].BaseAddress = AllEndPointsInclusive[Index];
+ AllRangePieces[AllRangePiecesCountActual].Length = 1;
+ AllRangePiecesCountActual++;
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ }
+ }
+
+ for (Index = 0; Index < AllRangePiecesCountActual; Index++) {
+ DetermineMemoryCacheType (DefaultType, &AllRangePieces[Index], RawMemoryRanges, RawMemoryRangeCount);
+ }
+
+ CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, PhysicalAddressBits, &AllRangePieces, &AllRangePiecesCountActual);
+ ASSERT (*MemoryRangeCount >= AllRangePiecesCountActual);
+ memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual * sizeof (MTRR_MEMORY_RANGE));
+ *MemoryRangeCount = AllRangePiecesCountActual;
+
+ free (AllEndPointsInclusive);
+ free (AllRangePieces);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
index 42df4ecc440..9c1c95c4821 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
@@ -103,14 +103,16 @@ CpuInitDataInitialize (
UINT32 Package;
UINT32 Thread;
EFI_CPU_PHYSICAL_LOCATION *Location;
- BOOLEAN *CoresVisited;
- UINTN Index;
UINT32 PackageIndex;
UINT32 CoreIndex;
- UINT32 First;
+ UINTN Pages;
+ UINT32 FirstPackage;
+ UINT32 *FirstCore;
+ UINT32 *FirstThread;
ACPI_CPU_DATA *AcpiCpuData;
CPU_STATUS_INFORMATION *CpuStatus;
- UINT32 *ValidCoreCountPerPackage;
+ UINT32 *ThreadCountPerPackage;
+ UINT8 *ThreadCountPerCore;
UINTN NumberOfCpus;
UINTN NumberOfEnabledProcessors;
@@ -127,8 +129,9 @@ CpuInitDataInitialize (
GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
- CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);
+ CpuFeaturesData->InitOrder = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus));
ASSERT (CpuFeaturesData->InitOrder != NULL);
+ ZeroMem (CpuFeaturesData->InitOrder, sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);
//
// Collect CPU Features information
@@ -202,35 +205,32 @@ CpuInitDataInitialize (
//
// Collect valid core count in each package because not all cores are valid.
//
- ValidCoreCountPerPackage= AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount);
- ASSERT (ValidCoreCountPerPackage != 0);
- CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ValidCoreCountPerPackage;
- CoresVisited = AllocatePool (sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);
- ASSERT (CoresVisited != NULL);
-
- for (Index = 0; Index < CpuStatus->PackageCount; Index ++ ) {
- ZeroMem (CoresVisited, sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);
- //
- // Collect valid cores in Current package.
- //
- for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
- Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- if (Location->Package == Index && !CoresVisited[Location->Core] ) {
- //
- // The ValidCores position for Location->Core is valid.
- // The possible values in ValidCores[Index] are 0 or 1.
- // FALSE means no valid threads in this Core.
- // TRUE means have valid threads in this core, no matter the thead count is 1 or more.
- //
- CoresVisited[Location->Core] = TRUE;
- ValidCoreCountPerPackage[Index]++;
- }
- }
+ ThreadCountPerPackage = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount);
+ ASSERT (ThreadCountPerPackage != NULL);
+ CpuStatus->ThreadCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ThreadCountPerPackage;
+
+ ThreadCountPerCore = AllocateZeroPool (sizeof (UINT8) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount);
+ ASSERT (ThreadCountPerCore != NULL);
+ CpuStatus->ThreadCountPerCore = (EFI_PHYSICAL_ADDRESS)(UINTN)ThreadCountPerCore;
+
+ for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
+ Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
+ ThreadCountPerPackage[Location->Package]++;
+ ThreadCountPerCore[Location->Package * CpuStatus->MaxCoreCount + Location->Core]++;
}
- FreePool (CoresVisited);
- for (Index = 0; Index <= Package; Index++) {
- DEBUG ((DEBUG_INFO, "Package: %d, Valid Core : %d\n", Index, ValidCoreCountPerPackage[Index]));
+ for (PackageIndex = 0; PackageIndex < CpuStatus->PackageCount; PackageIndex++) {
+ if (ThreadCountPerPackage[PackageIndex] != 0) {
+ DEBUG ((DEBUG_INFO, "P%02d: Thread Count = %d\n", PackageIndex, ThreadCountPerPackage[PackageIndex]));
+ for (CoreIndex = 0; CoreIndex < CpuStatus->MaxCoreCount; CoreIndex++) {
+ if (ThreadCountPerCore[PackageIndex * CpuStatus->MaxCoreCount + CoreIndex] != 0) {
+ DEBUG ((
+ DEBUG_INFO, " P%02d C%04d, Thread Count = %d\n", PackageIndex, CoreIndex,
+ ThreadCountPerCore[PackageIndex * CpuStatus->MaxCoreCount + CoreIndex]
+ ));
+ }
+ }
+ }
}
CpuFeaturesData->CpuFlags.CoreSemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);
@@ -240,74 +240,69 @@ CpuInitDataInitialize (
//
// Initialize CpuFeaturesData->InitOrder[].CpuInfo.First
+ // Use AllocatePages () instead of AllocatePool () because pool cannot be freed in PEI phase but page can.
//
+ Pages = EFI_SIZE_TO_PAGES (CpuStatus->PackageCount * sizeof (UINT32) + CpuStatus->PackageCount * CpuStatus->MaxCoreCount * sizeof (UINT32));
+ FirstCore = AllocatePages (Pages);
+ ASSERT (FirstCore != NULL);
+ FirstThread = FirstCore + CpuStatus->PackageCount;
//
- // Set First.Package for each thread belonging to the first package.
+ // Set FirstPackage, FirstCore[], FirstThread[] to maximum package ID, core ID, thread ID.
//
- First = MAX_UINT32;
+ FirstPackage = MAX_UINT32;
+ SetMem32 (FirstCore, CpuStatus->PackageCount * sizeof (UINT32), MAX_UINT32);
+ SetMem32 (FirstThread, CpuStatus->PackageCount * CpuStatus->MaxCoreCount * sizeof (UINT32), MAX_UINT32);
+
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- First = MIN (Location->Package, First);
+
+ //
+ // Save the minimum package ID in the platform.
+ //
+ FirstPackage = MIN (Location->Package, FirstPackage);
+
+ //
+ // Save the minimum core ID per package.
+ //
+ FirstCore[Location->Package] = MIN (Location->Core, FirstCore[Location->Package]);
+
+ //
+ // Save the minimum thread ID per core.
+ //
+ FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core] = MIN (
+ Location->Thread,
+ FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core]
+ );
}
+
+ //
+ // Update the First field.
+ //
for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- if (Location->Package == First) {
+
+ if (Location->Package == FirstPackage) {
CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Package = 1;
}
- }
- //
- // Set First.Die/Tile/Module for each thread assuming:
- // single Die under each package, single Tile under each Die, single Module under each Tile
- //
- for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
+ //
+ // Set First.Die/Tile/Module for each thread assuming:
+ // single Die under each package, single Tile under each Die, single Module under each Tile
+ //
CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Die = 1;
CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Tile = 1;
CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Module = 1;
- }
- for (PackageIndex = 0; PackageIndex < CpuStatus->PackageCount; PackageIndex++) {
- //
- // Set First.Core for each thread in the first core of each package.
- //
- First = MAX_UINT32;
- for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
- Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- if (Location->Package == PackageIndex) {
- First = MIN (Location->Core, First);
- }
+ if (Location->Core == FirstCore[Location->Package]) {
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Core = 1;
}
-
- for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
- Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- if (Location->Package == PackageIndex && Location->Core == First) {
- CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Core = 1;
- }
+ if (Location->Thread == FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core]) {
+ CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Thread = 1;
}
}
- for (PackageIndex = 0; PackageIndex < CpuStatus->PackageCount; PackageIndex++) {
- for (CoreIndex = 0; CoreIndex < CpuStatus->MaxCoreCount; CoreIndex++) {
- //
- // Set First.Thread for the first thread of each core.
- //
- First = MAX_UINT32;
- for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
- Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- if (Location->Package == PackageIndex && Location->Core == CoreIndex) {
- First = MIN (Location->Thread, First);
- }
- }
-
- for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
- Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;
- if (Location->Package == PackageIndex && Location->Core == CoreIndex && Location->Thread == First) {
- CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Thread = 1;
- }
- }
- }
- }
+ FreePages (FirstCore, Pages);
}
/**
@@ -894,11 +889,11 @@ ProgramProcessorRegister (
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
volatile UINT32 *SemaphorePtr;
UINT32 FirstThread;
- UINT32 PackageThreadsCount;
UINT32 CurrentThread;
+ UINT32 CurrentCore;
UINTN ProcessorIndex;
- UINTN ValidThreadCount;
- UINT32 *ValidCoreCountPerPackage;
+ UINT32 *ThreadCountPerPackage;
+ UINT8 *ThreadCountPerCore;
EFI_STATUS Status;
UINT64 CurrentValue;
@@ -1029,28 +1024,44 @@ ProgramProcessorRegister (
switch (RegisterTableEntry->Value) {
case CoreDepType:
SemaphorePtr = CpuFlags->CoreSemaphoreCount;
+ ThreadCountPerCore = (UINT8 *)(UINTN)CpuStatus->ThreadCountPerCore;
+
+ CurrentCore = ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core;
//
// Get Offset info for the first thread in the core which current thread belongs to.
//
- FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount;
+ FirstThread = CurrentCore * CpuStatus->MaxThreadCount;
CurrentThread = FirstThread + ApLocation->Thread;
+
//
- // First Notify all threads in current Core that this thread has ready.
+ // Different cores may have different valid threads in them. If driver maintail clearly
+ // thread index in different cores, the logic will be much complicated.
+ // Here driver just simply records the max thread number in all cores and use it as expect
+ // thread number for all cores.
+ // In below two steps logic, first current thread will Release semaphore for each thread
+ // in current core. Maybe some threads are not valid in this core, but driver don't
+ // care. Second, driver will let current thread wait semaphore for all valid threads in
+ // current core. Because only the valid threads will do release semaphore for this
+ // thread, driver here only need to wait the valid thread count.
+ //
+
+ //
+ // First Notify ALL THREADs in current Core that this thread is ready.
//
for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {
- LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);
+ LibReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);
}
//
- // Second, check whether all valid threads in current core have ready.
+ // Second, check whether all VALID THREADs (not all threads) in current core are ready.
//
- for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {
+ for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerCore[CurrentCore]; ProcessorIndex ++) {
LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);
}
break;
case PackageDepType:
SemaphorePtr = CpuFlags->PackageSemaphoreCount;
- ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;
+ ThreadCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ThreadCountPerPackage;
//
// Get Offset info for the first thread in the package which current thread belongs to.
//
@@ -1058,18 +1069,13 @@ ProgramProcessorRegister (
//
// Get the possible threads count for current package.
//
- PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount;
CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;
- //
- // Get the valid thread count for current package.
- //
- ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package];
//
- // Different packages may have different valid cores in them. If driver maintail clearly
- // cores number in different packages, the logic will be much complicated.
- // Here driver just simply records the max core number in all packages and use it as expect
- // core number for all packages.
+ // Different packages may have different valid threads in them. If driver maintail clearly
+ // thread index in different packages, the logic will be much complicated.
+ // Here driver just simply records the max thread number in all packages and use it as expect
+ // thread number for all packages.
// In below two steps logic, first current thread will Release semaphore for each thread
// in current package. Maybe some threads are not valid in this package, but driver don't
// care. Second, driver will let current thread wait semaphore for all valid threads in
@@ -1078,15 +1084,15 @@ ProgramProcessorRegister (
//
//
- // First Notify ALL THREADS in current package that this thread has ready.
+ // First Notify ALL THREADS in current package that this thread is ready.
//
- for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {
- LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; ProcessorIndex ++) {
+ LibReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);
}
//
- // Second, check whether VALID THREADS (not all threads) in current package have ready.
+ // Second, check whether VALID THREADS (not all threads) in current package are ready.
//
- for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {
+ for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerPackage[ApLocation->Package]; ProcessorIndex ++) {
LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);
}
break;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
index d10afa6f758..860a5295fe6 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
@@ -1,7 +1,7 @@
/** @file
CPU Register Table Library functions.
- Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -11,7 +11,6 @@
#include <Library/HobLib.h>
#include <Library/PeiServicesLib.h>
#include <Library/PeiServicesTablePointerLib.h>
-#include <Ppi/MpServices.h>
#include <Ppi/MpServices2.h>
#include "RegisterCpuFeatures.h"
@@ -75,10 +74,10 @@ GetMpService (
MP_SERVICES MpService;
//
- // Get MP Services Protocol
+ // Get MP Services2 Ppi
//
Status = PeiServicesLocatePpi (
- &gEfiPeiMpServicesPpiGuid,
+ &gEdkiiPeiMpServices2PpiGuid,
0,
NULL,
(VOID **)&MpService.Ppi
@@ -100,17 +99,17 @@ GetProcessorIndex (
)
{
EFI_STATUS Status;
- EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;
+ EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
UINTN ProcessorIndex;
- CpuMpPpi = CpuFeaturesData->MpService.Ppi;
+ CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
//
// For two reasons which use NULL for WhoAmI:
// 1. This function will be called by APs and AP should not use PeiServices Table
// 2. Check WhoAmI implementation, this parameter will not be used.
//
- Status = CpuMpPpi->WhoAmI(NULL, CpuMpPpi, &ProcessorIndex);
+ Status = CpuMp2Ppi->WhoAmI (CpuMp2Ppi, &ProcessorIndex);
ASSERT_EFI_ERROR (Status);
return ProcessorIndex;
}
@@ -131,16 +130,15 @@ GetProcessorInformation (
OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
)
{
- EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;
+ EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
EFI_STATUS Status;
CPU_FEATURES_DATA *CpuFeaturesData;
CpuFeaturesData = GetCpuFeaturesData ();
- CpuMpPpi = CpuFeaturesData->MpService.Ppi;
+ CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
- Status = CpuMpPpi->GetProcessorInfo (
- GetPeiServicesTablePointer(),
- CpuMpPpi,
+ Status = CpuMp2Ppi->GetProcessorInfo (
+ CpuMp2Ppi,
ProcessorNumber,
ProcessorInfoBuffer
);
@@ -162,18 +160,17 @@ StartupAllAPsWorker (
)
{
EFI_STATUS Status;
- EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;
+ EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
CPU_FEATURES_DATA *CpuFeaturesData;
CpuFeaturesData = GetCpuFeaturesData ();
- CpuMpPpi = CpuFeaturesData->MpService.Ppi;
+ CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
//
// Wakeup all APs for data collection.
//
- Status = CpuMpPpi->StartupAllAPs (
- GetPeiServicesTablePointer (),
- CpuMpPpi,
+ Status = CpuMp2Ppi->StartupAllAPs (
+ CpuMp2Ppi,
Procedure,
FALSE,
0,
@@ -203,17 +200,7 @@ StartupAllCPUsWorker (
//
// Get MP Services2 Ppi
//
- Status = PeiServicesLocatePpi (
- &gEdkiiPeiMpServices2PpiGuid,
- 0,
- NULL,
- (VOID **)&CpuMp2Ppi
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Wakeup all APs for data collection.
- //
+ CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
Status = CpuMp2Ppi->StartupAllCPUs (
CpuMp2Ppi,
Procedure,
@@ -234,18 +221,17 @@ SwitchNewBsp (
)
{
EFI_STATUS Status;
- EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;
+ EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
CPU_FEATURES_DATA *CpuFeaturesData;
CpuFeaturesData = GetCpuFeaturesData ();
- CpuMpPpi = CpuFeaturesData->MpService.Ppi;
+ CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
//
// Wakeup all APs for data collection.
//
- Status = CpuMpPpi->SwitchBSP (
- GetPeiServicesTablePointer (),
- CpuMpPpi,
+ Status = CpuMp2Ppi->SwitchBSP (
+ CpuMp2Ppi,
ProcessorNumber,
TRUE
);
@@ -269,18 +255,17 @@ GetNumberOfProcessor (
)
{
EFI_STATUS Status;
- EFI_PEI_MP_SERVICES_PPI *CpuMpPpi;
+ EDKII_PEI_MP_SERVICES2_PPI *CpuMp2Ppi;
CPU_FEATURES_DATA *CpuFeaturesData;
CpuFeaturesData = GetCpuFeaturesData ();
- CpuMpPpi = CpuFeaturesData->MpService.Ppi;
+ CpuMp2Ppi = CpuFeaturesData->MpService.Ppi;
//
// Get the number of CPUs
//
- Status = CpuMpPpi->GetNumberOfProcessors (
- GetPeiServicesTablePointer (),
- CpuMpPpi,
+ Status = CpuMp2Ppi->GetNumberOfProcessors (
+ CpuMp2Ppi,
NumberOfCpus,
NumberOfEnabledProcessors
);
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf
index fdbdfc73453..159cba73c46 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf
@@ -1,7 +1,7 @@
## @file
# Register CPU Features Library PEI instance.
#
-# Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -45,7 +45,6 @@
IoLib
[Ppis]
- gEfiPeiMpServicesPpiGuid ## CONSUMES
gEdkiiPeiMpServices2PpiGuid ## CONSUMES
[Pcd]
@@ -55,4 +54,4 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesSetting ## CONSUMES ## PRODUCES
[Depex]
- gEfiPeiMpServicesPpiGuid AND gEdkiiCpuFeaturesSetDoneGuid
+ gEdkiiPeiMpServices2PpiGuid AND gEdkiiCpuFeaturesSetDoneGuid
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeatures.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeatures.h
index d3d6c18f1d5..d798993ab2a 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeatures.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeatures.h
@@ -10,7 +10,7 @@
#define _REGISTER_CPU_FEATURES_H_
#include <PiPei.h>
#include <PiDxe.h>
-#include <Ppi/MpServices.h>
+#include <Ppi/MpServices2.h>
#include <Protocol/MpService.h>
#include <Library/BaseLib.h>
@@ -64,8 +64,8 @@ typedef struct {
} PROGRAM_CPU_REGISTER_FLAGS;
typedef union {
- EFI_MP_SERVICES_PROTOCOL *Protocol;
- EFI_PEI_MP_SERVICES_PPI *Ppi;
+ EFI_MP_SERVICES_PROTOCOL *Protocol;
+ EDKII_PEI_MP_SERVICES2_PPI *Ppi;
} MP_SERVICES;
typedef struct {
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
index 0bbe66e64b1..2661690ed2c 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
@@ -1,7 +1,7 @@
/** @file
CPU Register Table Library functions.
- Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -937,45 +937,52 @@ GetAcpiCpuData (
EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);
- if (AcpiCpuData != NULL) {
- return AcpiCpuData;
- }
-
- AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));
- ASSERT (AcpiCpuData != NULL);
+ if (AcpiCpuData == NULL) {
+ AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));
+ ASSERT (AcpiCpuData != NULL);
+ ZeroMem (AcpiCpuData, sizeof (ACPI_CPU_DATA));
- //
- // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
- //
- Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
- ASSERT_EFI_ERROR (Status);
+ //
+ // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure
+ //
+ Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);
+ ASSERT_EFI_ERROR (Status);
- GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
- AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
+ GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
+ AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;
+ }
- //
- // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
- //
- TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
- RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));
- ASSERT (RegisterTable != NULL);
+ if (AcpiCpuData->RegisterTable == 0 ||
+ AcpiCpuData->PreSmmInitRegisterTable == 0) {
+ //
+ // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs
+ //
+ NumberOfCpus = AcpiCpuData->NumberOfCpus;
+ TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);
+ RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));
+ ASSERT (RegisterTable != NULL);
- for (Index = 0; Index < NumberOfCpus; Index++) {
- Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);
- ASSERT_EFI_ERROR (Status);
+ for (Index = 0; Index < NumberOfCpus; Index++) {
+ Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);
+ ASSERT_EFI_ERROR (Status);
- RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
- RegisterTable[Index].TableLength = 0;
- RegisterTable[Index].AllocatedSize = 0;
- RegisterTable[Index].RegisterTableEntry = 0;
+ RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
+ RegisterTable[Index].TableLength = 0;
+ RegisterTable[Index].AllocatedSize = 0;
+ RegisterTable[Index].RegisterTableEntry = 0;
- RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
- RegisterTable[NumberOfCpus + Index].TableLength = 0;
- RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;
- RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
+ RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;
+ RegisterTable[NumberOfCpus + Index].TableLength = 0;
+ RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;
+ RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;
+ }
+ if (AcpiCpuData->RegisterTable == 0) {
+ AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
+ }
+ if (AcpiCpuData->PreSmmInitRegisterTable == 0) {
+ AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
+ }
}
- AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;
- AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);
return AcpiCpuData;
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h
new file mode 100644
index 00000000000..5928fbb84bf
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h
@@ -0,0 +1,48 @@
+/** @file
+ Internal library function definitions.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef CPU_FEATURES_LIB_H_
+#define CPU_FEATURES_LIB_H_
+
+/**
+ Performs library initialization.
+
+ This initialization function contains common functionality shared betwen all
+ library instance constructors.
+
+**/
+VOID
+CpuFeaturesLibInitialization (
+ VOID
+ );
+
+/**
+ Internal worker function that is called to complete CPU initialization at the
+ end of SmmCpuFeaturesInitializeProcessor().
+
+**/
+VOID
+FinishSmmCpuFeaturesInitializeProcessor (
+ VOID
+ );
+
+/**
+ Gets the maximum number of logical processors from the PCD PcdCpuMaxLogicalProcessorNumber.
+
+ This access is abstracted from the PCD services to enforce that the PCD be
+ FixedAtBuild in the Standalone MM build of this driver.
+
+ @return The value of PcdCpuMaxLogicalProcessorNumber.
+
+**/
+UINT32
+GetCpuMaxLogicalProcessorNumber (
+ VOID
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c
index b0798d8df89..d6166b75895 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/Ia32/SmmStmSupport.c
@@ -6,7 +6,7 @@
**/
-#include <PiSmm.h>
+#include <PiMm.h>
#include <Library/DebugLib.h>
#include "SmmStm.h"
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
index 4de831a5ae1..7cb6639df2b 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
@@ -1,78 +1,16 @@
/** @file
-The CPU specific programming for PiSmmCpuDxeSmm module.
+Implementation specific to the SmmCpuFeatureLib library instance.
-Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiSmm.h>
-#include <Library/SmmCpuFeaturesLib.h>
-#include <Library/BaseLib.h>
-#include <Library/MtrrLib.h>
-#include <Library/PcdLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DebugLib.h>
-#include <Register/Intel/Cpuid.h>
-#include <Register/Intel/SmramSaveStateMap.h>
-
-//
-// Machine Specific Registers (MSRs)
-//
-#define SMM_FEATURES_LIB_IA32_MTRR_CAP 0x0FE
-#define SMM_FEATURES_LIB_IA32_FEATURE_CONTROL 0x03A
-#define SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE 0x1F2
-#define SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK 0x1F3
-#define SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE 0x0A0
-#define SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK 0x0A1
-#define EFI_MSR_SMRR_MASK 0xFFFFF000
-#define EFI_MSR_SMRR_PHYS_MASK_VALID BIT11
-#define SMM_FEATURES_LIB_SMM_FEATURE_CONTROL 0x4E0
-
-//
-// MSRs required for configuration of SMM Code Access Check
-//
-#define SMM_FEATURES_LIB_IA32_MCA_CAP 0x17D
-#define SMM_CODE_ACCESS_CHK_BIT BIT58
-
-/**
- Internal worker function that is called to complete CPU initialization at the
- end of SmmCpuFeaturesInitializeProcessor().
-
-**/
-VOID
-FinishSmmCpuFeaturesInitializeProcessor (
- VOID
- );
-
-//
-// Set default value to assume SMRR is not supported
-//
-BOOLEAN mSmrrSupported = FALSE;
-
-//
-// Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
-//
-BOOLEAN mSmmFeatureControlSupported = FALSE;
-
-//
-// Set default value to assume IA-32 Architectural MSRs are used
-//
-UINT32 mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
-UINT32 mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
-
-//
-// Set default value to assume MTRRs need to be configured on each SMI
-//
-BOOLEAN mNeedConfigureMtrrs = TRUE;
-
-//
-// Array for state of SMRR enable on all CPUs
-//
-BOOLEAN *mSmrrEnabled;
+#include <PiMm.h>
+#include "CpuFeaturesLib.h"
/**
- The constructor function
+ The constructor function for the Traditional MM library instance without STM.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@@ -87,540 +25,7 @@ SmmCpuFeaturesLibConstructor (
IN EFI_SYSTEM_TABLE *SystemTable
)
{
- UINT32 RegEax;
- UINT32 RegEdx;
- UINTN FamilyId;
- UINTN ModelId;
-
- //
- // Retrieve CPU Family and Model
- //
- AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
- FamilyId = (RegEax >> 8) & 0xf;
- ModelId = (RegEax >> 4) & 0xf;
- if (FamilyId == 0x06 || FamilyId == 0x0f) {
- ModelId = ModelId | ((RegEax >> 12) & 0xf0);
- }
-
- //
- // Check CPUID(CPUID_VERSION_INFO).EDX[12] for MTRR capability
- //
- if ((RegEdx & BIT12) != 0) {
- //
- // Check MTRR_CAP MSR bit 11 for SMRR support
- //
- if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MTRR_CAP) & BIT11) != 0) {
- mSmrrSupported = TRUE;
- }
- }
-
- //
- // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- // Volume 3C, Section 35.3 MSRs in the Intel(R) Atom(TM) Processor Family
- //
- // If CPU Family/Model is 06_1CH, 06_26H, 06_27H, 06_35H or 06_36H, then
- // SMRR Physical Base and SMM Physical Mask MSRs are not available.
- //
- if (FamilyId == 0x06) {
- if (ModelId == 0x1C || ModelId == 0x26 || ModelId == 0x27 || ModelId == 0x35 || ModelId == 0x36) {
- mSmrrSupported = FALSE;
- }
- }
-
- //
- // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
- //
- // If CPU Family/Model is 06_0F or 06_17, then use Intel(R) Core(TM) 2
- // Processor Family MSRs
- //
- if (FamilyId == 0x06) {
- if (ModelId == 0x17 || ModelId == 0x0f) {
- mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE;
- mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK;
- }
- }
-
- //
- // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- // Volume 3C, Section 34.4.2 SMRAM Caching
- // An IA-32 processor does not automatically write back and invalidate its
- // caches before entering SMM or before exiting SMM. Because of this behavior,
- // care must be taken in the placement of the SMRAM in system memory and in
- // the caching of the SMRAM to prevent cache incoherence when switching back
- // and forth between SMM and protected mode operation.
- //
- // An IA-32 processor is a processor that does not support the Intel 64
- // Architecture. Support for the Intel 64 Architecture can be detected from
- // CPUID(CPUID_EXTENDED_CPU_SIG).EDX[29]
- //
- // If an IA-32 processor is detected, then set mNeedConfigureMtrrs to TRUE,
- // so caches are flushed on SMI entry and SMI exit, the interrupted code
- // MTRRs are saved/restored, and MTRRs for SMM are loaded.
- //
- AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
- if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
- AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
- if ((RegEdx & BIT29) != 0) {
- mNeedConfigureMtrrs = FALSE;
- }
- }
-
- //
- // Allocate array for state of SMRR enable on all CPUs
- //
- mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
- ASSERT (mSmrrEnabled != NULL);
+ CpuFeaturesLibInitialization ();
return EFI_SUCCESS;
}
-
-/**
- Called during the very first SMI into System Management Mode to initialize
- CPU features, including SMBASE, for the currently executing CPU. Since this
- is the first SMI, the SMRAM Save State Map is at the default address of
- SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
- CPU is specified by CpuIndex and CpuIndex can be used to access information
- about the currently executing CPU in the ProcessorInfo array and the
- HotPlugCpuData data structure.
-
- @param[in] CpuIndex The index of the CPU to initialize. The value
- must be between 0 and the NumberOfCpus field in
- the System Management System Table (SMST).
- @param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
- was elected as monarch during System Management
- Mode initialization.
- FALSE if the CpuIndex is not the index of the CPU
- that was elected as monarch during System
- Management Mode initialization.
- @param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
- structures. ProcessorInfo[CpuIndex] contains the
- information for the currently executing CPU.
- @param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
- contains the ApidId and SmBase arrays.
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesInitializeProcessor (
- IN UINTN CpuIndex,
- IN BOOLEAN IsMonarch,
- IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
- IN CPU_HOT_PLUG_DATA *CpuHotPlugData
- )
-{
- SMRAM_SAVE_STATE_MAP *CpuState;
- UINT64 FeatureControl;
- UINT32 RegEax;
- UINT32 RegEdx;
- UINTN FamilyId;
- UINTN ModelId;
-
- //
- // Configure SMBASE.
- //
- CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
- CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
-
- //
- // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
- //
- // If Intel(R) Core(TM) Core(TM) 2 Processor Family MSRs are being used, then
- // make sure SMRR Enable(BIT3) of MSR_FEATURE_CONTROL MSR(0x3A) is set before
- // accessing SMRR base/mask MSRs. If Lock(BIT0) of MSR_FEATURE_CONTROL MSR(0x3A)
- // is set, then the MSR is locked and can not be modified.
- //
- if (mSmrrSupported && mSmrrPhysBaseMsr == SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE) {
- FeatureControl = AsmReadMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL);
- if ((FeatureControl & BIT3) == 0) {
- if ((FeatureControl & BIT0) == 0) {
- AsmWriteMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL, FeatureControl | BIT3);
- } else {
- mSmrrSupported = FALSE;
- }
- }
- }
-
- //
- // If SMRR is supported, then program SMRR base/mask MSRs.
- // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first normal SMI.
- // The code that initializes SMM environment is running in normal mode
- // from SMRAM region. If SMRR is enabled here, then the SMRAM region
- // is protected and the normal mode code execution will fail.
- //
- if (mSmrrSupported) {
- //
- // SMRR size cannot be less than 4-KBytes
- // SMRR size must be of length 2^n
- // SMRR base alignment cannot be less than SMRR length
- //
- if ((CpuHotPlugData->SmrrSize < SIZE_4KB) ||
- (CpuHotPlugData->SmrrSize != GetPowerOfTwo32 (CpuHotPlugData->SmrrSize)) ||
- ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) != CpuHotPlugData->SmrrBase)) {
- //
- // Print message and halt if CPU is Monarch
- //
- if (IsMonarch) {
- DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size requirement!\n"));
- CpuDeadLoop ();
- }
- } else {
- AsmWriteMsr64 (mSmrrPhysBaseMsr, CpuHotPlugData->SmrrBase | MTRR_CACHE_WRITE_BACK);
- AsmWriteMsr64 (mSmrrPhysMaskMsr, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK));
- mSmrrEnabled[CpuIndex] = FALSE;
- }
- }
-
- //
- // Retrieve CPU Family and Model
- //
- AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
- FamilyId = (RegEax >> 8) & 0xf;
- ModelId = (RegEax >> 4) & 0xf;
- if (FamilyId == 0x06 || FamilyId == 0x0f) {
- ModelId = ModelId | ((RegEax >> 12) & 0xf0);
- }
-
- //
- // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- // Volume 3C, Section 35.10.1 MSRs in 4th Generation Intel(R) Core(TM)
- // Processor Family.
- //
- // If CPU Family/Model is 06_3C, 06_45, or 06_46 then use 4th Generation
- // Intel(R) Core(TM) Processor Family MSRs.
- //
- if (FamilyId == 0x06) {
- if (ModelId == 0x3C || ModelId == 0x45 || ModelId == 0x46 ||
- ModelId == 0x3D || ModelId == 0x47 || ModelId == 0x4E || ModelId == 0x4F ||
- ModelId == 0x3F || ModelId == 0x56 || ModelId == 0x57 || ModelId == 0x5C) {
- //
- // Check to see if the CPU supports the SMM Code Access Check feature
- // Do not access this MSR unless the CPU supports the SmmRegFeatureControl
- //
- if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) != 0) {
- mSmmFeatureControlSupported = TRUE;
- }
- }
- }
-
- //
- // Call internal worker function that completes the CPU initialization
- //
- FinishSmmCpuFeaturesInitializeProcessor ();
-}
-
-/**
- This function updates the SMRAM save state on the currently executing CPU
- to resume execution at a specific address after an RSM instruction. This
- function must evaluate the SMRAM save state to determine the execution mode
- the RSM instruction resumes and update the resume execution address with
- either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
- flag in the SMRAM save state must always be cleared. This function returns
- the value of the instruction pointer from the SMRAM save state that was
- replaced. If this function returns 0, then the SMRAM save state was not
- modified.
-
- This function is called during the very first SMI on each CPU after
- SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
- to signal that the SMBASE of each CPU has been updated before the default
- SMBASE address is used for the first SMI to the next CPU.
-
- @param[in] CpuIndex The index of the CPU to hook. The value
- must be between 0 and the NumberOfCpus
- field in the System Management System Table
- (SMST).
- @param[in] CpuState Pointer to SMRAM Save State Map for the
- currently executing CPU.
- @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
- 32-bit execution mode from 64-bit SMM.
- @param[in] NewInstructionPointer Instruction pointer to use if resuming to
- same execution mode as SMM.
-
- @retval 0 This function did modify the SMRAM save state.
- @retval > 0 The original instruction pointer value from the SMRAM save state
- before it was replaced.
-**/
-UINT64
-EFIAPI
-SmmCpuFeaturesHookReturnFromSmm (
- IN UINTN CpuIndex,
- IN SMRAM_SAVE_STATE_MAP *CpuState,
- IN UINT64 NewInstructionPointer32,
- IN UINT64 NewInstructionPointer
- )
-{
- return 0;
-}
-
-/**
- Hook point in normal execution mode that allows the one CPU that was elected
- as monarch during System Management Mode initialization to perform additional
- initialization actions immediately after all of the CPUs have processed their
- first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
- into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesSmmRelocationComplete (
- VOID
- )
-{
-}
-
-/**
- Determines if MTRR registers must be configured to set SMRAM cache-ability
- when executing in System Management Mode.
-
- @retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
- @retval FALSE MTRR registers do not need to be configured to set SMRAM
- cache-ability.
-**/
-BOOLEAN
-EFIAPI
-SmmCpuFeaturesNeedConfigureMtrrs (
- VOID
- )
-{
- return mNeedConfigureMtrrs;
-}
-
-/**
- Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
- returns TRUE.
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesDisableSmrr (
- VOID
- )
-{
- if (mSmrrSupported && mNeedConfigureMtrrs) {
- AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
- }
-}
-
-/**
- Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
- returns TRUE.
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesReenableSmrr (
- VOID
- )
-{
- if (mSmrrSupported && mNeedConfigureMtrrs) {
- AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
- }
-}
-
-/**
- Processor specific hook point each time a CPU enters System Management Mode.
-
- @param[in] CpuIndex The index of the CPU that has entered SMM. The value
- must be between 0 and the NumberOfCpus field in the
- System Management System Table (SMST).
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesRendezvousEntry (
- IN UINTN CpuIndex
- )
-{
- //
- // If SMRR is supported and this is the first normal SMI, then enable SMRR
- //
- if (mSmrrSupported && !mSmrrEnabled[CpuIndex]) {
- AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
- mSmrrEnabled[CpuIndex] = TRUE;
- }
-}
-
-/**
- Processor specific hook point each time a CPU exits System Management Mode.
-
- @param[in] CpuIndex The index of the CPU that is exiting SMM. The value must
- be between 0 and the NumberOfCpus field in the System
- Management System Table (SMST).
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesRendezvousExit (
- IN UINTN CpuIndex
- )
-{
-}
-
-/**
- Check to see if an SMM register is supported by a specified CPU.
-
- @param[in] CpuIndex The index of the CPU to check for SMM register support.
- The value must be between 0 and the NumberOfCpus field
- in the System Management System Table (SMST).
- @param[in] RegName Identifies the SMM register to check for support.
-
- @retval TRUE The SMM register specified by RegName is supported by the CPU
- specified by CpuIndex.
- @retval FALSE The SMM register specified by RegName is not supported by the
- CPU specified by CpuIndex.
-**/
-BOOLEAN
-EFIAPI
-SmmCpuFeaturesIsSmmRegisterSupported (
- IN UINTN CpuIndex,
- IN SMM_REG_NAME RegName
- )
-{
- if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- Returns the current value of the SMM register for the specified CPU.
- If the SMM register is not supported, then 0 is returned.
-
- @param[in] CpuIndex The index of the CPU to read the SMM register. The
- value must be between 0 and the NumberOfCpus field in
- the System Management System Table (SMST).
- @param[in] RegName Identifies the SMM register to read.
-
- @return The value of the SMM register specified by RegName from the CPU
- specified by CpuIndex.
-**/
-UINT64
-EFIAPI
-SmmCpuFeaturesGetSmmRegister (
- IN UINTN CpuIndex,
- IN SMM_REG_NAME RegName
- )
-{
- if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
- return AsmReadMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL);
- }
- return 0;
-}
-
-/**
- Sets the value of an SMM register on a specified CPU.
- If the SMM register is not supported, then no action is performed.
-
- @param[in] CpuIndex The index of the CPU to write the SMM register. The
- value must be between 0 and the NumberOfCpus field in
- the System Management System Table (SMST).
- @param[in] RegName Identifies the SMM register to write.
- registers are read-only.
- @param[in] Value The value to write to the SMM register.
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesSetSmmRegister (
- IN UINTN CpuIndex,
- IN SMM_REG_NAME RegName,
- IN UINT64 Value
- )
-{
- if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
- AsmWriteMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL, Value);
- }
-}
-
-/**
- Read an SMM Save State register on the target processor. If this function
- returns EFI_UNSUPPORTED, then the caller is responsible for reading the
- SMM Save Sate register.
-
- @param[in] CpuIndex The index of the CPU to read the SMM Save State. The
- value must be between 0 and the NumberOfCpus field in
- the System Management System Table (SMST).
- @param[in] Register The SMM Save State register to read.
- @param[in] Width The number of bytes to read from the CPU save state.
- @param[out] Buffer Upon return, this holds the CPU register value read
- from the save state.
-
- @retval EFI_SUCCESS The register was read from Save State.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_UNSUPPORTED This function does not support reading Register.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmCpuFeaturesReadSaveStateRegister (
- IN UINTN CpuIndex,
- IN EFI_SMM_SAVE_STATE_REGISTER Register,
- IN UINTN Width,
- OUT VOID *Buffer
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- Writes an SMM Save State register on the target processor. If this function
- returns EFI_UNSUPPORTED, then the caller is responsible for writing the
- SMM Save Sate register.
-
- @param[in] CpuIndex The index of the CPU to write the SMM Save State. The
- value must be between 0 and the NumberOfCpus field in
- the System Management System Table (SMST).
- @param[in] Register The SMM Save State register to write.
- @param[in] Width The number of bytes to write to the CPU save state.
- @param[in] Buffer Upon entry, this holds the new CPU register value.
-
- @retval EFI_SUCCESS The register was written to Save State.
- @retval EFI_INVALID_PARAMETER Buffer is NULL.
- @retval EFI_UNSUPPORTED This function does not support writing Register.
-**/
-EFI_STATUS
-EFIAPI
-SmmCpuFeaturesWriteSaveStateRegister (
- IN UINTN CpuIndex,
- IN EFI_SMM_SAVE_STATE_REGISTER Register,
- IN UINTN Width,
- IN CONST VOID *Buffer
- )
-{
- return EFI_UNSUPPORTED;
-}
-
-/**
- This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
- notification is completely processed.
-**/
-VOID
-EFIAPI
-SmmCpuFeaturesCompleteSmmReadyToLock (
- VOID
- )
-{
-}
-
-/**
- This API provides a method for a CPU to allocate a specific region for storing page tables.
-
- This API can be called more once to allocate memory for page tables.
-
- Allocates the number of 4KB pages of type EfiRuntimeServicesData 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 remaining to satisfy the request, then NULL is
- returned.
-
- This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
-
- @param Pages The number of 4 KB pages to allocate.
-
- @return A pointer to the allocated buffer for page tables.
- @retval NULL Fail to allocate a specific region for storing page tables,
- Or there is no preference on where the page tables are allocated in SMRAM.
-
-**/
-VOID *
-EFIAPI
-SmmCpuFeaturesAllocatePageTableMemory (
- IN UINTN Pages
- )
-{
- return NULL;
-}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
index af0e622bda2..e504218a497 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
@@ -17,8 +17,11 @@
CONSTRUCTOR = SmmCpuFeaturesLibConstructor
[Sources]
+ CpuFeaturesLib.h
SmmCpuFeaturesLib.c
+ SmmCpuFeaturesLibCommon.c
SmmCpuFeaturesLibNoStm.c
+ TraditionalMmCpuFeaturesLib.c
[Packages]
MdePkg/MdePkg.dec
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c
new file mode 100644
index 00000000000..b5c55f389b6
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibCommon.c
@@ -0,0 +1,613 @@
+/** @file
+Implementation shared across all library instances.
+
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+#include <Library/SmmCpuFeaturesLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MtrrLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Register/Intel/Cpuid.h>
+#include <Register/Intel/SmramSaveStateMap.h>
+#include "CpuFeaturesLib.h"
+
+//
+// Machine Specific Registers (MSRs)
+//
+#define SMM_FEATURES_LIB_IA32_MTRR_CAP 0x0FE
+#define SMM_FEATURES_LIB_IA32_FEATURE_CONTROL 0x03A
+#define SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE 0x1F2
+#define SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK 0x1F3
+#define SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE 0x0A0
+#define SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK 0x0A1
+#define EFI_MSR_SMRR_MASK 0xFFFFF000
+#define EFI_MSR_SMRR_PHYS_MASK_VALID BIT11
+#define SMM_FEATURES_LIB_SMM_FEATURE_CONTROL 0x4E0
+
+//
+// MSRs required for configuration of SMM Code Access Check
+//
+#define SMM_FEATURES_LIB_IA32_MCA_CAP 0x17D
+#define SMM_CODE_ACCESS_CHK_BIT BIT58
+
+//
+// Set default value to assume SMRR is not supported
+//
+BOOLEAN mSmrrSupported = FALSE;
+
+//
+// Set default value to assume MSR_SMM_FEATURE_CONTROL is not supported
+//
+BOOLEAN mSmmFeatureControlSupported = FALSE;
+
+//
+// Set default value to assume IA-32 Architectural MSRs are used
+//
+UINT32 mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
+UINT32 mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
+
+//
+// Set default value to assume MTRRs need to be configured on each SMI
+//
+BOOLEAN mNeedConfigureMtrrs = TRUE;
+
+//
+// Array for state of SMRR enable on all CPUs
+//
+BOOLEAN *mSmrrEnabled;
+
+/**
+ Performs library initialization.
+
+ This initialization function contains common functionality shared betwen all
+ library instance constructors.
+
+**/
+VOID
+CpuFeaturesLibInitialization (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINTN FamilyId;
+ UINTN ModelId;
+
+ //
+ // Retrieve CPU Family and Model
+ //
+ AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
+ FamilyId = (RegEax >> 8) & 0xf;
+ ModelId = (RegEax >> 4) & 0xf;
+ if (FamilyId == 0x06 || FamilyId == 0x0f) {
+ ModelId = ModelId | ((RegEax >> 12) & 0xf0);
+ }
+
+ //
+ // Check CPUID(CPUID_VERSION_INFO).EDX[12] for MTRR capability
+ //
+ if ((RegEdx & BIT12) != 0) {
+ //
+ // Check MTRR_CAP MSR bit 11 for SMRR support
+ //
+ if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MTRR_CAP) & BIT11) != 0) {
+ mSmrrSupported = TRUE;
+ }
+ }
+
+ //
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 35.3 MSRs in the Intel(R) Atom(TM) Processor Family
+ //
+ // If CPU Family/Model is 06_1CH, 06_26H, 06_27H, 06_35H or 06_36H, then
+ // SMRR Physical Base and SMM Physical Mask MSRs are not available.
+ //
+ if (FamilyId == 0x06) {
+ if (ModelId == 0x1C || ModelId == 0x26 || ModelId == 0x27 || ModelId == 0x35 || ModelId == 0x36) {
+ mSmrrSupported = FALSE;
+ }
+ }
+
+ //
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
+ //
+ // If CPU Family/Model is 06_0F or 06_17, then use Intel(R) Core(TM) 2
+ // Processor Family MSRs
+ //
+ if (FamilyId == 0x06) {
+ if (ModelId == 0x17 || ModelId == 0x0f) {
+ mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE;
+ mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSMASK;
+ }
+ }
+
+ //
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 34.4.2 SMRAM Caching
+ // An IA-32 processor does not automatically write back and invalidate its
+ // caches before entering SMM or before exiting SMM. Because of this behavior,
+ // care must be taken in the placement of the SMRAM in system memory and in
+ // the caching of the SMRAM to prevent cache incoherence when switching back
+ // and forth between SMM and protected mode operation.
+ //
+ // An IA-32 processor is a processor that does not support the Intel 64
+ // Architecture. Support for the Intel 64 Architecture can be detected from
+ // CPUID(CPUID_EXTENDED_CPU_SIG).EDX[29]
+ //
+ // If an IA-32 processor is detected, then set mNeedConfigureMtrrs to TRUE,
+ // so caches are flushed on SMI entry and SMI exit, the interrupted code
+ // MTRRs are saved/restored, and MTRRs for SMM are loaded.
+ //
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
+ AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT29) != 0) {
+ mNeedConfigureMtrrs = FALSE;
+ }
+ }
+
+ //
+ // Allocate array for state of SMRR enable on all CPUs
+ //
+ mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * GetCpuMaxLogicalProcessorNumber ());
+ ASSERT (mSmrrEnabled != NULL);
+}
+
+/**
+ Called during the very first SMI into System Management Mode to initialize
+ CPU features, including SMBASE, for the currently executing CPU. Since this
+ is the first SMI, the SMRAM Save State Map is at the default address of
+ SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
+ CPU is specified by CpuIndex and CpuIndex can be used to access information
+ about the currently executing CPU in the ProcessorInfo array and the
+ HotPlugCpuData data structure.
+
+ @param[in] CpuIndex The index of the CPU to initialize. The value
+ must be between 0 and the NumberOfCpus field in
+ the System Management System Table (SMST).
+ @param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
+ was elected as monarch during System Management
+ Mode initialization.
+ FALSE if the CpuIndex is not the index of the CPU
+ that was elected as monarch during System
+ Management Mode initialization.
+ @param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
+ structures. ProcessorInfo[CpuIndex] contains the
+ information for the currently executing CPU.
+ @param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
+ contains the ApidId and SmBase arrays.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesInitializeProcessor (
+ IN UINTN CpuIndex,
+ IN BOOLEAN IsMonarch,
+ IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
+ IN CPU_HOT_PLUG_DATA *CpuHotPlugData
+ )
+{
+ SMRAM_SAVE_STATE_MAP *CpuState;
+ UINT64 FeatureControl;
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ UINTN FamilyId;
+ UINTN ModelId;
+
+ //
+ // Configure SMBASE.
+ //
+ CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+ CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+
+ //
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
+ //
+ // If Intel(R) Core(TM) Core(TM) 2 Processor Family MSRs are being used, then
+ // make sure SMRR Enable(BIT3) of MSR_FEATURE_CONTROL MSR(0x3A) is set before
+ // accessing SMRR base/mask MSRs. If Lock(BIT0) of MSR_FEATURE_CONTROL MSR(0x3A)
+ // is set, then the MSR is locked and can not be modified.
+ //
+ if (mSmrrSupported && mSmrrPhysBaseMsr == SMM_FEATURES_LIB_IA32_CORE_SMRR_PHYSBASE) {
+ FeatureControl = AsmReadMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL);
+ if ((FeatureControl & BIT3) == 0) {
+ if ((FeatureControl & BIT0) == 0) {
+ AsmWriteMsr64 (SMM_FEATURES_LIB_IA32_FEATURE_CONTROL, FeatureControl | BIT3);
+ } else {
+ mSmrrSupported = FALSE;
+ }
+ }
+ }
+
+ //
+ // If SMRR is supported, then program SMRR base/mask MSRs.
+ // The EFI_MSR_SMRR_PHYS_MASK_VALID bit is not set until the first normal SMI.
+ // The code that initializes SMM environment is running in normal mode
+ // from SMRAM region. If SMRR is enabled here, then the SMRAM region
+ // is protected and the normal mode code execution will fail.
+ //
+ if (mSmrrSupported) {
+ //
+ // SMRR size cannot be less than 4-KBytes
+ // SMRR size must be of length 2^n
+ // SMRR base alignment cannot be less than SMRR length
+ //
+ if ((CpuHotPlugData->SmrrSize < SIZE_4KB) ||
+ (CpuHotPlugData->SmrrSize != GetPowerOfTwo32 (CpuHotPlugData->SmrrSize)) ||
+ ((CpuHotPlugData->SmrrBase & ~(CpuHotPlugData->SmrrSize - 1)) != CpuHotPlugData->SmrrBase)) {
+ //
+ // Print message and halt if CPU is Monarch
+ //
+ if (IsMonarch) {
+ DEBUG ((DEBUG_ERROR, "SMM Base/Size does not meet alignment/size requirement!\n"));
+ CpuDeadLoop ();
+ }
+ } else {
+ AsmWriteMsr64 (mSmrrPhysBaseMsr, CpuHotPlugData->SmrrBase | MTRR_CACHE_WRITE_BACK);
+ AsmWriteMsr64 (mSmrrPhysMaskMsr, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK));
+ mSmrrEnabled[CpuIndex] = FALSE;
+ }
+ }
+
+ //
+ // Retrieve CPU Family and Model
+ //
+ AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
+ FamilyId = (RegEax >> 8) & 0xf;
+ ModelId = (RegEax >> 4) & 0xf;
+ if (FamilyId == 0x06 || FamilyId == 0x0f) {
+ ModelId = ModelId | ((RegEax >> 12) & 0xf0);
+ }
+
+ //
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 35.10.1 MSRs in 4th Generation Intel(R) Core(TM)
+ // Processor Family.
+ //
+ // If CPU Family/Model is 06_3C, 06_45, or 06_46 then use 4th Generation
+ // Intel(R) Core(TM) Processor Family MSRs.
+ //
+ if (FamilyId == 0x06) {
+ if (ModelId == 0x3C || ModelId == 0x45 || ModelId == 0x46 ||
+ ModelId == 0x3D || ModelId == 0x47 || ModelId == 0x4E || ModelId == 0x4F ||
+ ModelId == 0x3F || ModelId == 0x56 || ModelId == 0x57 || ModelId == 0x5C ||
+ ModelId == 0x8C) {
+ //
+ // Check to see if the CPU supports the SMM Code Access Check feature
+ // Do not access this MSR unless the CPU supports the SmmRegFeatureControl
+ //
+ if ((AsmReadMsr64 (SMM_FEATURES_LIB_IA32_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) != 0) {
+ mSmmFeatureControlSupported = TRUE;
+ }
+ }
+ }
+
+ //
+ // Call internal worker function that completes the CPU initialization
+ //
+ FinishSmmCpuFeaturesInitializeProcessor ();
+}
+
+/**
+ This function updates the SMRAM save state on the currently executing CPU
+ to resume execution at a specific address after an RSM instruction. This
+ function must evaluate the SMRAM save state to determine the execution mode
+ the RSM instruction resumes and update the resume execution address with
+ either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
+ flag in the SMRAM save state must always be cleared. This function returns
+ the value of the instruction pointer from the SMRAM save state that was
+ replaced. If this function returns 0, then the SMRAM save state was not
+ modified.
+
+ This function is called during the very first SMI on each CPU after
+ SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
+ to signal that the SMBASE of each CPU has been updated before the default
+ SMBASE address is used for the first SMI to the next CPU.
+
+ @param[in] CpuIndex The index of the CPU to hook. The value
+ must be between 0 and the NumberOfCpus
+ field in the System Management System Table
+ (SMST).
+ @param[in] CpuState Pointer to SMRAM Save State Map for the
+ currently executing CPU.
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
+ 32-bit execution mode from 64-bit SMM.
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to
+ same execution mode as SMM.
+
+ @retval 0 This function did modify the SMRAM save state.
+ @retval > 0 The original instruction pointer value from the SMRAM save state
+ before it was replaced.
+**/
+UINT64
+EFIAPI
+SmmCpuFeaturesHookReturnFromSmm (
+ IN UINTN CpuIndex,
+ IN SMRAM_SAVE_STATE_MAP *CpuState,
+ IN UINT64 NewInstructionPointer32,
+ IN UINT64 NewInstructionPointer
+ )
+{
+ return 0;
+}
+
+/**
+ Hook point in normal execution mode that allows the one CPU that was elected
+ as monarch during System Management Mode initialization to perform additional
+ initialization actions immediately after all of the CPUs have processed their
+ first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
+ into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesSmmRelocationComplete (
+ VOID
+ )
+{
+}
+
+/**
+ Determines if MTRR registers must be configured to set SMRAM cache-ability
+ when executing in System Management Mode.
+
+ @retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
+ @retval FALSE MTRR registers do not need to be configured to set SMRAM
+ cache-ability.
+**/
+BOOLEAN
+EFIAPI
+SmmCpuFeaturesNeedConfigureMtrrs (
+ VOID
+ )
+{
+ return mNeedConfigureMtrrs;
+}
+
+/**
+ Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
+ returns TRUE.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesDisableSmrr (
+ VOID
+ )
+{
+ if (mSmrrSupported && mNeedConfigureMtrrs) {
+ AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) & ~EFI_MSR_SMRR_PHYS_MASK_VALID);
+ }
+}
+
+/**
+ Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
+ returns TRUE.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesReenableSmrr (
+ VOID
+ )
+{
+ if (mSmrrSupported && mNeedConfigureMtrrs) {
+ AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64(mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
+ }
+}
+
+/**
+ Processor specific hook point each time a CPU enters System Management Mode.
+
+ @param[in] CpuIndex The index of the CPU that has entered SMM. The value
+ must be between 0 and the NumberOfCpus field in the
+ System Management System Table (SMST).
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesRendezvousEntry (
+ IN UINTN CpuIndex
+ )
+{
+ //
+ // If SMRR is supported and this is the first normal SMI, then enable SMRR
+ //
+ if (mSmrrSupported && !mSmrrEnabled[CpuIndex]) {
+ AsmWriteMsr64 (mSmrrPhysMaskMsr, AsmReadMsr64 (mSmrrPhysMaskMsr) | EFI_MSR_SMRR_PHYS_MASK_VALID);
+ mSmrrEnabled[CpuIndex] = TRUE;
+ }
+}
+
+/**
+ Processor specific hook point each time a CPU exits System Management Mode.
+
+ @param[in] CpuIndex The index of the CPU that is exiting SMM. The value must
+ be between 0 and the NumberOfCpus field in the System
+ Management System Table (SMST).
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesRendezvousExit (
+ IN UINTN CpuIndex
+ )
+{
+}
+
+/**
+ Check to see if an SMM register is supported by a specified CPU.
+
+ @param[in] CpuIndex The index of the CPU to check for SMM register support.
+ The value must be between 0 and the NumberOfCpus field
+ in the System Management System Table (SMST).
+ @param[in] RegName Identifies the SMM register to check for support.
+
+ @retval TRUE The SMM register specified by RegName is supported by the CPU
+ specified by CpuIndex.
+ @retval FALSE The SMM register specified by RegName is not supported by the
+ CPU specified by CpuIndex.
+**/
+BOOLEAN
+EFIAPI
+SmmCpuFeaturesIsSmmRegisterSupported (
+ IN UINTN CpuIndex,
+ IN SMM_REG_NAME RegName
+ )
+{
+ if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ Returns the current value of the SMM register for the specified CPU.
+ If the SMM register is not supported, then 0 is returned.
+
+ @param[in] CpuIndex The index of the CPU to read the SMM register. The
+ value must be between 0 and the NumberOfCpus field in
+ the System Management System Table (SMST).
+ @param[in] RegName Identifies the SMM register to read.
+
+ @return The value of the SMM register specified by RegName from the CPU
+ specified by CpuIndex.
+**/
+UINT64
+EFIAPI
+SmmCpuFeaturesGetSmmRegister (
+ IN UINTN CpuIndex,
+ IN SMM_REG_NAME RegName
+ )
+{
+ if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
+ return AsmReadMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL);
+ }
+ return 0;
+}
+
+/**
+ Sets the value of an SMM register on a specified CPU.
+ If the SMM register is not supported, then no action is performed.
+
+ @param[in] CpuIndex The index of the CPU to write the SMM register. The
+ value must be between 0 and the NumberOfCpus field in
+ the System Management System Table (SMST).
+ @param[in] RegName Identifies the SMM register to write.
+ registers are read-only.
+ @param[in] Value The value to write to the SMM register.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesSetSmmRegister (
+ IN UINTN CpuIndex,
+ IN SMM_REG_NAME RegName,
+ IN UINT64 Value
+ )
+{
+ if (mSmmFeatureControlSupported && RegName == SmmRegFeatureControl) {
+ AsmWriteMsr64 (SMM_FEATURES_LIB_SMM_FEATURE_CONTROL, Value);
+ }
+}
+
+/**
+ Read an SMM Save State register on the target processor. If this function
+ returns EFI_UNSUPPORTED, then the caller is responsible for reading the
+ SMM Save Sate register.
+
+ @param[in] CpuIndex The index of the CPU to read the SMM Save State. The
+ value must be between 0 and the NumberOfCpus field in
+ the System Management System Table (SMST).
+ @param[in] Register The SMM Save State register to read.
+ @param[in] Width The number of bytes to read from the CPU save state.
+ @param[out] Buffer Upon return, this holds the CPU register value read
+ from the save state.
+
+ @retval EFI_SUCCESS The register was read from Save State.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED This function does not support reading Register.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuFeaturesReadSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN Width,
+ OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Writes an SMM Save State register on the target processor. If this function
+ returns EFI_UNSUPPORTED, then the caller is responsible for writing the
+ SMM Save Sate register.
+
+ @param[in] CpuIndex The index of the CPU to write the SMM Save State. The
+ value must be between 0 and the NumberOfCpus field in
+ the System Management System Table (SMST).
+ @param[in] Register The SMM Save State register to write.
+ @param[in] Width The number of bytes to write to the CPU save state.
+ @param[in] Buffer Upon entry, this holds the new CPU register value.
+
+ @retval EFI_SUCCESS The register was written to Save State.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_UNSUPPORTED This function does not support writing Register.
+**/
+EFI_STATUS
+EFIAPI
+SmmCpuFeaturesWriteSaveStateRegister (
+ IN UINTN CpuIndex,
+ IN EFI_SMM_SAVE_STATE_REGISTER Register,
+ IN UINTN Width,
+ IN CONST VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
+ notification is completely processed.
+**/
+VOID
+EFIAPI
+SmmCpuFeaturesCompleteSmmReadyToLock (
+ VOID
+ )
+{
+}
+
+/**
+ This API provides a method for a CPU to allocate a specific region for storing page tables.
+
+ This API can be called more once to allocate memory for page tables.
+
+ Allocates the number of 4KB pages of type EfiRuntimeServicesData 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 remaining to satisfy the request, then NULL is
+ returned.
+
+ This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
+
+ @param Pages The number of 4 KB pages to allocate.
+
+ @return A pointer to the allocated buffer for page tables.
+ @retval NULL Fail to allocate a specific region for storing page tables,
+ Or there is no preference on where the page tables are allocated in SMRAM.
+
+**/
+VOID *
+EFIAPI
+SmmCpuFeaturesAllocatePageTableMemory (
+ IN UINTN Pages
+ )
+{
+ return NULL;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibNoStm.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibNoStm.c
index ea3b3989d64..6baa6030627 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibNoStm.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibNoStm.c
@@ -7,8 +7,9 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiSmm.h>
+#include <PiMm.h>
#include <Library/SmmCpuFeaturesLib.h>
+#include "CpuFeaturesLib.h"
/**
Internal worker function that is called to complete CPU initialization at the
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
index 495dbe0432d..6583b3bd9ec 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
@@ -18,9 +18,11 @@
CONSTRUCTOR = SmmCpuFeaturesLibStmConstructor
[Sources]
- SmmCpuFeaturesLib.c
+ CpuFeaturesLib.h
+ SmmCpuFeaturesLibCommon.c
SmmStm.c
SmmStm.h
+ TraditionalMmCpuFeaturesLib.c
[Sources.Ia32]
Ia32/SmmStmSupport.c
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
index bc0eeb66d4e..6ae8fb923e2 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmStm.c
@@ -6,7 +6,7 @@
**/
-#include <PiSmm.h>
+#include <PiMm.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
@@ -21,6 +21,7 @@
#include <Protocol/MpService.h>
+#include "CpuFeaturesLib.h"
#include "SmmStm.h"
#define TXT_EVTYPE_BASE 0x400
@@ -29,22 +30,6 @@
#define RDWR_ACCS 3
#define FULL_ACCS 7
-/**
- The constructor function
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-SmmCpuFeaturesLibConstructor (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- );
-
EFI_HANDLE mStmSmmCpuHandle = NULL;
BOOLEAN mLockLoadMonitor = FALSE;
@@ -111,7 +96,7 @@ UINTN mMsegSize = 0;
BOOLEAN mStmConfigurationTableInitialized = FALSE;
/**
- The constructor function
+ The constructor function for the Traditional MM library instance with STM.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@@ -137,10 +122,9 @@ SmmCpuFeaturesLibStmConstructor (
SmmCpuFeaturesLibStmSmiEntryFixupAddress ();
//
- // Call the common constructor function
+ // Perform library initialization common across all instances
//
- Status = SmmCpuFeaturesLibConstructor (ImageHandle, SystemTable);
- ASSERT_EFI_ERROR (Status);
+ CpuFeaturesLibInitialization ();
//
// Lookup the MP Services Protocol
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.c
new file mode 100644
index 00000000000..ea985200102
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.c
@@ -0,0 +1,50 @@
+/** @file
+Standalone MM CPU specific programming.
+
+Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+#include <Library/PcdLib.h>
+#include "CpuFeaturesLib.h"
+
+/**
+ Gets the maximum number of logical processors from the PCD PcdCpuMaxLogicalProcessorNumber.
+
+ This access is abstracted from the PCD services to enforce that the PCD be
+ FixedAtBuild in the Standalone MM build of this driver.
+
+ @return The value of PcdCpuMaxLogicalProcessorNumber.
+
+**/
+UINT32
+GetCpuMaxLogicalProcessorNumber (
+ VOID
+ )
+{
+ return FixedPcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+}
+
+/**
+ The Standalone MM library constructor.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable A Pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS This constructor always returns success.
+
+**/
+EFI_STATUS
+EFIAPI
+StandaloneMmCpuFeaturesLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_MM_SYSTEM_TABLE *SystemTable
+ )
+{
+ CpuFeaturesLibInitialization ();
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
new file mode 100644
index 00000000000..ecd1cd4d690
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
@@ -0,0 +1,38 @@
+## @file
+# Standalone MM CPU specific programming.
+#
+# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = StandaloneMmCpuFeaturesLib
+ MODULE_UNI_FILE = SmmCpuFeaturesLib.uni
+ FILE_GUID = BB554A2D-F5DF-41D3-8C62-46476A2B2B18
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = SmmCpuFeaturesLib
+ CONSTRUCTOR = StandaloneMmCpuFeaturesLibConstructor
+
+[Sources]
+ CpuFeaturesLib.h
+ StandaloneMmCpuFeaturesLib.c
+ SmmCpuFeaturesLibCommon.c
+ SmmCpuFeaturesLibNoStm.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MemoryAllocationLib
+ PcdLib
+
+[FixedPcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber ## SOMETIMES_CONSUMES
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/TraditionalMmCpuFeaturesLib.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/TraditionalMmCpuFeaturesLib.c
new file mode 100644
index 00000000000..8a7b7ead767
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/TraditionalMmCpuFeaturesLib.c
@@ -0,0 +1,28 @@
+/** @file
+ Traditional MM CPU specific programming.
+
+ Copyright (c) Microsoft Corporation.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Library/PcdLib.h>
+#include "CpuFeaturesLib.h"
+
+/**
+ Gets the maximum number of logical processors from the PCD PcdCpuMaxLogicalProcessorNumber.
+
+ This access is abstracted from the PCD services to enforce that the PCD be
+ FixedAtBuild in the Standalone MM build of this driver.
+
+ @return The value of PcdCpuMaxLogicalProcessorNumber.
+
+**/
+UINT32
+GetCpuMaxLogicalProcessorNumber (
+ VOID
+ )
+{
+ return PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmmStmSupport.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmmStmSupport.c
index 07c48b8f67b..9ba17dd6c00 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmmStmSupport.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/SmmCpuFeaturesLib/X64/SmmStmSupport.c
@@ -6,7 +6,7 @@
**/
-#include <PiSmm.h>
+#include <PiMm.h>
#include <Library/DebugLib.h>
#include "SmmStm.h"
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c
new file mode 100644
index 00000000000..c1b36573986
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.c
@@ -0,0 +1,165 @@
+/** @file
+ VMGEXIT Base Support Library.
+
+ Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include <Uefi.h>
+#include <Library/VmgExitLib.h>
+
+/**
+ Perform VMGEXIT.
+
+ Sets the necessary fields of the GHCB, invokes the VMGEXIT instruction and
+ then handles the return actions.
+
+ The base library function returns an error in the form of a
+ GHCB_EVENT_INJECTION representing a GP_EXCEPTION.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] ExitCode VMGEXIT code to be assigned to the SwExitCode
+ field of the GHCB.
+ @param[in] ExitInfo1 VMGEXIT information to be assigned to the
+ SwExitInfo1 field of the GHCB.
+ @param[in] ExitInfo2 VMGEXIT information to be assigned to the
+ SwExitInfo2 field of the GHCB.
+
+ @retval 0 VMGEXIT succeeded.
+ @return Exception number to be propagated, VMGEXIT
+ processing did not succeed.
+
+**/
+UINT64
+EFIAPI
+VmgExit (
+ IN OUT GHCB *Ghcb,
+ IN UINT64 ExitCode,
+ IN UINT64 ExitInfo1,
+ IN UINT64 ExitInfo2
+ )
+{
+ GHCB_EVENT_INJECTION Event;
+
+ Event.Uint64 = 0;
+ Event.Elements.Vector = GP_EXCEPTION;
+ Event.Elements.Type = GHCB_EVENT_INJECTION_TYPE_EXCEPTION;
+ Event.Elements.Valid = 1;
+
+ return Event.Uint64;
+}
+
+/**
+ Perform pre-VMGEXIT initialization/preparation.
+
+ Performs the necessary steps in preparation for invoking VMGEXIT. Must be
+ called before setting any fields within the GHCB.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in, out] InterruptState A pointer to hold the current interrupt
+ state, used for restoring in VmgDone ()
+
+**/
+VOID
+EFIAPI
+VmgInit (
+ IN OUT GHCB *Ghcb,
+ IN OUT BOOLEAN *InterruptState
+ )
+{
+}
+
+/**
+ Perform post-VMGEXIT cleanup.
+
+ Performs the necessary steps to cleanup after invoking VMGEXIT. Must be
+ called after obtaining needed fields within the GHCB.
+
+ @param[in, out] Ghcb A pointer to the GHCB
+ @param[in] InterruptState An indicator to conditionally (re)enable
+ interrupts
+
+**/
+VOID
+EFIAPI
+VmgDone (
+ IN OUT GHCB *Ghcb,
+ IN BOOLEAN InterruptState
+ )
+{
+}
+
+/**
+ Marks a field at the specified offset as valid in the GHCB.
+
+ The ValidBitmap area represents the areas of the GHCB that have been marked
+ valid. Set the bit in ValidBitmap for the input offset.
+
+ @param[in, out] Ghcb Pointer to the Guest-Hypervisor Communication Block
+ @param[in] Offset Qword offset in the GHCB to mark valid
+
+**/
+VOID
+EFIAPI
+VmgSetOffsetValid (
+ IN OUT GHCB *Ghcb,
+ IN GHCB_REGISTER Offset
+ )
+{
+}
+
+/**
+ Checks if a specified offset is valid in the GHCB.
+
+ The ValidBitmap area represents the areas of the GHCB that have been marked
+ valid. Return whether the bit in the ValidBitmap is set for the input offset.
+
+ @param[in] Ghcb A pointer to the GHCB
+ @param[in] Offset Qword offset in the GHCB to mark valid
+
+ @retval TRUE Offset is marked valid in the GHCB
+ @retval FALSE Offset is not marked valid in the GHCB
+
+**/
+BOOLEAN
+EFIAPI
+VmgIsOffsetValid (
+ IN GHCB *Ghcb,
+ IN GHCB_REGISTER Offset
+ )
+{
+ return FALSE;
+}
+
+/**
+ Handle a #VC exception.
+
+ Performs the necessary processing to handle a #VC exception.
+
+ The base library function returns an error equal to VC_EXCEPTION,
+ to be propagated to the standard exception handling stack.
+
+ @param[in, out] ExceptionType Pointer to an EFI_EXCEPTION_TYPE to be set
+ as value to use on error.
+ @param[in, out] SystemContext Pointer to EFI_SYSTEM_CONTEXT
+
+ @retval EFI_SUCCESS Exception handled
+ @retval EFI_UNSUPPORTED #VC not supported, (new) exception value to
+ propagate provided
+ @retval EFI_PROTOCOL_ERROR #VC handling failed, (new) exception value to
+ propagate provided
+
+**/
+EFI_STATUS
+EFIAPI
+VmgExitHandleVc (
+ IN OUT EFI_EXCEPTION_TYPE *ExceptionType,
+ IN OUT EFI_SYSTEM_CONTEXT SystemContext
+ )
+{
+ *ExceptionType = VC_EXCEPTION;
+
+ return EFI_UNSUPPORTED;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
new file mode 100644
index 00000000000..fe3e0148017
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
@@ -0,0 +1,27 @@
+## @file
+# VMGEXIT Support Library.
+#
+# Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = VmgExitLibNull
+ MODULE_UNI_FILE = VmgExitLibNull.uni
+ FILE_GUID = 3cd7368f-ef9b-4a9b-9571-2ed93813677e
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = VmgExitLib
+
+[Sources.common]
+ VmgExitLibNull.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni
new file mode 100644
index 00000000000..8639bc0e8ce
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.uni
@@ -0,0 +1,15 @@
+// /** @file
+// VMGEXIT support library instance.
+//
+// VMGEXIT support library instance.
+//
+// Copyright (C) 2020, Advanced Micro Devices, Inc. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "VMGEXIT support NULL library instance"
+
+#string STR_MODULE_DESCRIPTION #language en-US "VMGEXIT support NULL library instance."
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
index c40cbe1e2cb..21fee45edfd 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.c
@@ -1,7 +1,7 @@
/** @file
PiSmmCommunication PEI Driver.
-Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -47,16 +47,10 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
+----------------------------------+<--
| EFI_SMM_COMMUNICATION_CONTEXT |
| SwSmiNumber | <- SMRAM
- | BufferPtrAddress |----------------
- +----------------------------------+ |
- |
- +----------------------------------+ |
- | EFI_SMM_COMMUNICATION_ACPI_TABLE | |
- | SwSmiNumber | <- AcpiTable |
- | BufferPtrAddress |--- |
- +----------------------------------+ | |
- | |
- +----------------------------------+<---------------
+ | BufferPtrAddress |---
+ +----------------------------------+ |
+ |
+ +----------------------------------+<--
| Communication Buffer Pointer | <- AcpiNvs
+----------------------------------+---
|
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
index f1a0982bb2a..6df07ac6cd9 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -1,7 +1,7 @@
/** @file
Code for Processor S3 restoration
-Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -235,11 +235,11 @@ ProgramProcessorRegister (
CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
volatile UINT32 *SemaphorePtr;
UINT32 FirstThread;
- UINT32 PackageThreadsCount;
UINT32 CurrentThread;
+ UINT32 CurrentCore;
UINTN ProcessorIndex;
- UINTN ValidThreadCount;
- UINT32 *ValidCoreCountPerPackage;
+ UINT32 *ThreadCountPerPackage;
+ UINT8 *ThreadCountPerCore;
EFI_STATUS Status;
UINT64 CurrentValue;
@@ -372,35 +372,52 @@ ProgramProcessorRegister (
//
ASSERT (
(ApLocation != NULL) &&
- (CpuStatus->ValidCoreCountPerPackage != 0) &&
+ (CpuStatus->ThreadCountPerPackage != 0) &&
+ (CpuStatus->ThreadCountPerCore != 0) &&
(CpuFlags->CoreSemaphoreCount != NULL) &&
(CpuFlags->PackageSemaphoreCount != NULL)
);
switch (RegisterTableEntry->Value) {
case CoreDepType:
SemaphorePtr = CpuFlags->CoreSemaphoreCount;
+ ThreadCountPerCore = (UINT8 *)(UINTN)CpuStatus->ThreadCountPerCore;
+
+ CurrentCore = ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core;
//
// Get Offset info for the first thread in the core which current thread belongs to.
//
- FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount;
+ FirstThread = CurrentCore * CpuStatus->MaxThreadCount;
CurrentThread = FirstThread + ApLocation->Thread;
+
//
- // First Notify all threads in current Core that this thread has ready.
+ // Different cores may have different valid threads in them. If driver maintail clearly
+ // thread index in different cores, the logic will be much complicated.
+ // Here driver just simply records the max thread number in all cores and use it as expect
+ // thread number for all cores.
+ // In below two steps logic, first current thread will Release semaphore for each thread
+ // in current core. Maybe some threads are not valid in this core, but driver don't
+ // care. Second, driver will let current thread wait semaphore for all valid threads in
+ // current core. Because only the valid threads will do release semaphore for this
+ // thread, driver here only need to wait the valid thread count.
+ //
+
+ //
+ // First Notify ALL THREADs in current Core that this thread is ready.
//
for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {
S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);
}
//
- // Second, check whether all valid threads in current core have ready.
+ // Second, check whether all VALID THREADs (not all threads) in current core are ready.
//
- for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {
+ for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerCore[CurrentCore]; ProcessorIndex ++) {
S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);
}
break;
case PackageDepType:
SemaphorePtr = CpuFlags->PackageSemaphoreCount;
- ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;
+ ThreadCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ThreadCountPerPackage;
//
// Get Offset info for the first thread in the package which current thread belongs to.
//
@@ -408,18 +425,13 @@ ProgramProcessorRegister (
//
// Get the possible threads count for current package.
//
- PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount;
CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;
- //
- // Get the valid thread count for current package.
- //
- ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package];
//
- // Different packages may have different valid cores in them. If driver maintail clearly
- // cores number in different packages, the logic will be much complicated.
- // Here driver just simply records the max core number in all packages and use it as expect
- // core number for all packages.
+ // Different packages may have different valid threads in them. If driver maintail clearly
+ // thread index in different packages, the logic will be much complicated.
+ // Here driver just simply records the max thread number in all packages and use it as expect
+ // thread number for all packages.
// In below two steps logic, first current thread will Release semaphore for each thread
// in current package. Maybe some threads are not valid in this package, but driver don't
// care. Second, driver will let current thread wait semaphore for all valid threads in
@@ -428,15 +440,15 @@ ProgramProcessorRegister (
//
//
- // First Notify all threads in current package that this thread has ready.
+ // First Notify ALL THREADS in current package that this thread is ready.
//
- for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {
+ for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; ProcessorIndex ++) {
S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);
}
//
- // Second, check whether all valid threads in current package have ready.
+ // Second, check whether VALID THREADS (not all threads) in current package are ready.
//
- for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {
+ for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerPackage[ApLocation->Package]; ProcessorIndex ++) {
S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);
}
break;
@@ -475,6 +487,9 @@ SetRegister (
} else {
RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable;
}
+ if (RegisterTables == NULL) {
+ return;
+ }
InitApicId = GetInitialApicId ();
RegisterTable = NULL;
@@ -936,7 +951,7 @@ InitSmmS3ResumeState (
}
/**
- Copy register table from ACPI NVS memory into SMRAM.
+ Copy register table from non-SMRAM into SMRAM.
@param[in] DestinationRegisterTableList Points to destination register table.
@param[in] SourceRegisterTableList Points to source register table.
@@ -955,7 +970,8 @@ CopyRegisterTable (
CopyMem (DestinationRegisterTableList, SourceRegisterTableList, NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
for (Index = 0; Index < NumberOfCpus; Index++) {
- if (DestinationRegisterTableList[Index].AllocatedSize != 0) {
+ if (DestinationRegisterTableList[Index].TableLength != 0) {
+ DestinationRegisterTableList[Index].AllocatedSize = DestinationRegisterTableList[Index].TableLength * sizeof (CPU_REGISTER_TABLE_ENTRY);
RegisterTableEntry = AllocateCopyPool (
DestinationRegisterTableList[Index].AllocatedSize,
(VOID *)(UINTN)SourceRegisterTableList[Index].RegisterTableEntry
@@ -967,6 +983,34 @@ CopyRegisterTable (
}
/**
+ Check whether the register table is empty or not.
+
+ @param[in] RegisterTable Point to the register table.
+ @param[in] NumberOfCpus Number of CPUs.
+
+ @retval TRUE The register table is empty.
+ @retval FALSE The register table is not empty.
+**/
+BOOLEAN
+IsRegisterTableEmpty (
+ IN CPU_REGISTER_TABLE *RegisterTable,
+ IN UINT32 NumberOfCpus
+ )
+{
+ UINTN Index;
+
+ if (RegisterTable != NULL) {
+ for (Index = 0; Index < NumberOfCpus; Index++) {
+ if (RegisterTable[Index].TableLength != 0) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/**
Get ACPI CPU data.
**/
@@ -1020,23 +1064,31 @@ GetAcpiCpuData (
CopyMem ((VOID *)(UINTN)mAcpiCpuData.IdtrProfile, (VOID *)(UINTN)AcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
- mAcpiCpuData.PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
- ASSERT (mAcpiCpuData.PreSmmInitRegisterTable != 0);
+ if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus)) {
+ mAcpiCpuData.PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
+ ASSERT (mAcpiCpuData.PreSmmInitRegisterTable != 0);
- CopyRegisterTable (
- (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable,
- (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->PreSmmInitRegisterTable,
- mAcpiCpuData.NumberOfCpus
- );
+ CopyRegisterTable (
+ (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.PreSmmInitRegisterTable,
+ (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->PreSmmInitRegisterTable,
+ mAcpiCpuData.NumberOfCpus
+ );
+ } else {
+ mAcpiCpuData.PreSmmInitRegisterTable = 0;
+ }
- mAcpiCpuData.RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
- ASSERT (mAcpiCpuData.RegisterTable != 0);
+ if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable, mAcpiCpuData.NumberOfCpus)) {
+ mAcpiCpuData.RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
+ ASSERT (mAcpiCpuData.RegisterTable != 0);
- CopyRegisterTable (
- (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable,
- (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable,
- mAcpiCpuData.NumberOfCpus
- );
+ CopyRegisterTable (
+ (CPU_REGISTER_TABLE *)(UINTN)mAcpiCpuData.RegisterTable,
+ (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable,
+ mAcpiCpuData.NumberOfCpus
+ );
+ } else {
+ mAcpiCpuData.RegisterTable = 0;
+ }
//
// Copy AP's GDT, IDT and Machine Check handler into SMRAM.
@@ -1059,12 +1111,19 @@ GetAcpiCpuData (
CpuStatus = &mAcpiCpuData.CpuStatus;
CopyMem (CpuStatus, &AcpiCpuData->CpuStatus, sizeof (CPU_STATUS_INFORMATION));
- if (AcpiCpuData->CpuStatus.ValidCoreCountPerPackage != 0) {
- CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
+ if (AcpiCpuData->CpuStatus.ThreadCountPerPackage != 0) {
+ CpuStatus->ThreadCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
sizeof (UINT32) * CpuStatus->PackageCount,
- (UINT32 *)(UINTN)AcpiCpuData->CpuStatus.ValidCoreCountPerPackage
+ (UINT32 *)(UINTN)AcpiCpuData->CpuStatus.ThreadCountPerPackage
+ );
+ ASSERT (CpuStatus->ThreadCountPerPackage != 0);
+ }
+ if (AcpiCpuData->CpuStatus.ThreadCountPerCore != 0) {
+ CpuStatus->ThreadCountPerCore = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
+ sizeof (UINT8) * (CpuStatus->PackageCount * CpuStatus->MaxCoreCount),
+ (UINT32 *)(UINTN)AcpiCpuData->CpuStatus.ThreadCountPerCore
);
- ASSERT (CpuStatus->ValidCoreCountPerPackage != 0);
+ ASSERT (CpuStatus->ThreadCountPerCore != 0);
}
if (AcpiCpuData->ApLocation != 0) {
mAcpiCpuData.ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
index 1804db48e0a..628d8c37c64 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
@@ -29,6 +29,26 @@ EnableCet (
);
/**
+ Get page table base address and the depth of the page table.
+
+ @param[out] Base Page table base address.
+ @param[out] FiveLevels TRUE means 5 level paging. FALSE means 4 level paging.
+**/
+VOID
+GetPageTable (
+ OUT UINTN *Base,
+ OUT BOOLEAN *FiveLevels OPTIONAL
+ )
+{
+ *Base = ((mInternalCr3 == 0) ?
+ (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64) :
+ mInternalCr3);
+ if (FiveLevels != NULL) {
+ *FiveLevels = FALSE;
+ }
+}
+
+/**
Create PageTable for SMM use.
@return PageTable Address
@@ -226,6 +246,7 @@ SetPageTableAttributes (
UINT64 *L1PageTable;
UINT64 *L2PageTable;
UINT64 *L3PageTable;
+ UINTN PageTableBase;
BOOLEAN IsSplitted;
BOOLEAN PageTableSplitted;
BOOLEAN CetEnabled;
@@ -268,9 +289,10 @@ SetPageTableAttributes (
DEBUG ((DEBUG_INFO, "Start...\n"));
PageTableSplitted = FALSE;
- L3PageTable = (UINT64 *)GetPageTableBase ();
+ GetPageTable (&PageTableBase, NULL);
+ L3PageTable = (UINT64 *)PageTableBase;
- SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
+ SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
for (Index3 = 0; Index3 < 4; Index3++) {
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
index e662a2dcfb1..84057170f90 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiEntry.nasm
@@ -1,5 +1,6 @@
;------------------------------------------------------------------------------ ;
; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -59,6 +60,7 @@ global ASM_PFX(gPatchSmiStack)
global ASM_PFX(gPatchSmbase)
extern ASM_PFX(mXdSupported)
global ASM_PFX(gPatchXdSupported)
+global ASM_PFX(gPatchMsrIa32MiscEnableSupported)
extern ASM_PFX(gSmiHandlerIdtr)
extern ASM_PFX(mCetSupported)
@@ -153,17 +155,30 @@ ASM_PFX(gPatchSmiCr3):
ASM_PFX(gPatchXdSupported):
cmp al, 0
jz @SkipXd
+
+; If MSR_IA32_MISC_ENABLE is supported, clear XD Disable bit
+ mov al, strict byte 1 ; source operand may be patched
+ASM_PFX(gPatchMsrIa32MiscEnableSupported):
+ cmp al, 1
+ jz MsrIa32MiscEnableSupported
+
+; MSR_IA32_MISC_ENABLE not supported
+ xor edx, edx
+ push edx ; don't try to restore the XD Disable bit just before RSM
+ jmp EnableNxe
+
;
; Check XD disable bit
;
+MsrIa32MiscEnableSupported:
mov ecx, MSR_IA32_MISC_ENABLE
rdmsr
push edx ; save MSR_IA32_MISC_ENABLE[63-32]
test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
- jz .5
+ jz EnableNxe
and dx, 0xFFFB ; clear XD Disable bit if it is set
wrmsr
-.5:
+EnableNxe:
mov ecx, MSR_EFER
rdmsr
or ax, MSR_EFER_XD ; enable NXE
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
index 403608dc364..ae8c90bec87 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
@@ -1,7 +1,7 @@
/** @file
SMM MP service implementation
-Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -22,6 +22,9 @@ UINTN mSemaphoreSize;
SPIN_LOCK *mPFLock = NULL;
SMM_CPU_SYNC_MODE mCpuSmmSyncMode;
BOOLEAN mMachineCheckSupported = FALSE;
+MM_COMPLETION mSmmStartupThisApToken;
+
+extern UINTN mSmmShadowStackSize;
/**
Performs an atomic compare exchange operation to get semaphore.
@@ -40,14 +43,18 @@ WaitForSemaphore (
{
UINT32 Value;
- do {
+ for (;;) {
Value = *Sem;
- } while (Value == 0 ||
- InterlockedCompareExchange32 (
- (UINT32*)Sem,
- Value,
- Value - 1
- ) != Value);
+ if (Value != 0 &&
+ InterlockedCompareExchange32 (
+ (UINT32*)Sem,
+ Value,
+ Value - 1
+ ) == Value) {
+ break;
+ }
+ CpuPause ();
+ }
return Value - 1;
}
@@ -916,7 +923,7 @@ Gen4GPageTable (
// Add two more pages for known good stack and stack guard page,
// then find the lower 2MB aligned address.
//
- High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1);
+ High2MBoundary = (mSmmStackArrayEnd - mSmmStackSize - mSmmShadowStackSize + EFI_PAGE_SIZE * 2) & ~(SIZE_2MB-1);
PagesNeeded = ((High2MBoundary - Low2MBoundary) / SIZE_2MB) + 1;
}
//
@@ -967,7 +974,7 @@ Gen4GPageTable (
// Mark the guard page as non-present
//
Pte[Index] = PageAddress | mAddressEncMask;
- GuardPage += mSmmStackSize;
+ GuardPage += (mSmmStackSize + mSmmShadowStackSize);
if (GuardPage > mSmmStackArrayEnd) {
GuardPage = 0;
}
@@ -1234,9 +1241,26 @@ InternalSmmStartupThisAp (
mSmmMpSyncData->CpuData[CpuIndex].Procedure = Procedure;
mSmmMpSyncData->CpuData[CpuIndex].Parameter = ProcArguments;
if (Token != NULL) {
- ProcToken= GetFreeToken (1);
- mSmmMpSyncData->CpuData[CpuIndex].Token = ProcToken;
- *Token = (MM_COMPLETION)ProcToken->SpinLock;
+ if (Token != &mSmmStartupThisApToken) {
+ //
+ // When Token points to mSmmStartupThisApToken, this routine is called
+ // from SmmStartupThisAp() in non-blocking mode (PcdCpuSmmBlockStartupThisAp == FALSE).
+ //
+ // In this case, caller wants to startup AP procedure in non-blocking
+ // mode and cannot get the completion status from the Token because there
+ // is no way to return the Token to caller from SmmStartupThisAp().
+ // Caller needs to use its implementation specific way to query the completion status.
+ //
+ // There is no need to allocate a token for such case so the 3 overheads
+ // can be avoided:
+ // 1. Call AllocateTokenBuffer() when there is no free token.
+ // 2. Get a free token from the token buffer.
+ // 3. Call ReleaseToken() in APHandler().
+ //
+ ProcToken = GetFreeToken (1);
+ mSmmMpSyncData->CpuData[CpuIndex].Token = ProcToken;
+ *Token = (MM_COMPLETION)ProcToken->SpinLock;
+ }
}
mSmmMpSyncData->CpuData[CpuIndex].Status = CpuStatus;
if (mSmmMpSyncData->CpuData[CpuIndex].Status != NULL) {
@@ -1468,8 +1492,6 @@ SmmStartupThisAp (
IN OUT VOID *ProcArguments OPTIONAL
)
{
- MM_COMPLETION Token;
-
gSmmCpuPrivate->ApWrapperFunc[CpuIndex].Procedure = Procedure;
gSmmCpuPrivate->ApWrapperFunc[CpuIndex].ProcedureArgument = ProcArguments;
@@ -1480,7 +1502,7 @@ SmmStartupThisAp (
ProcedureWrapper,
CpuIndex,
&gSmmCpuPrivate->ApWrapperFunc[CpuIndex],
- FeaturePcdGet (PcdCpuSmmBlockStartupThisAp) ? NULL : &Token,
+ FeaturePcdGet (PcdCpuSmmBlockStartupThisAp) ? NULL : &mSmmStartupThisApToken,
0,
NULL
);
@@ -1865,11 +1887,13 @@ InitializeMpServiceData (
IN UINTN ShadowStackSize
)
{
- UINT32 Cr3;
- UINTN Index;
- UINT8 *GdtTssTables;
- UINTN GdtTableStepSize;
- CPUID_VERSION_INFO_EDX RegEdx;
+ UINT32 Cr3;
+ UINTN Index;
+ UINT8 *GdtTssTables;
+ UINTN GdtTableStepSize;
+ CPUID_VERSION_INFO_EDX RegEdx;
+ UINT32 MaxExtendedFunction;
+ CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize;
//
// Determine if this CPU supports machine check
@@ -1896,9 +1920,17 @@ InitializeMpServiceData (
// Initialize physical address mask
// NOTE: Physical memory above virtual address limit is not supported !!!
//
- AsmCpuid (0x80000008, (UINT32*)&Index, NULL, NULL, NULL);
- gPhyMask = LShiftU64 (1, (UINT8)Index) - 1;
- gPhyMask &= (1ull << 48) - EFI_PAGE_SIZE;
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL);
+ if (MaxExtendedFunction >= CPUID_VIR_PHY_ADDRESS_SIZE) {
+ AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL);
+ } else {
+ VirPhyAddressSize.Bits.PhysicalAddressBits = 36;
+ }
+ gPhyMask = LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits) - 1;
+ //
+ // Clear the low 12 bits
+ //
+ gPhyMask &= 0xfffffffffffff000ULL;
//
// Create page tables
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 512ab1e97e2..6f35d89992e 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -263,6 +263,7 @@ extern UINTN mMaxNumberOfCpus;
extern UINTN mNumberOfCpus;
extern EFI_SMM_CPU_PROTOCOL mSmmCpu;
extern EFI_MM_MP_PROTOCOL mSmmMp;
+extern UINTN mInternalCr3;
///
/// The mode of the CPU at the time an SMI occurs
@@ -336,7 +337,7 @@ This function supports reading a CPU Save State register in SMBase relocation ha
@retval EFI_SUCCESS The register was read from Save State.
@retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
-@retval EFI_INVALID_PARAMETER This or Buffer is NULL.
+@retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type.
**/
EFI_STATUS
@@ -942,13 +943,15 @@ SetPageTableAttributes (
);
/**
- Return page table base.
+ Get page table base address and the depth of the page table.
- @return page table base.
+ @param[out] Base Page table base address.
+ @param[out] FiveLevels TRUE means 5 level paging. FALSE means 4 level paging.
**/
-UINTN
-GetPageTableBase (
- VOID
+VOID
+GetPageTable (
+ OUT UINTN *Base,
+ OUT BOOLEAN *FiveLevels OPTIONAL
);
/**
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
index 2a3a3fe753c..4f01579b343 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
@@ -32,7 +32,7 @@ PAGE_ATTRIBUTE_TABLE mPageAttributeTable[] = {
{Page1G, SIZE_1GB, PAGING_1G_ADDRESS_MASK_64},
};
-UINTN mInternalGr3;
+UINTN mInternalCr3;
/**
Set the internal page table base address.
@@ -46,23 +46,7 @@ SetPageTableBase (
IN UINTN Cr3
)
{
- mInternalGr3 = Cr3;
-}
-
-/**
- Return page table base.
-
- @return page table base.
-**/
-UINTN
-GetPageTableBase (
- VOID
- )
-{
- if (mInternalGr3 != 0) {
- return mInternalGr3;
- }
- return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);
+ mInternalCr3 = Cr3;
}
/**
@@ -131,21 +115,20 @@ GetPageTableEntry (
UINT64 *L3PageTable;
UINT64 *L4PageTable;
UINT64 *L5PageTable;
- IA32_CR4 Cr4;
+ UINTN PageTableBase;
BOOLEAN Enable5LevelPaging;
+ GetPageTable (&PageTableBase, &Enable5LevelPaging);
+
Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK;
Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK;
Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK;
Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK;
Index1 = ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK;
- Cr4.UintN = AsmReadCr4 ();
- Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);
-
if (sizeof(UINTN) == sizeof(UINT64)) {
if (Enable5LevelPaging) {
- L5PageTable = (UINT64 *)GetPageTableBase ();
+ L5PageTable = (UINT64 *)PageTableBase;
if (L5PageTable[Index5] == 0) {
*PageAttribute = PageNone;
return NULL;
@@ -153,7 +136,7 @@ GetPageTableEntry (
L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
} else {
- L4PageTable = (UINT64 *)GetPageTableBase ();
+ L4PageTable = (UINT64 *)PageTableBase;
}
if (L4PageTable[Index4] == 0) {
*PageAttribute = PageNone;
@@ -162,7 +145,7 @@ GetPageTableEntry (
L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);
} else {
- L3PageTable = (UINT64 *)GetPageTableBase ();
+ L3PageTable = (UINT64 *)PageTableBase;
}
if (L3PageTable[Index3] == 0) {
*PageAttribute = PageNone;
@@ -252,7 +235,7 @@ ConvertPageEntryAttribute (
if ((Attributes & EFI_MEMORY_RO) != 0) {
if (IsSet) {
NewPageEntry &= ~(UINT64)IA32_PG_RW;
- if (mInternalGr3 != 0) {
+ if (mInternalCr3 != 0) {
// Environment setup
// ReadOnly page need set Dirty bit for shadow stack
NewPageEntry |= IA32_PG_D;
@@ -435,7 +418,7 @@ ConvertMemoryPageAttributes (
EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress;
ASSERT (Attributes != 0);
- ASSERT ((Attributes & ~(EFI_MEMORY_RP | EFI_MEMORY_RO | EFI_MEMORY_XP)) == 0);
+ ASSERT ((Attributes & ~EFI_MEMORY_ATTRIBUTE_MASK) == 0);
ASSERT ((BaseAddress & (SIZE_4KB - 1)) == 0);
ASSERT ((Length & (SIZE_4KB - 1)) == 0);
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 00bf7a78ccc..17c7e552128 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -2,7 +2,7 @@
Enable SMM profile.
Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+Copyright (c) 2017 - 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -1015,6 +1015,13 @@ CheckFeatureSupported (
mXdSupported = FALSE;
PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
}
+
+ if (StandardSignatureIsAuthenticAMD ()) {
+ //
+ // AMD processors do not support MSR_IA32_MISC_ENABLE
+ //
+ PatchInstructionX86 (gPatchMsrIa32MiscEnableSupported, FALSE, 1);
+ }
}
if (mBtsSupported) {
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
index 5812f072259..0054da24627 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
@@ -2,6 +2,7 @@
SMM profile internal header file.
Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -13,6 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/DxeServicesTableLib.h>
#include <Library/CpuLib.h>
+#include <Library/UefiCpuLib.h>
#include <IndustryStandard/Acpi.h>
#include "SmmProfileArch.h"
@@ -99,6 +101,7 @@ extern SMM_S3_RESUME_STATE *mSmmS3ResumeState;
extern UINTN gSmiExceptionHandlers[];
extern BOOLEAN mXdSupported;
X86_ASSEMBLY_PATCH_LABEL gPatchXdSupported;
+X86_ASSEMBLY_PATCH_LABEL gPatchMsrIa32MiscEnableSupported;
extern UINTN *mPFEntryCount;
extern UINT64 (*mLastPFEntryValue)[MAX_PF_ENTRY_COUNT];
extern UINT64 *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
index 1be28dfa039..9fc5a498ff1 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
@@ -343,7 +343,7 @@ ReadSaveStateRegisterByIndex (
@retval EFI_SUCCESS The register was read from Save State.
@retval EFI_NOT_FOUND The register is not defined for the Save State of Processor.
- @retval EFI_INVALID_PARAMETER This or Buffer is NULL.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL, or Width does not meet requirement per Register type.
**/
EFI_STATUS
@@ -419,6 +419,13 @@ ReadSaveStateRegister (
}
//
+ // Make sure the incoming buffer is large enough to hold IoInfo before accessing
+ //
+ if (Width < sizeof (EFI_SMM_SAVE_STATE_IO_INFO)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
// Zero the IoInfo structure that will be returned in Buffer
//
IoInfo = (EFI_SMM_SAVE_STATE_IO_INFO *)Buffer;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
index 70f0119f6bc..a9a995db170 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c
@@ -13,6 +13,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define PAGE_TABLE_PAGES 8
#define ACC_MAX_BIT BIT3
+extern UINTN mSmmShadowStackSize;
+
LIST_ENTRY mPagePool = INITIALIZE_LIST_HEAD_VARIABLE (mPagePool);
BOOLEAN m1GPageTableSupport = FALSE;
BOOLEAN mCpuSmmRestrictedMemoryAccess;
@@ -105,6 +107,35 @@ Is5LevelPagingNeeded (
}
/**
+ Get page table base address and the depth of the page table.
+
+ @param[out] Base Page table base address.
+ @param[out] FiveLevels TRUE means 5 level paging. FALSE means 4 level paging.
+**/
+VOID
+GetPageTable (
+ OUT UINTN *Base,
+ OUT BOOLEAN *FiveLevels OPTIONAL
+ )
+{
+ IA32_CR4 Cr4;
+
+ if (mInternalCr3 == 0) {
+ *Base = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;
+ if (FiveLevels != NULL) {
+ Cr4.UintN = AsmReadCr4 ();
+ *FiveLevels = (BOOLEAN)(Cr4.Bits.LA57 == 1);
+ }
+ return;
+ }
+
+ *Base = mInternalCr3;
+ if (FiveLevels != NULL) {
+ *FiveLevels = m5LevelPagingNeeded;
+ }
+}
+
+/**
Set sub-entries number in entry.
@param[in, out] Entry Pointer to entry
@@ -180,11 +211,13 @@ CalculateMaximumSupportAddress (
/**
Set static page table.
- @param[in] PageTable Address of page table.
+ @param[in] PageTable Address of page table.
+ @param[in] PhysicalAddressBits The maximum physical address bits supported.
**/
VOID
SetStaticPageTable (
- IN UINTN PageTable
+ IN UINTN PageTable,
+ IN UINT8 PhysicalAddressBits
)
{
UINT64 PageAddress;
@@ -206,26 +239,26 @@ SetStaticPageTable (
// IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses
// when 5-Level Paging is disabled.
//
- ASSERT (mPhysicalAddressBits <= 52);
- if (!m5LevelPagingNeeded && mPhysicalAddressBits > 48) {
- mPhysicalAddressBits = 48;
+ ASSERT (PhysicalAddressBits <= 52);
+ if (!m5LevelPagingNeeded && PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
}
NumberOfPml5EntriesNeeded = 1;
- if (mPhysicalAddressBits > 48) {
- NumberOfPml5EntriesNeeded = (UINTN) LShiftU64 (1, mPhysicalAddressBits - 48);
- mPhysicalAddressBits = 48;
+ if (PhysicalAddressBits > 48) {
+ NumberOfPml5EntriesNeeded = (UINTN) LShiftU64 (1, PhysicalAddressBits - 48);
+ PhysicalAddressBits = 48;
}
NumberOfPml4EntriesNeeded = 1;
- if (mPhysicalAddressBits > 39) {
- NumberOfPml4EntriesNeeded = (UINTN) LShiftU64 (1, mPhysicalAddressBits - 39);
- mPhysicalAddressBits = 39;
+ if (PhysicalAddressBits > 39) {
+ NumberOfPml4EntriesNeeded = (UINTN) LShiftU64 (1, PhysicalAddressBits - 39);
+ PhysicalAddressBits = 39;
}
NumberOfPdpEntriesNeeded = 1;
- ASSERT (mPhysicalAddressBits > 30);
- NumberOfPdpEntriesNeeded = (UINTN) LShiftU64 (1, mPhysicalAddressBits - 30);
+ ASSERT (PhysicalAddressBits > 30);
+ NumberOfPdpEntriesNeeded = (UINTN) LShiftU64 (1, PhysicalAddressBits - 30);
//
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
@@ -407,7 +440,7 @@ SmmInitPageTable (
// When access to non-SMRAM memory is restricted, create page table
// that covers all memory space.
//
- SetStaticPageTable ((UINTN)PTEntry);
+ SetStaticPageTable ((UINTN)PTEntry, mPhysicalAddressBits);
} else {
//
// Add pages to page pool
@@ -985,6 +1018,7 @@ SmiPFHandler (
{
UINTN PFAddress;
UINTN GuardPageAddress;
+ UINTN ShadowStackGuardPageAddress;
UINTN CpuIndex;
ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT);
@@ -1001,18 +1035,24 @@ SmiPFHandler (
}
//
- // If a page fault occurs in SMRAM range, it might be in a SMM stack guard page,
+ // If a page fault occurs in SMRAM range, it might be in a SMM stack/shadow stack guard page,
// or SMM page protection violation.
//
if ((PFAddress >= mCpuHotPlugData.SmrrBase) &&
(PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) {
DumpCpuContext (InterruptType, SystemContext);
CpuIndex = GetCpuIndex ();
- GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * mSmmStackSize);
+ GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * (mSmmStackSize + mSmmShadowStackSize));
+ ShadowStackGuardPageAddress = (mSmmStackArrayBase + mSmmStackSize + EFI_PAGE_SIZE + CpuIndex * (mSmmStackSize + mSmmShadowStackSize));
if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
(PFAddress >= GuardPageAddress) &&
(PFAddress < (GuardPageAddress + EFI_PAGE_SIZE))) {
DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n"));
+ } else if ((FeaturePcdGet (PcdCpuSmmStackGuard)) &&
+ (mSmmShadowStackSize > 0) &&
+ (PFAddress >= ShadowStackGuardPageAddress) &&
+ (PFAddress < (ShadowStackGuardPageAddress + EFI_PAGE_SIZE))) {
+ DEBUG ((DEBUG_ERROR, "SMM shadow stack overflow!\n"));
} else {
if ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0) {
DEBUG ((DEBUG_ERROR, "SMM exception at execution (0x%lx)\n", PFAddress));
@@ -1111,15 +1151,12 @@ SetPageTableAttributes (
UINT64 *L3PageTable;
UINT64 *L4PageTable;
UINT64 *L5PageTable;
+ UINTN PageTableBase;
BOOLEAN IsSplitted;
BOOLEAN PageTableSplitted;
BOOLEAN CetEnabled;
- IA32_CR4 Cr4;
BOOLEAN Enable5LevelPaging;
- Cr4.UintN = AsmReadCr4 ();
- Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);
-
//
// Don't mark page table memory as read-only if
// - no restriction on access to non-SMRAM memory; or
@@ -1163,9 +1200,12 @@ SetPageTableAttributes (
DEBUG ((DEBUG_INFO, "Start...\n"));
PageTableSplitted = FALSE;
L5PageTable = NULL;
+
+ GetPageTable (&PageTableBase, &Enable5LevelPaging);
+
if (Enable5LevelPaging) {
- L5PageTable = (UINT64 *)GetPageTableBase ();
- SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L5PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
+ L5PageTable = (UINT64 *)PageTableBase;
+ SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
}
@@ -1176,7 +1216,7 @@ SetPageTableAttributes (
continue;
}
} else {
- L4PageTable = (UINT64 *)GetPageTableBase ();
+ L4PageTable = (UINT64 *)PageTableBase;
}
SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);
PageTableSplitted = (PageTableSplitted || IsSplitted);
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
index e5d1a9b77c7..334cc6c8d31 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmiEntry.nasm
@@ -1,5 +1,6 @@
;------------------------------------------------------------------------------ ;
; Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2020, AMD Incorporated. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -67,6 +68,7 @@ extern ASM_PFX(CpuSmmDebugExit)
global ASM_PFX(gPatchSmbase)
extern ASM_PFX(mXdSupported)
global ASM_PFX(gPatchXdSupported)
+global ASM_PFX(gPatchMsrIa32MiscEnableSupported)
global ASM_PFX(gPatchSmiStack)
global ASM_PFX(gPatchSmiCr3)
global ASM_PFX(gPatch5LevelPagingNeeded)
@@ -152,18 +154,32 @@ SkipEnable5LevelPaging:
ASM_PFX(gPatchXdSupported):
cmp al, 0
jz @SkipXd
+
+; If MSR_IA32_MISC_ENABLE is supported, clear XD Disable bit
+ mov al, strict byte 1 ; source operand may be patched
+ASM_PFX(gPatchMsrIa32MiscEnableSupported):
+ cmp al, 1
+ jz MsrIa32MiscEnableSupported
+
+; MSR_IA32_MISC_ENABLE not supported
+ sub esp, 4
+ xor rdx, rdx
+ push rdx ; don't try to restore the XD Disable bit just before RSM
+ jmp EnableNxe
+
;
; Check XD disable bit
;
+MsrIa32MiscEnableSupported:
mov ecx, MSR_IA32_MISC_ENABLE
rdmsr
sub esp, 4
push rdx ; save MSR_IA32_MISC_ENABLE[63-32]
test edx, BIT2 ; MSR_IA32_MISC_ENABLE[34]
- jz .0
+ jz EnableNxe
and dx, 0xFFFB ; clear XD Disable bit if it is set
wrmsr
-.0:
+EnableNxe:
mov ecx, MSR_EFER
rdmsr
or ax, MSR_EFER_XD ; enable NXE
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
index 45a85956a85..1f30c6d4d8e 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
@@ -93,7 +93,7 @@ InitGdt (
//
// Setup top of known good stack as IST1 for each processor.
//
- *(UINTN *)(TssBase + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * mSmmStackSize);
+ *(UINTN *)(TssBase + TSS_X64_IST1_OFFSET) = (mSmmStackArrayBase + EFI_PAGE_SIZE + Index * (mSmmStackSize + mSmmShadowStackSize));
}
}
@@ -121,7 +121,7 @@ GetProtectedModeCS (
GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;
for (Index = 0; Index < GdtEntryCount; Index++) {
if (GdtEntry->Bits.L == 0) {
- if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {
+ if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.DB == 1) {
break;
}
}
@@ -173,6 +173,7 @@ InitShadowStack (
{
UINTN SmmShadowStackSize;
UINT64 *InterruptSspTable;
+ UINT32 InterruptSsp;
if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
SmmShadowStackSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (PcdGet32 (PcdCpuSmmShadowStackSize)));
@@ -191,7 +192,19 @@ InitShadowStack (
ASSERT (mSmmInterruptSspTables != 0);
DEBUG ((DEBUG_INFO, "mSmmInterruptSspTables - 0x%x\n", mSmmInterruptSspTables));
}
- mCetInterruptSsp = (UINT32)((UINTN)ShadowStack + EFI_PAGES_TO_SIZE(1) - sizeof(UINT64));
+
+ //
+ // The highest address on the stack (0xFF8) is a save-previous-ssp token pointing to a location that is 40 bytes away - 0xFD0.
+ // The supervisor shadow stack token is just above it at address 0xFF0. This is where the interrupt SSP table points.
+ // So when an interrupt of exception occurs, we can use SAVESSP/RESTORESSP/CLEARSSBUSY for the supervisor shadow stack,
+ // due to the reason the RETF in SMM exception handler cannot clear the BUSY flag with same CPL.
+ // (only IRET or RETF with different CPL can clear BUSY flag)
+ // Please refer to UefiCpuPkg/Library/CpuExceptionHandlerLib/X64 for the full stack frame at runtime.
+ //
+ InterruptSsp = (UINT32)((UINTN)ShadowStack + EFI_PAGES_TO_SIZE(1) - sizeof(UINT64));
+ *(UINT32 *)(UINTN)InterruptSsp = (InterruptSsp - sizeof(UINT64) * 4) | 0x2;
+ mCetInterruptSsp = InterruptSsp - sizeof(UINT64);
+
mCetInterruptSspTable = (UINT32)(UINTN)(mSmmInterruptSspTables + sizeof(UINT64) * 8 * CpuIndex);
InterruptSspTable = (UINT64 *)(UINTN)mCetInterruptSspTable;
InterruptSspTable[1] = mCetInterruptSsp;
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
index 6ea15690331..fefe2a41590 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/ResetVector/Vtf0/Ia16/Real16ToFlat32.asm
@@ -129,5 +129,14 @@ LINEAR_CODE64_SEL equ $-GDT_BASE
DB 0 ; base 31:24
%endif
+; linear code segment descriptor
+LINEAR_CODE16_SEL equ $-GDT_BASE
+ DW 0xffff ; limit 15:0
+ DW 0 ; base 15:0
+ DB 0 ; base 23:16
+ DB PRESENT_FLAG(1)|DPL(0)|SYSTEM_FLAG(1)|DESC_TYPE(CODE32_TYPE)
+ DB GRANULARITY_FLAG(1)|DEFAULT_SIZE32(0)|CODE64_FLAG(0)|UPPER_LIMIT(0xf)
+ DB 0 ; base 31:24
+
GDT_END:
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/Ia32/ResetVec.nasmb b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/Ia32/ResetVec.nasmb
index 3b9a738b3d7..1d2203de501 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/Ia32/ResetVec.nasmb
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/Ia32/ResetVec.nasmb
@@ -10,7 +10,7 @@
; Abstract:
;
; Reset Vector Data structure
-; This structure is located at 0xFFFFFFC0
+; This structure is located at 0xFFFFF000
;
;------------------------------------------------------------------------------
@@ -23,19 +23,36 @@ USE16
;
ORG 0h
+
+;
+; 0xFFFFF000
+;
+; We enter here with CS:IP = 0xFF00:0x0000. Do a far-jump to change CS to 0xF000
+; and IP to ApStartup.
+;
+ApVector:
+ mov di, "AP"
+ jmp 0xF000:0xF000+ApStartup
+
+ TIMES 0xFC0-($-$$) nop
+
+;
+; This should be at 0xFFFFFFC0
+;
+
;
; Reserved
;
ReservedData: DD 0eeeeeeeeh, 0eeeeeeeeh
- TIMES 0x10-($-$$) DB 0
+ TIMES 0xFD0-($-$$) nop
;
-; This is located at 0xFFFFFFD0h
+; This is located at 0xFFFFFFD0
;
mov di, "PA"
jmp ApStartup
- TIMES 0x20-($-$$) DB 0
+ TIMES 0xFE0-($-$$) nop
;
; Pointer to the entry point of the PEI core
; It is located at 0xFFFFFFE0, and is fixed up by some build tool
@@ -53,7 +70,7 @@ ASM_PFX(InterruptHandler):
jmp $
iret
- TIMES 0x30-($-$$) DB 0
+ TIMES 0xFF0-($-$$) nop
;
; For IA32, the reset vector must be at 0xFFFFFFF0, i.e., 4G-16 byte
; Execution starts here upon power-on/platform-reset.
@@ -74,7 +91,7 @@ ApStartup:
DW -3
- TIMES 0x38-($-$$) DB 0
+ TIMES 0xFF8-($-$$) nop
;
; Ap reset vector segment address is at 0xFFFFFFF8
; This will be fixed up by some build tool,
@@ -83,7 +100,7 @@ ApStartup:
;
ApSegAddress: dd 12345678h
- TIMES 0x3c-($-$$) DB 0
+ TIMES 0xFFC-($-$$) nop
;
; BFV Base is at 0xFFFFFFFC
; This will be fixed up by some build tool,
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecCore.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecCore.inf
index f369de218a6..29322ae77c5 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecCore.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecCore.inf
@@ -68,6 +68,8 @@
## SOMETIMES_CONSUMES
gPeiSecPerformancePpiGuid
gEfiPeiCoreFvLocationPpiGuid
+ ## CONSUMES
+ gRepublishSecPpiPpiGuid
[Guids]
## SOMETIMES_PRODUCES ## HOB
@@ -75,6 +77,7 @@
[Pcd]
gUefiCpuPkgTokenSpaceGuid.PcdPeiTemporaryRamStackSize ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
[UserExtensions.TianoCore."ExtraFiles"]
SecCoreExtra.uni
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.c
index 961bce5ffe3..f8038a9f01d 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.c
@@ -35,6 +35,43 @@ EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
}
};
+/**
+ Migrates the Global Descriptor Table (GDT) to permanent memory.
+
+ @retval EFI_SUCCESS The GDT was migrated successfully.
+ @retval EFI_OUT_OF_RESOURCES The GDT could not be migrated due to lack of available memory.
+
+**/
+EFI_STATUS
+MigrateGdt (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN GdtBufferSize;
+ IA32_DESCRIPTOR Gdtr;
+ VOID *GdtBuffer;
+
+ AsmReadGdtr ((IA32_DESCRIPTOR *) &Gdtr);
+ GdtBufferSize = sizeof (IA32_SEGMENT_DESCRIPTOR) -1 + Gdtr.Limit + 1;
+
+ Status = PeiServicesAllocatePool (
+ GdtBufferSize,
+ &GdtBuffer
+ );
+ ASSERT (GdtBuffer != NULL);
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ GdtBuffer = ALIGN_POINTER (GdtBuffer, sizeof (IA32_SEGMENT_DESCRIPTOR));
+ CopyMem (GdtBuffer, (VOID *) Gdtr.Base, Gdtr.Limit + 1);
+ Gdtr.Base = (UINTN) GdtBuffer;
+ AsmWriteGdtr (&Gdtr);
+
+ return EFI_SUCCESS;
+}
+
//
// These are IDT entries pointing to 10:FFFFFFE4h.
//
@@ -370,7 +407,12 @@ SecTemporaryRamDone (
VOID
)
{
- BOOLEAN State;
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+ UINTN Index;
+ BOOLEAN State;
+ EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;
+ REPUBLISH_SEC_PPI_PPI *RepublishSecPpiPpi;
//
// Republish Sec Platform Information(2) PPI
@@ -378,6 +420,23 @@ SecTemporaryRamDone (
RepublishSecPlatformInformationPpi ();
//
+ // Re-install SEC PPIs using a PEIM produced service if published
+ //
+ for (Index = 0, Status = EFI_SUCCESS; Status == EFI_SUCCESS; Index++) {
+ Status = PeiServicesLocatePpi (
+ &gRepublishSecPpiPpiGuid,
+ Index,
+ &PeiPpiDescriptor,
+ (VOID **) &RepublishSecPpiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_INFO, "Calling RepublishSecPpi instance %d.\n", Index));
+ Status2 = RepublishSecPpiPpi->RepublishSecPpis ();
+ ASSERT_EFI_ERROR (Status2);
+ }
+ }
+
+ //
// Migrate DebugAgentContext.
//
InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, NULL, NULL);
@@ -385,7 +444,15 @@ SecTemporaryRamDone (
//
// Disable interrupts and save current interrupt state
//
- State = SaveAndDisableInterrupts();
+ State = SaveAndDisableInterrupts ();
+
+ //
+ // Migrate GDT before NEM near down
+ //
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ Status = MigrateGdt ();
+ ASSERT_EFI_ERROR (Status);
+ }
//
// Disable Temporary RAM after Stack and Heap have been migrated at this point.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.h
index 2ee98957e39..9b474dee79f 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecCore/SecMain.h
@@ -15,6 +15,7 @@
#include <Ppi/TemporaryRamDone.h>
#include <Ppi/SecPerformance.h>
#include <Ppi/PeiCoreFvLocation.h>
+#include <Ppi/RepublishSecPpi.h>
#include <Guid/FirmwarePerformance.h>
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c
new file mode 100644
index 00000000000..9bf39ce129e
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.c
@@ -0,0 +1,385 @@
+/** @file
+ Migrates SEC structures after permanent memory is installed.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+
+#include "SecMigrationPei.h"
+
+STATIC REPUBLISH_SEC_PPI_PPI mEdkiiRepublishSecPpiPpi = {
+ RepublishSecPpis
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_SEC_PLATFORM_INFORMATION_PPI mSecPlatformInformationPostMemoryPpi = {
+ SecPlatformInformationPostMemory
+ };
+
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_TEMPORARY_RAM_DONE_PPI mSecTemporaryRamDonePostMemoryPpi = {
+ SecTemporaryRamDonePostMemory
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mSecTemporaryRamSupportPostMemoryPpi = {
+ SecTemporaryRamSupportPostMemory
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED PEI_SEC_PERFORMANCE_PPI mSecPerformancePpi = {
+ GetPerformancePostMemory
+ };
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mEdkiiRepublishSecPpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gRepublishSecPpiPpiGuid,
+ &mEdkiiRepublishSecPpiPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecPlatformInformationPostMemoryDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiSecPlatformInformationPpiGuid,
+ &mSecPlatformInformationPostMemoryPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecTemporaryRamDonePostMemoryDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamDonePpiGuid,
+ &mSecTemporaryRamDonePostMemoryPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecTemporaryRamSupportPostMemoryDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamSupportPpiGuid,
+ &mSecTemporaryRamSupportPostMemoryPpi
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_PEI_PPI_DESCRIPTOR mSecPerformancePpiDescriptor = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gPeiSecPerformancePpiGuid,
+ &mSecPerformancePpi
+ };
+
+/**
+ Disables the use of Temporary RAM.
+
+ If present, this service is invoked by the PEI Foundation after
+ the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
+
+ @retval EFI_SUCCESS Dummy function, alway return this value.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamDonePostMemory (
+ VOID
+ )
+{
+ //
+ // Temporary RAM Done is already done in post-memory
+ // install a stub function that is located in permanent memory
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupportPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ )
+{
+ //
+ // Temporary RAM Support is already done in post-memory
+ // install a stub function that is located in permanent memory
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The performance data was successfully returned.
+ @retval EFI_INVALID_PARAMETER The This or Performance is NULL.
+ @retval EFI_NOT_FOUND Can't found the HOB created by the SecMigrationPei component.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPerformancePostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ )
+{
+ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContexHob;
+
+ if (This == NULL || Performance == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SecPlatformInformationContexHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ if (SecPlatformInformationContexHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Performance->ResetEnd = SecPlatformInformationContexHob->FirmwareSecPerformance.ResetEnd;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer.
+ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_NOT_FOUND Can't found the HOB created by SecMigrationPei component.
+ @retval EFI_BUFFER_TOO_SMALL The size of buffer pointed by StructureSize is too small and will return
+ the minimal required size in the buffer pointed by StructureSize.
+ @retval EFI_INVALID_PARAMETER The StructureSize is NULL or PlatformInformationRecord is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformationPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ )
+{
+ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContexHob;
+
+ if (StructureSize == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SecPlatformInformationContexHob = GetFirstGuidHob (&gEfiCallerIdGuid);
+ if (SecPlatformInformationContexHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (*StructureSize < SecPlatformInformationContexHob->Context.StructureSize) {
+ *StructureSize = SecPlatformInformationContexHob->Context.StructureSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
+
+ if (PlatformInformationRecord == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *StructureSize = SecPlatformInformationContexHob->Context.StructureSize;
+ CopyMem (
+ (VOID *) PlatformInformationRecord,
+ (VOID *) SecPlatformInformationContexHob->Context.PlatformInformationRecord,
+ (UINTN) SecPlatformInformationContexHob->Context.StructureSize
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This interface re-installs PPIs installed in SecCore from a post-memory PEIM.
+
+ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory
+ copy from a PEIM that has been shadowed to permanent memory.
+
+ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully.
+ @retval Others An error occurred re-installing the SecCore PPIs.
+
+**/
+EFI_STATUS
+EFIAPI
+RepublishSecPpis (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *PeiPpiDescriptor;
+ VOID *PeiPpi;
+ SEC_PLATFORM_INFORMATION_CONTEXT_HOB *SecPlatformInformationContextHob;
+ EFI_SEC_PLATFORM_INFORMATION_RECORD *SecPlatformInformationPtr;
+ UINT64 SecStructureSize;
+
+ SecPlatformInformationPtr = NULL;
+ SecStructureSize = 0;
+
+ Status = PeiServicesLocatePpi (
+ &gEfiTemporaryRamDonePpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecTemporaryRamDonePostMemoryDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiTemporaryRamSupportPpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecTemporaryRamSupportPostMemoryDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ Status = PeiServicesCreateHob (
+ EFI_HOB_TYPE_GUID_EXTENSION,
+ sizeof (SEC_PLATFORM_INFORMATION_CONTEXT_HOB),
+ (VOID **) &SecPlatformInformationContextHob
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "SecPlatformInformation Context HOB could not be created.\n"));
+ return Status;
+ }
+
+ SecPlatformInformationContextHob->Header.Name = gEfiCallerIdGuid;
+ SecPlatformInformationContextHob->Revision = 1;
+
+ Status = PeiServicesLocatePpi (
+ &gPeiSecPerformancePpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = ((PEI_SEC_PERFORMANCE_PPI *) PeiPpi)->GetPerformance (
+ GetPeiServicesTablePointer (),
+ (PEI_SEC_PERFORMANCE_PPI *) PeiPpi,
+ &SecPlatformInformationContextHob->FirmwareSecPerformance
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecPerformancePpiDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ Status = PeiServicesLocatePpi (
+ &gEfiSecPlatformInformationPpiGuid,
+ 0,
+ &PeiPpiDescriptor,
+ (VOID **) &PeiPpi
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = ((EFI_SEC_PLATFORM_INFORMATION_PPI *) PeiPpi)->PlatformInformation (
+ GetPeiServicesTablePointer (),
+ &SecStructureSize,
+ SecPlatformInformationPtr
+ );
+ ASSERT (Status == EFI_BUFFER_TOO_SMALL);
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ return EFI_NOT_FOUND;
+ }
+
+ ZeroMem ((VOID *) &(SecPlatformInformationContextHob->Context), sizeof (SEC_PLATFORM_INFORMATION_CONTEXT));
+ SecPlatformInformationContextHob->Context.PlatformInformationRecord = AllocatePool ((UINTN) SecStructureSize);
+ ASSERT (SecPlatformInformationContextHob->Context.PlatformInformationRecord != NULL);
+ if (SecPlatformInformationContextHob->Context.PlatformInformationRecord == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ SecPlatformInformationContextHob->Context.StructureSize = SecStructureSize;
+
+ Status = ((EFI_SEC_PLATFORM_INFORMATION_PPI *) PeiPpi)->PlatformInformation (
+ GetPeiServicesTablePointer (),
+ &(SecPlatformInformationContextHob->Context.StructureSize),
+ SecPlatformInformationContextHob->Context.PlatformInformationRecord
+ );
+ ASSERT_EFI_ERROR (Status);
+ if (!EFI_ERROR (Status)) {
+ Status = PeiServicesReInstallPpi (
+ PeiPpiDescriptor,
+ &mSecPlatformInformationPostMemoryDescriptor
+ );
+ ASSERT_EFI_ERROR (Status);
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is the entry point which installs an instance of REPUBLISH_SEC_PPI_PPI.
+
+ It install the RepublishSecPpi depent on PcdMigrateTemporaryRamFirmwareVolumes, install
+ the PPI when the PcdMigrateTemporaryRamFirmwareVolumes enabled.
+
+ @param[in] FileHandle Pointer to image file handle.
+ @param[in] PeiServices Pointer to PEI Services Table
+
+ @retval EFI_ABORTED Disable evacuate temporary memory feature by disable
+ PcdMigrateTemporaryRamFirmwareVolumes.
+ @retval EFI_SUCCESS An instance of REPUBLISH_SEC_PPI_PPI was installed successfully.
+ @retval Others An error occurred installing and instance of REPUBLISH_SEC_PPI_PPI.
+
+**/
+EFI_STATUS
+EFIAPI
+SecMigrationPeiInitialize (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_ABORTED;
+
+ if (PcdGetBool (PcdMigrateTemporaryRamFirmwareVolumes)) {
+ Status = PeiServicesInstallPpi (&mEdkiiRepublishSecPpiDescriptor);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h
new file mode 100644
index 00000000000..4c491e064cc
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.h
@@ -0,0 +1,158 @@
+/** @file
+ Migrates SEC structures after permanent memory is installed.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __SEC_MIGRATION_H__
+#define __SEC_MIGRATION_H__
+
+#include <Base.h>
+
+#include <Pi/PiPeiCis.h>
+#include <Ppi/RepublishSecPpi.h>
+#include <Ppi/SecPerformance.h>
+#include <Ppi/SecPlatformInformation.h>
+#include <Ppi/SecPlatformInformation2.h>
+#include <Ppi/TemporaryRamDone.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+/**
+ This interface conveys state information out of the Security (SEC) phase into PEI.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in,out] StructureSize Pointer to the variable describing size of the input buffer.
+ @param[out] PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_NOT_FOUND Can't found the HOB created by SecMigrationPei component.
+ @retval EFI_BUFFER_TOO_SMALL The size of buffer pointed by StructureSize is too small and will return
+ the minimal required size in the buffer pointed by StructureSize.
+ @retval EFI_INVALID_PARAMETER The StructureSize is NULL or PlatformInformationRecord is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformationPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN OUT UINT64 *StructureSize,
+ OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord
+ );
+
+/**
+ Re-installs the SEC Platform Information PPIs to implementation in this module to support post-memory.
+
+ @param[in] PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
+ @param[in] NotifyDescriptor Address of the notification descriptor data structure.
+ @param[in] Ppi Address of the PPI that was installed.
+
+ @retval EFI_SUCCESS The SEC Platform Information PPI could not be re-installed.
+ @return Others An error occurred during PPI re-install.
+
+**/
+EFI_STATUS
+EFIAPI
+SecPlatformInformationPpiNotifyCallback (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ );
+
+/**
+ This interface re-installs PPIs installed in SecCore from a post-memory PEIM.
+
+ This is to allow a platform that may not support relocation of SecCore to update the PPI instance to a post-memory
+ copy from a PEIM that has been shadowed to permanent memory.
+
+ @retval EFI_SUCCESS The SecCore PPIs were re-installed successfully.
+ @retval Others An error occurred re-installing the SecCore PPIs.
+
+**/
+EFI_STATUS
+EFIAPI
+RepublishSecPpis (
+ VOID
+ );
+
+/**
+ Disables the use of Temporary RAM.
+
+ If present, this service is invoked by the PEI Foundation after
+ the EFI_PEI_PERMANANT_MEMORY_INSTALLED_PPI is installed.
+
+ @retval EFI_SUCCESS Dummy function, alway return this value.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamDonePostMemory (
+ VOID
+ );
+
+/**
+ This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
+ permanent memory.
+
+ @param PeiServices Pointer to the PEI Services Table.
+ @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
+ Temporary RAM contents.
+ @param CopySize Amount of memory to migrate from temporary to permanent memory.
+
+ @retval EFI_SUCCESS The data was successfully returned.
+ @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
+ TemporaryMemoryBase > PermanentMemoryBase.
+
+**/
+EFI_STATUS
+EFIAPI
+SecTemporaryRamSupportPostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+/**
+ This interface conveys performance information out of the Security (SEC) phase into PEI.
+
+ This service is published by the SEC phase. The SEC phase handoff has an optional
+ EFI_PEI_PPI_DESCRIPTOR list as its final argument when control is passed from SEC into the
+ PEI Foundation. As such, if the platform supports collecting performance data in SEC,
+ this information is encapsulated into the data structure abstracted by this service.
+ This information is collected for the boot-strap processor (BSP) on IA-32.
+
+ @param[in] PeiServices The pointer to the PEI Services Table.
+ @param[in] This The pointer to this instance of the PEI_SEC_PERFORMANCE_PPI.
+ @param[out] Performance The pointer to performance data collected in SEC phase.
+
+ @retval EFI_SUCCESS The performance data was successfully returned.
+ @retval EFI_INVALID_PARAMETER The This or Performance is NULL.
+ @retval EFI_NOT_FOUND Can't found the HOB created by the SecMigrationPei component.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPerformancePostMemory (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN PEI_SEC_PERFORMANCE_PPI *This,
+ OUT FIRMWARE_SEC_PERFORMANCE *Performance
+ );
+
+typedef struct {
+ UINT64 StructureSize;
+ EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord;
+} SEC_PLATFORM_INFORMATION_CONTEXT;
+
+typedef struct {
+ EFI_HOB_GUID_TYPE Header;
+ UINT8 Revision;
+ UINT8 Reserved[3];
+ FIRMWARE_SEC_PERFORMANCE FirmwareSecPerformance;
+ SEC_PLATFORM_INFORMATION_CONTEXT Context;
+} SEC_PLATFORM_INFORMATION_CONTEXT_HOB;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
new file mode 100644
index 00000000000..7c2b7e2d3ff
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
@@ -0,0 +1,68 @@
+## @file
+# Migrates SEC structures after permanent memory is installed.
+#
+# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecMigrationPei
+ MODULE_UNI_FILE = SecMigrationPei.uni
+ FILE_GUID = 58B35361-8922-41BC-B313-EF7ED9ADFDF7
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = SecMigrationPeiInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ SecMigrationPei.c
+ SecMigrationPei.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ HobLib
+ MemoryAllocationLib
+ PeimEntryPoint
+ PeiServicesLib
+ PeiServicesTablePointerLib
+
+[Ppis]
+ ## PRODUCES
+ gRepublishSecPpiPpiGuid
+
+ ## SOMETIMES_PRODUCES
+ gEfiTemporaryRamDonePpiGuid
+
+ ## SOMETIME_PRODUCES
+ gEfiTemporaryRamSupportPpiGuid
+
+ ## SOMETIMES_PRODUCES
+ gPeiSecPerformancePpiGuid
+
+ ## SOMETIMES_CONSUMES
+ ## PRODUCES
+ gEfiSecPlatformInformationPpiGuid
+
+ ## SOMETIMES_CONSUMES
+ ## SOMETIMES_PRODUCES
+ gEfiSecPlatformInformation2PpiGuid
+
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdMigrateTemporaryRamFirmwareVolumes ## CONSUMES
+
+[Depex]
+ TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni
new file mode 100644
index 00000000000..62c2064ba21
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/SecMigrationPei/SecMigrationPei.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Migrates SEC structures after permanent memory is installed.
+//
+// Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Migrates SEC structures after permanent memory is installed"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Migrates SEC structures after permanent memory is installed."
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
new file mode 100644
index 00000000000..bcb046617cb
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc
@@ -0,0 +1,31 @@
+## @file
+# UefiCpuPkg DSC file used to build host-based unit tests.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ PLATFORM_NAME = UefiCpuPkgHostTest
+ PLATFORM_GUID = E00B9599-5B74-4FF7-AB9F-8183FB13B2F9
+ PLATFORM_VERSION = 0.1
+ DSC_SPECIFICATION = 0x00010005
+ OUTPUT_DIRECTORY = Build/UefiCpuPkg/HostTest
+ SUPPORTED_ARCHITECTURES = IA32|X64
+ BUILD_TARGETS = NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+
+[LibraryClasses]
+ MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
+
+[PcdsPatchableInModule]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|0
+
+[Components]
+ #
+ # Build HOST_APPLICATION that tests the MtrrLib
+ #
+ UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.ci.yaml
index d30ae3b2867..5d3e349464e 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.ci.yaml
@@ -2,12 +2,31 @@
# CI configuration for UefiCpuPkg
#
# Copyright (c) Microsoft Corporation
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ ]
+ },
"CompilerPlugin": {
"DscPath": "UefiCpuPkg.dsc"
},
+ ## options defined ci/Plugin/HostUnitTestCompilerPlugin
+ "HostUnitTestCompilerPlugin": {
+ "DscPath": "Test/UefiCpuPkgHostTest.dsc"
+ },
"CharEncodingCheck": {
"IgnoreFiles": []
},
@@ -18,7 +37,9 @@
"UefiCpuPkg/UefiCpuPkg.dec"
],
# For host based unit tests
- "AcceptableDependencies-HOST_APPLICATION":[],
+ "AcceptableDependencies-HOST_APPLICATION":[
+ "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
+ ],
# For UEFI shell based apps
"AcceptableDependencies-UEFI_APPLICATION":[],
"IgnoreInf": []
@@ -30,6 +51,10 @@
"UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf"
]
},
+ "HostUnitTestDscCompleteCheck": {
+ "IgnoreInf": [""],
+ "DscPath": "Test/UefiCpuPkgHostTest.dsc"
+ },
"GuidCheck": {
"IgnoreGuidName": ["SecCore", "ResetVector"], # Expected duplication for gEfiFirmwareVolumeTopFileGuid
"IgnoreGuidValue": [],
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dec b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dec
index 7ce1fa85b24..3bf636fa38e 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dec
@@ -1,7 +1,7 @@
## @file UefiCpuPkg.dec
# This Package provides UEFI compatible CPU modules and libraries.
#
-# Copyright (c) 2007 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -53,6 +53,15 @@
##
MpInitLib|Include/Library/MpInitLib.h
+ ## @libraryclass Provides function to support VMGEXIT processing.
+ VmgExitLib|Include/Library/VmgExitLib.h
+
+ ## @libraryclass Provides function to get CPU cache information.
+ CpuCacheInfoLib|Include/Library/CpuCacheInfoLib.h
+
+ ## @libraryclass Provides function for loading microcode.
+ MicrocodeLib|Include/Library/MicrocodeLib.h
+
[Guids]
gUefiCpuPkgTokenSpaceGuid = { 0xac05bf33, 0x995a, 0x4ed4, { 0xaa, 0xb8, 0xef, 0x7a, 0xe8, 0xf, 0x5c, 0xb0 }}
gMsegSmramGuid = { 0x5802bce4, 0xeeee, 0x4e33, { 0xa1, 0x30, 0xeb, 0xad, 0x27, 0xf0, 0xe4, 0x39 }}
@@ -84,6 +93,9 @@
## Include/Ppi/ShadowMicrocode.h
gEdkiiPeiShadowMicrocodePpiGuid = { 0x430f6965, 0x9a69, 0x41c5, { 0x93, 0xed, 0x8b, 0xf0, 0x64, 0x35, 0xc1, 0xc6 }}
+ ## Include/Ppi/RepublishSecPpi.h
+ gRepublishSecPpiPpiGuid = { 0x27a71b1e, 0x73ee, 0x43d6, { 0xac, 0xe3, 0x52, 0x1a, 0x2d, 0xc5, 0xd0, 0x92 }}
+
[PcdsFeatureFlag]
## Indicates if SMM Profile will be enabled.
# If enabled, instruction executions in and data accesses to memory outside of SMRAM will be logged.
@@ -158,6 +170,14 @@
# @Prompt Specify the count of pre allocated SMM MP tokens per chunk.
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmMpTokenCountPerChunk|64|UINT32|0x30002002
+ ## Area of memory where the SEV-ES work area block lives.
+ # @Prompt Configure the SEV-ES work area base
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaBase|0x0|UINT32|0x30002005
+
+ ## Size of teh area of memory where the SEV-ES work area block lives.
+ # @Prompt Configure the SEV-ES work area base
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsWorkAreaSize|0x0|UINT32|0x30002006
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## This value is the CPU Local APIC base address, which aligns the address on a 4-KByte boundary.
# @Prompt Configure base address of CPU Local APIC
@@ -370,5 +390,11 @@
# @ValidRange 0x80000001 | 0 - 1
gUefiCpuPkgTokenSpaceGuid.PcdCpuProcTraceOutputScheme|0x0|UINT8|0x60000015
+ ## This dynamic PCD indicates whether SEV-ES is enabled
+ # TRUE - SEV-ES is enabled
+ # FALSE - SEV-ES is not enabled
+ # @Prompt SEV-ES Status
+ gUefiCpuPkgTokenSpaceGuid.PcdSevEsIsEnabled|FALSE|BOOLEAN|0x60000016
+
[UserExtensions.TianoCore."ExtraFiles"]
UefiCpuPkgExtra.uni
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dsc b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dsc
index 79a22443ac9..5be5d4dc026 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.dsc
@@ -1,7 +1,7 @@
## @file
# UefiCpuPkg Package
#
-# Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -21,6 +21,8 @@
# External libraries to build package
#
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
@@ -38,6 +40,7 @@
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+ StandaloneMmDriverEntryPoint|MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
@@ -56,6 +59,8 @@
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
[LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -74,6 +79,7 @@
LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxPeiLib.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf
+ CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
[LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM]
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
@@ -85,13 +91,18 @@
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.inf
+ CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
[LibraryClasses.common.DXE_SMM_DRIVER]
SmmServicesTableLib|MdePkg/Library/SmmServicesTableLib/SmmServicesTableLib.inf
+ MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
MemoryAllocationLib|MdePkg/Library/SmmMemoryAllocationLib/SmmMemoryAllocationLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/SmmCpuExceptionHandlerLib.inf
+[LibraryClasses.common.MM_STANDALONE]
+ MmServicesTableLib|MdePkg/Library/StandaloneMmServicesTableLib/StandaloneMmServicesTableLib.inf
+
[LibraryClasses.common.UEFI_APPLICATION]
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
@@ -106,8 +117,8 @@
UefiCpuPkg/Library/SecPeiDxeTimerLibUefiCpu/SecPeiDxeTimerLibUefiCpu.inf
UefiCpuPkg/Application/Cpuid/Cpuid.inf
UefiCpuPkg/Library/CpuTimerLib/BaseCpuTimerLib.inf
- UefiCpuPkg/Library/CpuTimerLib/DxeCpuTimerLib.inf
- UefiCpuPkg/Library/CpuTimerLib/PeiCpuTimerLib.inf
+ UefiCpuPkg/Library/CpuCacheInfoLib/PeiCpuCacheInfoLib.inf
+ UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
[Components.IA32, Components.X64]
UefiCpuPkg/CpuDxe/CpuDxe.inf
@@ -120,6 +131,7 @@
NULL|UefiCpuPkg/Library/CpuCommonFeaturesLib/CpuCommonFeaturesLib.inf
}
UefiCpuPkg/CpuIo2Smm/CpuIo2Smm.inf
+ UefiCpuPkg/CpuIo2Smm/CpuIo2StandaloneMm.inf
UefiCpuPkg/CpuMpPei/CpuMpPei.inf
UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
@@ -136,6 +148,7 @@
UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
UefiCpuPkg/Library/MpInitLibUp/MpInitLibUp.inf
+ UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.inf
@@ -143,9 +156,12 @@
UefiCpuPkg/Library/SmmCpuPlatformHookLibNull/SmmCpuPlatformHookLibNull.inf
UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
+ UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
+ UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationPei.inf
UefiCpuPkg/PiSmmCommunication/PiSmmCommunicationSmm.inf
UefiCpuPkg/SecCore/SecCore.inf
+ UefiCpuPkg/SecMigrationPei/SecMigrationPei.inf
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf {
<Defines>
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.uni b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.uni
index 1780dfdc126..219c1963bf0 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.uni
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/UefiCpuPkg.uni
@@ -278,3 +278,14 @@
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuApStatusCheckIntervalInMicroSeconds_PROMPT #language en-US "Periodic interval value in microseconds for AP status check in DXE.\n"
#string STR_gUefiCpuPkgTokenSpaceGuid_PcdCpuApStatusCheckIntervalInMicroSeconds_HELP #language en-US "Periodic interval value in microseconds for the status check of APs for StartupAllAPs() and StartupThisAP() executed in non-blocking mode in DXE phase.\n"
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdSevEsIsEnabled_PROMPT #language en-US "Specifies whether SEV-ES is enabled"
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdSevEsIsEnabled_HELP #language en-US "Set to TRUE when running as an SEV-ES guest, FALSE otherwise."
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdSevEsWorkAreaBase_PROMPT #language en-US "Specify the address of the SEV-ES work area"
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdSevEsWorkAreaBase_HELP #language en-US "Specifies the address of the work area used by an SEV-ES guest."
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdSevEsWorkAreaSize_PROMPT #language en-US "Specify the size of the SEV-ES work area"
+
+#string STR_gUefiCpuPkgTokenSpaceGuid_PcdSevEsWorkAreaSize_HELP #language en-US "Specifies the size of the work area used by an SEV-ES guest."
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c
index cbdbfb5be4f..64377d9f6c1 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.c
@@ -2,7 +2,7 @@
This driver will report some MMIO/IO resources to dxe core, extract smbios and acpi
tables from bootloader.
- Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -101,6 +101,7 @@ BlDxeEntryPoint (
EFI_HOB_GUID_TYPE *GuidHob;
SYSTEM_TABLE_INFO *SystemTableInfo;
EFI_PEI_GRAPHICS_INFO_HOB *GfxInfo;
+ ACPI_BOARD_INFO *AcpiBoardInfo;
Status = EFI_SUCCESS;
//
@@ -153,6 +154,18 @@ BlDxeEntryPoint (
ASSERT_EFI_ERROR (Status);
}
+ //
+ // Set PcdPciExpressBaseAddress and PcdPciExpressBaseSize by HOB info
+ //
+ GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+ if (GuidHob != NULL) {
+ AcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);
+ Status = PcdSet64S (PcdPciExpressBaseAddress, AcpiBoardInfo->PcieBaseAddress);
+ ASSERT_EFI_ERROR (Status);
+ Status = PcdSet64S (PcdPciExpressBaseSize, AcpiBoardInfo->PcieBaseSize);
+ ASSERT_EFI_ERROR (Status);
+ }
+
return EFI_SUCCESS;
}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
index 6fbd235f126..95e0ba4255f 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
@@ -3,7 +3,7 @@
#
# Report some MMIO/IO resources to dxe core, extract smbios and acpi tables
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -53,6 +53,8 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution
gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize
[Depex]
TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.h
deleted file mode 100644
index c34b14e97a5..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/** @file
- The header file of bootloader support PEIM.
-
-Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-
-#ifndef __PEI_BOOTLOADER_SUPPORT_H__
-#define __PEI_BOOTLOADER_SUPPORT_H__
-
-#include <PiPei.h>
-#include <Library/PeimEntryPoint.h>
-#include <Library/PeiServicesLib.h>
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/HobLib.h>
-#include <Library/PcdLib.h>
-#include <Library/BlParseLib.h>
-#include <Library/MtrrLib.h>
-#include <Library/IoLib.h>
-#include <Library/PlatformSupportLib.h>
-#include <IndustryStandard/Acpi.h>
-#include <Guid/MemoryTypeInformation.h>
-#include <Guid/FirmwareFileSystem2.h>
-#include <Guid/SystemTableInfoGuid.h>
-#include <Guid/AcpiBoardInfoGuid.h>
-#include <Guid/GraphicsInfoHob.h>
-#include <Ppi/MasterBootMode.h>
-#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
-
-typedef struct {
- UINT32 UsableLowMemTop;
- UINT32 SystemLowMemTop;
-} PAYLOAD_MEM_INFO;
-
-#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
deleted file mode 100644
index 8121b32c85b..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
+++ /dev/null
@@ -1,73 +0,0 @@
-## @file
-# Bootloader Support PEI Module
-#
-# Parses bootloader information and report resource information into pei core. It will install
-# the memory as required.
-#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = BlSupportPeim
- FILE_GUID = 352C6AF8-315B-4bd6-B04F-31D4ED1EBE57
- MODULE_TYPE = PEIM
- VERSION_STRING = 1.0
- ENTRY_POINT = BlPeiEntryPoint
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64
-#
-
-[Sources]
- BlSupportPei.c
- BlSupportPei.h
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- IntelFsp2Pkg/IntelFsp2Pkg.dec
- IntelFsp2WrapperPkg/IntelFsp2WrapperPkg.dec
- UefiPayloadPkg/UefiPayloadPkg.dec
- UefiCpuPkg/UefiCpuPkg.dec
-
-[LibraryClasses]
- PeimEntryPoint
- PeiServicesLib
- BaseLib
- BaseMemoryLib
- DebugLib
- HobLib
- PcdLib
- BlParseLib
- MtrrLib
- IoLib
- PlatformSupportLib
-
-[Guids]
- gEfiMemoryTypeInformationGuid
- gEfiFirmwareFileSystem2Guid
- gUefiSystemTableInfoGuid
- gEfiGraphicsInfoHobGuid
- gEfiGraphicsDeviceInfoHobGuid
- gUefiAcpiBoardInfoGuid
-
-[Ppis]
- gEfiPeiMasterBootModePpiGuid
-
-[Pcd]
- gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
- gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
- gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIReclaimMemory
- gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiACPIMemoryNVS
- gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType
- gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData
- gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode
-
-[Depex]
- TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt
index c5fba82a424..5ed6f61ec7a 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BuildAndIntegrationInstructions.txt
@@ -1,6 +1,6 @@
================================================================================
Build And Integration Instructions
-2019 March 27th
+2020 Aug 1st
================================================================================
================================================================================
@@ -35,27 +35,25 @@ integrate it into coreboot or Slim Bootloader firmware.
B. HOW TO BUILD
================================================================================
1. Run the below two commands in windows command prompt window:
- edksetup.bat
+ > edksetup.bat
- For debug ia32 build:
- build -a IA32 -p UefiPayloadPkg\UefiPayloadPkgIa32.dsc -b DEBUG -t <ToolChain> -D BOOTLOADER=<Bootloader>
+ For pure X64 build:
+ > build -a x64 -p UefiPayloadPkg\UefiPayloadPkg.dsc -b <BuildType> -t <ToolChain>
+ -D BOOTLOADER=<Bootloader>
- For release ia32 build:
- build -a IA32 -p UefiPayloadPkg\UefiPayloadPkgIa32.dsc -b RELEASE -t <ToolChain> -D BOOTLOADER=<Bootloader>
+ For X64 build with IA32 entry point:
+ > build -a IA32 -a X64 -p UefiPayloadPkg\UefiPayloadPkg.dsc -b <BuildType> -t <ToolChain>
+ -D BOOTLOADER=<Bootloader>
- For debug X64 build:
- build -a IA32 -a X64 -p UefiPayloadPkg\UefiPayloadPkgIa32X64.dsc -b DEBUG -t <ToolChain> -D BOOTLOADER=<Bootloader>
-
- For release X64 build:
- build -a IA32 -a X64 -p UefiPayloadPkg\UefiPayloadPkgIa32X64.dsc -b RELEASE -t <ToolChain> -D BOOTLOADER=<Bootloader>
-
- <ToolChain> is the EDK II build environment on your host. Currently it was tested
- with VS2015x86 toolchain.
+ <BuildType> support 'DEBUG', 'RELEASE' and 'NOOPT'.
+ <ToolChain> is the EDK II build environment on your host. Tested with VS2015x86 toolchain.
<Bootloader> could be "SBL" for Slim Bootloader and "COREBOOT" for coreboot.
Refer to https://github.com/tianocore/tianocore.github.io/wiki/UDK2018-How-to-Build for
details about EDK II build steps.
+ NOTE: Pure 32bit UEFI payload support could be added if required later.
+
2. If build is successfully, the payload image (UEFIPAYLOAD.fd) will be generated inside the
folder of Build\UefiPayloadPkg.
@@ -65,9 +63,9 @@ C. HOW TO INTEGRATE INTO COREBOOT
1. Copy the payload image (UEFIPAYLOAD.fd) into the top-level directory of Coreboot source tree.
2. Run "make menuconfig" in linux console to start Coreboot configuration surface.
3. In the Payload section,
- 1) Choose "An ELF executable payload" for the option of "Add a payload".
- 2) Type the path of payload image for the option of "Payload path and filename".
- 3) Select the option of "Use LZMA compression for payloads".
+ 1) Choose "Tianocore Payload" for the option of "Add a payload".
+ 2) Update the path of payload image for the option of "Tianocore binary".
+ 3) Choose "UEFIPayload" for the option of "Tianocore Payload".
4. If the graphics console is required in UEFI payload, enable framebuffer initialization in coreboot.
This could be done by enabling native graphics or using VGA BIOS option rom.
5. Build the coreboot firmware image.
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h
index 6b853445324..a43e8f20a27 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Guid/AcpiBoardInfoGuid.h
@@ -24,6 +24,7 @@ typedef struct {
UINT64 PmTimerRegBase;
UINT64 ResetRegAddress;
UINT64 PcieBaseAddress;
+ UINT64 PcieBaseSize;
} ACPI_BOARD_INFO;
#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h
index 9fa1e77f22b..79eb3fc03ac 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Include/Library/BlParseLib.h
@@ -2,7 +2,7 @@
This library will parse the coreboot table in memory and extract those required
information.
- Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -16,7 +16,7 @@
#ifndef __BOOTLOADER_PARSE_LIB__
#define __BOOTLOADER_PARSE_LIB__
-#define GET_BOOTLOADER_PARAMETER() (*(UINT32 *)(UINTN)(PcdGet32(PcdPayloadStackTop) - sizeof(UINT32)))
+#define GET_BOOTLOADER_PARAMETER() (*(UINTN *)(UINTN)(PcdGet32(PcdPayloadStackTop) - sizeof(UINT64)))
#define SET_BOOTLOADER_PARAMETER(Value) GET_BOOTLOADER_PARAMETER()=Value
typedef RETURN_STATUS \
diff --git a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/Hob.c
index d1934a21ede..1a1705b0f3a 100644
--- a/src/VBox/Devices/EFI/Firmware/StandaloneMmPkg/Library/StandaloneMmCoreHobLib/StandaloneMmCoreHobLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/Hob.c
@@ -1,31 +1,26 @@
/** @file
- HOB Library implementation for Standalone MM Core.
-Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
-Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.<BR>
+ Copyright (c) 2010, Apple Inc. All rights reserved.<BR>
+ Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiMm.h>
+#include <PiPei.h>
-#include <Library/HobLib.h>
-#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
-#include <Guid/MemoryAllocationHob.h>
-
-//
-// Cache copy of HobList pointer.
-//
-VOID *gHobList = NULL;
+VOID *mHobList;
/**
Returns the pointer to the HOB list.
This function returns the pointer to first HOB in the list.
- If the pointer to the HOB list is NULL, then ASSERT().
@return The pointer to the HOB list.
@@ -36,8 +31,166 @@ GetHobList (
VOID
)
{
- ASSERT (gHobList != NULL);
- return gHobList;
+ ASSERT (mHobList != NULL);
+ return mHobList;
+}
+
+
+/**
+ Build a Handoff Information Table HOB
+
+ This function initialize a HOB region from EfiMemoryBegin with length
+ EfiMemoryLength. And EfiFreeMemoryBottom and EfiFreeMemoryTop should
+ be inside the HOB region.
+
+ @param[in] EfiMemoryBegin Total memory start address
+ @param[in] EfiMemoryLength Total memory length reported in handoff HOB.
+ @param[in] EfiFreeMemoryBottom Free memory start address
+ @param[in] EfiFreeMemoryTop Free memory end address.
+
+ @return The pointer to the handoff HOB table.
+
+**/
+EFI_HOB_HANDOFF_INFO_TABLE*
+EFIAPI
+HobConstructor (
+ IN VOID *EfiMemoryBegin,
+ IN UINTN EfiMemoryLength,
+ IN VOID *EfiFreeMemoryBottom,
+ IN VOID *EfiFreeMemoryTop
+ )
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *Hob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+
+ Hob = EfiFreeMemoryBottom;
+ HobEnd = (EFI_HOB_GENERIC_HEADER *)(Hob+1);
+
+ Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF;
+ Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE);
+ Hob->Header.Reserved = 0;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+
+ Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION;
+ Hob->BootMode = BOOT_WITH_FULL_CONFIGURATION;
+
+ Hob->EfiMemoryTop = (UINTN)EfiMemoryBegin + EfiMemoryLength;
+ Hob->EfiMemoryBottom = (UINTN)EfiMemoryBegin;
+ Hob->EfiFreeMemoryTop = (UINTN)EfiFreeMemoryTop;
+ Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS)(UINTN)(HobEnd+1);
+ Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS)(UINTN)HobEnd;
+
+ mHobList = Hob;
+ return Hob;
+}
+
+/**
+ 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
+ )
+{
+ EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
+ EFI_HOB_GENERIC_HEADER *HobEnd;
+ EFI_PHYSICAL_ADDRESS FreeMemory;
+ VOID *Hob;
+
+ HandOffHob = GetHobList ();
+
+ HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
+
+ FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
+
+ if (FreeMemory < HobLength) {
+ return NULL;
+ }
+
+ Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
+ ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType;
+ ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength;
+ ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0;
+
+ HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength);
+ HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
+ HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER);
+ HobEnd->Reserved = 0;
+ HobEnd++;
+ HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
+
+ return Hob;
+}
+
+/**
+ Builds a HOB that describes a chunk of system memory.
+
+ This function builds a HOB that describes a chunk of system memory.
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param ResourceType The type of resource described by this HOB.
+ @param ResourceAttribute The resource attributes of the memory described by this HOB.
+ @param PhysicalStart The 64 bit physical address of memory described by this HOB.
+ @param NumberOfBytes The length of the memory described by this HOB in bytes.
+
+**/
+VOID
+EFIAPI
+BuildResourceDescriptorHob (
+ IN EFI_RESOURCE_TYPE ResourceType,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 NumberOfBytes
+ )
+{
+ EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
+ ASSERT(Hob != NULL);
+
+ Hob->ResourceType = ResourceType;
+ Hob->ResourceAttribute = ResourceAttribute;
+ Hob->PhysicalStart = PhysicalStart;
+ Hob->ResourceLength = NumberOfBytes;
+}
+
+VOID
+EFIAPI
+BuildFvHobs (
+ IN EFI_PHYSICAL_ADDRESS PhysicalStart,
+ IN UINT64 NumberOfBytes,
+ IN EFI_RESOURCE_ATTRIBUTE_TYPE *ResourceAttribute
+ )
+{
+
+ EFI_RESOURCE_ATTRIBUTE_TYPE Resource;
+
+ BuildFvHob (PhysicalStart, NumberOfBytes);
+
+ if (ResourceAttribute == NULL) {
+ Resource = (EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE);
+ } else {
+ Resource = *ResourceAttribute;
+ }
+
+ BuildResourceDescriptorHob (EFI_RESOURCE_FIRMWARE_DEVICE, Resource, PhysicalStart, NumberOfBytes);
}
/**
@@ -48,7 +201,6 @@ GetHobList (
In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
unconditionally: it returns HobStart back if HobStart itself meets the requirement;
caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
-
If HobStart is NULL, then ASSERT().
@param Type The HOB type to return.
@@ -81,14 +233,14 @@ GetNextHob (
return NULL;
}
+
+
/**
Returns the first instance of a HOB type among the whole HOB list.
This function searches the first instance of a HOB type among the whole HOB list.
If there does not exist such HOB type in the HOB list, it will return NULL.
- If the pointer to the HOB list is NULL, then ASSERT().
-
@param Type The HOB type to return.
@return The next instance of a HOB type from the starting HOB.
@@ -106,19 +258,17 @@ GetFirstHob (
return GetNextHob (Type, HobList);
}
-/**
- Returns the next instance of the matched GUID HOB from the starting HOB.
+/**
This function searches the first instance of a HOB from the starting HOB pointer.
Such HOB should satisfy two conditions:
- its HOB type is EFI_HOB_TYPE_GUID_EXTENSION, and its GUID Name equals to the input Guid.
- If such a HOB from the starting HOB pointer does not exist, it will return NULL.
+ its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
+ If there does not exist such HOB from the starting HOB pointer, it will return NULL.
Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
- to extract the data section and its size information, respectively.
+ to extract the data section and its size info respectively.
In contrast with macro GET_NEXT_HOB(), this function does not skip the starting HOB pointer
unconditionally: it returns HobStart back if HobStart itself meets the requirement;
caller is required to use GET_NEXT_HOB() if it wishes to skip current HobStart.
-
If Guid is NULL, then ASSERT().
If HobStart is NULL, then ASSERT().
@@ -133,8 +283,7 @@ EFIAPI
GetNextGuidHob (
IN CONST EFI_GUID *Guid,
IN CONST VOID *HobStart
- )
-{
+ ){
EFI_PEI_HOB_POINTERS GuidHob;
GuidHob.Raw = (UINT8 *) HobStart;
@@ -147,17 +296,14 @@ GetNextGuidHob (
return GuidHob.Raw;
}
-/**
- Returns the first instance of the matched GUID HOB among the whole HOB list.
+/**
This function searches the first instance of a HOB among the whole HOB list.
Such HOB should satisfy two conditions:
its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid.
- If such a HOB from the starting HOB pointer does not exist, it will return NULL.
+ If there does not exist such HOB from the starting HOB pointer, it will return NULL.
Caller is required to apply GET_GUID_HOB_DATA () and GET_GUID_HOB_DATA_SIZE ()
- to extract the data section and its size information, respectively.
-
- If the pointer to the HOB list is NULL, then ASSERT().
+ to extract the data section and its size info respectively.
If Guid is NULL, then ASSERT().
@param Guid The GUID to match with in the HOB list.
@@ -177,74 +323,15 @@ GetFirstGuidHob (
return GetNextGuidHob (Guid, HobList);
}
-/**
- Get the system boot mode from the HOB list.
-
- This function returns the system boot mode information from the
- PHIT HOB in HOB list.
-
- If the pointer to the HOB list is NULL, then ASSERT().
-
- @param VOID
-
- @return The Boot Mode.
-
-**/
-EFI_BOOT_MODE
-EFIAPI
-GetBootModeHob (
- VOID
- )
-{
- EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
-
- HandOffHob = (EFI_HOB_HANDOFF_INFO_TABLE *) GetHobList ();
-
- return HandOffHob->BootMode;
-}
-
-VOID *
-CreateHob (
- IN UINT16 HobType,
- IN UINT16 HobLength
- )
-{
- EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob;
- EFI_HOB_GENERIC_HEADER *HobEnd;
- EFI_PHYSICAL_ADDRESS FreeMemory;
- VOID *Hob;
- HandOffHob = GetHobList ();
-
- HobLength = (UINT16)((HobLength + 0x7) & (~0x7));
- FreeMemory = HandOffHob->EfiFreeMemoryTop - HandOffHob->EfiFreeMemoryBottom;
-
- if (FreeMemory < HobLength) {
- return NULL;
- }
-
- Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList;
- ((EFI_HOB_GENERIC_HEADER*) Hob)->HobType = HobType;
- ((EFI_HOB_GENERIC_HEADER*) Hob)->HobLength = HobLength;
- ((EFI_HOB_GENERIC_HEADER*) Hob)->Reserved = 0;
-
- HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN)Hob + HobLength);
- HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
-
- HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
- HobEnd->HobLength = sizeof (EFI_HOB_GENERIC_HEADER);
- HobEnd->Reserved = 0;
- HobEnd++;
- HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd;
-
- return Hob;
-}
/**
Builds a HOB for a loaded PE32 module.
This function builds a HOB for a loaded PE32 module.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If ModuleName is NULL, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
@@ -285,43 +372,13 @@ BuildModuleHob (
}
/**
- Builds a HOB that describes a chunk of system memory.
-
- This function builds a HOB that describes a chunk of system memory.
- If there is no additional space for HOB creation, then ASSERT().
-
- @param ResourceType The type of resource described by this HOB.
- @param ResourceAttribute The resource attributes of the memory described by this HOB.
- @param PhysicalStart The 64 bit physical address of memory described by this HOB.
- @param NumberOfBytes The length of the memory described by this HOB in bytes.
-
-**/
-VOID
-EFIAPI
-BuildResourceDescriptorHob (
- IN EFI_RESOURCE_TYPE ResourceType,
- IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
- IN EFI_PHYSICAL_ADDRESS PhysicalStart,
- IN UINT64 NumberOfBytes
- )
-{
- EFI_HOB_RESOURCE_DESCRIPTOR *Hob;
-
- Hob = CreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR));
- ASSERT (Hob != NULL);
-
- Hob->ResourceType = ResourceType;
- Hob->ResourceAttribute = ResourceAttribute;
- Hob->PhysicalStart = PhysicalStart;
- Hob->ResourceLength = NumberOfBytes;
-}
-
-/**
Builds a GUID HOB with a certain data length.
This function builds a customized HOB tagged with a GUID for identification
and returns the start address of GUID HOB data so that caller can fill the customized data.
The HOB Header and Name field is already stripped.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If Guid is NULL, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
If DataLength >= (0x10000 - sizeof (EFI_HOB_GUID_TYPE)), then ASSERT().
@@ -358,6 +415,8 @@ BuildGuidHob (
This function builds a customized HOB tagged with a GUID for identification,
copies the input data to the HOB data field and returns the start address of the GUID HOB data.
The HOB Header and Name field is already stripped.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If Guid is NULL, then ASSERT().
If Data is NULL and DataLength > 0, then ASSERT().
If there is no additional space for HOB creation, then ASSERT().
@@ -387,10 +446,13 @@ BuildGuidDataHob (
return CopyMem (HobData, Data, DataLength);
}
+
/**
Builds a Firmware Volume HOB.
This function builds a Firmware Volume HOB.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@@ -417,6 +479,8 @@ BuildFvHob (
Builds a EFI_HOB_TYPE_FV2 HOB.
This function builds a EFI_HOB_TYPE_FV2 HOB.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param BaseAddress The base address of the Firmware Volume.
@@ -444,11 +508,58 @@ BuildFv2Hob (
CopyGuid (&Hob->FileName, FileName);
}
+/**
+ Builds a EFI_HOB_TYPE_FV3 HOB.
+
+ This function builds a EFI_HOB_TYPE_FV3 HOB.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
+
+ If there is no additional space for HOB creation, then ASSERT().
+
+ @param BaseAddress The base address of the Firmware Volume.
+ @param Length The size of the Firmware Volume in bytes.
+ @param AuthenticationStatus The authentication status.
+ @param ExtractedFv TRUE if the FV was extracted as a file within
+ another firmware volume. FALSE otherwise.
+ @param FvName The name of the Firmware Volume.
+ Valid only if IsExtractedFv is TRUE.
+ @param FileName The name of the file.
+ Valid only if IsExtractedFv is TRUE.
+
+**/
+VOID
+EFIAPI
+BuildFv3Hob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length,
+ IN UINT32 AuthenticationStatus,
+ IN BOOLEAN ExtractedFv,
+ IN CONST EFI_GUID *FvName, OPTIONAL
+ IN CONST EFI_GUID *FileName OPTIONAL
+ )
+{
+ EFI_HOB_FIRMWARE_VOLUME3 *Hob;
+
+ Hob = CreateHob (EFI_HOB_TYPE_FV3, sizeof (EFI_HOB_FIRMWARE_VOLUME3));
+
+ Hob->BaseAddress = BaseAddress;
+ Hob->Length = Length;
+ Hob->AuthenticationStatus = AuthenticationStatus;
+ Hob->ExtractedFv = ExtractedFv;
+ if (ExtractedFv) {
+ CopyGuid (&Hob->FvName, FvName);
+ CopyGuid (&Hob->FileName, FileName);
+ }
+}
+
/**
Builds a HOB for the CPU.
This function builds a HOB for the CPU.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
@param SizeOfMemorySpace The maximum physical memory addressability of the processor.
@@ -475,128 +586,121 @@ BuildCpuHob (
ZeroMem (Hob->Reserved, sizeof (Hob->Reserved));
}
+
/**
- Builds a HOB for the memory allocation.
+ Builds a HOB for the Stack.
- This function builds a HOB for the memory allocation.
+ This function builds a HOB for the stack.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
- @param BaseAddress The 64 bit physical address of the memory.
- @param Length The length of the memory allocation in bytes.
- @param MemoryType Type of memory allocated by this HOB.
+ @param BaseAddress The 64 bit physical address of the Stack.
+ @param Length The length of the stack in bytes.
**/
VOID
EFIAPI
-BuildMemoryAllocationHob (
+BuildStackHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
- IN UINT64 Length,
- IN EFI_MEMORY_TYPE MemoryType
+ IN UINT64 Length
)
{
- EFI_HOB_MEMORY_ALLOCATION *Hob;
+ EFI_HOB_MEMORY_ALLOCATION_STACK *Hob;
ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
((Length & (EFI_PAGE_SIZE - 1)) == 0));
- Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK));
- ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+ CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid);
Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
Hob->AllocDescriptor.MemoryLength = Length;
- Hob->AllocDescriptor.MemoryType = MemoryType;
+ Hob->AllocDescriptor.MemoryType = EfiBootServicesData;
+
//
// Zero the reserved space to match HOB spec
//
ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
}
-/**
- Builds a HOB that describes a chunk of system memory with Owner GUID.
-
- This function builds a HOB that describes a chunk of system memory.
- If there is no additional space for HOB creation, then ASSERT().
-
- @param ResourceType The type of resource described by this HOB.
- @param ResourceAttribute The resource attributes of the memory described by this HOB.
- @param PhysicalStart The 64 bit physical address of memory described by this HOB.
- @param NumberOfBytes The length of the memory described by this HOB in bytes.
- @param OwnerGUID GUID for the owner of this resource.
-
-**/
-VOID
-EFIAPI
-BuildResourceDescriptorWithOwnerHob (
- IN EFI_RESOURCE_TYPE ResourceType,
- IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute,
- IN EFI_PHYSICAL_ADDRESS PhysicalStart,
- IN UINT64 NumberOfBytes,
- IN EFI_GUID *OwnerGUID
- )
-{
- ASSERT (FALSE);
-}
/**
- Builds a Capsule Volume HOB.
+ Update the Stack Hob if the stack has been moved
- This function builds a Capsule Volume HOB.
- If the platform does not support Capsule Volume HOBs, then ASSERT().
- If there is no additional space for HOB creation, then ASSERT().
-
- @param BaseAddress The base address of the Capsule Volume.
- @param Length The size of the Capsule Volume in bytes.
+ @param BaseAddress The 64 bit physical address of the Stack.
+ @param Length The length of the stack in bytes.
**/
VOID
EFIAPI
-BuildCvHob (
+UpdateStackHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length
)
{
- ASSERT (FALSE);
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Hob.Raw = GetHobList ();
+ while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, Hob.Raw)) != NULL) {
+ if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &(Hob.MemoryAllocationStack->AllocDescriptor.Name))) {
+ //
+ // Build a new memory allocation HOB with old stack info with EfiConventionalMemory type
+ // to be reclaimed by DXE core.
+ //
+ BuildMemoryAllocationHob (
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress,
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength,
+ EfiConventionalMemory
+ );
+ //
+ // Update the BSP Stack Hob to reflect the new stack info.
+ //
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+ Hob.MemoryAllocationStack->AllocDescriptor.MemoryLength = Length;
+ break;
+ }
+ Hob.Raw = GET_NEXT_HOB (Hob);
+ }
}
+
/**
- Builds a HOB for the BSP store.
+ Builds a HOB for the memory allocation.
- This function builds a HOB for BSP store.
+ This function builds a HOB for the memory allocation.
+ It can only be invoked during PEI phase;
+ for DXE phase, it will ASSERT() since PEI HOB is read-only for DXE phase.
If there is no additional space for HOB creation, then ASSERT().
- @param BaseAddress The 64 bit physical address of the BSP.
- @param Length The length of the BSP store in bytes.
+ @param BaseAddress The 64 bit physical address of the memory.
+ @param Length The length of the memory allocation in bytes.
@param MemoryType Type of memory allocated by this HOB.
**/
VOID
EFIAPI
-BuildBspStoreHob (
+BuildMemoryAllocationHob (
IN EFI_PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN EFI_MEMORY_TYPE MemoryType
)
{
- ASSERT (FALSE);
-}
-
-/**
- Builds a HOB for the Stack.
+ EFI_HOB_MEMORY_ALLOCATION *Hob;
- This function builds a HOB for the stack.
- If there is no additional space for HOB creation, then ASSERT().
+ ASSERT (((BaseAddress & (EFI_PAGE_SIZE - 1)) == 0) &&
+ ((Length & (EFI_PAGE_SIZE - 1)) == 0));
- @param BaseAddress The 64 bit physical address of the Stack.
- @param Length The length of the stack in bytes.
+ Hob = CreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION));
-**/
-VOID
-EFIAPI
-BuildStackHob (
- IN EFI_PHYSICAL_ADDRESS BaseAddress,
- IN UINT64 Length
- )
-{
- ASSERT (FALSE);
+ ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID));
+ Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress;
+ Hob->AllocDescriptor.MemoryLength = Length;
+ Hob->AllocDescriptor.MemoryType = MemoryType;
+ //
+ // Zero the reserved space to match HOB spec
+ //
+ ZeroMem (Hob->AllocDescriptor.Reserved, sizeof (Hob->AllocDescriptor.Reserved));
}
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf
new file mode 100644
index 00000000000..48a262ddce3
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/HobLib/HobLib.inf
@@ -0,0 +1,39 @@
+#/** @file
+#
+# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = HobLib
+ FILE_GUID = AD6B4D55-8DBE-48C8-88E3-CFDBB6E9D193
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HobLib
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources.common]
+ Hob.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+
+[Guids]
+ gEfiHobMemoryAllocModuleGuid
+ gEfiHobMemoryAllocStackGuid
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c
new file mode 100644
index 00000000000..30c11185022
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c
@@ -0,0 +1,59 @@
+/** @file
+ PCI Segment Information Library that returns one segment whose
+ segment base address is retrieved from AcpiBoardInfo HOB.
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+#include <Guid/AcpiBoardInfoGuid.h>
+
+#include <Library/HobLib.h>
+#include <Library/PciSegmentInfoLib.h>
+#include <Library/DebugLib.h>
+
+STATIC PCI_SEGMENT_INFO mPciSegment0 = {
+ 0, // Segment number
+ 0, // To be fixed later
+ 0, // Start bus number
+ 255 // End bus number
+};
+
+/**
+ Return an array of PCI_SEGMENT_INFO holding the segment information.
+
+ Note: The returned array/buffer is owned by callee.
+
+ @param Count Return the count of segments.
+
+ @retval A callee owned array holding the segment information.
+**/
+PCI_SEGMENT_INFO *
+EFIAPI
+GetPciSegmentInfo (
+ UINTN *Count
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ ACPI_BOARD_INFO *AcpiBoardInfo;
+
+ ASSERT (Count != NULL);
+ if (Count == NULL) {
+ return NULL;
+ }
+
+ if (mPciSegment0.BaseAddress == 0) {
+ //
+ // Find the acpi board information guid hob
+ //
+ GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
+ ASSERT (GuidHob != NULL);
+
+ AcpiBoardInfo = (ACPI_BOARD_INFO *) GET_GUID_HOB_DATA (GuidHob);
+ mPciSegment0.BaseAddress = AcpiBoardInfo->PcieBaseAddress;
+ }
+ *Count = 1;
+ return &mPciSegment0;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf
new file mode 100644
index 00000000000..9f9adb7da89
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf
@@ -0,0 +1,36 @@
+## @file
+# PCI Segment Information Library that returns one segment whose
+# segment base address is retrieved from AcpiBoardInfo HOB.
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PciSegmentInfoLibAcpiBoardInfo
+ FILE_GUID = 0EA82AA2-6C36-4FD5-BC90-FFA3ECB5E0CE
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciSegmentInfoLib | DXE_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ PciSegmentInfoLibAcpiBoardInfo.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ PcdLib
+ HobLib
+ DebugLib
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
index 69e47e6032b..0e95c4c83d7 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManager.c
@@ -157,8 +157,6 @@ PlatformBootManagerBeforeConsole (
EFI_INPUT_KEY Down;
EFI_BOOT_MANAGER_LOAD_OPTION BootOption;
- PlatformConsoleInit ();
-
//
// Register ENTER as CONTINUE key
//
@@ -192,6 +190,8 @@ PlatformBootManagerBeforeConsole (
// Dispatch deferred images after EndOfDxe event and ReadyToLock installation.
//
EfiBootManagerDispatchDeferredImages ();
+
+ PlatformConsoleInit ();
}
/**
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/FindPeiCore.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/FindPeiCore.c
deleted file mode 100644
index 3f1acca9cbc..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/FindPeiCore.c
+++ /dev/null
@@ -1,193 +0,0 @@
-/** @file
- Locate the entry point for the PEI Core
-
-Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiPei.h>
-#include <Library/BaseLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-
-#include "SecMain.h"
-
-/**
- Find core image base.
-
- @param BootFirmwareVolumePtr Point to the boot firmware volume.
- @param SecCoreImageBase The base address of the SEC core image.
- @param PeiCoreImageBase The base address of the PEI core image.
-
-**/
-EFI_STATUS
-EFIAPI
-FindImageBase (
- IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
- OUT EFI_PHYSICAL_ADDRESS *SecCoreImageBase,
- OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
- )
-{
- EFI_PHYSICAL_ADDRESS CurrentAddress;
- EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
- EFI_FFS_FILE_HEADER *File;
- UINT32 Size;
- EFI_PHYSICAL_ADDRESS EndOfFile;
- EFI_COMMON_SECTION_HEADER *Section;
- EFI_PHYSICAL_ADDRESS EndOfSection;
-
- *SecCoreImageBase = 0;
- *PeiCoreImageBase = 0;
-
- CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) BootFirmwareVolumePtr;
- EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
-
- //
- // Loop through the FFS files in the Boot Firmware Volume
- //
- for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
-
- CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
- if (CurrentAddress > EndOfFirmwareVolume) {
- return EFI_NOT_FOUND;
- }
-
- File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
- if (IS_FFS_FILE2 (File)) {
- Size = FFS_FILE2_SIZE (File);
- if (Size <= 0x00FFFFFF) {
- return EFI_NOT_FOUND;
- }
- } else {
- Size = FFS_FILE_SIZE (File);
- if (Size < sizeof (EFI_FFS_FILE_HEADER)) {
- return EFI_NOT_FOUND;
- }
- }
-
- EndOfFile = CurrentAddress + Size;
- if (EndOfFile > EndOfFirmwareVolume) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Look for SEC Core / PEI Core files
- //
- if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
- File->Type != EFI_FV_FILETYPE_PEI_CORE) {
- continue;
- }
-
- //
- // Loop through the FFS file sections within the FFS file
- //
- if (IS_FFS_FILE2 (File)) {
- EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER2));
- } else {
- EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) File + sizeof (EFI_FFS_FILE_HEADER));
- }
- for (;;) {
- CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
- Section = (EFI_COMMON_SECTION_HEADER*)(UINTN) CurrentAddress;
-
- if (IS_SECTION2 (Section)) {
- Size = SECTION2_SIZE (Section);
- if (Size <= 0x00FFFFFF) {
- return EFI_NOT_FOUND;
- }
- } else {
- Size = SECTION_SIZE (Section);
- if (Size < sizeof (EFI_COMMON_SECTION_HEADER)) {
- return EFI_NOT_FOUND;
- }
- }
-
- EndOfSection = CurrentAddress + Size;
- if (EndOfSection > EndOfFile) {
- return EFI_NOT_FOUND;
- }
-
- //
- // Look for executable sections
- //
- if (Section->Type == EFI_SECTION_PE32 || Section->Type == EFI_SECTION_TE) {
- if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
- if (IS_SECTION2 (Section)) {
- *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
- } else {
- *SecCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
- }
- } else {
- if (IS_SECTION2 (Section)) {
- *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
- } else {
- *PeiCoreImageBase = (PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
- }
- }
- break;
- }
- }
-
- //
- // Both SEC Core and PEI Core images found
- //
- if (*SecCoreImageBase != 0 && *PeiCoreImageBase != 0) {
- return EFI_SUCCESS;
- }
- }
-}
-
-/**
- Find and return Pei Core entry point.
-
- It also find SEC and PEI Core file debug information. It will report them if
- remote debug is enabled.
-
- @param BootFirmwareVolumePtr Point to the boot firmware volume.
- @param PeiCoreEntryPoint The entry point of the PEI core.
-
-**/
-VOID
-EFIAPI
-FindAndReportEntryPoints (
- IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
- OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS SecCoreImageBase;
- EFI_PHYSICAL_ADDRESS PeiCoreImageBase;
- PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
-
- //
- // Find SEC Core and PEI Core image base
- //
- Status = FindImageBase (BootFirmwareVolumePtr, &SecCoreImageBase, &PeiCoreImageBase);
- ASSERT_EFI_ERROR (Status);
-
- ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
- //
- // Report SEC Core debug information when remote debug is enabled
- //
- ImageContext.ImageAddress = SecCoreImageBase;
- ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
- PeCoffLoaderRelocateImageExtraAction (&ImageContext);
-
- //
- // Report PEI Core debug information when remote debug is enabled
- //
- ImageContext.ImageAddress = PeiCoreImageBase;
- ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
- PeCoffLoaderRelocateImageExtraAction (&ImageContext);
-
- //
- // Find PEI Core entry point
- //
- Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
- if (EFI_ERROR (Status)) {
- *PeiCoreEntryPoint = 0;
- }
-
- return;
-}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/SecEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/SecEntry.nasm
deleted file mode 100644
index 2ce182a6fa6..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/SecEntry.nasm
+++ /dev/null
@@ -1,78 +0,0 @@
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Abstract:
-;
-; Entry point for the coreboot UEFI payload.
-;
-;------------------------------------------------------------------------------
-
-SECTION .text
-
-; C Functions
-extern ASM_PFX(SecStartup)
-
-; Pcds
-extern ASM_PFX(PcdGet32 (PcdPayloadFdMemBase))
-extern ASM_PFX(PcdGet32 (PcdPayloadStackTop))
-
-;
-; SecCore Entry Point
-;
-; Processor is in flat protected mode
-;
-; @param[in] EAX Initial value of the EAX register (BIST: Built-in Self Test)
-; @param[in] DI 'BP': boot-strap processor, or 'AP': application processor
-; @param[in] EBP Pointer to the start of the Boot Firmware Volume
-;
-; @return None This routine does not return
-;
-global ASM_PFX(_ModuleEntryPoint)
-ASM_PFX(_ModuleEntryPoint):
- ;
- ; Disable all the interrupts
- ;
- cli
-
- ;
- ; Save the Payload HOB base address before switching the stack
- ;
- mov eax, [esp + 4]
-
- ;
- ; Construct the temporary memory at 0x80000, length 0x10000
- ;
- mov esp, DWORD [ASM_PFX(PcdGet32 (PcdPayloadStackTop))]
-
- ;
- ; Push the Payload HOB base address onto new stack
- ;
- push eax
-
- ;
- ; Pass BFV into the PEI Core
- ;
- push DWORD [ASM_PFX(PcdGet32 (PcdPayloadFdMemBase))]
-
- ;
- ; Pass stack base into the PEI Core
- ;
- push BASE_512KB
-
- ;
- ; Pass stack size into the PEI Core
- ;
- push SIZE_64KB
-
- ;
- ; Pass Control into the PEI Core
- ;
- call ASM_PFX(SecStartup)
-
- ;
- ; Should never return
- ;
- jmp $
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/Stack.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/Stack.nasm
deleted file mode 100644
index 8b056b16fd2..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/Ia32/Stack.nasm
+++ /dev/null
@@ -1,72 +0,0 @@
-;------------------------------------------------------------------------------
-;
-; Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Abstract:
-;
-; Switch the stack from temporary memory to permanent memory.
-;
-;------------------------------------------------------------------------------
-
-SECTION .text
-
-;------------------------------------------------------------------------------
-; VOID
-; EFIAPI
-; SecSwitchStack (
-; UINT32 TemporaryMemoryBase,
-; UINT32 PermenentMemoryBase
-; );
-;------------------------------------------------------------------------------
-global ASM_PFX(SecSwitchStack)
-ASM_PFX(SecSwitchStack):
- ;
- ; Save three register: eax, ebx, ecx
- ;
- push eax
- push ebx
- push ecx
- push edx
-
- ;
- ; !!CAUTION!! this function address's is pushed into stack after
- ; migration of whole temporary memory, so need save it to permanent
- ; memory at first!
- ;
-
- mov ebx, [esp + 20] ; Save the first parameter
- mov ecx, [esp + 24] ; Save the second parameter
-
- ;
- ; Save this function's return address into permanent memory at first.
- ; Then, Fixup the esp point to permanent memory
- ;
- mov eax, esp
- sub eax, ebx
- add eax, ecx
- mov edx, [esp] ; copy pushed register's value to permanent memory
- mov [eax], edx
- mov edx, [esp + 4]
- mov [eax + 4], edx
- mov edx, [esp + 8]
- mov [eax + 8], edx
- mov edx, [esp + 12]
- mov [eax + 12], edx
- mov edx, [esp + 16] ; Update return address into permanent memory
- mov [eax + 16], edx
- mov esp, eax ; From now, esp is pointed to permanent memory
-
- ;
- ; Fixup the ebp point to permanent memory
- ;
- mov eax, ebp
- sub eax, ebx
- add eax, ecx
- mov ebp, eax ; From now, ebp is pointed to permanent memory
-
- pop edx
- pop ecx
- pop ebx
- pop eax
- ret
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecCore.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecCore.inf
deleted file mode 100644
index 58cb9f6a94c..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecCore.inf
+++ /dev/null
@@ -1,58 +0,0 @@
-## @file
-# This is the first module taking control from the coreboot.
-#
-# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#
-##
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = SecCore
- FILE_GUID = BA7BE337-6CFB-4dbb-B26C-21EC2FC16073
- MODULE_TYPE = SEC
- VERSION_STRING = 1.0
-
-
-#
-# The following information is for reference only and not required by the build tools.
-#
-# VALID_ARCHITECTURES = IA32 X64 EBC
-#
-
-[Sources]
- SecMain.c
- SecMain.h
- FindPeiCore.c
-
-[Sources.IA32]
- Ia32/Stack.nasm
- Ia32/SecEntry.nasm
-
-[Packages]
- MdePkg/MdePkg.dec
- MdeModulePkg/MdeModulePkg.dec
- UefiCpuPkg/UefiCpuPkg.dec
- UefiPayloadPkg/UefiPayloadPkg.dec
-
-[LibraryClasses]
- BaseMemoryLib
- DebugLib
- BaseLib
- PcdLib
- DebugAgentLib
- UefiCpuLib
- PeCoffGetEntryPointLib
- PeCoffExtraActionLib
-
-[Ppis]
- gEfiSecPlatformInformationPpiGuid # PPI ALWAYS_PRODUCED
- gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
- gEfiPayLoadHobBasePpiGuid # PPI ALWAYS_PRODUCED
-
-[Pcd]
- gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
- gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
- gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.c
deleted file mode 100644
index d544a7f7c1a..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.c
+++ /dev/null
@@ -1,288 +0,0 @@
-/** @file
- C functions in SEC
-
-Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-
-#include "SecMain.h"
-
-EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI gSecTemporaryRamSupportPpi = {
- SecTemporaryRamSupport
-};
-
-EFI_PEI_PPI_DESCRIPTOR mPeiSecPlatformInformationPpi[] = {
- {
- (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiTemporaryRamSupportPpiGuid,
- &gSecTemporaryRamSupportPpi
- }
-};
-
-//
-// These are IDT entries pointing to 10:FFFFFFE4h.
-//
-UINT64 mIdtEntryTemplate = 0xffff8e000010ffe4ULL;
-
-/**
- Caller provided function to be invoked at the end of InitializeDebugAgent().
-
- Entry point to the C language phase of SEC. After the SEC assembly
- code has initialized some temporary memory and set up the stack,
- the control is transferred to this function.
-
- @param[in] Context The first input parameter of InitializeDebugAgent().
-
-**/
-VOID
-EFIAPI
-SecStartupPhase2(
- IN VOID *Context
- );
-
-
-/**
-
- Entry point to the C language phase of SEC. After the SEC assembly
- code has initialized some temporary memory and set up the stack,
- the control is transferred to this function.
-
-
- @param SizeOfRam Size of the temporary memory available for use.
- @param TempRamBase Base address of temporary ram
- @param BootFirmwareVolume Base address of the Boot Firmware Volume.
- @param BootloaderParameter A parameter from bootloader, e.g. HobList from SlimBootloader
-
-**/
-VOID
-EFIAPI
-SecStartup (
- IN UINT32 SizeOfRam,
- IN UINT32 TempRamBase,
- IN VOID *BootFirmwareVolume,
- IN UINT32 BootloaderParameter
- )
-{
- EFI_SEC_PEI_HAND_OFF SecCoreData;
- IA32_DESCRIPTOR IdtDescriptor;
- SEC_IDT_TABLE IdtTableInStack;
- UINT32 Index;
- UINT32 PeiStackSize;
-
- PeiStackSize = (SizeOfRam >> 1);
-
- ASSERT (PeiStackSize < SizeOfRam);
-
- //
- // Process all libraries constructor function linked to SecCore.
- //
- ProcessLibraryConstructorList ();
-
- //
- // Initialize floating point operating environment
- // to be compliant with UEFI spec.
- //
- InitializeFloatingPointUnits ();
-
-
- // |-------------------|---->
- // |Idt Table |
- // |-------------------|
- // |PeiService Pointer | PeiStackSize
- // |-------------------|
- // | |
- // | Stack |
- // |-------------------|---->
- // | |
- // | |
- // | Heap | PeiTemporaryRamSize
- // | |
- // | |
- // |-------------------|----> TempRamBase
-
- IdtTableInStack.PeiService = 0;
- for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index ++) {
- CopyMem ((VOID*)&IdtTableInStack.IdtTable[Index], (VOID*)&mIdtEntryTemplate, sizeof (UINT64));
- }
-
- IdtDescriptor.Base = (UINTN) &IdtTableInStack.IdtTable;
- IdtDescriptor.Limit = (UINT16)(sizeof (IdtTableInStack.IdtTable) - 1);
-
- AsmWriteIdtr (&IdtDescriptor);
-
- //
- // Update the base address and length of Pei temporary memory
- //
- SecCoreData.DataSize = (UINT16) sizeof (EFI_SEC_PEI_HAND_OFF);
- SecCoreData.BootFirmwareVolumeBase = BootFirmwareVolume;
- SecCoreData.BootFirmwareVolumeSize = (UINTN)(0x100000000ULL - (UINTN) BootFirmwareVolume);
- SecCoreData.TemporaryRamBase = (VOID*)(UINTN) TempRamBase;
- SecCoreData.TemporaryRamSize = SizeOfRam;
- SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
- SecCoreData.PeiTemporaryRamSize = SizeOfRam - PeiStackSize;
- SecCoreData.StackBase = (VOID*)(UINTN)(TempRamBase + SecCoreData.PeiTemporaryRamSize);
- SecCoreData.StackSize = PeiStackSize;
-
- //
- // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready.
- //
- InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, &SecCoreData, SecStartupPhase2);
-
-}
-
-/**
- Caller provided function to be invoked at the end of InitializeDebugAgent().
-
- Entry point to the C language phase of SEC. After the SEC assembly
- code has initialized some temporary memory and set up the stack,
- the control is transferred to this function.
-
- @param[in] Context The first input parameter of InitializeDebugAgent().
-
-**/
-VOID
-EFIAPI
-SecStartupPhase2(
- IN VOID *Context
- )
-{
- EFI_SEC_PEI_HAND_OFF *SecCoreData;
- EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
-
- SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
- //
- // Find Pei Core entry point. It will report SEC and Pei Core debug information if remote debug
- // is enabled.
- //
- FindAndReportEntryPoints ((EFI_FIRMWARE_VOLUME_HEADER *) SecCoreData->BootFirmwareVolumeBase, &PeiCoreEntryPoint);
- if (PeiCoreEntryPoint == NULL)
- {
- CpuDeadLoop ();
- }
-
- //
- // Transfer the control to the PEI core
- //
- ASSERT (PeiCoreEntryPoint != NULL);
- (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPeiSecPlatformInformationPpi);
-
- //
- // Should not come here.
- //
- return ;
-}
-
-/**
- This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
- permanent memory.
-
- @param PeiServices Pointer to the PEI Services Table.
- @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
- Temporary RAM contents.
- @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
- Temporary RAM contents.
- @param CopySize Amount of memory to migrate from temporary to permanent memory.
-
- @retval EFI_SUCCESS The data was successfully returned.
- @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
- TemporaryMemoryBase > PermanentMemoryBase.
-
-**/
-EFI_STATUS
-EFIAPI
-SecTemporaryRamSupport (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
- IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
- IN UINTN CopySize
- )
-{
- IA32_DESCRIPTOR IdtDescriptor;
- VOID* OldHeap;
- VOID* NewHeap;
- VOID* OldStack;
- VOID* NewStack;
- DEBUG_AGENT_CONTEXT_POSTMEM_SEC DebugAgentContext;
- BOOLEAN OldStatus;
- UINTN PeiStackSize;
-
- PeiStackSize = (CopySize >> 1);
-
- ASSERT (PeiStackSize < CopySize);
-
- //
- // |-------------------|---->
- // | Stack | PeiStackSize
- // |-------------------|---->
- // | Heap | PeiTemporaryRamSize
- // |-------------------|----> TempRamBase
- //
- // |-------------------|---->
- // | Heap | PeiTemporaryRamSize
- // |-------------------|---->
- // | Stack | PeiStackSize
- // |-------------------|----> PermanentMemoryBase
- //
-
- OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
- NewHeap = (VOID*)((UINTN)PermanentMemoryBase + PeiStackSize);
-
- OldStack = (VOID*)((UINTN)TemporaryMemoryBase + CopySize - PeiStackSize);
- NewStack = (VOID*)(UINTN)PermanentMemoryBase;
-
- DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
- DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
-
- OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
- //
- // Initialize Debug Agent to support source level debug in PEI phase after memory ready.
- // It will build HOB and fix up the pointer in IDT table.
- //
- InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
-
- //
- // Migrate Heap
- //
- CopyMem (NewHeap, OldHeap, CopySize - PeiStackSize);
-
- //
- // Migrate Stack
- //
- CopyMem (NewStack, OldStack, PeiStackSize);
-
-
- //
- // We need *not* fix the return address because currently,
- // The PeiCore is executed in flash.
- //
-
- //
- // Rebase IDT table in permanent memory
- //
- AsmReadIdtr (&IdtDescriptor);
- IdtDescriptor.Base = IdtDescriptor.Base - (UINTN)OldStack + (UINTN)NewStack;
-
- AsmWriteIdtr (&IdtDescriptor);
-
-
- //
- // Program MTRR
- //
-
- //
- // SecSwitchStack function must be invoked after the memory migration
- // immediately, also we need fixup the stack change caused by new call into
- // permanent memory.
- //
- SecSwitchStack (
- (UINT32) (UINTN) OldStack,
- (UINT32) (UINTN) NewStack
- );
-
- SaveAndSetDebugTimerInterrupt (OldStatus);
-
- return EFI_SUCCESS;
-}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.h
deleted file mode 100644
index dc6bbdb9058..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/SecCore/SecMain.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/** @file
- Master header file for SecCore.
-
-Copyright (c) 2013, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef _SEC_CORE_H_
-#define _SEC_CORE_H_
-
-
-#include <PiPei.h>
-
-#include <Ppi/SecPlatformInformation.h>
-#include <Ppi/TemporaryRamSupport.h>
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/PcdLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiCpuLib.h>
-#include <Library/PeCoffGetEntryPointLib.h>
-#include <Library/PeCoffExtraActionLib.h>
-#include <Library/DebugAgentLib.h>
-
-
-#define SEC_IDT_ENTRY_COUNT 34
-
-typedef struct _SEC_IDT_TABLE {
- //
- // Reserved 8 bytes preceding IDT to store EFI_PEI_SERVICES**, since IDT base
- // address should be 8-byte alignment.
- // Note: For IA32, only the 4 bytes immediately preceding IDT is used to store
- // EFI_PEI_SERVICES**
- //
- UINT64 PeiService;
- UINT64 IdtTable[SEC_IDT_ENTRY_COUNT];
-} SEC_IDT_TABLE;
-
-/**
- Switch the stack in the temporary memory to the one in the permanent memory.
-
- This function must be invoked after the memory migration immediately. The relative
- position of the stack in the temporary and permanent memory is same.
-
- @param TemporaryMemoryBase Base address of the temporary memory.
- @param PermenentMemoryBase Base address of the permanent memory.
-**/
-VOID
-EFIAPI
-SecSwitchStack (
- UINT32 TemporaryMemoryBase,
- UINT32 PermenentMemoryBase
- );
-
-/**
- This service of the TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
- permanent memory.
-
- @param PeiServices Pointer to the PEI Services Table.
- @param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
- Temporary RAM contents.
- @param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
- Temporary RAM contents.
- @param CopySize Amount of memory to migrate from temporary to permanent memory.
-
- @retval EFI_SUCCESS The data was successfully returned.
- @retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
- TemporaryMemoryBase > PermanentMemoryBase.
-
-**/
-EFI_STATUS
-EFIAPI
-SecTemporaryRamSupport (
- IN CONST EFI_PEI_SERVICES **PeiServices,
- IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
- IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
- IN UINTN CopySize
- );
-
-/**
- Entry point to the C language phase of SEC. After the SEC assembly
- code has initialized some temporary memory and set up the stack,
- the control is transferred to this function.
-
- @param SizeOfRam Size of the temporary memory available for use.
- @param TempRamBase Base address of temporary ram
- @param BootFirmwareVolume Base address of the Boot Firmware Volume.
- @param BootloaderParameter A parameter from bootloader, e.g. HobList from SlimBootloader
-
-**/
-VOID
-EFIAPI
-SecStartup (
- IN UINT32 SizeOfRam,
- IN UINT32 TempRamBase,
- IN VOID *BootFirmwareVolume,
- IN UINT32 BootloaderParameter
- );
-
-/**
- Find and return Pei Core entry point.
-
- It also find SEC and PEI Core file debug information. It will report them if
- remote debug is enabled.
-
- @param BootFirmwareVolumePtr Point to the boot firmware volume.
- @param PeiCoreEntryPoint Point to the PEI core entry point.
-
-**/
-VOID
-EFIAPI
-FindAndReportEntryPoints (
- IN EFI_FIRMWARE_VOLUME_HEADER *BootFirmwareVolumePtr,
- OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
- );
-
-/**
- Autogenerated function that calls the library constructors for all of the module's
- dependent libraries. This function must be called by the SEC Core once a stack has
- been established.
-
-**/
-VOID
-EFIAPI
-ProcessLibraryConstructorList (
- VOID
- );
-
-#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c
new file mode 100644
index 00000000000..822b34c91e0
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c
@@ -0,0 +1,365 @@
+/** @file
+ Ia32-specific functionality for DxeLoad.
+
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include "VirtualMemory.h"
+#include "UefiPayloadEntry.h"
+
+#define STACK_SIZE 0x20000
+#define IDT_ENTRY_COUNT 32
+
+typedef struct _X64_IDT_TABLE {
+ //
+ // Reserved 4 bytes preceding PeiService and IdtTable,
+ // since IDT base address should be 8-byte alignment.
+ //
+ UINT32 Reserved;
+ CONST EFI_PEI_SERVICES **PeiService;
+ X64_IDT_GATE_DESCRIPTOR IdtTable[IDT_ENTRY_COUNT];
+} X64_IDT_TABLE;
+
+//
+// Global Descriptor Table (GDT)
+//
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT gGdtEntries[] = {
+/* selector { Global Segment Descriptor } */
+/* 0x00 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //null descriptor
+/* 0x08 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear data segment descriptor
+/* 0x10 */ {{0xffff, 0, 0, 0xf, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //linear code segment descriptor
+/* 0x18 */ {{0xffff, 0, 0, 0x3, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
+/* 0x20 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system code segment descriptor
+/* 0x28 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
+/* 0x30 */ {{0xffff, 0, 0, 0x2, 1, 0, 1, 0xf, 0, 0, 1, 1, 0}}, //system data segment descriptor
+/* 0x38 */ {{0xffff, 0, 0, 0xa, 1, 0, 1, 0xf, 0, 1, 0, 1, 0}}, //system code segment descriptor
+/* 0x40 */ {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, //spare segment descriptor
+};
+
+//
+// IA32 Gdt register
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST IA32_DESCRIPTOR gGdt = {
+ sizeof (gGdtEntries) - 1,
+ (UINTN) gGdtEntries
+ };
+
+GLOBAL_REMOVE_IF_UNREFERENCED IA32_DESCRIPTOR gLidtDescriptor = {
+ sizeof (X64_IDT_GATE_DESCRIPTOR) * IDT_ENTRY_COUNT - 1,
+ 0
+};
+
+/**
+ Allocates and fills in the Page Directory and Page Table Entries to
+ establish a 4G page table.
+
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+
+ @return The address of page table.
+
+**/
+UINTN
+Create4GPageTablesIa32Pae (
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize
+ )
+{
+ UINT8 PhysicalAddressBits;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ UINTN IndexOfPdpEntries;
+ UINTN IndexOfPageDirectoryEntries;
+ UINT32 NumberOfPdpEntriesNeeded;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ UINTN TotalPagesNum;
+ UINTN PageAddress;
+ UINT64 AddressEncMask;
+
+ //
+ // Make sure AddressEncMask is contained to smallest supported address field
+ //
+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
+
+ PhysicalAddressBits = 32;
+
+ //
+ // Calculate the table entries needed.
+ //
+ NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, (PhysicalAddressBits - 30));
+
+ TotalPagesNum = NumberOfPdpEntriesNeeded + 1;
+ PageAddress = (UINTN) AllocatePageTableMemory (TotalPagesNum);
+ ASSERT (PageAddress != 0);
+
+ PageMap = (VOID *) PageAddress;
+ PageAddress += SIZE_4KB;
+
+ PageDirectoryPointerEntry = PageMap;
+ PhysicalAddress = 0;
+
+ for (IndexOfPdpEntries = 0; IndexOfPdpEntries < NumberOfPdpEntriesNeeded; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
+ //
+ PageDirectoryEntry = (VOID *) PageAddress;
+ PageAddress += SIZE_4KB;
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64) (UINTN) PageDirectoryEntry | AddressEncMask;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress += SIZE_2MB) {
+ if ((IsNullDetectionEnabled () && PhysicalAddress == 0)
+ || ((PhysicalAddress < StackBase + StackSize)
+ && ((PhysicalAddress + SIZE_2MB) > StackBase))) {
+ //
+ // Need to split this 2M page that covers stack range.
+ //
+ Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, 0, 0);
+ } else {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress | AddressEncMask;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+ }
+
+ for (; IndexOfPdpEntries < 512; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ ZeroMem (
+ PageDirectoryPointerEntry,
+ sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)
+ );
+ }
+
+ //
+ // Protect the page table by marking the memory used for page table to be
+ // read-only.
+ //
+ EnablePageTableProtection ((UINTN)PageMap, FALSE);
+
+ return (UINTN) PageMap;
+}
+
+/**
+ The function will check if IA32 PAE is supported.
+
+ @retval TRUE IA32 PAE is supported.
+ @retval FALSE IA32 PAE is not supported.
+
+**/
+BOOLEAN
+IsIa32PaeSupport (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ BOOLEAN Ia32PaeSupport;
+
+ Ia32PaeSupport = FALSE;
+ AsmCpuid (0x0, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x1) {
+ AsmCpuid (0x1, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT6) != 0) {
+ Ia32PaeSupport = TRUE;
+ }
+ }
+
+ return Ia32PaeSupport;
+}
+
+/**
+ The function will check if page table should be setup or not.
+
+ @retval TRUE Page table should be created.
+ @retval FALSE Page table should not be created.
+
+**/
+BOOLEAN
+ToBuildPageTable (
+ VOID
+ )
+{
+ if (!IsIa32PaeSupport ()) {
+ return FALSE;
+ }
+
+ if (IsNullDetectionEnabled ()) {
+ return TRUE;
+ }
+
+ if (PcdGet8 (PcdHeapGuardPropertyMask) != 0) {
+ return TRUE;
+ }
+
+ if (PcdGetBool (PcdCpuStackGuard)) {
+ return TRUE;
+ }
+
+ if (IsEnableNonExecNeeded ()) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Transfers control to DxeCore.
+
+ This function performs a CPU architecture specific operations to execute
+ the entry point of DxeCore with the parameters of HobList.
+
+ @param DxeCoreEntryPoint The entry point of DxeCore.
+ @param HobList The start of HobList passed to DxeCore.
+
+**/
+VOID
+HandOffToDxeCore (
+ IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+{
+ EFI_PHYSICAL_ADDRESS BaseOfStack;
+ EFI_PHYSICAL_ADDRESS TopOfStack;
+ UINTN PageTables;
+ X64_IDT_GATE_DESCRIPTOR *IdtTable;
+ UINTN SizeOfTemplate;
+ VOID *TemplateBase;
+ EFI_PHYSICAL_ADDRESS VectorAddress;
+ UINT32 Index;
+ X64_IDT_TABLE *IdtTableForX64;
+
+ //
+ // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
+ //
+ if (IsNullDetectionEnabled ()) {
+ ClearFirst4KPage (HobList.Raw);
+ BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
+ }
+
+ BaseOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
+ ASSERT (BaseOfStack != 0);
+
+ if (FeaturePcdGet(PcdDxeIplSwitchToLongMode)) {
+ //
+ // Compute the top of the stack we were allocated, which is used to load X64 dxe core.
+ // Pre-allocate a 32 bytes which confroms to x64 calling convention.
+ //
+ // The first four parameters to a function are passed in rcx, rdx, r8 and r9.
+ // Any further parameters are pushed on the stack. Furthermore, space (4 * 8bytes) for the
+ // register parameters is reserved on the stack, in case the called function
+ // wants to spill them; this is important if the function is variadic.
+ //
+ TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32;
+
+ //
+ // x64 Calling Conventions requires that the stack must be aligned to 16 bytes
+ //
+ TopOfStack = (EFI_PHYSICAL_ADDRESS) (UINTN) ALIGN_POINTER (TopOfStack, 16);
+
+ //
+ // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA
+ // memory, it may be corrupted when copying FV to high-end memory
+ //
+ AsmWriteGdtr (&gGdt);
+ //
+ // Create page table and save PageMapLevel4 to CR3
+ //
+ PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE, 0, 0);
+
+ //
+ // Paging might be already enabled. To avoid conflict configuration,
+ // disable paging first anyway.
+ //
+ AsmWriteCr0 (AsmReadCr0 () & (~BIT31));
+ AsmWriteCr3 (PageTables);
+
+ //
+ // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
+ //
+ UpdateStackHob (BaseOfStack, STACK_SIZE);
+
+ SizeOfTemplate = AsmGetVectorTemplatInfo (&TemplateBase);
+
+ VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) AllocatePages (EFI_SIZE_TO_PAGES(sizeof (X64_IDT_TABLE) + SizeOfTemplate * IDT_ENTRY_COUNT));
+ ASSERT (VectorAddress != 0);
+
+ //
+ // Store EFI_PEI_SERVICES** in the 4 bytes immediately preceding IDT to avoid that
+ // it may not be gotten correctly after IDT register is re-written.
+ //
+ IdtTableForX64 = (X64_IDT_TABLE *) (UINTN) VectorAddress;
+ IdtTableForX64->PeiService = NULL;
+
+ VectorAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) (IdtTableForX64 + 1);
+ IdtTable = IdtTableForX64->IdtTable;
+ for (Index = 0; Index < IDT_ENTRY_COUNT; Index++) {
+ IdtTable[Index].Ia32IdtEntry.Bits.GateType = 0x8e;
+ IdtTable[Index].Ia32IdtEntry.Bits.Reserved_0 = 0;
+ IdtTable[Index].Ia32IdtEntry.Bits.Selector = SYS_CODE64_SEL;
+
+ IdtTable[Index].Ia32IdtEntry.Bits.OffsetLow = (UINT16) VectorAddress;
+ IdtTable[Index].Ia32IdtEntry.Bits.OffsetHigh = (UINT16) (RShiftU64 (VectorAddress, 16));
+ IdtTable[Index].Offset32To63 = (UINT32) (RShiftU64 (VectorAddress, 32));
+ IdtTable[Index].Reserved = 0;
+
+ CopyMem ((VOID *) (UINTN) VectorAddress, TemplateBase, SizeOfTemplate);
+ AsmVectorFixup ((VOID *) (UINTN) VectorAddress, (UINT8) Index);
+
+ VectorAddress += SizeOfTemplate;
+ }
+
+ gLidtDescriptor.Base = (UINTN) IdtTable;
+
+
+ AsmWriteIdtr (&gLidtDescriptor);
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a() Stack Base: 0x%lx, Stack Size: 0x%x\n",
+ __FUNCTION__,
+ BaseOfStack,
+ STACK_SIZE
+ ));
+
+ //
+ // Go to Long Mode and transfer control to DxeCore.
+ // Interrupts will not get turned on until the CPU AP is loaded.
+ // Call x64 drivers passing in single argument, a pointer to the HOBs.
+ //
+ AsmEnablePaging64 (
+ SYS_CODE64_SEL,
+ DxeCoreEntryPoint,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw),
+ 0,
+ TopOfStack
+ );
+ } else {
+ // 32bit UEFI payload could be supported if required later.
+ DEBUG ((DEBUG_ERROR, "NOT support 32bit UEFI payload\n"));
+ ASSERT (FALSE);
+ CpuDeadLoop();
+ }
+
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm
new file mode 100644
index 00000000000..91c49ca4831
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/IdtVectorAsm.nasm
@@ -0,0 +1,71 @@
+;/** @file
+;
+; IDT vector entry.
+;
+; Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+;**/
+
+ SECTION .text
+
+;
+;------------------------------------------------------------------------------
+; Generic IDT Vector Handlers for the Host.
+;
+;------------------------------------------------------------------------------
+
+ALIGN 8
+global ASM_PFX(AsmGetVectorTemplatInfo)
+global ASM_PFX(AsmVectorFixup)
+
+@VectorTemplateBase:
+ push eax
+ db 0x6a ; push #VectorNumber
+@VectorNum:
+ db 0
+ mov eax, CommonInterruptEntry
+ jmp eax
+@VectorTemplateEnd:
+
+global ASM_PFX(AsmGetVectorTemplatInfo)
+ASM_PFX(AsmGetVectorTemplatInfo):
+ mov ecx, [esp + 4]
+ mov dword [ecx], @VectorTemplateBase
+ mov eax, (@VectorTemplateEnd - @VectorTemplateBase)
+ ret
+
+global ASM_PFX(AsmVectorFixup)
+ASM_PFX(AsmVectorFixup):
+ mov eax, dword [esp + 8]
+ mov ecx, [esp + 4]
+ mov [ecx + (@VectorNum - @VectorTemplateBase)], al
+ ret
+
+;---------------------------------------;
+; CommonInterruptEntry ;
+;---------------------------------------;
+; The follow algorithm is used for the common interrupt routine.
+
+;
+; +---------------------+ <-- 16-byte aligned ensured by processor
+; + Old SS +
+; +---------------------+
+; + Old RSP +
+; +---------------------+
+; + RFlags +
+; +---------------------+
+; + CS +
+; +---------------------+
+; + RIP +
+; +---------------------+
+; + Error Code +
+; +---------------------+
+; + Vector Number +
+; +---------------------+
+
+CommonInterruptEntry:
+ cli
+
+ jmp $
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm
new file mode 100644
index 00000000000..b661889386f
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/Ia32/SecEntry.nasm
@@ -0,0 +1,46 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+;* SPDX-License-Identifier: BSD-2-Clause-Patent
+
+;------------------------------------------------------------------------------
+
+#include <Base.h>
+
+SECTION .text
+
+extern ASM_PFX(PayloadEntry)
+extern ASM_PFX(PcdGet32 (PcdPayloadStackTop))
+
+;
+; SecCore Entry Point
+;
+; Processor is in flat protected mode
+
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+ ;
+ ; Disable all the interrupts
+ ;
+ cli
+
+ ;
+ ; Save the bootloader parameter base address
+ ;
+ mov eax, [esp + 4]
+
+ mov esp, FixedPcdGet32 (PcdPayloadStackTop)
+
+ ;
+ ; Push the bootloader parameter address onto new stack
+ ;
+ push 0
+ push eax
+
+ ;
+ ; Call into C code
+ ;
+ call ASM_PFX(PayloadEntry)
+ jmp $
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
new file mode 100644
index 00000000000..4a87ddc7efe
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
@@ -0,0 +1,307 @@
+/** @file
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiPayloadEntry.h"
+
+/**
+ Allocate pages for code.
+
+ @param[in] Pages Number of pages to be allocated.
+
+ @return Allocated memory.
+**/
+VOID*
+AllocateCodePages (
+ IN UINTN Pages
+ )
+{
+ VOID *Alloc;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ Alloc = AllocatePages (Pages);
+ if (Alloc == NULL) {
+ return NULL;
+ }
+
+ // find the HOB we just created, and change the type to EfiBootServicesCode
+ Hob.Raw = GetFirstHob (EFI_HOB_TYPE_MEMORY_ALLOCATION);
+ while (Hob.Raw != NULL) {
+ if (Hob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress == (UINTN)Alloc) {
+ Hob.MemoryAllocation->AllocDescriptor.MemoryType = EfiBootServicesCode;
+ return Alloc;
+ }
+ Hob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, GET_NEXT_HOB (Hob));
+ }
+
+ ASSERT (FALSE);
+
+ FreePages (Alloc, Pages);
+ return NULL;
+}
+
+
+/**
+ Loads and relocates a PE/COFF image
+
+ @param[in] PeCoffImage Point to a Pe/Coff image.
+ @param[out] ImageAddress The image memory address after relocation.
+ @param[out] ImageSize The image size.
+ @param[out] EntryPoint The image entry point.
+
+ @return EFI_SUCCESS If the image is loaded and relocated successfully.
+ @return Others If the image failed to load or relocate.
+**/
+EFI_STATUS
+LoadPeCoffImage (
+ IN VOID *PeCoffImage,
+ OUT EFI_PHYSICAL_ADDRESS *ImageAddress,
+ OUT UINT64 *ImageSize,
+ OUT EFI_PHYSICAL_ADDRESS *EntryPoint
+ )
+{
+ RETURN_STATUS Status;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ VOID *Buffer;
+
+ ZeroMem (&ImageContext, sizeof (ImageContext));
+
+ ImageContext.Handle = PeCoffImage;
+ ImageContext.ImageRead = PeCoffLoaderImageReadFromMemory;
+
+ Status = PeCoffLoaderGetImageInfo (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Allocate Memory for the image
+ //
+ Buffer = AllocateCodePages (EFI_SIZE_TO_PAGES((UINT32)ImageContext.ImageSize));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
+
+ //
+ // Load the image to our new buffer
+ //
+ Status = PeCoffLoaderLoadImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Relocate the image in our new buffer
+ //
+ Status = PeCoffLoaderRelocateImage (&ImageContext);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ *ImageAddress = ImageContext.ImageAddress;
+ *ImageSize = ImageContext.ImageSize;
+ *EntryPoint = ImageContext.EntryPoint;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function searchs a given file type within a valid FV.
+
+ @param FvHeader A pointer to firmware volume header that contains the set of files
+ to be searched.
+ @param FileType File type to be searched.
+ @param FileHeader A pointer to the discovered file, if successful.
+
+ @retval EFI_SUCCESS Successfully found FileType
+ @retval EFI_NOT_FOUND File type can't be found.
+**/
+EFI_STATUS
+FvFindFile (
+ IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader,
+ IN EFI_FV_FILETYPE FileType,
+ OUT EFI_FFS_FILE_HEADER **FileHeader
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) FvHeader;
+ EndOfFirmwareVolume = CurrentAddress + FvHeader->FvLength;
+
+ //
+ // Loop through the FFS files
+ //
+ for (EndOfFile = CurrentAddress + FvHeader->HeaderLength; ; ) {
+ CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ break;
+ }
+
+ File = (EFI_FFS_FILE_HEADER*)(UINTN) CurrentAddress;
+ if (IS_FFS_FILE2 (File)) {
+ Size = FFS_FILE2_SIZE (File);
+ if (Size <= 0x00FFFFFF) {
+ break;
+ }
+ } else {
+ Size = FFS_FILE_SIZE (File);
+ if (Size < sizeof (EFI_FFS_FILE_HEADER)) {
+ break;
+ }
+ }
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ break;
+ }
+
+ //
+ // Look for file type
+ //
+ if (File->Type == FileType) {
+ *FileHeader = File;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ This function searchs a given section type within a valid FFS file.
+
+ @param FileHeader A pointer to the file header that contains the set of sections to
+ be searched.
+ @param SearchType The value of the section type to search.
+ @param SectionData A pointer to the discovered section, if successful.
+
+ @retval EFI_SUCCESS The section was found.
+ @retval EFI_NOT_FOUND The section was not found.
+
+**/
+EFI_STATUS
+FileFindSection (
+ IN EFI_FFS_FILE_HEADER *FileHeader,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT VOID **SectionData
+ )
+{
+ UINT32 FileSize;
+ EFI_COMMON_SECTION_HEADER *Section;
+ UINT32 SectionSize;
+ UINT32 Index;
+
+ if (IS_FFS_FILE2 (FileHeader)) {
+ FileSize = FFS_FILE2_SIZE (FileHeader);
+ } else {
+ FileSize = FFS_FILE_SIZE (FileHeader);
+ }
+ FileSize -= sizeof (EFI_FFS_FILE_HEADER);
+
+ Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1);
+ Index = 0;
+ while (Index < FileSize) {
+ if (Section->Type == SectionType) {
+ if (IS_SECTION2 (Section)) {
+ *SectionData = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER2));
+ } else {
+ *SectionData = (VOID *)((UINT8 *) Section + sizeof (EFI_COMMON_SECTION_HEADER));
+ }
+ return EFI_SUCCESS;
+ }
+
+ if (IS_SECTION2 (Section)) {
+ SectionSize = SECTION2_SIZE (Section);
+ } else {
+ SectionSize = SECTION_SIZE (Section);
+ }
+
+ SectionSize = GET_OCCUPIED_SIZE (SectionSize, 4);
+ ASSERT (SectionSize != 0);
+ Index += SectionSize;
+
+ Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionSize);
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+
+/**
+ Find DXE core from FV and build DXE core HOBs.
+
+ @param[out] DxeCoreEntryPoint DXE core entry point
+
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval EFI_NOT_FOUND If it failed to load DXE FV.
+**/
+EFI_STATUS
+LoadDxeCore (
+ OUT PHYSICAL_ADDRESS *DxeCoreEntryPoint
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_VOLUME_HEADER *PayloadFv;
+ EFI_FIRMWARE_VOLUME_HEADER *DxeCoreFv;
+ EFI_FFS_FILE_HEADER *FileHeader;
+ VOID *PeCoffImage;
+ EFI_PHYSICAL_ADDRESS ImageAddress;
+ UINT64 ImageSize;
+
+ PayloadFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdPayloadFdMemBase);
+
+ //
+ // DXE FV is inside Payload FV. Here find DXE FV from Payload FV
+ //
+ Status = FvFindFile (PayloadFv, EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, &FileHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = FileFindSection (FileHeader, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, (VOID **)&DxeCoreFv);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Report DXE FV to DXE core
+ //
+ BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) DxeCoreFv, DxeCoreFv->FvLength);
+
+ //
+ // Find DXE core file from DXE FV
+ //
+ Status = FvFindFile (DxeCoreFv, EFI_FV_FILETYPE_DXE_CORE, &FileHeader);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = FileFindSection (FileHeader, EFI_SECTION_PE32, (VOID **)&PeCoffImage);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get DXE core info
+ //
+ Status = LoadPeCoffImage (PeCoffImage, &ImageAddress, &ImageSize, DxeCoreEntryPoint);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ BuildModuleHob (&FileHeader->Name, ImageAddress, EFI_SIZE_TO_PAGES ((UINT32) ImageSize) * EFI_PAGE_SIZE, *DxeCoreEntryPoint);
+
+ return EFI_SUCCESS;
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c
new file mode 100644
index 00000000000..470f81cd027
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/MemoryAllocation.c
@@ -0,0 +1,201 @@
+/** @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_TYPE_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;
+}
+
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c
index 4cd9b69831d..4b5003a3034 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/BlSupportPei/BlSupportPei.c
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.c
@@ -1,144 +1,58 @@
/** @file
- This PEIM will parse bootloader information and report resource information into pei core.
- This file contains the main entrypoint of the PEIM.
-Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "BlSupportPei.h"
-
-#define LEGACY_8259_MASK_REGISTER_MASTER 0x21
-#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1
-
-EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
- { EfiACPIReclaimMemory, FixedPcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory) },
- { EfiACPIMemoryNVS, FixedPcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS) },
- { EfiReservedMemoryType, FixedPcdGet32 (PcdMemoryTypeEfiReservedMemoryType) },
- { EfiRuntimeServicesData, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesData) },
- { EfiRuntimeServicesCode, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode) },
- { EfiMaxMemoryType, 0 }
-};
-
-EFI_PEI_PPI_DESCRIPTOR mPpiBootMode[] = {
- {
- EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
- &gEfiPeiMasterBootModePpiGuid,
- NULL
- }
-};
-EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = {
- MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8, MAX_UINT8
-};
+#include "UefiPayloadEntry.h"
/**
- Create memory mapped io resource hob.
+ Callback function to build resource descriptor HOB
- @param MmioBase Base address of the memory mapped io range
- @param MmioSize Length of the memory mapped io range
+ This function build a HOB based on the memory map entry info.
-**/
-VOID
-BuildMemoryMappedIoRangeHob (
- EFI_PHYSICAL_ADDRESS MmioBase,
- UINT64 MmioSize
- )
-{
- BuildResourceDescriptorHob (
- EFI_RESOURCE_MEMORY_MAPPED_IO,
- (EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_TESTED),
- MmioBase,
- MmioSize
- );
-
- BuildMemoryAllocationHob (
- MmioBase,
- MmioSize,
- EfiMemoryMappedIO
- );
-}
-
-/**
- Check the integrity of firmware volume header
-
- @param[in] FwVolHeader A pointer to a firmware volume header
-
- @retval TRUE The firmware volume is consistent
- @retval FALSE The firmware volume has corrupted.
+ @param MemoryMapEntry Memory map entry info got from bootloader.
+ @param Params Not used for now.
+ @retval RETURN_SUCCESS Successfully build a HOB.
**/
-STATIC
-BOOLEAN
-IsFvHeaderValid (
- IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader
+EFI_STATUS
+MemInfoCallback (
+ IN MEMROY_MAP_ENTRY *MemoryMapEntry,
+ IN VOID *Params
)
{
- UINT16 Checksum;
+ EFI_PHYSICAL_ADDRESS Base;
+ EFI_RESOURCE_TYPE Type;
+ UINT64 Size;
+ EFI_RESOURCE_ATTRIBUTE_TYPE Attribue;
- // Skip nv storage fv
- if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {
- return FALSE;
- }
+ Type = (MemoryMapEntry->Type == 1) ? EFI_RESOURCE_SYSTEM_MEMORY : EFI_RESOURCE_MEMORY_RESERVED;
+ Base = MemoryMapEntry->Base;
+ Size = MemoryMapEntry->Size;
- if ( (FwVolHeader->Revision != EFI_FVH_REVISION) ||
- (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||
- (FwVolHeader->FvLength == ((UINTN) -1)) ||
- ((FwVolHeader->HeaderLength & 0x01 ) !=0) ) {
- return FALSE;
- }
+ Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_TESTED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
- Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength);
- if (Checksum != 0) {
- DEBUG (( DEBUG_ERROR,
- "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n",
- FwVolHeader->Checksum,
- (UINT16)( Checksum + FwVolHeader->Checksum )));
- return TRUE; //FALSE; Need update UEFI build tool when patching entrypoin @start of fd.
+ if (Base >= BASE_4GB ) {
+ // Remove tested attribute to avoid DXE core to dispatch driver to memory above 4GB
+ Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;
}
- return TRUE;
-}
-
-/**
- Install FvInfo PPI and create fv hobs for remained fvs
+ BuildResourceDescriptorHob (Type, Attribue, (EFI_PHYSICAL_ADDRESS)Base, Size);
+ DEBUG ((DEBUG_INFO , "buildhob: base = 0x%lx, size = 0x%lx, type = 0x%x\n", Base, Size, Type));
-**/
-VOID
-PeiReportRemainedFvs (
- VOID
- )
-{
- UINT8* TempPtr;
- UINT8* EndPtr;
-
- TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase);
- EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize));
-
- for (;TempPtr < EndPtr;) {
- if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) {
- if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase)) {
- // Skip the PEI FV
- DEBUG((DEBUG_INFO, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength));
-
- PeiServicesInstallFvInfoPpi (
- NULL,
- (VOID *) (UINTN) TempPtr,
- (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength,
- NULL,
- NULL
- );
- BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength);
- }
- }
- TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength;
- }
+ return RETURN_SUCCESS;
}
+
/**
Find the board related info from ACPI table
@@ -240,8 +154,10 @@ Done:
if (MmCfgHdr != NULL) {
MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8*) MmCfgHdr + sizeof (*MmCfgHdr));
AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress;
+ AcpiBoardInfo->PcieBaseSize = (MmCfgBase->EndBusNumber + 1 - MmCfgBase->StartBusNumber) * 4096 * 32 * 8;
} else {
AcpiBoardInfo->PcieBaseAddress = 0;
+ AcpiBoardInfo->PcieBaseSize = 0;
}
DEBUG ((DEBUG_INFO, "PmCtrl Reg 0x%lx\n", AcpiBoardInfo->PmCtrlRegBase));
DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n", AcpiBoardInfo->PmTimerRegBase));
@@ -250,6 +166,7 @@ Done:
DEBUG ((DEBUG_INFO, "PmEvt Reg 0x%lx\n", AcpiBoardInfo->PmEvtBase));
DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n", AcpiBoardInfo->PmGpeEnBase));
DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress));
+ DEBUG ((DEBUG_INFO, "PcieBaseSize 0x%lx\n", AcpiBoardInfo->PcieBaseSize));
//
// Verify values for proper operation
@@ -296,91 +213,19 @@ Done:
return RETURN_SUCCESS;
}
-EFI_STATUS
-MemInfoCallback (
- IN MEMROY_MAP_ENTRY *MemoryMapEntry,
- IN VOID *Params
- )
-{
- PAYLOAD_MEM_INFO *MemInfo;
- UINTN Attribue;
- EFI_PHYSICAL_ADDRESS Base;
- EFI_RESOURCE_TYPE Type;
- UINT64 Size;
- UINT32 SystemLowMemTop;
-
- Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_TESTED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;
-
- MemInfo = (PAYLOAD_MEM_INFO *)Params;
- Type = (MemoryMapEntry->Type == 1) ? EFI_RESOURCE_SYSTEM_MEMORY : EFI_RESOURCE_MEMORY_RESERVED;
- Base = MemoryMapEntry->Base;
- Size = MemoryMapEntry->Size;
-
- if ((Base < 0x100000) && ((Base + Size) > 0x100000)) {
- Size -= (0x100000 - Base);
- Base = 0x100000;
- }
-
- if (Base >= 0x100000) {
- if (Type == EFI_RESOURCE_SYSTEM_MEMORY) {
- if (Base < 0x100000000ULL) {
- MemInfo->UsableLowMemTop = (UINT32)(Base + Size);
- } else {
- Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;
- }
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- Attribue,
- (EFI_PHYSICAL_ADDRESS)Base,
- Size
- );
- } else if (Type == EFI_RESOURCE_MEMORY_RESERVED) {
- BuildResourceDescriptorHob (
- EFI_RESOURCE_MEMORY_RESERVED,
- Attribue,
- (EFI_PHYSICAL_ADDRESS)Base,
- Size
- );
- if (Base < 0x100000000ULL) {
- SystemLowMemTop = ((UINT32)(Base + Size) + 0x0FFFFFFF) & 0xF0000000;
- if (SystemLowMemTop > MemInfo->SystemLowMemTop) {
- MemInfo->SystemLowMemTop = SystemLowMemTop;
- }
- }
- }
- }
-
- return EFI_SUCCESS;
-}
/**
- This is the entrypoint of PEIM
-
- @param FileHandle Handle of the file being invoked.
- @param PeiServices Describes the list of possible PEI Services.
+ It will build HOBs based on information from bootloaders.
- @retval EFI_SUCCESS if it completed successfully.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval Others If it failed to build required HOBs.
**/
EFI_STATUS
-EFIAPI
-BlPeiEntryPoint (
- IN EFI_PEI_FILE_HANDLE FileHandle,
- IN CONST EFI_PEI_SERVICES **PeiServices
+BuildHobFromBl (
+ VOID
)
{
EFI_STATUS Status;
- UINT64 LowMemorySize;
- UINT64 PeiMemSize = SIZE_64MB;
- EFI_PHYSICAL_ADDRESS PeiMemBase = 0;
- UINT32 RegEax;
- UINT8 PhysicalAddressBits;
- PAYLOAD_MEM_INFO PldMemInfo;
SYSTEM_TABLE_INFO SysTableInfo;
SYSTEM_TABLE_INFO *NewSysTableInfo;
ACPI_BOARD_INFO AcpiBoardInfo;
@@ -390,120 +235,15 @@ BlPeiEntryPoint (
EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo;
EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo;
-
- //
- // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED
- // is intentionally omitted to prevent erasing of the coreboot header
- // record before it is processed by ParseMemoryInfo.
- //
- BuildResourceDescriptorHob (
- EFI_RESOURCE_SYSTEM_MEMORY,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- (EFI_PHYSICAL_ADDRESS)(0),
- (UINT64)(0xA0000)
- );
-
- BuildResourceDescriptorHob (
- EFI_RESOURCE_MEMORY_RESERVED,
- (
- EFI_RESOURCE_ATTRIBUTE_PRESENT |
- EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
- EFI_RESOURCE_ATTRIBUTE_TESTED |
- EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
- EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
- ),
- (EFI_PHYSICAL_ADDRESS)(0xA0000),
- (UINT64)(0x60000)
- );
-
-
//
- // Parse memory info
+ // Parse memory info and build memory HOBs
//
- ZeroMem (&PldMemInfo, sizeof(PldMemInfo));
- Status = ParseMemoryInfo (MemInfoCallback, &PldMemInfo);
+ Status = ParseMemoryInfo (MemInfoCallback, NULL);
if (EFI_ERROR(Status)) {
return Status;
}
//
- // Install memory
- //
- LowMemorySize = PldMemInfo.UsableLowMemTop;
- PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1));
- DEBUG ((DEBUG_INFO, "Low memory 0x%lx\n", LowMemorySize));
- DEBUG ((DEBUG_INFO, "SystemLowMemTop 0x%x\n", PldMemInfo.SystemLowMemTop));
- DEBUG ((DEBUG_INFO, "PeiMemBase: 0x%lx.\n", PeiMemBase));
- DEBUG ((DEBUG_INFO, "PeiMemSize: 0x%lx.\n", PeiMemSize));
- Status = PeiServicesInstallPeiMemory (PeiMemBase, PeiMemSize);
- ASSERT_EFI_ERROR (Status);
-
- //
- // Set cache on the physical memory
- //
- MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack);
- MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack);
-
- //
- // Create Memory Type Information HOB
- //
- BuildGuidDataHob (
- &gEfiMemoryTypeInformationGuid,
- mDefaultMemoryTypeInformation,
- sizeof(mDefaultMemoryTypeInformation)
- );
-
- //
- // Create Fv hob
- //
- PeiReportRemainedFvs ();
-
- BuildMemoryAllocationHob (
- PcdGet32 (PcdPayloadFdMemBase),
- PcdGet32 (PcdPayloadFdMemSize),
- EfiBootServicesData
- );
-
- //
- // Build CPU memory space and IO space hob
- //
- AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
- if (RegEax >= 0x80000008) {
- AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- PhysicalAddressBits = (UINT8) RegEax;
- } else {
- PhysicalAddressBits = 36;
- }
-
- //
- // Create a CPU hand-off information
- //
- BuildCpuHob (PhysicalAddressBits, 16);
-
- //
- // Report Local APIC range
- //
- BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB);
-
- //
- // Boot mode
- //
- Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION);
- ASSERT_EFI_ERROR (Status);
-
- Status = PeiServicesInstallPpi (mPpiBootMode);
- ASSERT_EFI_ERROR (Status);
-
- //
// Create guid hob for frame buffer information
//
Status = ParseGfxInfo (&GfxInfo);
@@ -558,12 +298,118 @@ BlPeiEntryPoint (
return Status;
}
+ return EFI_SUCCESS;
+}
+
+
+/**
+ This function will build some generic HOBs that doesn't depend on information from bootloaders.
+
+**/
+VOID
+BuildGenericHob (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT8 PhysicalAddressBits;
+ EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
+
+ // The UEFI payload FV
+ BuildMemoryAllocationHob (PcdGet32 (PcdPayloadFdMemBase), PcdGet32 (PcdPayloadFdMemSize), EfiBootServicesData);
+
+ //
+ // Build CPU memory space and IO space hob
+ //
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+
+ BuildCpuHob (PhysicalAddressBits, 16);
+
+ //
+ // Report Local APIC range, cause sbl HOB to be NULL, comment now
+ //
+ ResourceAttribute = (
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED
+ );
+ BuildResourceDescriptorHob (EFI_RESOURCE_MEMORY_MAPPED_IO, ResourceAttribute, 0xFEC80000, SIZE_512KB);
+ BuildMemoryAllocationHob ( 0xFEC80000, SIZE_512KB, EfiMemoryMappedIO);
+
+}
+
+
+/**
+ Entry point to the C language phase of UEFI payload.
+
+ @retval It will not return if SUCCESS, and return error when passing bootloader parameter.
+**/
+EFI_STATUS
+EFIAPI
+PayloadEntry (
+ IN UINTN BootloaderParameter
+ )
+{
+ EFI_STATUS Status;
+ PHYSICAL_ADDRESS DxeCoreEntryPoint;
+ EFI_HOB_HANDOFF_INFO_TABLE *HandoffHobTable;
+ UINTN MemBase;
+ UINTN MemSize;
+ UINTN HobMemBase;
+ UINTN HobMemTop;
+ EFI_PEI_HOB_POINTERS Hob;
+
+ // Call constructor for all libraries
+ ProcessLibraryConstructorList ();
+
+ DEBUG ((DEBUG_INFO, "GET_BOOTLOADER_PARAMETER() = 0x%lx\n", GET_BOOTLOADER_PARAMETER()));
+ DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN)));
+
+ // Initialize floating point operating environment to be compliant with UEFI spec.
+ InitializeFloatingPointUnits ();
+
+ // HOB region is used for HOB and memory allocation for this module
+ MemBase = PcdGet32 (PcdPayloadFdMemBase);
+ HobMemBase = ALIGN_VALUE (MemBase + PcdGet32 (PcdPayloadFdMemSize), SIZE_1MB);
+ HobMemTop = HobMemBase + FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
+
+ // DXE core assumes the memory below HOB region could be used, so include the FV region memory into HOB range.
+ MemSize = HobMemTop - MemBase;
+ HandoffHobTable = HobConstructor ((VOID *)MemBase, MemSize, (VOID *)HobMemBase, (VOID *)HobMemTop);
+
+ // Build HOB based on information from Bootloader
+ Status = BuildHobFromBl ();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "BuildHobFromBl Status = %r\n", Status));
+ return Status;
+ }
+
+ // Build other HOBs required by DXE
+ BuildGenericHob ();
+
+ // Load the DXE Core
+ Status = LoadDxeCore (&DxeCoreEntryPoint);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "DxeCoreEntryPoint = 0x%lx\n", DxeCoreEntryPoint));
+
//
// Mask off all legacy 8259 interrupt sources
//
IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
+ Hob.HandoffInformationTable = HandoffHobTable;
+ HandOffToDxeCore (DxeCoreEntryPoint, Hob);
+
+ // Should not get here
+ CpuDeadLoop ();
return EFI_SUCCESS;
}
-
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h
new file mode 100644
index 00000000000..b66fd992511
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.h
@@ -0,0 +1,134 @@
+/** @file
+*
+* Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#ifndef __UEFI_PAYLOAD_ENTRY_H__
+#define __UEFI_PAYLOAD_ENTRY_H__
+
+#include <PiPei.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Guid/MemoryAllocationHob.h>
+#include <Library/IoLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/BlParseLib.h>
+#include <Library/PlatformSupportLib.h>
+#include <Library/UefiCpuLib.h>
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h>
+#include <Guid/SerialPortInfoGuid.h>
+#include <Guid/SystemTableInfoGuid.h>
+#include <Guid/MemoryMapInfoGuid.h>
+#include <Guid/AcpiBoardInfoGuid.h>
+#include <Guid/GraphicsInfoHob.h>
+
+
+#define LEGACY_8259_MASK_REGISTER_MASTER 0x21
+#define LEGACY_8259_MASK_REGISTER_SLAVE 0xA1
+#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \
+ ((ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)))
+
+/**
+ Auto-generated function that calls the library constructors for all of the module's
+ dependent libraries.
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+ VOID
+ );
+
+/**
+ 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
+ );
+
+/**
+ Update the Stack Hob if the stack has been moved
+
+ @param BaseAddress The 64 bit physical address of the Stack.
+ @param Length The length of the stack in bytes.
+
+**/
+VOID
+EFIAPI
+UpdateStackHob (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINT64 Length
+ );
+
+/**
+ Build a Handoff Information Table HOB
+
+ This function initialize a HOB region from EfiMemoryBegin with length
+ EfiMemoryLength. And EfiFreeMemoryBottom and EfiFreeMemoryTop should
+ be inside the HOB region.
+
+ @param[in] EfiMemoryBegin Total memory start address
+ @param[in] EfiMemoryLength Total memory length reported in handoff HOB.
+ @param[in] EfiFreeMemoryBottom Free memory start address
+ @param[in] EfiFreeMemoryTop Free memory end address.
+
+ @return The pointer to the handoff HOB table.
+
+**/
+EFI_HOB_HANDOFF_INFO_TABLE*
+EFIAPI
+HobConstructor (
+ IN VOID *EfiMemoryBegin,
+ IN UINTN EfiMemoryLength,
+ IN VOID *EfiFreeMemoryBottom,
+ IN VOID *EfiFreeMemoryTop
+ );
+
+/**
+ Find DXE core from FV and build DXE core HOBs.
+
+ @param[out] DxeCoreEntryPoint DXE core entry point
+
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval EFI_NOT_FOUND If it failed to load DXE FV.
+**/
+EFI_STATUS
+LoadDxeCore (
+ OUT PHYSICAL_ADDRESS *DxeCoreEntryPoint
+ );
+
+/**
+ Transfers control to DxeCore.
+
+ This function performs a CPU architecture specific operations to execute
+ the entry point of DxeCore with the parameters of HobList.
+
+ @param DxeCoreEntryPoint The entry point of DxeCore.
+ @param HobList The start of HobList passed to DxeCore.
+**/
+VOID
+HandOffToDxeCore (
+ IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,
+ IN EFI_PEI_HOB_POINTERS HobList
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
new file mode 100644
index 00000000000..5be2c263c09
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
@@ -0,0 +1,93 @@
+## @file
+# This is the first module for UEFI payload.
+#
+# Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PayloadEntry
+ FILE_GUID = 2119BBD7-9432-4f47-B5E2-5C4EA31B6BDC
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64
+#
+
+[Sources]
+ UefiPayloadEntry.c
+ LoadDxeCore.c
+ MemoryAllocation.c
+
+[Sources.Ia32]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ Ia32/DxeLoadFunc.c
+ Ia32/IdtVectorAsm.nasm
+ Ia32/SecEntry.nasm
+
+[Sources.X64]
+ X64/VirtualMemory.h
+ X64/VirtualMemory.c
+ X64/DxeLoadFunc.c
+ X64/SecEntry.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ UefiPayloadPkg/UefiPayloadPkg.dec
+
+[LibraryClasses]
+ BaseMemoryLib
+ DebugLib
+ BaseLib
+ SerialPortLib
+ IoLib
+ BlParseLib
+ HobLib
+ PeCoffLib
+ PlatformSupportLib
+ UefiCpuLib
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+ gEfiFirmwareFileSystem2Guid
+ gUefiSystemTableInfoGuid
+ gEfiGraphicsInfoHobGuid
+ gEfiGraphicsDeviceInfoHobGuid
+ gUefiAcpiBoardInfoGuid
+
+[FeaturePcd.IA32]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUMES
+
+[FeaturePcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUMES
+
+
+[Pcd.IA32,Pcd.X64]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ## CONSUMES
+
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop
+ gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize
+
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIMES_CONSUMES
+ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIMES_CONSUMES
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c
new file mode 100644
index 00000000000..144139bd274
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/DxeLoadFunc.c
@@ -0,0 +1,107 @@
+/** @file
+ x64-specifc functionality for DxeLoad.
+
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include "X64/VirtualMemory.h"
+#include "UefiPayloadEntry.h"
+#define STACK_SIZE 0x20000
+
+
+/**
+ Transfers control to DxeCore.
+
+ This function performs a CPU architecture specific operations to execute
+ the entry point of DxeCore with the parameters of HobList.
+ It also installs EFI_END_OF_PEI_PPI to signal the end of PEI phase.
+
+ @param DxeCoreEntryPoint The entry point of DxeCore.
+ @param HobList The start of HobList passed to DxeCore.
+
+**/
+VOID
+HandOffToDxeCore (
+ IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint,
+ IN EFI_PEI_HOB_POINTERS HobList
+ )
+{
+ VOID *BaseOfStack;
+ VOID *TopOfStack;
+ UINTN PageTables;
+ VOID *GhcbBase;
+ UINTN GhcbSize;
+
+ //
+ // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.
+ //
+ if (IsNullDetectionEnabled ()) {
+ ClearFirst4KPage (HobList.Raw);
+ BuildMemoryAllocationHob (0, EFI_PAGES_TO_SIZE (1), EfiBootServicesData);
+ }
+
+
+ //
+ // Allocate 128KB for the Stack
+ //
+ BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE));
+ ASSERT (BaseOfStack != NULL);
+
+ //
+ // Compute the top of the stack we were allocated. Pre-allocate a UINTN
+ // for safety.
+ //
+ TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);
+ TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);
+
+ //
+ // Get the address and size of the GHCB pages
+ //
+ GhcbBase = (VOID *) PcdGet64 (PcdGhcbBase);
+ GhcbSize = PcdGet64 (PcdGhcbSize);
+
+ PageTables = 0;
+ if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
+ //
+ // Create page table and save PageMapLevel4 to CR3
+ //
+ PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE,
+ (EFI_PHYSICAL_ADDRESS) (UINTN) GhcbBase, GhcbSize);
+ } else {
+ //
+ // Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE
+ // for the DxeIpl and the DxeCore are both X64.
+ //
+ ASSERT (PcdGetBool (PcdSetNxForStack) == FALSE);
+ ASSERT (PcdGetBool (PcdCpuStackGuard) == FALSE);
+ }
+
+
+ if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {
+ AsmWriteCr3 (PageTables);
+ }
+
+ //
+ // Update the contents of BSP stack HOB to reflect the real stack info passed to DxeCore.
+ //
+ UpdateStackHob ((EFI_PHYSICAL_ADDRESS)(UINTN) BaseOfStack, STACK_SIZE);
+
+ //
+ // Transfer the control to the entry point of DxeCore.
+ //
+ SwitchStack (
+ (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint,
+ HobList.Raw,
+ NULL,
+ TopOfStack
+ );
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm
new file mode 100644
index 00000000000..654f1166589
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/SecEntry.nasm
@@ -0,0 +1,47 @@
+;------------------------------------------------------------------------------
+;*
+;* Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+;* SPDX-License-Identifier: BSD-2-Clause-Patent
+
+;------------------------------------------------------------------------------
+
+#include <Base.h>
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(PayloadEntry)
+extern ASM_PFX(PcdGet32 (PcdPayloadStackTop))
+
+;
+; SecCore Entry Point
+;
+; Processor is in flat protected mode
+
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+
+ ;
+ ; Disable all the interrupts
+ ;
+ cli
+
+
+ mov rsp, FixedPcdGet32 (PcdPayloadStackTop)
+
+ ;
+ ; Push the bootloader parameter address onto new stack
+ ;
+ push rcx
+ mov rax, 0
+ push rax ; shadow space
+ push rax
+ push rax
+ push rax
+
+ ;
+ ; Call into C code
+ ;
+ call ASM_PFX(PayloadEntry)
+ jmp $
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c
new file mode 100644
index 00000000000..196e88a2052
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c
@@ -0,0 +1,939 @@
+/** @file
+ x64 Virtual Memory Management Services in the form of an IA-32 driver.
+ Used to establish a 1:1 Virtual to Physical Mapping that is required to
+ enter Long Mode (x64 64-bit mode).
+
+ While we make a 1:1 mapping (identity mapping) for all physical pages
+ we still need to use the MTRR's to ensure that the cachability attributes
+ for all memory regions is correct.
+
+ The basic idea is to use 2MB page table entries where ever possible. If
+ more granularity of cachability is required then 4K page tables are used.
+
+ References:
+ 1) IA-32 Intel(R) Architecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+
+Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/HobLib.h>
+#include <Register/Intel/Cpuid.h>
+#include "VirtualMemory.h"
+
+//
+// Global variable to keep track current available memory used as page table.
+//
+PAGE_TABLE_POOL *mPageTablePool = NULL;
+
+/**
+ Clear legacy memory located at the first 4K-page, if available.
+
+ This function traverses the whole HOB list to check if memory from 0 to 4095
+ exists and has not been allocated, and then clear it if so.
+
+ @param HobStart The start of HobList passed to DxeCore.
+
+**/
+VOID
+ClearFirst4KPage (
+ IN VOID *HobStart
+ )
+{
+ EFI_PEI_HOB_POINTERS RscHob;
+ EFI_PEI_HOB_POINTERS MemHob;
+ BOOLEAN DoClear;
+
+ RscHob.Raw = HobStart;
+ MemHob.Raw = HobStart;
+ DoClear = FALSE;
+
+ //
+ // Check if page 0 exists and free
+ //
+ while ((RscHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR,
+ RscHob.Raw)) != NULL) {
+ if (RscHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY &&
+ RscHob.ResourceDescriptor->PhysicalStart == 0) {
+ DoClear = TRUE;
+ //
+ // Make sure memory at 0-4095 has not been allocated.
+ //
+ while ((MemHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION,
+ MemHob.Raw)) != NULL) {
+ if (MemHob.MemoryAllocation->AllocDescriptor.MemoryBaseAddress
+ < EFI_PAGE_SIZE) {
+ DoClear = FALSE;
+ break;
+ }
+ MemHob.Raw = GET_NEXT_HOB (MemHob);
+ }
+ break;
+ }
+ RscHob.Raw = GET_NEXT_HOB (RscHob);
+ }
+
+ if (DoClear) {
+ DEBUG ((DEBUG_INFO, "Clearing first 4K-page!\r\n"));
+ SetMem (NULL, EFI_PAGE_SIZE, 0);
+ }
+
+ return;
+}
+
+/**
+ Return configure status of NULL pointer detection feature.
+
+ @return TRUE NULL pointer detection feature is enabled
+ @return FALSE NULL pointer detection feature is disabled
+
+**/
+BOOLEAN
+IsNullDetectionEnabled (
+ VOID
+ )
+{
+ return ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) != 0);
+}
+
+/**
+ The function will check if Execute Disable Bit is available.
+
+ @retval TRUE Execute Disable Bit is available.
+ @retval FALSE Execute Disable Bit is not available.
+
+**/
+BOOLEAN
+IsExecuteDisableBitAvailable (
+ VOID
+ )
+{
+ UINT32 RegEax;
+ UINT32 RegEdx;
+ BOOLEAN Available;
+
+ Available = FALSE;
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT20) != 0) {
+ //
+ // Bit 20: Execute Disable Bit available.
+ //
+ Available = TRUE;
+ }
+ }
+
+ return Available;
+}
+
+/**
+ Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not.
+
+ @retval TRUE IA32_EFER.NXE should be enabled.
+ @retval FALSE IA32_EFER.NXE should not be enabled.
+
+**/
+BOOLEAN
+IsEnableNonExecNeeded (
+ VOID
+ )
+{
+ if (!IsExecuteDisableBitAvailable ()) {
+ return FALSE;
+ }
+
+ //
+ // XD flag (BIT63) in page table entry is only valid if IA32_EFER.NXE is set.
+ // Features controlled by Following PCDs need this feature to be enabled.
+ //
+ return (PcdGetBool (PcdSetNxForStack) ||
+ PcdGet64 (PcdDxeNxMemoryProtectionPolicy) != 0 ||
+ PcdGet32 (PcdImageProtectionPolicy) != 0);
+}
+
+/**
+ Enable Execute Disable Bit.
+
+**/
+VOID
+EnableExecuteDisableBit (
+ VOID
+ )
+{
+ UINT64 MsrRegisters;
+
+ MsrRegisters = AsmReadMsr64 (0xC0000080);
+ MsrRegisters |= BIT11;
+ AsmWriteMsr64 (0xC0000080, MsrRegisters);
+}
+
+/**
+ The function will check if page table entry should be splitted to smaller
+ granularity.
+
+ @param Address Physical memory address.
+ @param Size Size of the given physical memory.
+ @param StackBase Base address of stack.
+ @param StackSize Size of stack.
+ @param GhcbBase Base address of GHCB pages.
+ @param GhcbSize Size of GHCB area.
+
+ @retval TRUE Page table should be split.
+ @retval FALSE Page table should not be split.
+**/
+BOOLEAN
+ToSplitPageTable (
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN UINTN Size,
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
+ )
+{
+ if (IsNullDetectionEnabled () && Address == 0) {
+ return TRUE;
+ }
+
+ if (PcdGetBool (PcdCpuStackGuard)) {
+ if (StackBase >= Address && StackBase < (Address + Size)) {
+ return TRUE;
+ }
+ }
+
+ if (PcdGetBool (PcdSetNxForStack)) {
+ if ((Address < StackBase + StackSize) && ((Address + Size) > StackBase)) {
+ return TRUE;
+ }
+ }
+
+ if (GhcbBase != 0) {
+ if ((Address < GhcbBase + GhcbSize) && ((Address + Size) > GhcbBase)) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+/**
+ Initialize a buffer pool for page table use only.
+
+ To reduce the potential split operation on page table, the pages reserved for
+ page table should be allocated in the times of PAGE_TABLE_POOL_UNIT_PAGES and
+ at the boundary of PAGE_TABLE_POOL_ALIGNMENT. So the page pool is always
+ initialized with number of pages greater than or equal to the given PoolPages.
+
+ Once the pages in the pool are used up, this method should be called again to
+ reserve at least another PAGE_TABLE_POOL_UNIT_PAGES. But usually this won't
+ happen in practice.
+
+ @param PoolPages The least page number of the pool to be created.
+
+ @retval TRUE The pool is initialized successfully.
+ @retval FALSE The memory is out of resource.
+**/
+BOOLEAN
+InitializePageTablePool (
+ IN UINTN PoolPages
+ )
+{
+ VOID *Buffer;
+
+ //
+ // Always reserve at least PAGE_TABLE_POOL_UNIT_PAGES, including one page for
+ // header.
+ //
+ PoolPages += 1; // Add one page for header.
+ PoolPages = ((PoolPages - 1) / PAGE_TABLE_POOL_UNIT_PAGES + 1) *
+ PAGE_TABLE_POOL_UNIT_PAGES;
+ Buffer = AllocateAlignedPages (PoolPages, PAGE_TABLE_POOL_ALIGNMENT);
+ if (Buffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "ERROR: Out of aligned pages\r\n"));
+ return FALSE;
+ }
+
+ //
+ // Link all pools into a list for easier track later.
+ //
+ if (mPageTablePool == NULL) {
+ mPageTablePool = Buffer;
+ mPageTablePool->NextPool = mPageTablePool;
+ } else {
+ ((PAGE_TABLE_POOL *)Buffer)->NextPool = mPageTablePool->NextPool;
+ mPageTablePool->NextPool = Buffer;
+ mPageTablePool = Buffer;
+ }
+
+ //
+ // Reserve one page for pool header.
+ //
+ mPageTablePool->FreePages = PoolPages - 1;
+ mPageTablePool->Offset = EFI_PAGES_TO_SIZE (1);
+
+ return TRUE;
+}
+
+/**
+ This API provides a way to allocate memory for page table.
+
+ This API can be called more than once to allocate memory for page tables.
+
+ Allocates the number of 4KB pages 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 remaining 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 *
+AllocatePageTableMemory (
+ IN UINTN Pages
+ )
+{
+ VOID *Buffer;
+
+ if (Pages == 0) {
+ return NULL;
+ }
+
+ //
+ // Renew the pool if necessary.
+ //
+ if (mPageTablePool == NULL ||
+ Pages > mPageTablePool->FreePages) {
+ if (!InitializePageTablePool (Pages)) {
+ return NULL;
+ }
+ }
+
+ Buffer = (UINT8 *)mPageTablePool + mPageTablePool->Offset;
+
+ mPageTablePool->Offset += EFI_PAGES_TO_SIZE (Pages);
+ mPageTablePool->FreePages -= Pages;
+
+ return Buffer;
+}
+
+/**
+ Split 2M page to 4K.
+
+ @param[in] PhysicalAddress Start physical address the 2M page covered.
+ @param[in, out] PageEntry2M Pointer to 2M page entry.
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
+
+**/
+VOID
+Split2MPageTo4K (
+ IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
+ IN OUT UINT64 *PageEntry2M,
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
+ )
+{
+ EFI_PHYSICAL_ADDRESS PhysicalAddress4K;
+ UINTN IndexOfPageTableEntries;
+ PAGE_TABLE_4K_ENTRY *PageTableEntry;
+ UINT64 AddressEncMask;
+
+ //
+ // Make sure AddressEncMask is contained to smallest supported address field
+ //
+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
+
+ PageTableEntry = AllocatePageTableMemory (1);
+ ASSERT (PageTableEntry != NULL);
+
+ //
+ // Fill in 2M page entry.
+ //
+ *PageEntry2M = (UINT64) (UINTN) PageTableEntry | AddressEncMask | IA32_PG_P | IA32_PG_RW;
+
+ PhysicalAddress4K = PhysicalAddress;
+ for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) {
+ //
+ // Fill in the Page Table entries
+ //
+ PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K;
+
+ //
+ // The GHCB range consists of two pages per CPU, the GHCB and a
+ // per-CPU variable page. The GHCB page needs to be mapped as an
+ // unencrypted page while the per-CPU variable page needs to be
+ // mapped encrypted. These pages alternate in assignment.
+ //
+ if ((GhcbBase == 0)
+ || (PhysicalAddress4K < GhcbBase)
+ || (PhysicalAddress4K >= GhcbBase + GhcbSize)
+ || (((PhysicalAddress4K - GhcbBase) & SIZE_4KB) != 0)) {
+ PageTableEntry->Uint64 |= AddressEncMask;
+ }
+ PageTableEntry->Bits.ReadWrite = 1;
+
+ if ((IsNullDetectionEnabled () && PhysicalAddress4K == 0) ||
+ (PcdGetBool (PcdCpuStackGuard) && PhysicalAddress4K == StackBase)) {
+ PageTableEntry->Bits.Present = 0;
+ } else {
+ PageTableEntry->Bits.Present = 1;
+ }
+
+ if (PcdGetBool (PcdSetNxForStack)
+ && (PhysicalAddress4K >= StackBase)
+ && (PhysicalAddress4K < StackBase + StackSize)) {
+ //
+ // Set Nx bit for stack.
+ //
+ PageTableEntry->Bits.Nx = 1;
+ }
+ }
+}
+
+/**
+ Split 1G page to 2M.
+
+ @param[in] PhysicalAddress Start physical address the 1G page covered.
+ @param[in, out] PageEntry1G Pointer to 1G page entry.
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
+
+**/
+VOID
+Split1GPageTo2M (
+ IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
+ IN OUT UINT64 *PageEntry1G,
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
+ )
+{
+ EFI_PHYSICAL_ADDRESS PhysicalAddress2M;
+ UINTN IndexOfPageDirectoryEntries;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ UINT64 AddressEncMask;
+
+ //
+ // Make sure AddressEncMask is contained to smallest supported address field
+ //
+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
+
+ PageDirectoryEntry = AllocatePageTableMemory (1);
+ ASSERT (PageDirectoryEntry != NULL);
+
+ //
+ // Fill in 1G page entry.
+ //
+ *PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | AddressEncMask | IA32_PG_P | IA32_PG_RW;
+
+ PhysicalAddress2M = PhysicalAddress;
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {
+ if (ToSplitPageTable (PhysicalAddress2M, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) {
+ //
+ // Need to split this 2M page that covers NULL or stack range.
+ //
+ Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize);
+ } else {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64) PhysicalAddress2M | AddressEncMask;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+}
+
+/**
+ Set one page of page table pool memory to be read-only.
+
+ @param[in] PageTableBase Base address of page table (CR3).
+ @param[in] Address Start address of a page to be set as read-only.
+ @param[in] Level4Paging Level 4 paging flag.
+
+**/
+VOID
+SetPageTablePoolReadOnly (
+ IN UINTN PageTableBase,
+ IN EFI_PHYSICAL_ADDRESS Address,
+ IN BOOLEAN Level4Paging
+ )
+{
+ UINTN Index;
+ UINTN EntryIndex;
+ UINT64 AddressEncMask;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ UINT64 *PageTable;
+ UINT64 *NewPageTable;
+ UINT64 PageAttr;
+ UINT64 LevelSize[5];
+ UINT64 LevelMask[5];
+ UINTN LevelShift[5];
+ UINTN Level;
+ UINT64 PoolUnitSize;
+
+ ASSERT (PageTableBase != 0);
+
+ //
+ // Since the page table is always from page table pool, which is always
+ // located at the boundary of PcdPageTablePoolAlignment, we just need to
+ // set the whole pool unit to be read-only.
+ //
+ Address = Address & PAGE_TABLE_POOL_ALIGN_MASK;
+
+ LevelShift[1] = PAGING_L1_ADDRESS_SHIFT;
+ LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
+ LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
+ LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
+
+ LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
+ LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
+ LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
+ LevelMask[4] = PAGING_1G_ADDRESS_MASK_64;
+
+ LevelSize[1] = SIZE_4KB;
+ LevelSize[2] = SIZE_2MB;
+ LevelSize[3] = SIZE_1GB;
+ LevelSize[4] = SIZE_512GB;
+
+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &
+ PAGING_1G_ADDRESS_MASK_64;
+ PageTable = (UINT64 *)(UINTN)PageTableBase;
+ PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
+
+ for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) {
+ Index = ((UINTN)RShiftU64 (Address, LevelShift[Level]));
+ Index &= PAGING_PAE_INDEX_MASK;
+
+ PageAttr = PageTable[Index];
+ if ((PageAttr & IA32_PG_PS) == 0) {
+ //
+ // Go to next level of table.
+ //
+ PageTable = (UINT64 *)(UINTN)(PageAttr & ~AddressEncMask &
+ PAGING_4K_ADDRESS_MASK_64);
+ continue;
+ }
+
+ if (PoolUnitSize >= LevelSize[Level]) {
+ //
+ // Clear R/W bit if current page granularity is not larger than pool unit
+ // size.
+ //
+ if ((PageAttr & IA32_PG_RW) != 0) {
+ while (PoolUnitSize > 0) {
+ //
+ // PAGE_TABLE_POOL_UNIT_SIZE and PAGE_TABLE_POOL_ALIGNMENT are fit in
+ // one page (2MB). Then we don't need to update attributes for pages
+ // crossing page directory. ASSERT below is for that purpose.
+ //
+ ASSERT (Index < EFI_PAGE_SIZE/sizeof (UINT64));
+
+ PageTable[Index] &= ~(UINT64)IA32_PG_RW;
+ PoolUnitSize -= LevelSize[Level];
+
+ ++Index;
+ }
+ }
+
+ break;
+
+ } else {
+ //
+ // The smaller granularity of page must be needed.
+ //
+ ASSERT (Level > 1);
+
+ NewPageTable = AllocatePageTableMemory (1);
+ ASSERT (NewPageTable != NULL);
+
+ PhysicalAddress = PageAttr & LevelMask[Level];
+ for (EntryIndex = 0;
+ EntryIndex < EFI_PAGE_SIZE/sizeof (UINT64);
+ ++EntryIndex) {
+ NewPageTable[EntryIndex] = PhysicalAddress | AddressEncMask |
+ IA32_PG_P | IA32_PG_RW;
+ if (Level > 2) {
+ NewPageTable[EntryIndex] |= IA32_PG_PS;
+ }
+ PhysicalAddress += LevelSize[Level - 1];
+ }
+
+ PageTable[Index] = (UINT64)(UINTN)NewPageTable | AddressEncMask |
+ IA32_PG_P | IA32_PG_RW;
+ PageTable = NewPageTable;
+ }
+ }
+}
+
+/**
+ Prevent the memory pages used for page table from been overwritten.
+
+ @param[in] PageTableBase Base address of page table (CR3).
+ @param[in] Level4Paging Level 4 paging flag.
+
+**/
+VOID
+EnablePageTableProtection (
+ IN UINTN PageTableBase,
+ IN BOOLEAN Level4Paging
+ )
+{
+ PAGE_TABLE_POOL *HeadPool;
+ PAGE_TABLE_POOL *Pool;
+ UINT64 PoolSize;
+ EFI_PHYSICAL_ADDRESS Address;
+
+ if (mPageTablePool == NULL) {
+ return;
+ }
+
+ //
+ // Disable write protection, because we need to mark page table to be write
+ // protected.
+ //
+ AsmWriteCr0 (AsmReadCr0() & ~CR0_WP);
+
+ //
+ // SetPageTablePoolReadOnly might update mPageTablePool. It's safer to
+ // remember original one in advance.
+ //
+ HeadPool = mPageTablePool;
+ Pool = HeadPool;
+ do {
+ Address = (EFI_PHYSICAL_ADDRESS)(UINTN)Pool;
+ PoolSize = Pool->Offset + EFI_PAGES_TO_SIZE (Pool->FreePages);
+
+ //
+ // The size of one pool must be multiple of PAGE_TABLE_POOL_UNIT_SIZE, which
+ // is one of page size of the processor (2MB by default). Let's apply the
+ // protection to them one by one.
+ //
+ while (PoolSize > 0) {
+ SetPageTablePoolReadOnly(PageTableBase, Address, Level4Paging);
+ Address += PAGE_TABLE_POOL_UNIT_SIZE;
+ PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
+ }
+
+ Pool = Pool->NextPool;
+ } while (Pool != HeadPool);
+
+ //
+ // Enable write protection, after page table attribute updated.
+ //
+ AsmWriteCr0 (AsmReadCr0() | CR0_WP);
+}
+
+/**
+ Allocates and fills in the Page Directory and Page Table Entries to
+ establish a 1:1 Virtual to Physical mapping.
+
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB base address.
+ @param[in] GhcbSize GHCB size.
+
+ @return The address of 4 level page map.
+
+**/
+UINTN
+CreateIdentityMappingPageTables (
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
+ )
+{
+ UINT32 RegEax;
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_ECX EcxFlags;
+ UINT32 RegEdx;
+ UINT8 PhysicalAddressBits;
+ EFI_PHYSICAL_ADDRESS PageAddress;
+ UINTN IndexOfPml5Entries;
+ UINTN IndexOfPml4Entries;
+ UINTN IndexOfPdpEntries;
+ UINTN IndexOfPageDirectoryEntries;
+ UINT32 NumberOfPml5EntriesNeeded;
+ UINT32 NumberOfPml4EntriesNeeded;
+ UINT32 NumberOfPdpEntriesNeeded;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel5Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageMap;
+ PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry;
+ PAGE_TABLE_ENTRY *PageDirectoryEntry;
+ UINTN TotalPagesNum;
+ UINTN BigPageAddress;
+ VOID *Hob;
+ BOOLEAN Page5LevelSupport;
+ BOOLEAN Page1GSupport;
+ PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
+ UINT64 AddressEncMask;
+ IA32_CR4 Cr4;
+
+ //
+ // Set PageMapLevel5Entry to suppress incorrect compiler/analyzer warnings
+ //
+ PageMapLevel5Entry = NULL;
+
+ //
+ // Make sure AddressEncMask is contained to smallest supported address field
+ //
+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & PAGING_1G_ADDRESS_MASK_64;
+
+ Page1GSupport = FALSE;
+ if (PcdGetBool(PcdUse1GPageTable)) {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000001) {
+ AsmCpuid (0x80000001, NULL, NULL, NULL, &RegEdx);
+ if ((RegEdx & BIT26) != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+ }
+
+ //
+ // Get physical address bits supported.
+ //
+ Hob = GetFirstHob (EFI_HOB_TYPE_CPU);
+ if (Hob != NULL) {
+ PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;
+ } else {
+ AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= 0x80000008) {
+ AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
+ PhysicalAddressBits = (UINT8) RegEax;
+ } else {
+ PhysicalAddressBits = 36;
+ }
+ }
+
+ Page5LevelSupport = FALSE;
+ if (PcdGetBool (PcdUse5LevelPageTable)) {
+ AsmCpuidEx (
+ CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL,
+ &EcxFlags.Uint32, NULL, NULL
+ );
+ if (EcxFlags.Bits.FiveLevelPage != 0) {
+ Page5LevelSupport = TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "AddressBits=%u 5LevelPaging=%u 1GPage=%u\n", PhysicalAddressBits, Page5LevelSupport, Page1GSupport));
+
+ //
+ // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses
+ // when 5-Level Paging is disabled,
+ // due to either unsupported by HW, or disabled by PCD.
+ //
+ ASSERT (PhysicalAddressBits <= 52);
+ if (!Page5LevelSupport && PhysicalAddressBits > 48) {
+ PhysicalAddressBits = 48;
+ }
+
+ //
+ // Calculate the table entries needed.
+ //
+ NumberOfPml5EntriesNeeded = 1;
+ if (PhysicalAddressBits > 48) {
+ NumberOfPml5EntriesNeeded = (UINT32) LShiftU64 (1, PhysicalAddressBits - 48);
+ PhysicalAddressBits = 48;
+ }
+
+ NumberOfPml4EntriesNeeded = 1;
+ if (PhysicalAddressBits > 39) {
+ NumberOfPml4EntriesNeeded = (UINT32) LShiftU64 (1, PhysicalAddressBits - 39);
+ PhysicalAddressBits = 39;
+ }
+
+ NumberOfPdpEntriesNeeded = 1;
+ ASSERT (PhysicalAddressBits > 30);
+ NumberOfPdpEntriesNeeded = (UINT32) LShiftU64 (1, PhysicalAddressBits - 30);
+
+ //
+ // Pre-allocate big pages to avoid later allocations.
+ //
+ if (!Page1GSupport) {
+ TotalPagesNum = ((NumberOfPdpEntriesNeeded + 1) * NumberOfPml4EntriesNeeded + 1) * NumberOfPml5EntriesNeeded + 1;
+ } else {
+ TotalPagesNum = (NumberOfPml4EntriesNeeded + 1) * NumberOfPml5EntriesNeeded + 1;
+ }
+
+ //
+ // Substract the one page occupied by PML5 entries if 5-Level Paging is disabled.
+ //
+ if (!Page5LevelSupport) {
+ TotalPagesNum--;
+ }
+
+ DEBUG ((DEBUG_INFO, "Pml5=%u Pml4=%u Pdp=%u TotalPage=%Lu\n",
+ NumberOfPml5EntriesNeeded, NumberOfPml4EntriesNeeded,
+ NumberOfPdpEntriesNeeded, (UINT64)TotalPagesNum));
+
+ BigPageAddress = (UINTN) AllocatePageTableMemory (TotalPagesNum);
+ ASSERT (BigPageAddress != 0);
+
+ //
+ // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
+ //
+ PageMap = (VOID *) BigPageAddress;
+ if (Page5LevelSupport) {
+ //
+ // By architecture only one PageMapLevel5 exists - so lets allocate storage for it.
+ //
+ PageMapLevel5Entry = PageMap;
+ BigPageAddress += SIZE_4KB;
+ }
+ PageAddress = 0;
+
+ for ( IndexOfPml5Entries = 0
+ ; IndexOfPml5Entries < NumberOfPml5EntriesNeeded
+ ; IndexOfPml5Entries++) {
+ //
+ // Each PML5 entry points to a page of PML4 entires.
+ // So lets allocate space for them and fill them in in the IndexOfPml4Entries loop.
+ // When 5-Level Paging is disabled, below allocation happens only once.
+ //
+ PageMapLevel4Entry = (VOID *) BigPageAddress;
+ BigPageAddress += SIZE_4KB;
+
+ if (Page5LevelSupport) {
+ //
+ // Make a PML5 Entry
+ //
+ PageMapLevel5Entry->Uint64 = (UINT64) (UINTN) PageMapLevel4Entry | AddressEncMask;
+ PageMapLevel5Entry->Bits.ReadWrite = 1;
+ PageMapLevel5Entry->Bits.Present = 1;
+ PageMapLevel5Entry++;
+ }
+
+ for ( IndexOfPml4Entries = 0
+ ; IndexOfPml4Entries < (NumberOfPml5EntriesNeeded == 1 ? NumberOfPml4EntriesNeeded : 512)
+ ; IndexOfPml4Entries++, PageMapLevel4Entry++) {
+ //
+ // Each PML4 entry points to a page of Page Directory Pointer entires.
+ // So lets allocate space for them and fill them in in the IndexOfPdpEntries loop.
+ //
+ PageDirectoryPointerEntry = (VOID *) BigPageAddress;
+ BigPageAddress += SIZE_4KB;
+
+ //
+ // Make a PML4 Entry
+ //
+ PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry | AddressEncMask;
+ PageMapLevel4Entry->Bits.ReadWrite = 1;
+ PageMapLevel4Entry->Bits.Present = 1;
+
+ if (Page1GSupport) {
+ PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {
+ if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSize, GhcbBase, GhcbSize)) {
+ Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize, GhcbBase, GhcbSize);
+ } else {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectory1GEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;
+ PageDirectory1GEntry->Bits.ReadWrite = 1;
+ PageDirectory1GEntry->Bits.Present = 1;
+ PageDirectory1GEntry->Bits.MustBe1 = 1;
+ }
+ }
+ } else {
+ for ( IndexOfPdpEntries = 0
+ ; IndexOfPdpEntries < (NumberOfPml4EntriesNeeded == 1 ? NumberOfPdpEntriesNeeded : 512)
+ ; IndexOfPdpEntries++, PageDirectoryPointerEntry++) {
+ //
+ // Each Directory Pointer entries points to a page of Page Directory entires.
+ // So allocate space for them and fill them in in the IndexOfPageDirectoryEntries loop.
+ //
+ PageDirectoryEntry = (VOID *) BigPageAddress;
+ BigPageAddress += SIZE_4KB;
+
+ //
+ // Fill in a Page Directory Pointer Entries
+ //
+ PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry | AddressEncMask;
+ PageDirectoryPointerEntry->Bits.ReadWrite = 1;
+ PageDirectoryPointerEntry->Bits.Present = 1;
+
+ for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {
+ if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) {
+ //
+ // Need to split this 2M page that covers NULL or stack range.
+ //
+ Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize);
+ } else {
+ //
+ // Fill in the Page Directory entries
+ //
+ PageDirectoryEntry->Uint64 = (UINT64)PageAddress | AddressEncMask;
+ PageDirectoryEntry->Bits.ReadWrite = 1;
+ PageDirectoryEntry->Bits.Present = 1;
+ PageDirectoryEntry->Bits.MustBe1 = 1;
+ }
+ }
+ }
+
+ //
+ // Fill with null entry for unused PDPTE
+ //
+ ZeroMem (PageDirectoryPointerEntry, (512 - IndexOfPdpEntries) * sizeof(PAGE_MAP_AND_DIRECTORY_POINTER));
+ }
+ }
+
+ //
+ // For the PML4 entries we are not using fill in a null entry.
+ //
+ ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER));
+ }
+
+ if (Page5LevelSupport) {
+ Cr4.UintN = AsmReadCr4 ();
+ Cr4.Bits.LA57 = 1;
+ AsmWriteCr4 (Cr4.UintN);
+ //
+ // For the PML5 entries we are not using fill in a null entry.
+ //
+ ZeroMem (PageMapLevel5Entry, (512 - IndexOfPml5Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER));
+ }
+
+ //
+ // Protect the page table by marking the memory used for page table to be
+ // read-only.
+ //
+ EnablePageTableProtection ((UINTN)PageMap, TRUE);
+
+ //
+ // Set IA32_EFER.NXE if necessary.
+ //
+ if (IsEnableNonExecNeeded ()) {
+ EnableExecuteDisableBit ();
+ }
+
+ return (UINTN)PageMap;
+}
+
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h
new file mode 100644
index 00000000000..0fbbc906db8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h
@@ -0,0 +1,330 @@
+/** @file
+ x64 Long Mode Virtual Memory Management Definitions
+
+ References:
+ 1) IA-32 Intel(R) Architecture Software Developer's Manual Volume 1:Basic Architecture, Intel
+ 2) IA-32 Intel(R) Architecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel
+ 3) IA-32 Intel(R) Architecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel
+ 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef _VIRTUAL_MEMORY_H_
+#define _VIRTUAL_MEMORY_H_
+
+
+#define SYS_CODE64_SEL 0x38
+
+
+#pragma pack(1)
+
+typedef union {
+ struct {
+ UINT32 LimitLow : 16;
+ UINT32 BaseLow : 16;
+ UINT32 BaseMid : 8;
+ UINT32 Type : 4;
+ UINT32 System : 1;
+ UINT32 Dpl : 2;
+ UINT32 Present : 1;
+ UINT32 LimitHigh : 4;
+ UINT32 Software : 1;
+ UINT32 Reserved : 1;
+ UINT32 DefaultSize : 1;
+ UINT32 Granularity : 1;
+ UINT32 BaseHigh : 8;
+ } Bits;
+ UINT64 Uint64;
+} IA32_GDT;
+
+typedef struct {
+ IA32_IDT_GATE_DESCRIPTOR Ia32IdtEntry;
+ UINT32 Offset32To63;
+ UINT32 Reserved;
+} X64_IDT_GATE_DESCRIPTOR;
+
+//
+// Page-Map Level-4 Offset (PML4) and
+// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB
+//
+
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Reserved:1; // Reserved
+ UINT64 MustBeZero:2; // Must Be Zero
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // No Execute bit
+ } Bits;
+ UINT64 Uint64;
+} PAGE_MAP_AND_DIRECTORY_POINTER;
+
+//
+// Page Table Entry 4KB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 PAT:1; //
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PageTableBaseAddress:40; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_4K_ENTRY;
+
+//
+// Page Table Entry 2MB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:8; // Must be zero;
+ UINT64 PageTableBaseAddress:31; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_ENTRY;
+
+//
+// Page Table Entry 1GB
+//
+typedef union {
+ struct {
+ UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory
+ UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write
+ UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User
+ UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching
+ UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached
+ UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU)
+ UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page
+ UINT64 MustBe1:1; // Must be 1
+ UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write
+ UINT64 Available:3; // Available for use by system software
+ UINT64 PAT:1; //
+ UINT64 MustBeZero:17; // Must be zero;
+ UINT64 PageTableBaseAddress:22; // Page Table Base Address
+ UINT64 AvabilableHigh:11; // Available for use by system software
+ UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution
+ } Bits;
+ UINT64 Uint64;
+} PAGE_TABLE_1G_ENTRY;
+
+#pragma pack()
+
+#define CR0_WP BIT16
+
+#define IA32_PG_P BIT0
+#define IA32_PG_RW BIT1
+#define IA32_PG_PS BIT7
+
+#define PAGING_PAE_INDEX_MASK 0x1FF
+
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
+#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
+#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
+
+#define PAGING_L1_ADDRESS_SHIFT 12
+#define PAGING_L2_ADDRESS_SHIFT 21
+#define PAGING_L3_ADDRESS_SHIFT 30
+#define PAGING_L4_ADDRESS_SHIFT 39
+
+#define PAGING_PML4E_NUMBER 4
+
+#define PAGE_TABLE_POOL_ALIGNMENT BASE_2MB
+#define PAGE_TABLE_POOL_UNIT_SIZE SIZE_2MB
+#define PAGE_TABLE_POOL_UNIT_PAGES EFI_SIZE_TO_PAGES (PAGE_TABLE_POOL_UNIT_SIZE)
+#define PAGE_TABLE_POOL_ALIGN_MASK \
+ (~(EFI_PHYSICAL_ADDRESS)(PAGE_TABLE_POOL_ALIGNMENT - 1))
+
+typedef struct {
+ VOID *NextPool;
+ UINTN Offset;
+ UINTN FreePages;
+} PAGE_TABLE_POOL;
+
+/**
+ Check if Execute Disable Bit (IA32_EFER.NXE) should be enabled or not.
+
+ @retval TRUE IA32_EFER.NXE should be enabled.
+ @retval FALSE IA32_EFER.NXE should not be enabled.
+
+**/
+BOOLEAN
+IsEnableNonExecNeeded (
+ VOID
+ );
+
+/**
+ Enable Execute Disable Bit.
+
+**/
+VOID
+EnableExecuteDisableBit (
+ VOID
+ );
+
+/**
+ Split 2M page to 4K.
+
+ @param[in] PhysicalAddress Start physical address the 2M page covered.
+ @param[in, out] PageEntry2M Pointer to 2M page entry.
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
+
+**/
+VOID
+Split2MPageTo4K (
+ IN EFI_PHYSICAL_ADDRESS PhysicalAddress,
+ IN OUT UINT64 *PageEntry2M,
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbSize
+ );
+
+/**
+ Allocates and fills in the Page Directory and Page Table Entries to
+ establish a 1:1 Virtual to Physical mapping.
+
+ @param[in] StackBase Stack base address.
+ @param[in] StackSize Stack size.
+ @param[in] GhcbBase GHCB page area base address.
+ @param[in] GhcbSize GHCB page area size.
+
+ @return The address of 4 level page map.
+
+**/
+UINTN
+CreateIdentityMappingPageTables (
+ IN EFI_PHYSICAL_ADDRESS StackBase,
+ IN UINTN StackSize,
+ IN EFI_PHYSICAL_ADDRESS GhcbBase,
+ IN UINTN GhcbkSize
+ );
+
+
+/**
+
+ Fix up the vector number in the vector code.
+
+ @param VectorBase Base address of the vector handler.
+ @param VectorNum Index of vector.
+
+**/
+VOID
+EFIAPI
+AsmVectorFixup (
+ VOID *VectorBase,
+ UINT8 VectorNum
+ );
+
+
+/**
+
+ Get the information of vector template.
+
+ @param TemplateBase Base address of the template code.
+
+ @return Size of the Template code.
+
+**/
+UINTN
+EFIAPI
+AsmGetVectorTemplatInfo (
+ OUT VOID **TemplateBase
+ );
+
+/**
+ Clear legacy memory located at the first 4K-page.
+
+ This function traverses the whole HOB list to check if memory from 0 to 4095
+ exists and has not been allocated, and then clear it if so.
+
+ @param HobStart The start of HobList passed to DxeCore.
+
+**/
+VOID
+ClearFirst4KPage (
+ IN VOID *HobStart
+ );
+
+/**
+ Return configure status of NULL pointer detection feature.
+
+ @return TRUE NULL pointer detection feature is enabled
+ @return FALSE NULL pointer detection feature is disabled
+**/
+BOOLEAN
+IsNullDetectionEnabled (
+ VOID
+ );
+
+/**
+ Prevent the memory pages used for page table from been overwritten.
+
+ @param[in] PageTableBase Base address of page table (CR3).
+ @param[in] Level4Paging Level 4 paging flag.
+
+**/
+VOID
+EnablePageTableProtection (
+ IN UINTN PageTableBase,
+ IN BOOLEAN Level4Paging
+ );
+
+/**
+ This API provides a way to allocate memory for page table.
+
+ This API can be called more than once to allocate memory for page tables.
+
+ Allocates the number of 4KB pages 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 remaining 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 *
+AllocatePageTableMemory (
+ IN UINTN Pages
+ );
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec
index ef5e7645ab0..73e835d9572 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dec
@@ -3,7 +3,7 @@
#
# Provides drivers and definitions to create uefi payload for bootloaders.
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -68,4 +68,5 @@ gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiReservedMemoryType|0x04|UINT32|0x0
gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesData|0xC0|UINT32|0x00000015
gUefiPayloadPkgTokenSpaceGuid.PcdMemoryTypeEfiRuntimeServicesCode|0x80|UINT32|0x00000016
-
+# Size of the region used by UEFI in permanent memory
+gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x02000000|UINT32|0x00000017
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dsc
index 8008d93acb2..8fcf3871704 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32X64.dsc
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -3,7 +3,8 @@
#
# Provides drivers and definitions to create uefi payload for bootloaders.
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@@ -41,7 +42,7 @@
#
# PCI options
#
- DEFINE PCIE_BASE = 0xE0000000
+ DEFINE PCIE_BASE_SUPPORT = TRUE
#
# Serial port set up
@@ -59,6 +60,9 @@
DEFINE UART_DEFAULT_STOP_BITS = 1
DEFINE DEFAULT_TERMINAL_TYPE = 0
+ # Enabling the serial terminal will slow down the boot menu redering!
+ DEFINE DISABLE_SERIAL_TERMINAL = FALSE
+
#
# typedef struct {
# UINT16 VendorId; ///< Vendor ID to match the PCI device. The value 0xFFFF terminates the list of entries.
@@ -89,6 +93,12 @@
INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
+[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
################################################################################
#
@@ -103,12 +113,13 @@
# Library Class section - list of all Library Classes needed by this Platform.
#
################################################################################
+
+!include MdePkg/MdeLibs.dsc.inc
+
[LibraryClasses]
#
# Entry point
#
- PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
- PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
@@ -122,17 +133,19 @@
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-!if $(PCIE_BASE) == 0
+!if $(PCIE_BASE_SUPPORT) == FALSE
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
!else
PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
!endif
- PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
+ PciSegmentLib|MdePkg/Library/PciSegmentLibSegmentInfo/BasePciSegmentLibSegmentInfo.inf
+ PciSegmentInfoLib|UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
#
# UEFI & PI
@@ -145,8 +158,6 @@
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
- PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
- PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
@@ -169,6 +180,7 @@
#
MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
+ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf
#
# Platform
@@ -205,24 +217,12 @@
AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf
+ VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
-[LibraryClasses.IA32.SEC]
- DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+[LibraryClasses.common.SEC]
+ HobLib|UefiPayloadPkg/Library/HobLib/HobLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
- MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
- DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
- ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
-
-[LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.PEIM]
- PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
- HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
- MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
- ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
- ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
-!if $(SOURCE_DEBUG_ENABLE)
- DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
-!endif
[LibraryClasses.common.DXE_CORE]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
@@ -234,6 +234,7 @@
DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
!endif
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
[LibraryClasses.common.DXE_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -246,12 +247,14 @@
!endif
CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+ VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf
[LibraryClasses.common.DXE_RUNTIME_DRIVER]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
+ VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf
[LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION]
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
@@ -265,12 +268,6 @@
#
################################################################################
[PcdsFeatureFlag]
-!if $(TARGET) == DEBUG
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
-!else
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
-!endif
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
@@ -285,10 +282,15 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
+!if $(TARGET) == DEBUG
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
+!else
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
+!endif
+ gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
- gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|$(PCIE_BASE)
!if $(SOURCE_DEBUG_ENABLE)
gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
@@ -307,7 +309,7 @@
# The following parameters are set by Library/PlatformHookLib
#
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x3f8
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|$(BAUD_RATE)
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1
@@ -359,35 +361,22 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31
gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|0
+ gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseSize|0
################################################################################
#
# Components Section - list of all EDK II Modules needed by this Platform.
#
################################################################################
-[Components.IA32]
- #
- # SEC Core
- #
- UefiPayloadPkg/SecCore/SecCore.inf
-
- #
- # PEI Core
- #
- MdeModulePkg/Core/Pei/PeiMain.inf
-
- #
- # PEIM
- #
- MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
- <LibraryClasses>
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- }
- MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
- MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
- UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+!if "IA32" in $(ARCH)
+ [Components.IA32]
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+!else
+ [Components.X64]
+ UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
+!endif
[Components.X64]
#
@@ -471,6 +460,7 @@
MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+ MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
#
# SD/eMMC Support
@@ -504,7 +494,9 @@
MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+!if $(DISABLE_SERIAL_TERMINAL) == FALSE
MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+!endif
UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
#------------------------------
@@ -569,6 +561,7 @@
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf
index 574665c1102..715a6515998 100644
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf
+++ b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkg.fdf
@@ -3,28 +3,38 @@
#
# Provides drivers and definitions to create uefi payload for bootloaders.
#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2014 - 2020, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
+[Defines]
+DEFINE FD_BASE = 0x00800000
+DEFINE FD_BLOCK_SIZE = 0x00001000
+
+!if $(TARGET) == "NOOPT"
+DEFINE FD_SIZE = 0x00850000
+DEFINE NUM_BLOCKS = 0x850
+!else
+
+DEFINE FD_SIZE = 0x00410000
+DEFINE NUM_BLOCKS = 0x410
+!endif
+
################################################################################
[FD.UefiPayload]
-BaseAddress = 0x800000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
-Size = 0x410000|gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
+BaseAddress = $(FD_BASE) | gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase
+Size = $(FD_SIZE) | gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize
ErasePolarity = 1
-BlockSize = 0x1000
-NumBlocks = 0x410
-
-0x00000000|0x030000
-FV = PEIFV
+BlockSize = $(FD_BLOCK_SIZE)
+NumBlocks = $(NUM_BLOCKS)
-0x00030000|0x3E0000
-FV = DXEFV
+0x00000000|$(FD_SIZE)
+FV = PLDFV
################################################################################
-[FV.PEIFV]
-BlockSize = 0x1000
+[FV.PLDFV]
+BlockSize = $(FD_BLOCK_SIZE)
FvAlignment = 16
ERASE_POLARITY = 1
MEMORY_MAPPED = TRUE
@@ -42,19 +52,16 @@ READ_STATUS = TRUE
READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
-INF UefiPayloadPkg/SecCore/SecCore.inf
+INF UefiPayloadPkg/UefiPayloadEntry/UefiPayloadEntry.inf
-INF MdeModulePkg/Core/Pei/PeiMain.inf
-INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
-INF MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
-INF MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
-INF UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
-INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+FILE FV_IMAGE = 4E35FD93-9C72-4c15-8C4B-E77F1DB2D793 {
+ SECTION FV_IMAGE = DXEFV
+}
################################################################################
[FV.DXEFV]
-BlockSize = 0x1000
+BlockSize = $(FD_BLOCK_SIZE)
FvForceRebase = FALSE
FvAlignment = 16
ERASE_POLARITY = 1
@@ -74,9 +81,9 @@ READ_LOCK_CAP = TRUE
READ_LOCK_STATUS = TRUE
APRIORI DXE {
+ INF MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
INF MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
- INF MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
- INF MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
+ INF UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
}
#
@@ -131,7 +138,9 @@ INF MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
INF MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
INF MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
INF MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
+!if $(DISABLE_SERIAL_TERMINAL) == FALSE
INF MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
+!endif
INF UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
#
@@ -145,6 +154,7 @@ INF MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
INF MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
INF MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
INF MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
+INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
INF FatPkg/EnhancedFatDxe/Fat.inf
diff --git a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32.dsc b/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
deleted file mode 100644
index f8f0199591d..00000000000
--- a/src/VBox/Devices/EFI/Firmware/UefiPayloadPkg/UefiPayloadPkgIa32.dsc
+++ /dev/null
@@ -1,576 +0,0 @@
-## @file
-# Bootloader Payload Package
-#
-# Provides drivers and definitions to create uefi payload for bootloaders.
-#
-# Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-##
-
-################################################################################
-#
-# Defines Section - statements that will be processed to create a Makefile.
-#
-################################################################################
-[Defines]
- PLATFORM_NAME = UefiPayloadPkg
- PLATFORM_GUID = F71608AB-D63D-4491-B744-A99998C8CD96
- PLATFORM_VERSION = 0.1
- DSC_SPECIFICATION = 0x00010005
- SUPPORTED_ARCHITECTURES = IA32
- BUILD_TARGETS = DEBUG|RELEASE|NOOPT
- SKUID_IDENTIFIER = DEFAULT
- OUTPUT_DIRECTORY = Build/UefiPayloadPkgIA32
- FLASH_DEFINITION = UefiPayloadPkg/UefiPayloadPkg.fdf
-
- DEFINE SOURCE_DEBUG_ENABLE = FALSE
-
- #
- # SBL: UEFI payload for Slim Bootloader
- # COREBOOT: UEFI payload for coreboot
- #
- DEFINE BOOTLOADER = SBL
-
- #
- # CPU options
- #
- DEFINE MAX_LOGICAL_PROCESSORS = 64
-
- #
- # PCI options
- #
- DEFINE PCIE_BASE = 0xE0000000
-
- #
- # Serial port set up
- #
- DEFINE BAUD_RATE = 115200
- DEFINE SERIAL_CLOCK_RATE = 1843200
- DEFINE SERIAL_LINE_CONTROL = 3 # 8-bits, no parity
- DEFINE SERIAL_HARDWARE_FLOW_CONTROL = FALSE
- DEFINE SERIAL_DETECT_CABLE = FALSE
- DEFINE SERIAL_FIFO_CONTROL = 7 # Enable FIFO
- DEFINE SERIAL_EXTENDED_TX_FIFO_SIZE = 16
- DEFINE UART_DEFAULT_BAUD_RATE = $(BAUD_RATE)
- DEFINE UART_DEFAULT_DATA_BITS = 8
- DEFINE UART_DEFAULT_PARITY = 1
- DEFINE UART_DEFAULT_STOP_BITS = 1
- DEFINE DEFAULT_TERMINAL_TYPE = 0
-
- #
- # typedef struct {
- # UINT16 VendorId; ///< Vendor ID to match the PCI device. The value 0xFFFF terminates the list of entries.
- # UINT16 DeviceId; ///< Device ID to match the PCI device
- # UINT32 ClockRate; ///< UART clock rate. Set to 0 for default clock rate of 1843200 Hz
- # UINT64 Offset; ///< The byte offset into to the BAR
- # UINT8 BarIndex; ///< Which BAR to get the UART base address
- # UINT8 RegisterStride; ///< UART register stride in bytes. Set to 0 for default register stride of 1 byte.
- # UINT16 ReceiveFifoDepth; ///< UART receive FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes.
- # UINT16 TransmitFifoDepth; ///< UART transmit FIFO depth in bytes. Set to 0 for a default FIFO depth of 16 bytes.
- # UINT8 Reserved[2];
- # } PCI_SERIAL_PARAMETER;
- #
- # Vendor FFFF Device 0000 Prog Interface 1, BAR #0, Offset 0, Stride = 1, Clock 1843200 (0x1c2000)
- #
- # [Vendor] [Device] [----ClockRate---] [------------Offset-----------] [Bar] [Stride] [RxFifo] [TxFifo] [Rsvd] [Vendor]
- DEFINE PCI_SERIAL_PARAMETERS = {0xff,0xff, 0x00,0x00, 0x0,0x20,0x1c,0x00, 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, 0x00, 0x01, 0x0,0x0, 0x0,0x0, 0x0,0x0, 0xff,0xff}
-
- #
- # Shell options: [BUILD_SHELL, MIN_BIN, NONE, UEFI_BIN]
- #
- DEFINE SHELL_TYPE = BUILD_SHELL
-
-[BuildOptions]
- *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
- GCC:*_UNIXGCC_*_CC_FLAGS = -DMDEPKG_NDEBUG
- GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
- INTEL:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
- MSFT:RELEASE_*_*_CC_FLAGS = /D MDEPKG_NDEBUG
-
-
-################################################################################
-#
-# SKU Identification section - list of all SKU IDs supported by this Platform.
-#
-################################################################################
-[SkuIds]
- 0|DEFAULT
-
-################################################################################
-#
-# Library Class section - list of all Library Classes needed by this Platform.
-#
-################################################################################
-[LibraryClasses]
- #
- # Entry point
- #
- PeiCoreEntryPoint|MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
- PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
- DxeCoreEntryPoint|MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
- UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
- UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
-
- #
- # Basic
- #
- BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
- BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
- SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
- PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
- CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
- IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
-!if $(PCIE_BASE) == 0
- PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
- PciCf8Lib|MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.inf
-!else
- PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
- PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
-!endif
- PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
- PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
- PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
- CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
-
- #
- # UEFI & PI
- #
- UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
- UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
- UefiRuntimeLib|MdePkg/Library/UefiRuntimeLib/UefiRuntimeLib.inf
- UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
- UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
- HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
- DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
- UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
- PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLibIdt/PeiServicesTablePointerLibIdt.inf
- PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
- DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
- DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
- UefiCpuLib|UefiCpuPkg/Library/BaseUefiCpuLib/BaseUefiCpuLib.inf
- SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
-
- #
- # Generic Modules
- #
- UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
- UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
- OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
- CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
- SecurityManagementLib|MdeModulePkg/Library/DxeSecurityManagementLib/DxeSecurityManagementLib.inf
- UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
- CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
- FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
-
- #
- # CPU
- #
- MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
- LocalApicLib|UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.inf
-
- #
- # Platform
- #
- TimerLib|UefiPayloadPkg/Library/AcpiTimerLib/AcpiTimerLib.inf
- ResetSystemLib|UefiPayloadPkg/Library/ResetSystemLib/ResetSystemLib.inf
- SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
- PlatformHookLib|UefiPayloadPkg/Library/PlatformHookLib/PlatformHookLib.inf
- PlatformBootManagerLib|UefiPayloadPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
- IoApicLib|PcAtChipsetPkg/Library/BaseIoApicLib/BaseIoApicLib.inf
-
- #
- # Misc
- #
- DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
- PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
-!if $(SOURCE_DEBUG_ENABLE) == TRUE
- PeCoffExtraActionLib|SourceLevelDebugPkg/Library/PeCoffExtraActionLibDebug/PeCoffExtraActionLibDebug.inf
- DebugCommunicationLib|SourceLevelDebugPkg/Library/DebugCommunicationLibSerialPort/DebugCommunicationLibSerialPort.inf
-!else
- PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
- DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
-!endif
- PlatformSupportLib|UefiPayloadPkg/Library/PlatformSupportLibNull/PlatformSupportLibNull.inf
-!if $(BOOTLOADER) == "COREBOOT"
- BlParseLib|UefiPayloadPkg/Library/CbParseLib/CbParseLib.inf
-!else
- BlParseLib|UefiPayloadPkg/Library/SblParseLib/SblParseLib.inf
-!endif
-
- DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
- LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
- FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
- AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
- TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
- VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf
-
-[LibraryClasses.IA32.SEC]
- DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
- MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
- DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
- ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
-
-[LibraryClasses.IA32.PEI_CORE, LibraryClasses.IA32.PEIM]
- PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
- HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
- MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
- ReportStatusCodeLib|MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
- ExtractGuidedSectionLib|MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
-!if $(SOURCE_DEBUG_ENABLE)
- DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/SecPeiDebugAgentLib.inf
-!endif
-
-[LibraryClasses.common.DXE_CORE]
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
- MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
- ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
- ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
-!if $(SOURCE_DEBUG_ENABLE)
- DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
-!endif
- CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
-
-[LibraryClasses.common.DXE_DRIVER]
- PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
- HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
- MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
- ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
- ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
-!if $(SOURCE_DEBUG_ENABLE)
- DebugAgentLib|SourceLevelDebugPkg/Library/DebugAgent/DxeDebugAgentLib.inf
-!endif
- CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
- MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
-
-[LibraryClasses.common.DXE_RUNTIME_DRIVER]
- PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
- HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
- MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
- ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf
-
-[LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION]
- PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
- MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
- ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
- HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
-
-################################################################################
-#
-# Pcd Section - list of all EDK II PCD Entries defined by this Platform.
-#
-################################################################################
-[PcdsFeatureFlag]
-!if $(TARGET) == DEBUG
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|TRUE
-!else
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseSerial|FALSE
-!endif
- gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeUseMemory|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdConOutGopSupport|TRUE
- gEfiMdeModulePkgTokenSpaceGuid.PcdConOutUgaSupport|FALSE
-
-[PcdsFixedAtBuild]
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x10000
- gEfiMdeModulePkgTokenSpaceGuid.PcdMaxHardwareErrorVariableSize|0x8000
- gEfiMdeModulePkgTokenSpaceGuid.PcdVariableStoreSize|0x10000
- #
- # Make VariableRuntimeDxe work at emulated non-volatile variable mode.
- #
- gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvModeEnable|TRUE
-
- gEfiMdeModulePkgTokenSpaceGuid.PcdVpdBaseAddress|0x0
- gEfiMdeModulePkgTokenSpaceGuid.PcdBootManagerMenuFile|{ 0x21, 0xaa, 0x2c, 0x46, 0x14, 0x76, 0x03, 0x45, 0x83, 0x6e, 0x8a, 0xb6, 0xf4, 0x66, 0x23, 0x31 }
-
- gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress|$(PCIE_BASE)
-
-!if $(SOURCE_DEBUG_ENABLE)
- gEfiSourceLevelDebugPkgTokenSpaceGuid.PcdDebugLoadImageMethod|0x2
-!endif
-
-[PcdsPatchableInModule.common]
- gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x7
- gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
-!if $(SOURCE_DEBUG_ENABLE)
- gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
-!else
- gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
-!endif
-
- #
- # The following parameters are set by Library/PlatformHookLib
- #
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|FALSE
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x3f8
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialBaudRate|$(BAUD_RATE)
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterStride|1
-
- #
- # Enable these parameters to be set on the command line
- #
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialClockRate|$(SERIAL_CLOCK_RATE)
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialLineControl|$(SERIAL_LINE_CONTROL)
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseHardwareFlowControl|$(SERIAL_HARDWARE_FLOW_CONTROL)
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialDetectCable|$(SERIAL_DETECT_CABLE)
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialFifoControl|$(SERIAL_FIFO_CONTROL)
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialExtendedTxFifoSize|$(SERIAL_EXTENDED_TX_FIFO_SIZE)
-
- gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE
- gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate|$(UART_DEFAULT_BAUD_RATE)
- gEfiMdePkgTokenSpaceGuid.PcdUartDefaultDataBits|$(UART_DEFAULT_DATA_BITS)
- gEfiMdePkgTokenSpaceGuid.PcdUartDefaultParity|$(UART_DEFAULT_PARITY)
- gEfiMdePkgTokenSpaceGuid.PcdUartDefaultStopBits|$(UART_DEFAULT_STOP_BITS)
- gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|$(DEFAULT_TERMINAL_TYPE)
- gEfiMdeModulePkgTokenSpaceGuid.PcdPciSerialParameters|$(PCI_SERIAL_PARAMETERS)
-
- gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|$(MAX_LOGICAL_PROCESSORS)
-
-
-################################################################################
-#
-# Pcd Dynamic Section - list of all EDK II PCD Entries defined by this Platform
-#
-################################################################################
-
-[PcdsDynamicDefault]
- gEfiMdeModulePkgTokenSpaceGuid.PcdEmuVariableNvStoreReserved|0
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64|0
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|0
- gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|0
- gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3
-
- ## This PCD defines the video horizontal resolution.
- # This PCD could be set to 0 then video resolution could be at highest resolution.
- gEfiMdeModulePkgTokenSpaceGuid.PcdVideoHorizontalResolution|0
- ## This PCD defines the video vertical resolution.
- # This PCD could be set to 0 then video resolution could be at highest resolution.
- gEfiMdeModulePkgTokenSpaceGuid.PcdVideoVerticalResolution|0
-
- ## The PCD is used to specify the video horizontal resolution of text setup.
- gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoHorizontalResolution|0
- ## The PCD is used to specify the video vertical resolution of text setup.
- gEfiMdeModulePkgTokenSpaceGuid.PcdSetupVideoVerticalResolution|0
-
- gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow|31
- gEfiMdeModulePkgTokenSpaceGuid.PcdConOutColumn|100
-
-################################################################################
-#
-# Components Section - list of all EDK II Modules needed by this Platform.
-#
-################################################################################
-[Components.IA32]
- #
- # SEC Core
- #
- UefiPayloadPkg/SecCore/SecCore.inf
-
- #
- # PEI Core
- #
- MdeModulePkg/Core/Pei/PeiMain.inf
-
- #
- # PEIM
- #
- MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
- <LibraryClasses>
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- }
- MdeModulePkg/Universal/ReportStatusCodeRouter/Pei/ReportStatusCodeRouterPei.inf
- MdeModulePkg/Universal/StatusCodeHandler/Pei/StatusCodeHandlerPei.inf
-
- UefiPayloadPkg/BlSupportPei/BlSupportPei.inf
- MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
-
-[Components.IA32]
- #
- # DXE Core
- #
- MdeModulePkg/Core/Dxe/DxeMain.inf {
- <LibraryClasses>
- NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
- }
-
- #
- # Components that produce the architectural protocols
- #
- MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
- UefiCpuPkg/CpuDxe/CpuDxe.inf
- MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
- MdeModulePkg/Application/UiApp/UiApp.inf {
- <LibraryClasses>
- NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
- NULL|MdeModulePkg/Library/BootManagerUiLib/BootManagerUiLib.inf
- NULL|MdeModulePkg/Library/BootMaintenanceManagerUiLib/BootMaintenanceManagerUiLib.inf
- }
-
- PcAtChipsetPkg/HpetTimerDxe/HpetTimerDxe.inf
- MdeModulePkg/Universal/Metronome/Metronome.inf
- MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
- MdeModulePkg/Core/RuntimeDxe/RuntimeDxe.inf
- MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
- MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
- MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
- PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
- MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
-
- #
- # Following are the DXE drivers
- #
- MdeModulePkg/Universal/PCD/Dxe/Pcd.inf {
- <LibraryClasses>
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
- }
-
- MdeModulePkg/Universal/ReportStatusCodeRouter/RuntimeDxe/ReportStatusCodeRouterRuntimeDxe.inf
- MdeModulePkg/Universal/StatusCodeHandler/RuntimeDxe/StatusCodeHandlerRuntimeDxe.inf
- UefiCpuPkg/CpuIo2Dxe/CpuIo2Dxe.inf
- MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
- MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf
- MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf
- MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf
- MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf
-
- UefiPayloadPkg/BlSupportDxe/BlSupportDxe.inf
-
- #
- # SMBIOS Support
- #
- MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf
-
- #
- # ACPI Support
- #
- MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf
-
- #
- # PCI Support
- #
- MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
- MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
- <LibraryClasses>
- PciHostBridgeLib|UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
- }
-
- #
- # SCSI/ATA/IDE/DISK Support
- #
- MdeModulePkg/Universal/Disk/DiskIoDxe/DiskIoDxe.inf
- MdeModulePkg/Universal/Disk/PartitionDxe/PartitionDxe.inf
- MdeModulePkg/Universal/Disk/UnicodeCollation/EnglishDxe/EnglishDxe.inf
- FatPkg/EnhancedFatDxe/Fat.inf
- MdeModulePkg/Bus/Pci/SataControllerDxe/SataControllerDxe.inf
- MdeModulePkg/Bus/Ata/AtaBusDxe/AtaBusDxe.inf
- MdeModulePkg/Bus/Ata/AtaAtapiPassThru/AtaAtapiPassThru.inf
- MdeModulePkg/Bus/Scsi/ScsiBusDxe/ScsiBusDxe.inf
- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDiskDxe.inf
-
- #
- # SD/eMMC Support
- #
- MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
- MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
- MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
-
- #
- # Usb Support
- #
- MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
- MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
- MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
- MdeModulePkg/Bus/Usb/UsbBusDxe/UsbBusDxe.inf
- MdeModulePkg/Bus/Usb/UsbKbDxe/UsbKbDxe.inf
- MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
-
- #
- # ISA Support
- #
- MdeModulePkg/Universal/SerialDxe/SerialDxe.inf
-!if $(PS2_KEYBOARD_ENABLE) == TRUE
- OvmfPkg/SioBusDxe/SioBusDxe.inf
- MdeModulePkg/Bus/Isa/Ps2KeyboardDxe/Ps2KeyboardDxe.inf
-!endif
-
- #
- # Console Support
- #
- MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe.inf
- MdeModulePkg/Universal/Console/ConSplitterDxe/ConSplitterDxe.inf
- MdeModulePkg/Universal/Console/GraphicsConsoleDxe/GraphicsConsoleDxe.inf
- MdeModulePkg/Universal/Console/TerminalDxe/TerminalDxe.inf
- UefiPayloadPkg/GraphicsOutputDxe/GraphicsOutputDxe.inf
-
- #------------------------------
- # Build the shell
- #------------------------------
-
-!if $(SHELL_TYPE) == BUILD_SHELL
-
- #
- # Shell Lib
- #
-[LibraryClasses]
- BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
- DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
- FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
- ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
- !include NetworkPkg/NetworkLibs.dsc.inc
-
-[Components.IA32]
- ShellPkg/DynamicCommand/TftpDynamicCommand/TftpDynamicCommand.inf {
- <PcdsFixedAtBuild>
- ## This flag is used to control initialization of the shell library
- # This should be FALSE for compiling the dynamic command.
- gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
- }
- ShellPkg/DynamicCommand/DpDynamicCommand/DpDynamicCommand.inf {
- <PcdsFixedAtBuild>
- ## This flag is used to control initialization of the shell library
- # This should be FALSE for compiling the dynamic command.
- gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
- }
- ShellPkg/Application/Shell/Shell.inf {
- <PcdsFixedAtBuild>
- ## This flag is used to control initialization of the shell library
- # This should be FALSE for compiling the shell application itself only.
- gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
-
- #------------------------------
- # Basic commands
- #------------------------------
-
- <LibraryClasses>
- NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
- NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
- NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
- NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
- NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
- NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
-
- #------------------------------
- # Networking commands
- #------------------------------
-
- <LibraryClasses>
- NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
-
- #------------------------------
- # Support libraries
- #------------------------------
-
- <LibraryClasses>
- DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
- DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
- HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
- PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf
- ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
- ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
- SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
- }
-
-!endif
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c
new file mode 100644
index 00000000000..e262e5239d8
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.c
@@ -0,0 +1,49 @@
+/** @file
+ Unit Test Debug Assert Library
+
+ Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/BaseLib.h>
+#include <Library/UnitTestLib.h>
+
+///
+/// Point to jump buffer used with SetJump()/LongJump() to test if a function
+/// under test generates an expected ASSERT() condition.
+///
+BASE_LIBRARY_JUMP_BUFFER *gUnitTestExpectAssertFailureJumpBuffer = NULL;
+
+/**
+ Unit test library replacement for DebugAssert() in DebugLib.
+
+ If FileName is NULL, then a <FileName> string of "(NULL) Filename" is printed.
+ If Description is NULL, then a <Description> string of "(NULL) Description" is printed.
+
+ @param FileName The pointer to the name of the source file that generated the assert condition.
+ @param LineNumber The line number in the source file that generated the assert condition
+ @param Description The pointer to the description of the assert condition.
+
+**/
+VOID
+EFIAPI
+UnitTestDebugAssert (
+ IN CONST CHAR8 *FileName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *Description
+ )
+{
+ CHAR8 Message[256];
+
+ if (gUnitTestExpectAssertFailureJumpBuffer != NULL) {
+ UT_LOG_INFO ("Detected expected ASSERT: %a(%d): %a\n", FileName, LineNumber, Description);
+ LongJump (gUnitTestExpectAssertFailureJumpBuffer, 1);
+ } else {
+ AsciiStrCpyS (Message, sizeof(Message), "Detected unexpected ASSERT(");
+ AsciiStrCatS (Message, sizeof(Message), Description);
+ AsciiStrCatS (Message, sizeof(Message), ")");
+ UnitTestAssertTrue (FALSE, "", LineNumber, FileName, Message);
+ }
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf
new file mode 100644
index 00000000000..4e9a3d9510d
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf
@@ -0,0 +1,31 @@
+## @file
+# Unit Test Debug Assert Library
+#
+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UnitTestDebugAssertLib
+ MODULE_UNI_FILE = UnitTestDebugAssertLib.uni
+ FILE_GUID = 9D53AD0D-5416-451F-A5BF-E5420051A99B
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL
+
+#
+# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+ UnitTestDebugAssertLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UnitTestLib
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni
new file mode 100644
index 00000000000..9b794aa2059
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.uni
@@ -0,0 +1,11 @@
+// /** @file
+// Unit Test Debug Assert Library
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT #language en-US "Unit Test Debug Assert Library"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Unit Test Debug Assert Library"
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c
index 9be4f0ef367..2def1318ce0 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/Assert.c
@@ -13,6 +13,8 @@
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
+extern BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer;
+
STATIC
EFI_STATUS
AddUnitTestFailure (
@@ -40,6 +42,7 @@ AddUnitTestFailure (
STATIC
VOID
+EFIAPI
UnitTestLogFailure (
IN FAILURE_TYPE FailureType,
IN CONST CHAR8 *Format,
@@ -71,7 +74,7 @@ UnitTestLogFailure (
FailureType
);
- return;
+ LongJump (&gUnitTestJumpBuffer, 1);
}
/**
@@ -103,16 +106,16 @@ UnitTestAssertTrue (
)
{
if (!Expression) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTTRUE,
- "%a::%d Expression (%a) is not TRUE!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Expression (%a) is not TRUE!\n",
+ FileName,
LineNumber,
Description
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Expression (%a) is not TRUE!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTTRUE,
+ "%a:%d: Expression (%a) is not TRUE!\n",
+ FileName,
LineNumber,
Description
);
@@ -149,16 +152,16 @@ UnitTestAssertFalse (
)
{
if (Expression) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTFALSE,
- "%a::%d Expression(%a) is not FALSE!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Expression (%a) is not FALSE!\n",
+ FileName,
LineNumber,
Description
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Expression (%a) is not FALSE!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTFALSE,
+ "%a:%d: Expression(%a) is not FALSE!\n",
+ FileName,
LineNumber,
Description
);
@@ -195,17 +198,17 @@ UnitTestAssertNotEfiError (
)
{
if (EFI_ERROR (Status)) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTNOTEFIERROR,
- "%a::%d Status '%a' is EFI_ERROR (%r)!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Status '%a' is EFI_ERROR (%r)!\n",
+ FileName,
LineNumber,
Description,
Status
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Status '%a' is EFI_ERROR (%r)!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTNOTEFIERROR,
+ "%a:%d: Status '%a' is EFI_ERROR (%r)!\n",
+ FileName,
LineNumber,
Description,
Status
@@ -248,19 +251,19 @@ UnitTestAssertEqual (
)
{
if (ValueA != ValueB) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTEQUAL,
- "%a::%d Value %a != %a (%d != %d)!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Value %a != %a (%d != %d)!\n",
+ FileName,
LineNumber,
DescriptionA,
DescriptionB,
ValueA,
ValueB
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Value %a != %a (%d != %d)!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTEQUAL,
+ "%a:%d: Value %a != %a (%d != %d)!\n",
+ FileName,
LineNumber,
DescriptionA,
DescriptionB,
@@ -310,18 +313,18 @@ UnitTestAssertMemEqual (
)
{
if (CompareMem(BufferA, BufferB, Length) != 0) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTEQUAL,
- "%a::%d Memory at %a != %a for length %d bytes!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Value %a != %a for length %d bytes!\n",
+ FileName,
LineNumber,
DescriptionA,
DescriptionB,
Length
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Value %a != %a for length %d bytes!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTEQUAL,
+ "%a:%d: Memory at %a != %a for length %d bytes!\n",
+ FileName,
LineNumber,
DescriptionA,
DescriptionB,
@@ -366,19 +369,19 @@ UnitTestAssertNotEqual (
)
{
if (ValueA == ValueB) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTNOTEQUAL,
- "%a::%d Value %a == %a (%d == %d)!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Value %a == %a (%d == %d)!\n",
+ FileName,
LineNumber,
DescriptionA,
DescriptionB,
ValueA,
ValueB
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Value %a == %a (%d == %d)!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTNOTEQUAL,
+ "%a:%d: Value %a == %a (%d == %d)!\n",
+ FileName,
LineNumber,
DescriptionA,
DescriptionB,
@@ -421,18 +424,18 @@ UnitTestAssertStatusEqual (
)
{
if (Status != Expected) {
- UnitTestLogFailure (
- FAILURETYPE_ASSERTSTATUSEQUAL,
- "%a::%d Status '%a' is %r, should be %r!\n",
- FunctionName,
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Status '%a' is %r, should be %r!\n",
+ FileName,
LineNumber,
Description,
Status,
Expected
);
- UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Status '%a' is %r, should be %r!\n",
- FunctionName,
+ UnitTestLogFailure (
+ FAILURETYPE_ASSERTSTATUSEQUAL,
+ "%a:%d: Status '%a' is %r, should be %r!\n",
+ FileName,
LineNumber,
Description,
Status,
@@ -473,19 +476,96 @@ UnitTestAssertNotNull (
)
{
if (Pointer == NULL) {
+ UT_LOG_ERROR (
+ "[ASSERT FAIL] %a:%d: Pointer (%a) is NULL!\n",
+ FileName,
+ LineNumber,
+ PointerName
+ );
UnitTestLogFailure (
FAILURETYPE_ASSERTNOTNULL,
- "%a::%d Pointer (%a) is NULL!\n",
- FunctionName,
+ "%a:%d: Pointer (%a) is NULL!\n",
+ FileName,
LineNumber,
PointerName
);
+ }
+ return (Pointer != NULL);
+}
+
+/**
+ If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return
+ TRUE because an ASSERT() was expected when FunctionCall was executed and an
+ ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a
+ warning message and return TRUE because ASSERT() macros are disabled. If
+ UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and
+ return FALSE because an ASSERT() was expected when FunctionCall was executed,
+ but no ASSERT() conditions were triggered. The log messages contain
+ FunctionName, LineNumber, and FileName strings to provide the location of the
+ UT_EXPECT_ASSERT_FAILURE() macro.
+
+ @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that
+ is either pass, skipped, or failed.
+ @param[in] FunctionName Null-terminated ASCII string of the function
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] LineNumber The source file line number of the the function
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] FileName Null-terminated ASCII string of the filename
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] FunctionCall Null-terminated ASCII string of the function call
+ executed by the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[out] ResultStatus Used to return the UnitTestStatus value to the
+ caller of UT_EXPECT_ASSERT_FAILURE(). This is
+ optional parameter that may be NULL.
+
+ @retval TRUE UnitTestStatus is UNIT_TEST_PASSED.
+ @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED.
+ @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.
+**/
+BOOLEAN
+EFIAPI
+UnitTestExpectAssertFailure (
+ IN UNIT_TEST_STATUS UnitTestStatus,
+ IN CONST CHAR8 *FunctionName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *FileName,
+ IN CONST CHAR8 *FunctionCall,
+ OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL
+ )
+{
+ if (ResultStatus != NULL) {
+ *ResultStatus = UnitTestStatus;
+ }
+ if (UnitTestStatus == UNIT_TEST_PASSED) {
+ UT_LOG_INFO (
+ "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n",
+ FileName,
+ LineNumber,
+ FunctionCall
+ );
+ }
+ if (UnitTestStatus == UNIT_TEST_SKIPPED) {
+ UT_LOG_WARNING (
+ "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n",
+ FileName,
+ LineNumber,
+ FunctionCall
+ );
+ }
+ if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
UT_LOG_ERROR (
- "[ASSERT FAIL] %a::%d Pointer (%a) is NULL!\n",
- FunctionName,
+ "[ASSERT FAIL] %a:%d: Function call (%a) did not ASSERT()!\n",
+ FileName,
LineNumber,
- PointerName
+ FunctionCall
+ );
+ UnitTestLogFailure (
+ FAILURETYPE_EXPECTASSERT,
+ "%a:%d: Function call (%a) did not ASSERT()!\n",
+ FileName,
+ LineNumber,
+ FunctionCall
);
}
- return (Pointer != NULL);
+ return (UnitTestStatus != UNIT_TEST_ERROR_TEST_FAILED);
}
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c
index 1b8a71b12e3..cc58909b9f1 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/AssertCmocka.c
@@ -333,3 +333,71 @@ UnitTestAssertNotNull (
return (Pointer != NULL);
}
+
+/**
+ If UnitTestStatus is UNIT_TEST_PASSED, then log an info message and return
+ TRUE because an ASSERT() was expected when FunctionCall was executed and an
+ ASSERT() was triggered. If UnitTestStatus is UNIT_TEST_SKIPPED, then log a
+ warning message and return TRUE because ASSERT() macros are disabled. If
+ UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED, then log an error message and
+ return FALSE because an ASSERT() was expected when FunctionCall was executed,
+ but no ASSERT() conditions were triggered. The log messages contain
+ FunctionName, LineNumber, and FileName strings to provide the location of the
+ UT_EXPECT_ASSERT_FAILURE() macro.
+
+ @param[in] UnitTestStatus The status from UT_EXPECT_ASSERT_FAILURE() that
+ is either pass, skipped, or failed.
+ @param[in] FunctionName Null-terminated ASCII string of the function
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] LineNumber The source file line number of the the function
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] FileName Null-terminated ASCII string of the filename
+ executing the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[in] FunctionCall Null-terminated ASCII string of the function call
+ executed by the UT_EXPECT_ASSERT_FAILURE() macro.
+ @param[out] ResultStatus Used to return the UnitTestStatus value to the
+ caller of UT_EXPECT_ASSERT_FAILURE(). This is
+ optional parameter that may be NULL.
+
+ @retval TRUE UnitTestStatus is UNIT_TEST_PASSED.
+ @retval TRUE UnitTestStatus is UNIT_TEST_SKIPPED.
+ @retval FALSE UnitTestStatus is UNIT_TEST_ERROR_TEST_FAILED.
+**/
+BOOLEAN
+EFIAPI
+UnitTestExpectAssertFailure (
+ IN UNIT_TEST_STATUS UnitTestStatus,
+ IN CONST CHAR8 *FunctionName,
+ IN UINTN LineNumber,
+ IN CONST CHAR8 *FileName,
+ IN CONST CHAR8 *FunctionCall,
+ OUT UNIT_TEST_STATUS *ResultStatus OPTIONAL
+ )
+{
+ CHAR8 TempStr[MAX_STRING_SIZE];
+
+ if (ResultStatus != NULL) {
+ *ResultStatus = UnitTestStatus;
+ }
+ if (UnitTestStatus == UNIT_TEST_PASSED) {
+ UT_LOG_INFO (
+ "[ASSERT PASS] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) detected expected assert\n",
+ FileName,
+ LineNumber,
+ FunctionCall
+ );
+ }
+ if (UnitTestStatus == UNIT_TEST_SKIPPED) {
+ UT_LOG_WARNING (
+ "[ASSERT WARN] %a:%d: UT_EXPECT_ASSERT_FAILURE(%a) disabled\n",
+ FileName,
+ LineNumber,
+ FunctionCall
+ );
+ }
+ if (UnitTestStatus == UNIT_TEST_ERROR_TEST_FAILED) {
+ snprintf (TempStr, sizeof(TempStr), "UT_EXPECT_ASSERT_FAILURE(%s) did not trigger ASSERT()", FunctionCall);
+ _assert_true (FALSE, TempStr, FileName, (INT32)LineNumber);
+ }
+ return (UnitTestStatus != UNIT_TEST_ERROR_TEST_FAILED);
+}
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c
index 7167856887a..672cca341dd 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTests.c
@@ -14,6 +14,8 @@
STATIC UNIT_TEST_FRAMEWORK_HANDLE mFrameworkHandle = NULL;
+BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer;
+
UNIT_TEST_FRAMEWORK_HANDLE
GetActiveFrameworkHandle (
VOID
@@ -75,7 +77,14 @@ RunTestSuite (
// Next, if we're still running, make sure that our test prerequisites are in place.
if (Test->Result == UNIT_TEST_PENDING && Test->Prerequisite != NULL) {
DEBUG ((DEBUG_VERBOSE, "PREREQ\n"));
- if (Test->Prerequisite (Test->Context) != UNIT_TEST_PASSED) {
+ if (SetJump (&gUnitTestJumpBuffer) == 0) {
+ if (Test->Prerequisite (Test->Context) != UNIT_TEST_PASSED) {
+ DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n"));
+ Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;
+ ParentFramework->CurrentTest = NULL;
+ continue;
+ }
+ } else {
DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n"));
Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;
ParentFramework->CurrentTest = NULL;
@@ -88,14 +97,20 @@ RunTestSuite (
// We set the status to UNIT_TEST_RUNNING in case the test needs to reboot
// or quit. The UNIT_TEST_RUNNING state will allow the test to resume
// but will prevent the Prerequisite from being dispatched a second time.
- Test->Result = UNIT_TEST_RUNNING;
- Test->Result = Test->RunTest (Test->Context);
+ if (SetJump (&gUnitTestJumpBuffer) == 0) {
+ Test->Result = UNIT_TEST_RUNNING;
+ Test->Result = Test->RunTest (Test->Context);
+ } else {
+ Test->Result = UNIT_TEST_ERROR_TEST_FAILED;
+ }
//
// Finally, clean everything up, if need be.
if (Test->CleanUp != NULL) {
DEBUG ((DEBUG_VERBOSE, "CLEANUP\n"));
- Test->CleanUp (Test->Context);
+ if (SetJump (&gUnitTestJumpBuffer) == 0) {
+ Test->CleanUp (Test->Context);
+ }
}
//
@@ -162,7 +177,7 @@ RunAllTestSuites (
//
// Save current state so if test is started again it doesn't have to run. It will just report
//
- SaveFrameworkState (FrameworkHandle, NULL, 0);
+ SaveFrameworkState (NULL, 0);
OutputUnitTestFrameworkReport (FrameworkHandle);
mFrameworkHandle = NULL;
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c
index 8808963749a..e3591e0b473 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/RunTestsCmocka.c
@@ -53,21 +53,9 @@ CmockaUnitTestFunctionRunner (
UnitTest->Result = UNIT_TEST_SKIPPED;
} else {
UnitTest->Result = UNIT_TEST_RUNNING;
-
Framework->CurrentTest = UnitTest;
UnitTest->Result = UnitTest->RunTest (UnitTest->Context);
Framework->CurrentTest = NULL;
-
- // Print out the log messages - This is a partial solution as it
- // does not get the log into the XML. Need cmocka changes to support
- // stdout and stderr in their xml format
- //
- if (UnitTest->Log != NULL) {
- print_message("UnitTest: %s - %s\n", UnitTest->Name, UnitTest->Description);
- print_message("Log Output Start\n");
- print_message("%s", UnitTest->Log);
- print_message("Log Output End\n");
- }
}
}
@@ -112,13 +100,24 @@ CmockaUnitTestTeardownFunctionRunner (
Suite = (UNIT_TEST_SUITE *)(UnitTest->ParentSuite);
Framework = (UNIT_TEST_FRAMEWORK *)(Suite->ParentFramework);
- if (UnitTest->CleanUp == NULL) {
- return 0;
+ if (UnitTest->CleanUp != NULL) {
+ Framework->CurrentTest = UnitTest;
+ UnitTest->CleanUp (UnitTest->Context);
+ Framework->CurrentTest = NULL;
+ }
+
+ //
+ // Print out the log messages - This is a partial solution as it
+ // does not get the log into the XML. Need cmocka changes to support
+ // stdout and stderr in their xml format
+ //
+ if (UnitTest->Log != NULL) {
+ print_message("UnitTest: %s - %s\n", UnitTest->Name, UnitTest->Description);
+ print_message("Log Output Start\n");
+ print_message("%s", UnitTest->Log);
+ print_message("Log Output End\n");
}
- Framework->CurrentTest = UnitTest;
- UnitTest->CleanUp (UnitTest->Context);
- Framework->CurrentTest = NULL;
//
// Return 0 for success. Non-zero for error.
//
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c
index dcdde200db8..a240de554cb 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.c
@@ -781,11 +781,9 @@ SerializeState (
at least the current execution count) which will be saved by the framework and
passed to the test case upon resume.
- Generally called from within a test case prior to quitting or rebooting.
+ This should be called while the current test framework is valid and active. It is
+ generally called from within a test case prior to quitting or rebooting.
- @param[in] FrameworkHandle A handle to the current running framework that
- dispatched the test. Necessary for recording
- certain test events with the framework.
@param[in] ContextToSave A buffer of test case-specific data to be saved
along with framework state. Will be passed as
"Context" to the test case upon resume. This
@@ -793,7 +791,7 @@ SerializeState (
@param[in] ContextToSaveSize Size of the ContextToSave buffer.
@retval EFI_SUCCESS The framework state and context were saved.
- @retval EFI_INVALID_PARAMETER FrameworkHandle is NULL.
+ @retval EFI_NOT_FOUND An active framework handle was not found.
@retval EFI_INVALID_PARAMETER ContextToSave is not NULL and
ContextToSaveSize is 0.
@retval EFI_INVALID_PARAMETER ContextToSave is >= 4GB.
@@ -806,21 +804,28 @@ SerializeState (
EFI_STATUS
EFIAPI
SaveFrameworkState (
- IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle,
IN UNIT_TEST_CONTEXT ContextToSave OPTIONAL,
IN UINTN ContextToSaveSize
)
{
- EFI_STATUS Status;
- UNIT_TEST_SAVE_HEADER *Header;
+ EFI_STATUS Status;
+ UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle;
+ UNIT_TEST_SAVE_HEADER *Header;
Header = NULL;
+ FrameworkHandle = GetActiveFrameworkHandle ();
+
+ //
+ // Return a unique error code if the framework is not set.
+ //
+ if (FrameworkHandle == NULL) {
+ return EFI_NOT_FOUND;
+ }
//
// First, let's not make assumptions about the parameters.
//
- if (FrameworkHandle == NULL ||
- (ContextToSave != NULL && ContextToSaveSize == 0) ||
+ if ((ContextToSave != NULL && ContextToSaveSize == 0) ||
ContextToSaveSize > MAX_UINT32) {
return EFI_INVALID_PARAMETER;
}
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
index b7fcb24af68..6c03766d0cc 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
@@ -12,7 +12,7 @@
FILE_GUID = 98CEF9CA-15CE-40A3-ADE8-C299953CD0F6
VERSION_STRING = 1.0
MODULE_TYPE = UEFI_DRIVER
- LIBRARY_CLASS = UnitTestLib|PEIM DXE_DRIVER DXE_SMM_DRIVER UEFI_DRIVER UEFI_APPLICATION
+ LIBRARY_CLASS = UnitTestLib|PEI_CORE PEIM DXE_CORE MM_STANDALONE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_DRIVER UEFI_APPLICATION
[Sources]
UnitTestLib.c
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c
index 144e3fca1c1..c31ee7cdc1a 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLib.c
@@ -11,6 +11,7 @@
#include <Library/DebugLib.h>
VOID
+EFIAPI
ReportPrint (
IN CONST CHAR8 *Format,
...
@@ -49,7 +50,8 @@ struct _UNIT_TEST_FAILURE_TYPE_STRING mFailureTypeStrings[] = {
{ FAILURETYPE_ASSERTNOTEQUAL, "ASSERT_NOTEQUAL FAILURE"},
{ FAILURETYPE_ASSERTNOTEFIERROR, "ASSERT_NOTEFIERROR FAILURE"},
{ FAILURETYPE_ASSERTSTATUSEQUAL, "ASSERT_STATUSEQUAL FAILURE"},
- { FAILURETYPE_ASSERTNOTNULL , "ASSERT_NOTNULL FAILURE"},
+ { FAILURETYPE_ASSERTNOTNULL, "ASSERT_NOTNULL FAILURE"},
+ { FAILURETYPE_EXPECTASSERT, "EXPECT_ASSERT FAILURE"},
{ 0, "*UNKNOWN* Failure"}
};
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.c
index 19b345cdbc1..569e55782fb 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.c
@@ -12,6 +12,7 @@
#include <Library/DebugLib.h>
VOID
+EFIAPI
ReportPrint (
IN CONST CHAR8 *Format,
...
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.c
index 13b4e13dc7b..b0ef12a55a6 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.c
@@ -11,6 +11,7 @@
#include <Library/DebugLib.h>
VOID
+EFIAPI
ReportPrint (
IN CONST CHAR8 *Format,
...
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h
index 2ab40565dbd..25d5c9c41e6 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/PrivateInclude/UnitTestFrameworkTypes.h
@@ -44,6 +44,7 @@ typedef UINT32 FAILURE_TYPE;
#define FAILURETYPE_ASSERTNOTEFIERROR (6)
#define FAILURETYPE_ASSERTSTATUSEQUAL (7)
#define FAILURETYPE_ASSERTNOTNULL (8)
+#define FAILURETYPE_EXPECTASSERT (9)
///
/// Unit Test context structure tracked by the unit test framework.
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/ReadMe.md b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/ReadMe.md
index e5f14ab6d42..8b33814209e 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/ReadMe.md
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/ReadMe.md
@@ -229,6 +229,8 @@ https://api.cmocka.org/
## Development
+### Iterating on a Single Test
+
When using the EDK2 Pytools for CI testing, the host-based unit tests will be built and run on any build that includes
the `NOOPT` build target.
@@ -239,6 +241,169 @@ the following command will build only the SafeIntLib host-based test from the Md
stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2017 -p MdePkg -t NOOPT BUILDMODULE=MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.inf
```
+### Hooking BaseLib
+
+Most unit test mocking can be performed by the functions provided in the UnitTestFramework libraries, but since
+BaseLib is consumed by the Framework itself, it requires different techniques to substitute parts of the
+functionality.
+
+To solve some of this, the UnitTestFramework consumes a special implementation of BaseLib for host-based tests.
+This implementation contains a [hook table](https://github.com/tianocore/edk2/blob/e188ecc8b4aed8fdd26b731d43883861f5e5e7b4/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h#L507)
+that can be used to substitute test functionality for any of the BaseLib functions. By default, this implementation
+will use the underlying BaseLib implementation, so the unit test writer only has to supply minimal code to test a
+particular case.
+
+### Debugging the Framework Itself
+
+While most of the tests that are produced by the UnitTestFramework are easy to step through in a debugger, the Framework
+itself consumes code (mostly Cmocka) that sets its own build flags. These flags cause parts of the Framework to not
+export symbols and captures exceptions, and as such are harder to debug. We have provided a Stuart parameter to force
+symbolic debugging to be enabled.
+
+You can run a build by adding the `BLD_*_UNIT_TESTING_DEBUG=TRUE` parameter to enable this build option.
+
+```bash
+stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 -p MdePkg -t NOOPT BLD_*_UNIT_TESTING_DEBUG=TRUE
+```
+
+## Building and Running Host-Based Tests
+
+The EDK2 CI infrastructure provides a convenient way to run all host-based tests -- in the the entire tree or just
+selected packages -- and aggregate all the the reports, including highlighting any failures. This functionality is
+provided through the Stuart build system (published by EDK2-PyTools) and the `NOOPT` build target.
+
+### Building Locally
+
+First, to make sure you're working with the latest PyTools, run the following command:
+
+```bash
+# Would recommend to run this in a Python venv, but that's out of scope for this doc.
+python -m pip install --upgrade -r ./pip-requirements.txt
+```
+
+After that, the following commands will set up the build and run the host-based tests.
+
+```bash
+# Setup repo for building
+# stuart_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=<GCC5, VS2019, etc.>
+stuart_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019
+
+# Update all binary dependencies
+# stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=<GCC5, VS2019, etc.>
+stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019
+
+# Build and run the tests
+# stuart_ci_build -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=<GCC5, VS2019, etc.> -t NOOPT [-p <Package Name>]
+stuart_ci_build -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 -t NOOPT -p MdePkg
+```
+
+### Evaluating the Results
+
+In your immediate output, any build failures will be highlighted. You can see these below as "WARNING" and "ERROR" messages.
+
+```text
+(edk_env) PS C:\_uefi\edk2> stuart_ci_build -c .\.pytool\CISettings.py TOOL_CHAIN_TAG=VS2019 -t NOOPT -p MdePkg
+
+SECTION - Init SDE
+SECTION - Loading Plugins
+SECTION - Start Invocable Tool
+SECTION - Getting Environment
+SECTION - Loading plugins
+SECTION - Building MdePkg Package
+PROGRESS - --Running MdePkg: Host Unit Test Compiler Plugin NOOPT --
+WARNING - Allowing Override for key TARGET_ARCH
+PROGRESS - Start time: 2020-07-27 17:18:08.521672
+PROGRESS - Setting up the Environment
+PROGRESS - Running Pre Build
+PROGRESS - Running Build NOOPT
+PROGRESS - Running Post Build
+SECTION - Run Host based Unit Tests
+SUBSECTION - Testing for architecture: X64
+WARNING - TestBaseSafeIntLibHost.exe Test Failed
+WARNING - Test SafeInt8ToUint8 - UT_ASSERT_EQUAL(0x5b:5b, Result:5c)
+c:\_uefi\edk2\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: error: Failure!
+ERROR - Plugin Failed: Host-Based Unit Test Runner returned 1
+CRITICAL - Post Build failed
+PROGRESS - End time: 2020-07-27 17:18:19.792313 Total time Elapsed: 0:00:11
+ERROR - --->Test Failed: Host Unit Test Compiler Plugin NOOPT returned 1
+ERROR - Overall Build Status: Error
+PROGRESS - There were 1 failures out of 1 attempts
+SECTION - Summary
+ERROR - Error
+
+(edk_env) PS C:\_uefi\edk2>
+```
+
+If a test fails, you can run it manually to get more details...
+
+```text
+(edk_env) PS C:\_uefi\edk2> .\Build\MdePkg\HostTest\NOOPT_VS2019\X64\TestBaseSafeIntLibHost.exe
+
+Int Safe Lib Unit Test Application v0.1
+---------------------------------------------------------
+------------ RUNNING ALL TEST SUITES --------------
+---------------------------------------------------------
+---------------------------------------------------------
+RUNNING TEST SUITE: Int Safe Conversions Test Suite
+---------------------------------------------------------
+[==========] Running 71 test(s).
+[ RUN ] Test SafeInt8ToUint8
+[ ERROR ] --- UT_ASSERT_EQUAL(0x5b:5b, Result:5c)
+[ LINE ] --- c:\_uefi\edk2\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: error: Failure!
+[ FAILED ] Test SafeInt8ToUint8
+[ RUN ] Test SafeInt8ToUint16
+[ OK ] Test SafeInt8ToUint16
+[ RUN ] Test SafeInt8ToUint32
+[ OK ] Test SafeInt8ToUint32
+[ RUN ] Test SafeInt8ToUintn
+[ OK ] Test SafeInt8ToUintn
+...
+```
+
+You can also, if you are so inclined, read the output from the exact instance of the test that was run during
+`stuart_ci_build`. The ouput file can be found on a path that looks like:
+
+`Build/<Package>/HostTest/<Arch>/<TestName>.<TestSuiteName>.<Arch>.result.xml`
+
+A sample of this output looks like:
+
+```xml
+<!--
+ Excerpt taken from:
+ Build\MdePkg\HostTest\NOOPT_VS2019\X64\TestBaseSafeIntLibHost.exe.Int Safe Conversions Test Suite.X64.result.xml
+ -->
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuites>
+ <testsuite name="Int Safe Conversions Test Suite" time="0.000" tests="71" failures="1" errors="0" skipped="0" >
+ <testcase name="Test SafeInt8ToUint8" time="0.000" >
+ <failure><![CDATA[UT_ASSERT_EQUAL(0x5c:5c, Result:5b)
+c:\_uefi\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: error: Failure!]]></failure>
+ </testcase>
+ <testcase name="Test SafeInt8ToUint16" time="0.000" >
+ </testcase>
+ <testcase name="Test SafeInt8ToUint32" time="0.000" >
+ </testcase>
+ <testcase name="Test SafeInt8ToUintn" time="0.000" >
+ </testcase>
+```
+
+### XML Reporting Mode
+
+Since these applications are built using the CMocka framework, they can also use the following env variables to output
+in a structured XML rather than text:
+
+```text
+CMOCKA_MESSAGE_OUTPUT=xml
+CMOCKA_XML_FILE=<absolute or relative path to output file>
+```
+
+This mode is used by the test running plugin to aggregate the results for CI test status reporting in the web view.
+
+### Important Note
+
+This works on both Windows and Linux, but is currently limited to x64 architectures. Working on getting others, but we
+also welcome contributions.
+
## Known Limitations
### PEI, DXE, SMM
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTest.c b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTest.c
index fbc57143bd0..1ece809032f 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTest.c
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTest.c
@@ -182,6 +182,466 @@ GlobalPointerShouldBeChangeable (
}
/**
+ Unit-Test Test Suite Setup (before) function that enables ASSERT() macros.
+**/
+VOID
+EFIAPI
+TestSuiteEnableAsserts (
+ VOID
+ )
+{
+ //
+ // Set BIT0 (DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED)
+ //
+ PatchPcdSet8 (PcdDebugPropertyMask, PcdGet8 (PcdDebugPropertyMask) | BIT0);
+}
+
+/**
+ Unit-Test Test Suite Setup (before) function that disables ASSERT() macros.
+**/
+VOID
+EFIAPI
+TestSuiteDisableAsserts (
+ VOID
+ )
+{
+ //
+ // Clear BIT0 (DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED)
+ //
+ PatchPcdSet8 (PcdDebugPropertyMask, PcdGet8 (PcdDebugPropertyMask) & (~BIT0));
+}
+
+/**
+ Sample unit test using the UT_ASSERT_TRUE() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertTrue (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT64 Result;
+
+ //
+ // This test passes because expression always evaluated to TRUE.
+ //
+ UT_ASSERT_TRUE (TRUE);
+
+ //
+ // This test passes because expression always evaluates to TRUE.
+ //
+ Result = LShiftU64 (BIT0, 1);
+ UT_ASSERT_TRUE (Result == BIT1);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_FALSE() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertFalse (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT64 Result;
+
+ //
+ // This test passes because expression always evaluated to FALSE.
+ //
+ UT_ASSERT_FALSE (FALSE);
+
+ //
+ // This test passes because expression always evaluates to FALSE.
+ //
+ Result = LShiftU64 (BIT0, 1);
+ UT_ASSERT_FALSE (Result == BIT0);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_EQUAL() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertEqual (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT64 Result;
+
+ //
+ // This test passes because both values are always equal.
+ //
+ UT_ASSERT_EQUAL (1, 1);
+
+ //
+ // This test passes because both values are always equal.
+ //
+ Result = LShiftU64 (BIT0, 1);
+ UT_ASSERT_EQUAL (Result, BIT1);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_MEM_EQUAL() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertMemEqual (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ CHAR8 *String1;
+ CHAR8 *String2;
+ UINTN Length;
+
+ //
+ // This test passes because String1 and String2 are the same.
+ //
+ String1 = "Hello";
+ String2 = "Hello";
+ Length = sizeof ("Hello");
+ UT_ASSERT_MEM_EQUAL (String1, String2, Length);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_NOT_EQUAL() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertNotEqual (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT64 Result;
+
+ //
+ // This test passes because both values are never equal.
+ //
+ UT_ASSERT_NOT_EQUAL (0, 1);
+
+ //
+ // This test passes because both values are never equal.
+ //
+ Result = LShiftU64 (BIT0, 1);
+ UT_ASSERT_NOT_EQUAL (Result, BIT0);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_NOT_EFI_ERROR() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertNotEfiError (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // This test passes because the status is not an EFI error.
+ //
+ UT_ASSERT_NOT_EFI_ERROR (EFI_SUCCESS);
+
+ //
+ // This test passes because the status is not an EFI error.
+ //
+ UT_ASSERT_NOT_EFI_ERROR (EFI_WARN_BUFFER_TOO_SMALL);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_STATUS_EQUAL() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertStatusEqual (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // This test passes because the status value are always equal.
+ //
+ UT_ASSERT_STATUS_EQUAL (EFI_SUCCESS, EFI_SUCCESS);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_ASSERT_NOT_NULL() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtAssertNotNull (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ UINT64 Result;
+
+ //
+ // This test passes because the pointer is never NULL.
+ //
+ UT_ASSERT_NOT_NULL (&Result);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_EXPECT_ASSERT_FAILURE() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtExpectAssertFailure (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // This test passes because it directly triggers an ASSERT().
+ //
+ UT_EXPECT_ASSERT_FAILURE (ASSERT (FALSE), NULL);
+
+ //
+ // This test passes because DecimalToBcd() generates an ASSERT() if the
+ // value passed in is >= 100. The expected ASSERT() is caught by the unit
+ // test framework and UT_EXPECT_ASSERT_FAILURE() returns without an error.
+ //
+ UT_EXPECT_ASSERT_FAILURE (DecimalToBcd8 (101), NULL);
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_LOG_ERROR() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtLogError (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // Example of logging.
+ //
+ UT_LOG_ERROR ("UT_LOG_ERROR() message\n");
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_LOG_WARNING() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtLogWarning (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // Example of logging.
+ //
+ UT_LOG_WARNING ("UT_LOG_WARNING() message\n");
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_LOG_INFO() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtLogInfo (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // Example of logging.
+ //
+ UT_LOG_INFO ("UT_LOG_INFO() message\n");
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
+ Sample unit test using the UT_LOG_VERBOSE() macro.
+
+ @param[in] Context [Optional] An optional parameter that enables:
+ 1) test-case reuse with varied parameters and
+ 2) test-case re-entry for Target tests that need a
+ reboot. This parameter is a VOID* and it is the
+ responsibility of the test author to ensure that the
+ contents are well understood by all test cases that may
+ consume it.
+
+ @retval UNIT_TEST_PASSED The Unit test has completed and the test
+ case was successful.
+ @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed.
+**/
+UNIT_TEST_STATUS
+EFIAPI
+MacroUtLogVerbose (
+ IN UNIT_TEST_CONTEXT Context
+ )
+{
+ //
+ // Example of logging.
+ //
+ UT_LOG_VERBOSE ("UT_LOG_VERBOSE() message\n");
+
+ return UNIT_TEST_PASSED;
+}
+
+/**
Initialize the unit test framework, suite, and unit tests for the
sample unit tests and run the unit tests.
@@ -199,6 +659,8 @@ UefiTestMain (
UNIT_TEST_FRAMEWORK_HANDLE Framework;
UNIT_TEST_SUITE_HANDLE SimpleMathTests;
UNIT_TEST_SUITE_HANDLE GlobalVarTests;
+ UNIT_TEST_SUITE_HANDLE MacroTestsAssertsEnabled;
+ UNIT_TEST_SUITE_HANDLE MacroTestsAssertsDisabled;
Framework = NULL;
@@ -237,6 +699,54 @@ UefiTestMain (
AddTestCase (GlobalVarTests, "You should be able to change a global pointer", "Pointer", GlobalPointerShouldBeChangeable, MakeSureThatPointerIsNull, ClearThePointer, NULL);
//
+ // Populate the Macro Tests with ASSERT() enabled
+ //
+ Status = CreateUnitTestSuite (&MacroTestsAssertsEnabled, Framework, "Macro Tests with ASSERT() enabled", "Sample.MacroAssertsEnabled", TestSuiteEnableAsserts, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MacroTestsAssertsEnabled\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_TRUE() macro", "MacroUtAssertTrue", MacroUtAssertTrue, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_FALSE() macro", "MacroUtAssertFalse", MacroUtAssertFalse, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_EQUAL() macro", "MacroUtAssertEqual", MacroUtAssertEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_MEM_EQUAL() macro", "MacroUtAssertMemEqual", MacroUtAssertMemEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_NOT_EQUAL() macro", "MacroUtAssertNotEqual", MacroUtAssertNotEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_NOT_EFI_ERROR() macro", "MacroUtAssertNotEfiError", MacroUtAssertNotEfiError, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_STATUS_EQUAL() macro", "MacroUtAssertStatusEqual", MacroUtAssertStatusEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_ASSERT_NOT_NULL() macro", "MacroUtAssertNotNull", MacroUtAssertNotNull, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_EXPECT_ASSERT_FAILURE() macro", "MacroUtExpectAssertFailure", MacroUtExpectAssertFailure, NULL, NULL, NULL);
+
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_LOG_ERROR() macro", "MacroUtLogError", MacroUtLogError, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_LOG_WARNING() macro", "MacroUtLogWarning", MacroUtLogWarning, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_LOG_INFO() macro", "MacroUtLogInfo", MacroUtLogInfo, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsEnabled, "Test UT_LOG_VERBOSE() macro", "MacroUtLogVerbose", MacroUtLogVerbose, NULL, NULL, NULL);
+
+ //
+ // Populate the Macro Tests with ASSERT() disabled
+ //
+ Status = CreateUnitTestSuite (&MacroTestsAssertsDisabled, Framework, "Macro Tests with ASSERT() disabled", "Sample.MacroAssertsDisables", TestSuiteDisableAsserts, NULL);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MacroTestsAssertsDisabled\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto EXIT;
+ }
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_TRUE() macro", "MacroUtAssertTrue", MacroUtAssertTrue, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_FALSE() macro", "MacroUtAssertFalse", MacroUtAssertFalse, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_EQUAL() macro", "MacroUtAssertEqual", MacroUtAssertEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_MEM_EQUAL() macro", "MacroUtAssertMemEqual", MacroUtAssertMemEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_NOT_EQUAL() macro", "MacroUtAssertNotEqual", MacroUtAssertNotEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_NOT_EFI_ERROR() macro", "MacroUtAssertNotEfiError", MacroUtAssertNotEfiError, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_STATUS_EQUAL() macro", "MacroUtAssertStatusEqual", MacroUtAssertStatusEqual, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_ASSERT_NOT_NULL() macro", "MacroUtAssertNotNull", MacroUtAssertNotNull, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_EXPECT_ASSERT_FAILURE() macro", "MacroUtExpectAssertFailure", MacroUtExpectAssertFailure, NULL, NULL, NULL);
+
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_LOG_ERROR() macro", "MacroUtLogError", MacroUtLogError, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_LOG_WARNING() macro", "MacroUtLogWarning", MacroUtLogWarning, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_LOG_INFO() macro", "MacroUtLogInfo", MacroUtLogInfo, NULL, NULL, NULL);
+ AddTestCase (MacroTestsAssertsDisabled, "Test UT_LOG_VERBOSE() macro", "MacroUtLogVerbose", MacroUtLogVerbose, NULL, NULL, NULL);
+
+ //
// Execute the tests.
//
Status = RunAllTestSuites (Framework);
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf
index ac76d7254ff..32c29a62f4c 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf
@@ -32,5 +32,8 @@
UnitTestLib
PrintLib
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
+
[Depex]
TRUE
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf
index b631bcdb789..4a64ab16b81 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf
@@ -28,3 +28,6 @@
BaseLib
DebugLib
UnitTestLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf
index ef498e8c94d..bb747f716e7 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf
@@ -32,5 +32,8 @@
UnitTestLib
PrintLib
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
+
[Depex]
gEfiPeiMemoryDiscoveredPpiGuid
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestSmm.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestSmm.inf
index 1f0c64484df..46370dade42 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestSmm.inf
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestSmm.inf
@@ -33,5 +33,8 @@
UnitTestLib
PrintLib
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
+
[Depex]
gEfiSmmCpuProtocolGuid
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf
index 833bef0c1a0..12fd3c0e714 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf
@@ -31,3 +31,6 @@
DebugLib
UnitTestLib
PrintLib
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
index 310ad451278..32c6d7a39af 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
@@ -18,6 +18,9 @@
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+[PcdsPatchableInModule]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
+
[Components]
#
# Build HOST_APPLICATION that tests the SampleUnitTest
@@ -25,7 +28,7 @@
UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf
#
- # Build Libraries
+ # Build HOST_APPLICATION Libraries
#
UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
index 21ce9d38d7c..148762752c1 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
@@ -5,6 +5,22 @@
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
{
+ ## options defined .pytool/Plugin/LicenseCheck
+ "LicenseCheck": {
+ "IgnoreFiles": []
+ },
+ "EccCheck": {
+ ## Exception sample looks like below:
+ ## "ExceptionList": [
+ ## "<ErrorID>", "<KeyWord>"
+ ## ]
+ "ExceptionList": [
+ ],
+ ## Both file path and directory path are accepted.
+ "IgnoreFiles": [
+ "Library/CmockaLib/cmocka"
+ ]
+ },
## options defined .pytool/Plugin/CompilerPlugin
"CompilerPlugin": {
"DscPath": "UnitTestFrameworkPkg.dsc"
@@ -62,6 +78,8 @@
"Library/CmockaLib/cmocka/**/*.*" # not going to spell check a submodule
],
"ExtendWords": [ # words to extend to the dictionary for this package
+ "testcase",
+ "testsuites",
"cmocka",
"buildmodule",
"criterium",
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc
index 14f89ec5a1c..b49bde9eb13 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dsc
@@ -1,7 +1,7 @@
## @file
# UnitTestFrameworkPkg
#
-# Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2019 - 2021, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -19,6 +19,10 @@
SKUID_IDENTIFIER = DEFAULT
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
+!include MdePkg/MdeLibs.dsc.inc
+
+[PcdsPatchableInModule]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
[Components]
UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
@@ -28,6 +32,7 @@
UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibConOut.inf
UnitTestFrameworkPkg/Library/UnitTestBootLibUsbClass/UnitTestBootLibUsbClass.inf
UnitTestFrameworkPkg/Library/UnitTestPersistenceLibSimpleFileSystem/UnitTestPersistenceLibSimpleFileSystem.inf
+ UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf
UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestDxe.inf
UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestPei.inf
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
index c04cc8342f3..dbeb5f602e6 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
@@ -9,6 +9,10 @@
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
[LibraryClasses.common.HOST_APPLICATION]
+ BaseLib|MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
+ UnitTestHostBaseLib|MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
+ CpuLib|MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
+ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf
CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
@@ -16,12 +20,17 @@
[BuildOptions]
GCC:*_*_*_CC_FLAGS = -fno-pie
+!ifdef $(UNIT_TESTING_DEBUG)
+ MSFT:*_*_*_CC_FLAGS = -D UNIT_TESTING_DEBUG=1
+ GCC:*_*_*_CC_FLAGS = -D UNIT_TESTING_DEBUG=1
+ XCODE:*_*_*_CC_FLAGS = -D UNIT_TESTING_DEBUG=1
+!endif
[BuildOptions.common.EDKII.HOST_APPLICATION]
#
# MSFT
#
- MSFT:*_*_*_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /IGNORE:4001 /NOLOGO /SUBSYSTEM:CONSOLE /DEBUG /NODEFAULTLIB:libcmt.lib libcmtd.lib
+ MSFT:*_*_*_DLINK_FLAGS == /out:"$(BIN_DIR)\$(BASE_NAME).exe" /pdb:"$(BIN_DIR)\$(BASE_NAME).pdb" /IGNORE:4001 /NOLOGO /SUBSYSTEM:CONSOLE /DEBUG /STACK:0x40000,0x40000 /NODEFAULTLIB:libcmt.lib libcmtd.lib
MSFT:*_*_IA32_DLINK_FLAGS = /MACHINE:I386
MSFT:*_*_X64_DLINK_FLAGS = /MACHINE:AMD64
diff --git a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
index 32214f30707..b014914ffbd 100644
--- a/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
+++ b/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
@@ -16,7 +16,9 @@
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
- DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+ DebugLib|MdeModulePkg/Library/PeiDxeDebugLibReportStatusCode/PeiDxeDebugLibReportStatusCode.inf
+ ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
@@ -27,6 +29,7 @@
UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceLibNull/UnitTestPersistenceLibNull.inf
UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.inf
+ NULL|UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLib.inf
[LibraryClasses.ARM, LibraryClasses.AARCH64]
#
@@ -54,5 +57,6 @@
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x17
[BuildOptions]
- MSFT:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
- GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+ MSFT:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D EDKII_UNIT_TEST_FRAMEWORK_ENABLED
+ GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D EDKII_UNIT_TEST_FRAMEWORK_ENABLED
+ XCODE:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES -D EDKII_UNIT_TEST_FRAMEWORK_ENABLED
diff --git a/src/VBox/Devices/EFI/Firmware/edksetup.bat b/src/VBox/Devices/EFI/Firmware/edksetup.bat
index 7b9377aaa5c..7ad137bb3e9 100755
--- a/src/VBox/Devices/EFI/Firmware/edksetup.bat
+++ b/src/VBox/Devices/EFI/Firmware/edksetup.bat
@@ -120,7 +120,7 @@ if not defined CLANG_BIN (
@echo.
@echo !!! WARNING !!! CLANG_BIN environment variable is not set
@if exist "C:\Program Files\LLVM\bin\clang.exe" (
- @set CLANG_BIN=C:\Program Files\LLVM\bin\
+ @set "CLANG_BIN=C:\Program Files\LLVM\bin\"
@echo Found LLVM, setting CLANG_BIN environment variable to C:\Program Files\LLVM\bin\
)
)
diff --git a/src/VBox/Devices/EFI/Firmware/pip-requirements.txt b/src/VBox/Devices/EFI/Firmware/pip-requirements.txt
index 999f008d429..ac4d23d4c44 100644
--- a/src/VBox/Devices/EFI/Firmware/pip-requirements.txt
+++ b/src/VBox/Devices/EFI/Firmware/pip-requirements.txt
@@ -14,3 +14,5 @@
edk2-pytool-library==0.10.*
edk2-pytool-extensions~=0.13.3
+edk2-basetools==0.1.2
+antlr4-python3-runtime==4.7.1