summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/pull_request_template.md27
-rw-r--r--.github/workflows/pr-labeler.yml36
-rw-r--r--.github/workflows/pr-labeler/regex.yml16
-rw-r--r--ArmPkg/ArmPkg.dec10
-rw-r--r--ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c2
-rw-r--r--ArmVirtPkg/ArmVirt.dsc.inc5
-rw-r--r--ArmVirtPkg/ArmVirtCloudHv.dsc3
-rw-r--r--ArmVirtPkg/ArmVirtKvmTool.dsc4
-rw-r--r--ArmVirtPkg/ArmVirtQemu.dsc20
-rw-r--r--ArmVirtPkg/ArmVirtQemu.fdf2
-rw-r--r--ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc6
-rw-r--r--ArmVirtPkg/ArmVirtQemuKernel.dsc12
-rw-r--r--ArmVirtPkg/ArmVirtXen.dsc6
-rw-r--r--ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c14
-rw-r--r--ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf1
-rw-r--r--ArmVirtPkg/PlatformCI/PlatformBuildLib.py2
-rw-r--r--BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml6
-rw-r--r--BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml6
-rw-r--r--BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml6
-rwxr-xr-xBaseTools/Scripts/PatchCheck.py2
-rw-r--r--CryptoPkg/CryptoPkgMbedTls.dsc1
-rw-r--r--CryptoPkg/Include/Library/BaseCryptLib.h4
-rw-r--r--CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c6
-rw-r--r--CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c8
-rw-r--r--CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c8
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf43
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c227
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Hash/CryptSm3.c235
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h49
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf23
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c138
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c214
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c278
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c100
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h29
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c635
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c113
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c1354
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c689
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c352
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c140
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c381
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c1940
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c114
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c114
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf27
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/SecCryptLib.inf1
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf32
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/BaseMemAllocation.c122
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/DummyOpensslSupport.c571
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/UnitTestHostCrtWrapper.c63
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf40
-rw-r--r--CryptoPkg/Library/OpensslLib/OpensslStub/uefiprov.c11
-rw-r--r--DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h41
-rw-r--r--DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c67
-rw-r--r--EmulatorPkg/EmulatorPkg.dsc14
-rw-r--r--EmulatorPkg/EmulatorPkg.fdf11
-rw-r--r--EmulatorPkg/Unix/Host/Gasket.h2
-rw-r--r--IntelFsp2Pkg/Tools/PatchFv.py2
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c5
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h1
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf5
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c2
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c5
-rw-r--r--MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h7
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c433
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h167
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni10
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c198
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf41
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c162
-rw-r--r--MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf41
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHc.c115
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHc.h117
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHc.uni10
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.c101
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.inf47
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.c79
-rw-r--r--MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.inf45
-rw-r--r--MdeModulePkg/Core/Dxe/Gcd/Gcd.c11
-rw-r--r--MdeModulePkg/Core/Dxe/Mem/Page.c38
-rw-r--r--MdeModulePkg/Core/PiSmmCore/Smi.c1
-rw-r--r--MdeModulePkg/Include/Library/SpiHcPlatformLib.h148
-rw-r--r--MdeModulePkg/Include/Pi/PrePiDxeCis.h25
-rw-r--r--MdeModulePkg/Include/Pi/PrePiHob.h20
-rw-r--r--MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.c145
-rw-r--r--MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.inf33
-rw-r--r--MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.uni11
-rw-r--r--MdeModulePkg/MdeModulePkg.dec10
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc6
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c12
-rw-r--r--MdePkg/Include/IndustryStandard/IpmiNetFnOem.h18
-rw-r--r--MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h32
-rw-r--r--MdePkg/Include/IndustryStandard/UefiTcgPlatform.h38
-rw-r--r--MdePkg/Include/Pi/PiDxeCis.h13
-rw-r--r--MdePkg/Include/Pi/PiHob.h14
-rw-r--r--MdePkg/Include/Ppi/DelayedDispatch.h24
-rw-r--r--MdePkg/Include/Protocol/DevicePath.h22
-rw-r--r--MdePkg/Include/Protocol/SpiConfiguration.h4
-rw-r--r--MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S1
-rw-r--r--MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm1
-rw-r--r--MdePkg/Library/BaseRngLib/AArch64/Rndr.c1
-rw-r--r--MdePkg/MdeLibs.dsc.inc3
-rw-r--r--MdePkg/Test/MdePkgHostTest.dsc1
-rw-r--r--MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiBootServicesTableLib.h78
-rw-r--r--MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockHash2.h67
-rw-r--r--MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockRng.h48
-rw-r--r--MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.cpp69
-rw-r--r--MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf32
-rw-r--r--MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockHash2.cpp27
-rw-r--r--MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockRng.cpp21
-rw-r--r--NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c10
-rw-r--r--NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c11
-rw-r--r--NetworkPkg/DnsDxe/DnsDhcp.c10
-rw-r--r--NetworkPkg/DnsDxe/DnsImpl.c11
-rw-r--r--NetworkPkg/HttpBootDxe/HttpBootDhcp6.c10
-rw-r--r--NetworkPkg/IScsiDxe/IScsiCHAP.c19
-rw-r--r--NetworkPkg/IScsiDxe/IScsiMisc.c14
-rw-r--r--NetworkPkg/IScsiDxe/IScsiMisc.h6
-rw-r--r--NetworkPkg/Include/Library/NetLib.h40
-rw-r--r--NetworkPkg/Ip4Dxe/Ip4Driver.c10
-rw-r--r--NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c9
-rw-r--r--NetworkPkg/Ip6Dxe/Ip6Driver.c17
-rw-r--r--NetworkPkg/Ip6Dxe/Ip6If.c12
-rw-r--r--NetworkPkg/Ip6Dxe/Ip6Mld.c12
-rw-r--r--NetworkPkg/Ip6Dxe/Ip6Nd.c33
-rw-r--r--NetworkPkg/Ip6Dxe/Ip6Nd.h8
-rw-r--r--NetworkPkg/Library/DxeNetLib/DxeNetLib.c130
-rw-r--r--NetworkPkg/Library/DxeNetLib/DxeNetLib.inf14
-rw-r--r--NetworkPkg/NetworkPkg.dec7
-rw-r--r--NetworkPkg/SecurityFixes.yaml61
-rw-r--r--NetworkPkg/TcpDxe/TcpDriver.c105
-rw-r--r--NetworkPkg/TcpDxe/TcpDxe.inf11
-rw-r--r--NetworkPkg/TcpDxe/TcpFunc.h23
-rw-r--r--NetworkPkg/TcpDxe/TcpInput.c13
-rw-r--r--NetworkPkg/TcpDxe/TcpMain.h59
-rw-r--r--NetworkPkg/TcpDxe/TcpMisc.c244
-rw-r--r--NetworkPkg/TcpDxe/TcpTimer.c3
-rw-r--r--NetworkPkg/Test/NetworkPkgHostTest.dsc1
-rw-r--r--NetworkPkg/Udp4Dxe/Udp4Driver.c10
-rw-r--r--NetworkPkg/Udp6Dxe/Udp6Driver.c11
-rw-r--r--NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp102
-rw-r--r--NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf3
-rw-r--r--NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c9
-rw-r--r--NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c11
-rw-r--r--NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c12
-rw-r--r--OvmfPkg/AmdSev/AmdSevX64.dsc1
-rw-r--r--OvmfPkg/AmdSevDxe/AmdSevDxe.c4
-rw-r--r--OvmfPkg/CloudHv/CloudHvX64.dsc1
-rw-r--r--OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c10
-rw-r--r--OvmfPkg/Library/PeilessStartupLib/Hob.c4
-rw-r--r--OvmfPkg/Library/PlatformInitLib/IntelTdx.c8
-rw-r--r--OvmfPkg/Library/PlatformInitLib/MemDetect.c135
-rw-r--r--OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf6
-rw-r--r--OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c33
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/Ia32/Semaphore.c (renamed from UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c)13
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm151
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h127
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.c549
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf60
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c100
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/X64/Semaphore.c (renamed from UefiCpuPkg/PiSmmCpuDxeSmm/X64/Semaphore.c)13
-rw-r--r--OvmfPkg/Library/SmmRelocationLib/X64/SmmInit.nasm (renamed from UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmInit.nasm)85
-rw-r--r--OvmfPkg/Microvm/MicrovmX64.dsc1
-rw-r--r--OvmfPkg/OvmfPkgIa32.dsc7
-rw-r--r--OvmfPkg/OvmfPkgIa32.fdf5
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.dsc7
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.fdf5
-rw-r--r--OvmfPkg/OvmfPkgX64.dsc7
-rw-r--r--OvmfPkg/OvmfPkgX64.fdf5
-rw-r--r--OvmfPkg/OvmfXen.dsc5
-rw-r--r--OvmfPkg/OvmfXen.fdf5
-rw-r--r--OvmfPkg/PlatformCI/PlatformBuildLib.py2
-rw-r--r--OvmfPkg/PlatformPei/AmdSev.c4
-rw-r--r--OvmfPkg/PlatformPei/Platform.c3
-rw-r--r--OvmfPkg/PlatformPei/Platform.h5
-rw-r--r--OvmfPkg/PlatformPei/PlatformPei.inf5
-rw-r--r--OvmfPkg/PlatformPei/SmmRelocation.c80
-rw-r--r--OvmfPkg/SmmAccess/SmmAccess2Dxe.c4
-rw-r--r--OvmfPkg/SmmAccess/SmmAccess2Dxe.inf5
-rw-r--r--OvmfPkg/SmmAccess/SmmAccessPei.c116
-rw-r--r--OvmfPkg/SmmAccess/SmmAccessPei.inf11
-rw-r--r--OvmfPkg/SmmAccess/SmramInternal.c72
-rw-r--r--OvmfPkg/SmmAccess/SmramInternal.h19
-rw-r--r--OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.c15
-rw-r--r--OvmfPkg/VirtioRngDxe/VirtioRng.c13
-rw-r--r--OvmfPkg/VirtioRngDxe/VirtioRng.h1
-rw-r--r--RedfishPkg/Include/Library/RedfishPlatformConfigLib.h4
-rw-r--r--RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h4
-rw-r--r--RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c4
-rw-r--r--RedfishPkg/RedfishPkg.dec6
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c4
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h2
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c86
-rw-r--r--RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h16
m---------SecurityPkg/DeviceSecurity/SpdmLib/libspdm0
-rw-r--r--SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c8
-rw-r--r--SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c15
-rw-r--r--StandaloneMmPkg/Core/Mmi.c1
-rw-r--r--UefiCpuPkg/Include/Library/SmmRelocationLib.h42
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.c49
-rw-r--r--UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c4
-rw-r--r--UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c4
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/AmdSmmRelocationLib.inf60
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/AmdSmramSaveStateConfig.c125
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/Ia32/Semaphore.c39
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm151
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h127
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.c549
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf61
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c136
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/X64/Semaphore.c66
-rw-r--r--UefiCpuPkg/Library/SmmRelocationLib/X64/SmmInit.nasm201
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c21
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm96
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c10
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c421
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h103
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf7
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmMpPerf.h2
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c69
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dec3
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dsc2
-rw-r--r--UefiPayloadPkg/Readme.md4
-rw-r--r--UefiPayloadPkg/UefiPayloadPkg.dsc2
-rw-r--r--pip-requirements.txt6
226 files changed, 14883 insertions, 1340 deletions
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..70e8c56496
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,27 @@
+# Description
+
+<_Include a description of the change and why this change was made._>
+
+<_For each item, place an "x" in between `[` and `]` if true. Example: `[x]` (you can also check items in GitHub UI)_>
+
+<_Create the PR as a Draft PR if it is only created to run CI checks._>
+
+<_Delete lines in \<\> tags before creating the PR._>
+
+- [ ] Breaking change?
+ - **Breaking change** - Will this cause a break in build or boot behavior?
+ - Examples: Add a new library class or move a module to a different repo.
+- [ ] Impacts security?
+ - **Security** - Does the change have a direct security impact?
+ - Examples: Crypto algorithm change or buffer overflow fix.
+- [ ] Includes tests?
+ - **Tests** - Does the change include any explicit test code?
+ - Examples: Unit tests or integration tests.
+
+## How This Was Tested
+
+<_Describe the test(s) that were run to verify the changes._>
+
+## Integration Instructions
+
+<_Describe how these changes should be integrated. Use N/A if nothing is required._>
diff --git a/.github/workflows/pr-labeler.yml b/.github/workflows/pr-labeler.yml
new file mode 100644
index 0000000000..1b7daa61fa
--- /dev/null
+++ b/.github/workflows/pr-labeler.yml
@@ -0,0 +1,36 @@
+# This workflow automatically applies labels to pull requests based on regular expression matches against the content
+# in the pull request.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# For more information, see:
+# https://github.com/github/issue-labeler
+
+name: Apply Labels Based on Message Content
+
+on:
+ pull_request_target:
+ types:
+ - edited
+ - opened
+ - reopened
+ - synchronize
+ workflow_dispatch:
+
+jobs:
+ sync:
+ name: Label PR from Description
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ pull-requests: write
+
+ steps:
+ - name: Apply Labels Based on PR Description
+ uses: github/issue-labeler@v3.1
+ with:
+ configuration-path: .github/workflows/pr-labeler/regex.yml
+ enable-versioned-regex: 0
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/pr-labeler/regex.yml b/.github/workflows/pr-labeler/regex.yml
new file mode 100644
index 0000000000..b14746d169
--- /dev/null
+++ b/.github/workflows/pr-labeler/regex.yml
@@ -0,0 +1,16 @@
+# Specifies labels to apply to pull requests based on regular expressions.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# For more information, see:
+# https://github.com/github/issue-labeler
+
+impact:breaking-change:
+ - '\s*-\s*\[\s*[x|X]\s*\] Breaking change\?'
+
+impact:security:
+ - '\s*-\s*\[\s*[x|X]\s*\] Impacts security\?'
+
+impact:testing:
+ - '\s*-\s*\[\s*[x|X]\s*\] Includes tests\?'
diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec
index 7fe2b9bca4..ac030e295b 100644
--- a/ArmPkg/ArmPkg.dec
+++ b/ArmPkg/ArmPkg.dec
@@ -139,11 +139,6 @@
# Define if the GICv3 controller should use the GICv2 legacy
gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042
- ## Define the conduit to use for monitor calls.
- # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
- # If PcdMonitorConduitHvc = TRUE, conduit = HVC
- gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
-
# Whether to remap all unused memory NX before installing the CPU arch
# protocol driver. This is needed on platforms that map all DRAM with RWX
# attributes initially, and can be disabled otherwise.
@@ -317,6 +312,11 @@
gArmTokenSpaceGuid.PcdSystemBiosRelease|0xFFFF|UINT16|0x30000058
gArmTokenSpaceGuid.PcdEmbeddedControllerFirmwareRelease|0xFFFF|UINT16|0x30000059
+ ## Define the conduit to use for monitor calls.
+ # Default PcdMonitorConduitHvc = FALSE, conduit = SMC
+ # If PcdMonitorConduitHvc = TRUE, conduit = HVC
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
+
[PcdsFixedAtBuild.common, PcdsDynamic.common]
#
# ARM Architectural Timer
diff --git a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
index 741f5c6157..ec5b0b6619 100644
--- a/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
+++ b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
@@ -26,7 +26,7 @@ ArmMonitorCall (
IN OUT ARM_MONITOR_ARGS *Args
)
{
- if (FeaturePcdGet (PcdMonitorConduitHvc)) {
+ if (PcdGetBool (PcdMonitorConduitHvc)) {
ArmCallHvc ((ARM_HVC_ARGS *)Args);
} else {
ArmCallSmc ((ARM_SMC_ARGS *)Args);
diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index 2bc6a29eb1..7044790a1e 100644
--- a/ArmVirtPkg/ArmVirt.dsc.inc
+++ b/ArmVirtPkg/ArmVirt.dsc.inc
@@ -156,7 +156,9 @@
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
!endif
BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
- RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
+ RngLib|MdePkg/Library/BaseRngLib/BaseRngLib.inf
+ ArmTrngLib|ArmPkg/Library/ArmTrngLib/ArmTrngLib.inf
+ ArmMonitorLib|ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf
#
# Secure Boot dependencies
@@ -266,6 +268,7 @@
[LibraryClasses.ARM]
ArmSoftFloatLib|ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
+ RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
[BuildOptions]
GCC:RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
diff --git a/ArmVirtPkg/ArmVirtCloudHv.dsc b/ArmVirtPkg/ArmVirtCloudHv.dsc
index 5cb2a609b1..d5055a0341 100644
--- a/ArmVirtPkg/ArmVirtCloudHv.dsc
+++ b/ArmVirtPkg/ArmVirtCloudHv.dsc
@@ -201,6 +201,9 @@
[PcdsDynamicHii]
gUefiOvmfPkgTokenSpaceGuid.PcdForceNoAcpi|L"ForceNoAcpi"|gOvmfVariableGuid|0x0|FALSE|NV,BS
+[PcdsPatchableInModule.common]
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
################################################################################
#
# Components Section - list of all EDK II Modules needed by this Platform
diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 20da331966..ae0dd1497f 100644
--- a/ArmVirtPkg/ArmVirtKvmTool.dsc
+++ b/ArmVirtPkg/ArmVirtKvmTool.dsc
@@ -126,8 +126,6 @@
# Use MMIO for accessing RTC controller registers.
gPcAtChipsetPkgTokenSpaceGuid.PcdRtcUseMmio|TRUE
- gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
-
[PcdsFixedAtBuild.common]
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000000F
@@ -167,6 +165,8 @@
#
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|16
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
[PcdsPatchableInModule.common]
#
# This will be overridden in the code
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 7e2ff33ad1..64aa4e96e5 100644
--- a/ArmVirtPkg/ArmVirtQemu.dsc
+++ b/ArmVirtPkg/ArmVirtQemu.dsc
@@ -49,10 +49,10 @@
!include NetworkPkg/NetworkDefines.dsc.inc
-!include ArmVirtPkg/ArmVirt.dsc.inc
-
!include MdePkg/MdeLibs.dsc.inc
+!include ArmVirtPkg/ArmVirt.dsc.inc
+
[LibraryClasses.common]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
@@ -293,6 +293,10 @@
gEfiNetworkPkgTokenSpaceGuid.PcdIPv4PXESupport|0x01
gEfiNetworkPkgTokenSpaceGuid.PcdIPv6PXESupport|0x01
+ # whether to use HVC or SMC to issue monitor calls - this typically depends
+ # on the exception level at which the UEFI system firmware executes
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
#
# TPM2 support
#
@@ -318,11 +322,7 @@
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|L"Timeout"|gEfiGlobalVariableGuid|0x0|5
[LibraryClasses.common.PEI_CORE, LibraryClasses.common.PEIM]
-!if $(TPM2_ENABLE) == TRUE
PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
-!else
- PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
-!endif
################################################################################
#
@@ -339,11 +339,11 @@
ArmVirtPkg/MemoryInitPei/MemoryInitPeim.inf
ArmPkg/Drivers/CpuPei/CpuPei.inf
-!if $(TPM2_ENABLE) == TRUE
MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
<LibraryClasses>
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
}
+!if $(TPM2_ENABLE) == TRUE
MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf {
<LibraryClasses>
ResetSystemLib|ArmVirtPkg/Library/ArmVirtPsciResetSystemPeiLib/ArmVirtPsciResetSystemPeiLib.inf
@@ -432,6 +432,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
}
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
#
# Status Code Routing
@@ -555,6 +556,11 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
#
+ # Hash2 Protocol Support
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# TPM2 support
#
!if $(TPM2_ENABLE) == TRUE
diff --git a/ArmVirtPkg/ArmVirtQemu.fdf b/ArmVirtPkg/ArmVirtQemu.fdf
index 764f652afd..6073a31970 100644
--- a/ArmVirtPkg/ArmVirtQemu.fdf
+++ b/ArmVirtPkg/ArmVirtQemu.fdf
@@ -111,8 +111,8 @@ READ_LOCK_STATUS = TRUE
INF ArmPkg/Drivers/CpuPei/CpuPei.inf
INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
-!if $(TPM2_ENABLE) == TRUE
INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+!if $(TPM2_ENABLE) == TRUE
INF MdeModulePkg/Universal/ResetSystemPei/ResetSystemPei.inf
INF OvmfPkg/Tcg/Tcg2Config/Tcg2ConfigPei.inf
INF SecurityPkg/Tcg/Tcg2Pei/Tcg2Pei.inf
diff --git a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
index c5d097ffb9..38906004d7 100644
--- a/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
+++ b/ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc
@@ -75,6 +75,7 @@ READ_LOCK_STATUS = TRUE
INF ArmPkg/Drivers/TimerDxe/TimerDxe.inf
INF OvmfPkg/VirtNorFlashDxe/VirtNorFlashDxe.inf
INF MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
#
# FAT filesystem + GPT/MBR partitioning + UDF filesystem + virtio-fs
@@ -178,6 +179,11 @@ READ_LOCK_STATUS = TRUE
INF MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
#
+ # Hash2 Protocol producer
+ #
+ INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# TPM2 support
#
!if $(TPM2_ENABLE) == TRUE
diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
index efe2df97bd..2cf96accbd 100644
--- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
+++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
@@ -46,10 +46,10 @@
!include NetworkPkg/NetworkDefines.dsc.inc
-!include ArmVirtPkg/ArmVirt.dsc.inc
-
!include MdePkg/MdeLibs.dsc.inc
+!include ArmVirtPkg/ArmVirt.dsc.inc
+
[LibraryClasses.common]
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
@@ -203,6 +203,8 @@
gArmTokenSpaceGuid.PcdFdBaseAddress|0x0
gArmTokenSpaceGuid.PcdFvBaseAddress|0x0
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
[PcdsDynamicDefault.common]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3
@@ -339,6 +341,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
}
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
#
# Status Code Routing
@@ -462,6 +465,11 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
#
+ # Hash2 Protocol Support
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# ACPI Support
#
OvmfPkg/PlatformHasAcpiDtDxe/PlatformHasAcpiDtDxe.inf
diff --git a/ArmVirtPkg/ArmVirtXen.dsc b/ArmVirtPkg/ArmVirtXen.dsc
index 5809832e66..1505709a29 100644
--- a/ArmVirtPkg/ArmVirtXen.dsc
+++ b/ArmVirtPkg/ArmVirtXen.dsc
@@ -23,10 +23,10 @@
SKUID_IDENTIFIER = DEFAULT
FLASH_DEFINITION = ArmVirtPkg/ArmVirtXen.fdf
-!include ArmVirtPkg/ArmVirt.dsc.inc
-
!include MdePkg/MdeLibs.dsc.inc
+!include ArmVirtPkg/ArmVirt.dsc.inc
+
[LibraryClasses]
SerialPortLib|OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.inf
!if $(TARGET) != RELEASE
@@ -120,6 +120,8 @@
gArmTokenSpaceGuid.PcdFdBaseAddress|0x0
gArmTokenSpaceGuid.PcdFvBaseAddress|0x0
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
[PcdsDynamicDefault.common]
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|0x0
diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
index 7ab4aa2d6b..b8e9208301 100644
--- a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
+++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c
@@ -18,6 +18,8 @@
#include <Library/FdtSerialPortAddressLib.h>
#include <libfdt.h>
+#include <Chipset/AArch64.h>
+
#include <Guid/EarlyPL011BaseAddress.h>
#include <Guid/FdtHob.h>
@@ -224,5 +226,17 @@ PlatformPeim (
BuildFvHob (PcdGet64 (PcdFvBaseAddress), PcdGet32 (PcdFvSize));
+ #ifdef MDE_CPU_AARCH64
+ //
+ // Set the SMCCC conduit to SMC if executing at EL2, which is typically the
+ // exception level that services HVCs rather than the one that invokes them.
+ //
+ if (ArmReadCurrentEL () == AARCH64_EL2) {
+ Status = PcdSetBoolS (PcdMonitorConduitHvc, FALSE);
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ #endif
+
return EFI_SUCCESS;
}
diff --git a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
index e9a34b6e2e..a38b89c103 100644
--- a/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
+++ b/ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.inf
@@ -45,6 +45,7 @@
[Pcd]
gArmTokenSpaceGuid.PcdFvBaseAddress
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc
gEfiSecurityPkgTokenSpaceGuid.PcdTpmBaseAddress ## SOMETIMES_PRODUCES
gUefiOvmfPkgTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
diff --git a/ArmVirtPkg/PlatformCI/PlatformBuildLib.py b/ArmVirtPkg/PlatformCI/PlatformBuildLib.py
index 0ddaccf9c2..3abab09141 100644
--- a/ArmVirtPkg/PlatformCI/PlatformBuildLib.py
+++ b/ArmVirtPkg/PlatformCI/PlatformBuildLib.py
@@ -240,6 +240,8 @@ class PlatformBuilder(UefiBuilder, BuildSettingsManager):
args += " -serial stdio"
# Mount disk with startup.nsh
args += f" -drive file=fat:rw:{VirtualDrive},format=raw,media=disk"
+ # Provides Rng services to the Guest VM
+ args += " -device virtio-rng-pci"
# Conditional Args
if (self.env.GetValue("QEMU_HEADLESS").upper() == "TRUE"):
diff --git a/BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml b/BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml
index 5ec56c6bf0..dbc9c2ba02 100644
--- a/BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml
+++ b/BaseTools/Plugin/CodeQL/codeqlcli_ext_dep.yaml
@@ -16,9 +16,9 @@
"scope": "codeql-ext-dep",
"type": "web",
"name": "codeql_cli",
- "source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.16.1/codeql.zip",
- "version": "2.16.1",
- "sha256": "86a98f6ebb8fd49efadf367f3275c438669fcb8426962c33415129aad8e093e6",
+ "source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.17.3/codeql.zip",
+ "version": "2.17.3",
+ "sha256": "e5ac1d87ab38e405c9af5db234a338b10dffabc98a648903f1664dd2a566dfd5",
"compression_type": "zip",
"internal_path": "/codeql/",
"flags": ["set_shell_var", ],
diff --git a/BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml b/BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml
index 5b4a919f1d..536322f2b3 100644
--- a/BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml
+++ b/BaseTools/Plugin/CodeQL/codeqlcli_linux_ext_dep.yaml
@@ -14,9 +14,9 @@
"scope": "codeql-linux-ext-dep",
"type": "web",
"name": "codeql_linux_cli",
- "source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.16.1/codeql-linux64.zip",
- "version": "2.16.1",
- "sha256": "40dbb6c0c4064bd14601a02e60c61661fdc0271469f90eb91a2e7d51d4cbc171",
+ "source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.17.3/codeql-linux64.zip",
+ "version": "2.17.3",
+ "sha256": "9fba000c4b821534d354bc16821aa066fdb1304446226ea449870e64a8ad3c7a",
"compression_type": "zip",
"internal_path": "/codeql/",
"flags": ["set_shell_var", ],
diff --git a/BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml b/BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml
index c0c018c953..93a81ffd50 100644
--- a/BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml
+++ b/BaseTools/Plugin/CodeQL/codeqlcli_windows_ext_dep.yaml
@@ -14,9 +14,9 @@
"scope": "codeql-windows-ext-dep",
"type": "web",
"name": "codeql_windows_cli",
- "source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.16.1/codeql-win64.zip",
- "version": "2.16.1",
- "sha256": "9ebe5ea8a7d0a77425428d50d49912319117fccee24ecb62f6219c12584f4f28",
+ "source": "https://github.com/github/codeql-cli-binaries/releases/download/v2.17.3/codeql-win64.zip",
+ "version": "2.17.3",
+ "sha256": "4c6fbf2ea2eaf0f47bf0347eacf54c6b9d6bdf7acb6b63e17f9e6f2dd83b34e7",
"compression_type": "zip",
"internal_path": "/codeql/",
"flags": ["set_shell_var", ],
diff --git a/BaseTools/Scripts/PatchCheck.py b/BaseTools/Scripts/PatchCheck.py
index a3b812fb73..762a1a89f9 100755
--- a/BaseTools/Scripts/PatchCheck.py
+++ b/BaseTools/Scripts/PatchCheck.py
@@ -234,8 +234,6 @@ class CommitMessageCheck:
def check_misc_signatures(self):
for sigtype in self.sig_types:
sigs = self.find_signatures(sigtype)
- if sigtype == 'Cc' and len(sigs) == 0:
- self.error('No Cc: tags for maintainers/reviewers found!')
cve_re = re.compile('CVE-[0-9]{4}-[0-9]{5}[^0-9]')
diff --git a/CryptoPkg/CryptoPkgMbedTls.dsc b/CryptoPkg/CryptoPkgMbedTls.dsc
index 5d0ae6ff3f..c97b28c0b5 100644
--- a/CryptoPkg/CryptoPkgMbedTls.dsc
+++ b/CryptoPkg/CryptoPkgMbedTls.dsc
@@ -88,6 +88,7 @@
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
MbedTlsLib|CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf
+ OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index 86f784a1d2..ac5841f1d9 100644
--- a/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -2351,6 +2351,8 @@ Pkcs7FreeSigners (
unchained to the signer's certificates.
The input signed data could be wrapped in a ContentInfo structure.
+ Pkcs7GetCertificatesList has not been implemented in BaseCryptoLibMbedTls.
+
@param[in] P7Data Pointer to the PKCS#7 message.
@param[in] P7Length Length of the PKCS#7 message in bytes.
@param[out] SignerChainCerts Pointer to the certificates list chained to signer's
@@ -3139,6 +3141,8 @@ DhComputeKey (
If Seed is NULL, then default seed is used.
If this interface is not supported, then return FALSE.
+ RandomSeed has not been implemented in BaseCryptoLibMbedTls.
+
@param[in] Seed Pointer to seed value.
If NULL, default seed is used.
@param[in] SeedSize Size of seed value.
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
index 1182323b63..7ebec9dbad 100644
--- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptX509.c
@@ -839,17 +839,17 @@ X509GetTBSCert (
Length = 0;
Inf = ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)CertSize);
- if (((Inf & 0x80) == 0x00) && (Asn1Tag != V_ASN1_SEQUENCE)) {
+ if (((Inf & 0x80) == 0x80) && (Asn1Tag != V_ASN1_SEQUENCE)) {
return FALSE;
}
*TBSCert = (UINT8 *)Temp;
- ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length);
+ Inf = ASN1_get_object (&Temp, (long *)&Length, (int *)&Asn1Tag, (int *)&ObjClass, (long)Length);
//
// Verify the parsed TBSCertificate is one correct SEQUENCE data.
//
- if (((Inf & 0x80) == 0x00) && (Asn1Tag != V_ASN1_SEQUENCE)) {
+ if (((Inf & 0x80) == 0x80) && (Asn1Tag != V_ASN1_SEQUENCE)) {
return FALSE;
}
diff --git a/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c b/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c
index 9e2fcefe08..51c7435898 100644
--- a/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c
+++ b/CryptoPkg/Library/BaseCryptLib/Rand/CryptRand.c
@@ -43,14 +43,6 @@ RandomSeed (
}
//
- // The software PRNG implementation built in OpenSSL depends on message digest algorithm.
- // Make sure SHA-1 digest algorithm is available here.
- //
- if (EVP_add_digest (EVP_sha1 ()) == 0) {
- return FALSE;
- }
-
- //
// Seed the pseudorandom number generator with user-supplied value.
// NOTE: A cryptographic PRNG must be seeded with unpredictable data.
//
diff --git a/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c b/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c
index 30454bf10f..b94c16de56 100644
--- a/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c
+++ b/CryptoPkg/Library/BaseCryptLib/Rand/CryptRandTsc.c
@@ -41,14 +41,6 @@ RandomSeed (
}
//
- // The software PRNG implementation built in OpenSSL depends on message digest algorithm.
- // Make sure SHA-1 digest algorithm is available here.
- //
- if (EVP_add_digest (EVP_sha1 ()) == 0) {
- return FALSE;
- }
-
- //
// Seed the pseudorandom number generator with user-supplied value.
// NOTE: A cryptographic PRNG must be seeded with unpredictable data.
//
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf
index 16def792c5..b76b4e6067 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/BaseCryptLib.inf
@@ -27,34 +27,38 @@
[Sources]
InternalCryptLib.h
- Cipher/CryptAeadAesGcmNull.c
- Cipher/CryptAes.c
+ Hash/CryptMd5.c
+ Hash/CryptSha1.c
Hash/CryptSha256.c
Hash/CryptSha512.c
Hash/CryptParallelHashNull.c
- Hash/CryptSm3Null.c
- Hash/CryptMd5.c
- Hash/CryptSha1.c
+ Hash/CryptSm3.c
Hmac/CryptHmac.c
Kdf/CryptHkdf.c
+ Cipher/CryptAes.c
+ Cipher/CryptAeadAesGcm.c
Pk/CryptRsaBasic.c
- Pk/CryptRsaExtNull.c
- Pk/CryptRsaPss.c
- Pk/CryptRsaPssSignNull.c
- Bn/CryptBnNull.c
- Pem/CryptPemNull.c
+ Pk/CryptRsaExt.c
+ Pk/CryptPkcs1Oaep.c
+ Pk/CryptPkcs5Pbkdf2.c
+ Pk/CryptPkcs7Sign.c
+ Pk/CryptPkcs7VerifyCommon.c
+ Pk/CryptPkcs7VerifyBase.c
+ Pk/CryptPkcs7VerifyEku.c
Pk/CryptDhNull.c
+ Pk/CryptX509.c
+ Pk/CryptAuthenticode.c
+ Pk/CryptTs.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSign.c
Pk/CryptEcNull.c
- Pk/CryptPkcs1OaepNull.c
- Pk/CryptPkcs5Pbkdf2Null.c
- Pk/CryptPkcs7SignNull.c
- Pk/CryptPkcs7VerifyNull.c
- Pk/CryptPkcs7VerifyEkuNull.c
- Pk/CryptX509Null.c
- Pk/CryptAuthenticodeNull.c
- Pk/CryptTsNull.c
- Rand/CryptRandNull.c
+ Pem/CryptPem.c
+ Bn/CryptBnNull.c
+ Rand/CryptRand.c
+
SysCall/CrtWrapper.c
+ SysCall/DummyOpensslSupport.c
+ SysCall/BaseMemAllocation.c
SysCall/TimerWrapper.c
[Packages]
@@ -68,6 +72,7 @@
UefiRuntimeServicesTableLib
DebugLib
MbedTlsLib
+ OpensslLib
PrintLib
IntrinsicLib
RngLib
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c
new file mode 100644
index 0000000000..b49d6f9f87
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Cipher/CryptAeadAesGcm.c
@@ -0,0 +1,227 @@
+/** @file
+ AEAD (AES-GCM) Wrapper Implementation over MbedTLS.
+
+ RFC 5116 - An Interface and Algorithms for Authenticated Encryption
+ NIST SP800-38d - Cipher Modes of Operation: Galois / Counter Mode(GCM) and GMAC
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/gcm.h>
+
+/**
+ Performs AEAD AES-GCM authenticated encryption on a data buffer and additional authenticated data (AAD).
+
+ IvSize must be 12, otherwise FALSE is returned.
+ KeySize must be 16, 24 or 32, otherwise FALSE is returned.
+ TagSize must be 12, 13, 14, 15, 16, otherwise FALSE is returned.
+
+ @param[in] Key Pointer to the encryption key.
+ @param[in] KeySize Size of the encryption key in bytes.
+ @param[in] Iv Pointer to the IV value.
+ @param[in] IvSize Size of the IV value in bytes.
+ @param[in] AData Pointer to the additional authenticated data (AAD).
+ @param[in] ADataSize Size of the additional authenticated data (AAD) in bytes.
+ @param[in] DataIn Pointer to the input data buffer to be encrypted.
+ @param[in] DataInSize Size of the input data buffer in bytes.
+ @param[out] TagOut Pointer to a buffer that receives the authentication tag output.
+ @param[in] TagSize Size of the authentication tag in bytes.
+ @param[out] DataOut Pointer to a buffer that receives the encryption output.
+ @param[out] DataOutSize Size of the output data buffer in bytes.
+
+ @retval TRUE AEAD AES-GCM authenticated encryption succeeded.
+ @retval FALSE AEAD AES-GCM authenticated encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+AeadAesGcmEncrypt (
+ IN CONST UINT8 *Key,
+ IN UINTN KeySize,
+ IN CONST UINT8 *Iv,
+ IN UINTN IvSize,
+ IN CONST UINT8 *AData,
+ IN UINTN ADataSize,
+ IN CONST UINT8 *DataIn,
+ IN UINTN DataInSize,
+ OUT UINT8 *TagOut,
+ IN UINTN TagSize,
+ OUT UINT8 *DataOut,
+ OUT UINTN *DataOutSize
+ )
+{
+ mbedtls_gcm_context Ctx;
+ INT32 Ret;
+
+ if (DataInSize > INT_MAX) {
+ return FALSE;
+ }
+
+ if (ADataSize > INT_MAX) {
+ return FALSE;
+ }
+
+ if (IvSize != 12) {
+ return FALSE;
+ }
+
+ switch (KeySize) {
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ return FALSE;
+ }
+
+ if ((TagSize != 12) && (TagSize != 13) && (TagSize != 14) && (TagSize != 15) && (TagSize != 16)) {
+ return FALSE;
+ }
+
+ if (DataOutSize != NULL) {
+ if ((*DataOutSize > INT_MAX) || (*DataOutSize < DataInSize)) {
+ return FALSE;
+ }
+ }
+
+ mbedtls_gcm_init (&Ctx);
+
+ Ret = mbedtls_gcm_setkey (&Ctx, MBEDTLS_CIPHER_ID_AES, Key, (UINT32)(KeySize * 8));
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_gcm_crypt_and_tag (
+ &Ctx,
+ MBEDTLS_GCM_ENCRYPT,
+ (UINT32)DataInSize,
+ Iv,
+ (UINT32)IvSize,
+ AData,
+ (UINT32)ADataSize,
+ DataIn,
+ DataOut,
+ TagSize,
+ TagOut
+ );
+ mbedtls_gcm_free (&Ctx);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ if (DataOutSize != NULL) {
+ *DataOutSize = DataInSize;
+ }
+
+ return TRUE;
+}
+
+/**
+ Performs AEAD AES-GCM authenticated decryption on a data buffer and additional authenticated data (AAD).
+
+ IvSize must be 12, otherwise FALSE is returned.
+ KeySize must be 16, 24 or 32, otherwise FALSE is returned.
+ TagSize must be 12, 13, 14, 15, 16, otherwise FALSE is returned.
+ If additional authenticated data verification fails, FALSE is returned.
+
+ @param[in] Key Pointer to the encryption key.
+ @param[in] KeySize Size of the encryption key in bytes.
+ @param[in] Iv Pointer to the IV value.
+ @param[in] IvSize Size of the IV value in bytes.
+ @param[in] AData Pointer to the additional authenticated data (AAD).
+ @param[in] ADataSize Size of the additional authenticated data (AAD) in bytes.
+ @param[in] DataIn Pointer to the input data buffer to be decrypted.
+ @param[in] DataInSize Size of the input data buffer in bytes.
+ @param[in] Tag Pointer to a buffer that contains the authentication tag.
+ @param[in] TagSize Size of the authentication tag in bytes.
+ @param[out] DataOut Pointer to a buffer that receives the decryption output.
+ @param[out] DataOutSize Size of the output data buffer in bytes.
+
+ @retval TRUE AEAD AES-GCM authenticated decryption succeeded.
+ @retval FALSE AEAD AES-GCM authenticated decryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+AeadAesGcmDecrypt (
+ IN CONST UINT8 *Key,
+ IN UINTN KeySize,
+ IN CONST UINT8 *Iv,
+ IN UINTN IvSize,
+ IN CONST UINT8 *AData,
+ IN UINTN ADataSize,
+ IN CONST UINT8 *DataIn,
+ IN UINTN DataInSize,
+ IN CONST UINT8 *Tag,
+ IN UINTN TagSize,
+ OUT UINT8 *DataOut,
+ OUT UINTN *DataOutSize
+ )
+{
+ mbedtls_gcm_context Ctx;
+ INT32 Ret;
+
+ if (DataInSize > INT_MAX) {
+ return FALSE;
+ }
+
+ if (ADataSize > INT_MAX) {
+ return FALSE;
+ }
+
+ if (IvSize != 12) {
+ return FALSE;
+ }
+
+ switch (KeySize) {
+ case 16:
+ case 24:
+ case 32:
+ break;
+ default:
+ return FALSE;
+ }
+
+ if ((TagSize != 12) && (TagSize != 13) && (TagSize != 14) && (TagSize != 15) && (TagSize != 16)) {
+ return FALSE;
+ }
+
+ if (DataOutSize != NULL) {
+ if ((*DataOutSize > INT_MAX) || (*DataOutSize < DataInSize)) {
+ return FALSE;
+ }
+ }
+
+ mbedtls_gcm_init (&Ctx);
+
+ Ret = mbedtls_gcm_setkey (&Ctx, MBEDTLS_CIPHER_ID_AES, Key, (UINT32)(KeySize * 8));
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_gcm_auth_decrypt (
+ &Ctx,
+ (UINT32)DataInSize,
+ Iv,
+ (UINT32)IvSize,
+ AData,
+ (UINT32)ADataSize,
+ Tag,
+ (UINT32)TagSize,
+ DataIn,
+ DataOut
+ );
+ mbedtls_gcm_free (&Ctx);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ if (DataOutSize != NULL) {
+ *DataOutSize = DataInSize;
+ }
+
+ return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Hash/CryptSm3.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Hash/CryptSm3.c
new file mode 100644
index 0000000000..1a442d714e
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Hash/CryptSm3.c
@@ -0,0 +1,235 @@
+/** @file
+ SM3 Digest Wrapper Implementations over openssl.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include "internal/sm3.h"
+
+/**
+ Retrieves the size, in bytes, of the context buffer required for SM3 hash operations.
+
+ @return The size, in bytes, of the context buffer required for SM3 hash operations.
+
+**/
+UINTN
+EFIAPI
+Sm3GetContextSize (
+ VOID
+ )
+{
+ //
+ // Retrieves Openssl SM3 Context Size
+ //
+ return (UINTN)(sizeof (SM3_CTX));
+}
+
+/**
+ Initializes user-supplied memory pointed by Sm3Context as SM3 hash context for
+ subsequent use.
+
+ If Sm3Context is NULL, then return FALSE.
+
+ @param[out] Sm3Context Pointer to SM3 context being initialized.
+
+ @retval TRUE SM3 context initialization succeeded.
+ @retval FALSE SM3 context initialization failed.
+
+**/
+BOOLEAN
+EFIAPI
+Sm3Init (
+ OUT VOID *Sm3Context
+ )
+{
+ //
+ // Check input parameters.
+ //
+ if (Sm3Context == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Openssl SM3 Context Initialization
+ //
+ ossl_sm3_init ((SM3_CTX *)Sm3Context);
+ return TRUE;
+}
+
+/**
+ Makes a copy of an existing SM3 context.
+
+ If Sm3Context is NULL, then return FALSE.
+ If NewSm3Context is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] Sm3Context Pointer to SM3 context being copied.
+ @param[out] NewSm3Context Pointer to new SM3 context.
+
+ @retval TRUE SM3 context copy succeeded.
+ @retval FALSE SM3 context copy failed.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+Sm3Duplicate (
+ IN CONST VOID *Sm3Context,
+ OUT VOID *NewSm3Context
+ )
+{
+ //
+ // Check input parameters.
+ //
+ if ((Sm3Context == NULL) || (NewSm3Context == NULL)) {
+ return FALSE;
+ }
+
+ CopyMem (NewSm3Context, Sm3Context, sizeof (SM3_CTX));
+
+ return TRUE;
+}
+
+/**
+ Digests the input data and updates SM3 context.
+
+ This function performs SM3 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.
+ SM3 context should be already correctly initialized by Sm3Init(), and should not be finalized
+ by Sm3Final(). Behavior with invalid context is undefined.
+
+ If Sm3Context is NULL, then return FALSE.
+
+ @param[in, out] Sm3Context Pointer to the SM3 context.
+ @param[in] Data Pointer to the buffer containing the data to be hashed.
+ @param[in] DataSize Size of Data buffer in bytes.
+
+ @retval TRUE SM3 data digest succeeded.
+ @retval FALSE SM3 data digest failed.
+
+**/
+BOOLEAN
+EFIAPI
+Sm3Update (
+ IN OUT VOID *Sm3Context,
+ IN CONST VOID *Data,
+ IN UINTN DataSize
+ )
+{
+ //
+ // Check input parameters.
+ //
+ if (Sm3Context == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Check invalid parameters, in case that only DataLength was checked in Openssl
+ //
+ if ((Data == NULL) && (DataSize != 0)) {
+ return FALSE;
+ }
+
+ //
+ // Openssl SM3 Hash Update
+ //
+ ossl_sm3_update ((SM3_CTX *)Sm3Context, Data, DataSize);
+
+ return TRUE;
+}
+
+/**
+ Completes computation of the SM3 digest value.
+
+ This function completes SM3 hash computation and retrieves the digest value into
+ the specified memory. After this function has been called, the SM3 context cannot
+ be used again.
+ SM3 context should be already correctly initialized by Sm3Init(), and should not be
+ finalized by Sm3Final(). Behavior with invalid SM3 context is undefined.
+
+ If Sm3Context is NULL, then return FALSE.
+ If HashValue is NULL, then return FALSE.
+
+ @param[in, out] Sm3Context Pointer to the SM3 context.
+ @param[out] HashValue Pointer to a buffer that receives the SM3 digest
+ value (32 bytes).
+
+ @retval TRUE SM3 digest computation succeeded.
+ @retval FALSE SM3 digest computation failed.
+
+**/
+BOOLEAN
+EFIAPI
+Sm3Final (
+ IN OUT VOID *Sm3Context,
+ OUT UINT8 *HashValue
+ )
+{
+ //
+ // Check input parameters.
+ //
+ if ((Sm3Context == NULL) || (HashValue == NULL)) {
+ return FALSE;
+ }
+
+ //
+ // Openssl SM3 Hash Finalization
+ //
+ ossl_sm3_final (HashValue, (SM3_CTX *)Sm3Context);
+
+ return TRUE;
+}
+
+/**
+ Computes the SM3 message digest of a input data buffer.
+
+ This function performs the SM3 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 SM3 digest
+ value (32 bytes).
+
+ @retval TRUE SM3 digest computation succeeded.
+ @retval FALSE SM3 digest computation failed.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+Sm3HashAll (
+ IN CONST VOID *Data,
+ IN UINTN DataSize,
+ OUT UINT8 *HashValue
+ )
+{
+ SM3_CTX Ctx;
+
+ //
+ // Check input parameters.
+ //
+ if (HashValue == NULL) {
+ return FALSE;
+ }
+
+ if ((Data == NULL) && (DataSize != 0)) {
+ return FALSE;
+ }
+
+ //
+ // SM3 Hash Computation.
+ //
+ ossl_sm3_init (&Ctx);
+
+ ossl_sm3_update (&Ctx, Data, DataSize);
+
+ ossl_sm3_final (HashValue, &Ctx);
+
+ return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
index 039aa32028..c9f19dd0cd 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
@@ -22,4 +22,53 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
#include <mbedtls/mbedtls_config.h>
+/**
+ The MbedTLS function f_rng, which MbedtlsRand implements.
+
+ @param[in] RngState Not used, just for compatibility with mbedlts.
+ @param[out] Output Pointer to buffer to receive random value.
+ @param[in] Len Size of random bytes to generate.
+
+ @retval 0 Pseudorandom byte stream generated successfully.
+ @retval Non-0 Pseudorandom number generator fails to generate due to lack of entropy.
+**/
+INT32
+MbedtlsRand (
+ VOID *RngState,
+ UINT8 *Output,
+ UINTN Len
+ );
+
+/**
+ Check input P7Data is a wrapped ContentInfo structure or not. If not construct
+ a new structure to wrap P7Data.
+
+ Caution: This function may receive untrusted input.
+ UEFI Authenticated Variable is external input, so this function will do basic
+ check for PKCS#7 data structure.
+
+ @param[in] P7Data Pointer to the PKCS#7 message to verify.
+ @param[in] P7Length Length of the PKCS#7 message in bytes.
+ @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise
+ return FALSE.
+ @param[out] WrapData If return status of this function is TRUE:
+ 1) when WrapFlag is TRUE, pointer to P7Data.
+ 2) when WrapFlag is FALSE, pointer to a new ContentInfo
+ structure. It's caller's responsibility to free this
+ buffer.
+ @param[out] WrapDataSize Length of ContentInfo structure in bytes.
+
+ @retval TRUE The operation is finished successfully.
+ @retval FALSE The operation is failed due to lack of resources.
+
+**/
+BOOLEAN
+WrapPkcs7Data (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ OUT BOOLEAN *WrapFlag,
+ OUT UINT8 **WrapData,
+ OUT UINTN *WrapDataSize
+ );
+
#endif
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf
index 72b22a24e8..3c057660d8 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/PeiCryptLib.inf
@@ -38,31 +38,35 @@
Hash/CryptMd5.c
Hash/CryptSha1.c
Hash/CryptSha256.c
- Hash/CryptSm3Null.c
Hash/CryptSha512.c
Hash/CryptParallelHashNull.c
+ Hash/CryptSm3.c
Hmac/CryptHmac.c
Kdf/CryptHkdf.c
Cipher/CryptAes.c
Cipher/CryptAeadAesGcmNull.c
Pk/CryptRsaBasic.c
Pk/CryptRsaExtNull.c
- Pk/CryptRsaPss.c
- Pk/CryptRsaPssSignNull.c
- Bn/CryptBnNull.c
- Pem/CryptPemNull.c
- Pk/CryptDhNull.c
- Pk/CryptEcNull.c
Pk/CryptPkcs1OaepNull.c
Pk/CryptPkcs5Pbkdf2Null.c
Pk/CryptPkcs7SignNull.c
- Pk/CryptPkcs7VerifyNull.c
- Pk/CryptPkcs7VerifyEkuNull.c
+ Pk/CryptPkcs7VerifyCommon.c
+ Pk/CryptPkcs7VerifyBase.c
+ Pk/CryptPkcs7VerifyEku.c
+ Pk/CryptDhNull.c
Pk/CryptX509Null.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSignNull.c
+ Pk/CryptEcNull.c
+ Pem/CryptPemNull.c
Rand/CryptRandNull.c
+ Bn/CryptBnNull.c
+
SysCall/CrtWrapper.c
+ SysCall/DummyOpensslSupport.c
+ SysCall/BaseMemAllocation.c
SysCall/ConstantTimeClock.c
[Packages]
@@ -75,6 +79,7 @@
MemoryAllocationLib
DebugLib
MbedTlsLib
+ OpensslLib
IntrinsicLib
PrintLib
PeiServicesTablePointerLib
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c
new file mode 100644
index 0000000000..56411174dd
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pem/CryptPem.c
@@ -0,0 +1,138 @@
+/** @file
+ PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pem.h>
+#include <mbedtls/pk.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/ecdsa.h>
+
+/**
+ Retrieve the RSA Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
+ RSA private key component. Use RsaFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If RsaContext is NULL, then return FALSE.
+
+ @retval TRUE RSA Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **RsaContext
+ )
+{
+ INT32 Ret;
+ mbedtls_pk_context Pk;
+ mbedtls_rsa_context *Rsa;
+ UINT8 *NewPemData;
+ UINTN PasswordLen;
+
+ if ((PemData == NULL) || (RsaContext == NULL) || (PemSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ NewPemData = NULL;
+ if (PemData[PemSize - 1] != 0) {
+ NewPemData = AllocateZeroPool (PemSize + 1);
+ if (NewPemData == NULL) {
+ return FALSE;
+ }
+
+ CopyMem (NewPemData, PemData, PemSize + 1);
+ NewPemData[PemSize] = 0;
+ PemData = NewPemData;
+ PemSize += 1;
+ }
+
+ mbedtls_pk_init (&Pk);
+
+ if (Password != NULL) {
+ PasswordLen = AsciiStrLen (Password);
+ } else {
+ PasswordLen = 0;
+ }
+
+ Ret = mbedtls_pk_parse_key (&Pk, PemData, PemSize, (CONST UINT8 *)Password, PasswordLen, NULL, NULL);
+
+ if (NewPemData != NULL) {
+ FreePool (NewPemData);
+ NewPemData = NULL;
+ }
+
+ if (Ret != 0) {
+ mbedtls_pk_free (&Pk);
+ return FALSE;
+ }
+
+ if (mbedtls_pk_get_type (&Pk) != MBEDTLS_PK_RSA) {
+ mbedtls_pk_free (&Pk);
+ return FALSE;
+ }
+
+ Rsa = RsaNew ();
+ if (Rsa == NULL) {
+ mbedtls_pk_free (&Pk);
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_copy (Rsa, mbedtls_pk_rsa (Pk));
+ if (Ret != 0) {
+ RsaFree (Rsa);
+ mbedtls_pk_free (&Pk);
+ return FALSE;
+ }
+
+ mbedtls_pk_free (&Pk);
+
+ *RsaContext = Rsa;
+ return TRUE;
+}
+
+/**
+ Retrieve the EC Private Key from the password-protected PEM key data.
+
+ @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
+ @param[in] PemSize Size of the PEM key data in bytes.
+ @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC private key component. Use EcFree() function to free the
+ resource.
+
+ If PemData is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Private Key was retrieved successfully.
+ @retval FALSE Invalid PEM key data or incorrect password.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPrivateKeyFromPem (
+ IN CONST UINT8 *PemData,
+ IN UINTN PemSize,
+ IN CONST CHAR8 *Password,
+ OUT VOID **EcContext
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c
new file mode 100644
index 0000000000..9d8301b2c0
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptAuthenticode.c
@@ -0,0 +1,214 @@
+/** @file
+ Authenticode Portable Executable Signature Verification which does not provide
+ real capabilities.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
+
+//
+// OID ASN.1 Value for SPC_INDIRECT_DATA_OBJID
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSpcIndirectOidValue[] = {
+ 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04
+};
+
+/**
+ Verifies the validity of a PE/COFF Authenticode Signature as described in "Windows
+ Authenticode Portable Executable Signature Format".
+
+ Return FALSE to indicate this interface is not supported.
+
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed
+ PE/COFF image to be verified.
+ @param[in] DataSize Size of the Authenticode Signature in bytes.
+ @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which
+ is used for certificate chain verification.
+ @param[in] CertSize Size of the trusted certificate in bytes.
+ @param[in] ImageHash Pointer to the original image file hash value. The procedure
+ for calculating the image hash value is described in Authenticode
+ specification.
+ @param[in] HashSize Size of Image hash value in bytes.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+AuthenticodeVerify (
+ IN CONST UINT8 *AuthData,
+ IN UINTN DataSize,
+ IN CONST UINT8 *TrustedCert,
+ IN UINTN CertSize,
+ IN CONST UINT8 *ImageHash,
+ IN UINTN HashSize
+ )
+{
+ BOOLEAN Status;
+ CONST UINT8 *OrigAuthData;
+ UINT8 *SpcIndirectDataContent;
+ UINT8 Asn1Byte;
+ UINTN ContentSize;
+ CONST UINT8 *SpcIndirectDataOid;
+ UINT8 *Ptr;
+ UINT8 *End;
+ INT32 Len;
+ UINTN ObjLen;
+
+ OrigAuthData = AuthData;
+
+ //
+ // Check input parameters.
+ //
+ if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) {
+ return FALSE;
+ }
+
+ if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ if (DataSize <= HashSize) {
+ return FALSE;
+ }
+
+ Ptr = (UINT8 *)(UINTN)AuthData;
+ Len = (UINT32)DataSize;
+ End = Ptr + Len;
+
+ // ContentInfo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // ContentType
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // content
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ End = Ptr + ObjLen;
+ // signedData
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // version
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // digestAlgo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // encapContentInfo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ End = Ptr + ObjLen;
+ // eContentType
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+
+ SpcIndirectDataOid = Ptr;
+ if ((ObjLen != sizeof (mSpcIndirectOidValue)) ||
+ (CompareMem (
+ SpcIndirectDataOid,
+ mSpcIndirectOidValue,
+ sizeof (mSpcIndirectOidValue)
+ ) != 0))
+ {
+ //
+ // Un-matched SPC_INDIRECT_DATA_OBJID.
+ //
+ goto _Exit;
+ }
+
+ Ptr += ObjLen;
+ // eContent
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ SpcIndirectDataContent = Ptr;
+
+ //
+ // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent.
+ //
+ Asn1Byte = *(SpcIndirectDataContent + 1);
+
+ if ((Asn1Byte & 0x80) == 0) {
+ //
+ // Short Form of Length Encoding (Length < 128)
+ //
+ ContentSize = (UINTN)(Asn1Byte & 0x7F);
+ //
+ // Skip the SEQUENCE Tag;
+ //
+ SpcIndirectDataContent += 2;
+ } else if ((Asn1Byte & 0x81) == 0x81) {
+ //
+ // Long Form of Length Encoding (128 <= Length < 255, Single Octet)
+ //
+ ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));
+ //
+ // Skip the SEQUENCE Tag;
+ //
+ SpcIndirectDataContent += 3;
+ } else if ((Asn1Byte & 0x82) == 0x82) {
+ //
+ // Long Form of Length Encoding (Length > 255, Two Octet)
+ //
+ ContentSize = (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 2));
+ ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3));
+ //
+ // Skip the SEQUENCE Tag;
+ //
+ SpcIndirectDataContent += 4;
+ } else {
+ goto _Exit;
+ }
+
+ //
+ // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent
+ // defined in Authenticode
+ // NOTE: Need to double-check HashLength here!
+ //
+ if (ContentSize < HashSize) {
+ return FALSE;
+ }
+
+ if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) {
+ //
+ // Un-matched PE/COFF Hash Value
+ //
+ goto _Exit;
+ }
+
+ //
+ // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature
+ //
+ Status = (BOOLEAN)Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);
+
+_Exit:
+
+ return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
new file mode 100644
index 0000000000..61ccdd78e6
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
@@ -0,0 +1,278 @@
+/** @file
+ This file contains UEFI wrapper functions for RSA PKCS1v2 OAEP encryption routines.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+#include <mbedtls/x509_crt.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ encrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - X509 key size does not match any known key size.
+ - Fail to parse X509 certificate.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+ - Data size is too large for the provided key size (max size is a function of key size
+ and hash digest size).
+
+ @param[in] PublicKey A pointer to the DER-encoded X509 certificate that
+ will be used to encrypt the data.
+ @param[in] PublicKeySize Size of the X509 cert buffer.
+ @param[in] InData Data to be encrypted.
+ @param[in] InDataSize Size of the data buffer.
+ @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer
+ to be used when initializing the PRNG. NULL otherwise.
+ @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer.
+ 0 otherwise.
+ @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] EncryptedDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs1v2Encrypt (
+ IN CONST UINT8 *PublicKey,
+ IN UINTN PublicKeySize,
+ IN UINT8 *InData,
+ IN UINTN InDataSize,
+ IN CONST UINT8 *PrngSeed OPTIONAL,
+ IN UINTN PrngSeedSize OPTIONAL,
+ OUT UINT8 **EncryptedData,
+ OUT UINTN *EncryptedDataSize
+ )
+{
+ BOOLEAN Result;
+ UINT32 Ret;
+ UINT8 *OutData;
+ mbedtls_x509_crt CertContext;
+ mbedtls_rsa_context RsaContext;
+
+ //
+ // Check input parameters.
+ //
+ if ((PublicKey == NULL) || (InData == NULL) ||
+ (EncryptedData == NULL) || (EncryptedDataSize == NULL))
+ {
+ return FALSE;
+ }
+
+ //
+ // Check public key size.
+ //
+ if (PublicKeySize > UINT_MAX) {
+ //
+ // Public key size is too large for implementation.
+ //
+ return FALSE;
+ }
+
+ *EncryptedData = NULL;
+ *EncryptedDataSize = 0;
+ Result = FALSE;
+ OutData = NULL;
+
+ mbedtls_x509_crt_init (&CertContext);
+
+ if (mbedtls_x509_crt_parse_der (&CertContext, PublicKey, (UINT32)PublicKeySize) != 0) {
+ goto _Exit;
+ }
+
+ if (mbedtls_pk_get_type (&CertContext.pk) != MBEDTLS_PK_RSA) {
+ goto _Exit;
+ }
+
+ mbedtls_rsa_init (&RsaContext);
+ if (mbedtls_rsa_set_padding (&RsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE) != 0) {
+ goto _Exit;
+ }
+
+ Ret = mbedtls_rsa_copy (&RsaContext, mbedtls_pk_rsa (CertContext.pk));
+ if (Ret != 0) {
+ goto _Exit;
+ }
+
+ *EncryptedDataSize = RsaContext.len;
+
+ //
+ // Allocate a buffer for the output data.
+ //
+ OutData = AllocateZeroPool (*EncryptedDataSize);
+ if (OutData == NULL) {
+ //
+ // Fail to allocate the output buffer.
+ //
+ goto _Exit;
+ }
+
+ Ret = mbedtls_rsa_pkcs1_encrypt (
+ &RsaContext,
+ MbedtlsRand,
+ NULL,
+ InDataSize,
+ InData,
+ OutData
+ );
+ if (Ret != 0) {
+ FreePool (OutData);
+ OutData = NULL;
+ goto _Exit;
+ }
+
+ *EncryptedData = OutData;
+ Result = TRUE;
+
+_Exit:
+ //
+ // Release Resources
+ //
+ if (&CertContext != NULL) {
+ mbedtls_x509_crt_free (&CertContext);
+ }
+
+ if (&RsaContext != NULL) {
+ mbedtls_rsa_free (&RsaContext);
+ }
+
+ return Result;
+}
+
+/**
+ Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ encrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - X509 key size does not match any known key size.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+ - Data size is too large for the provided key size (max size is a function of key size
+ and hash digest size).
+
+ @param[in] RsaContext A pointer to an RSA context created by RsaNew() and
+ provisioned with a public key using RsaSetKey().
+ @param[in] InData Data to be encrypted.
+ @param[in] InDataSize Size of the data buffer.
+ @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer
+ to be used when initializing the PRNG. NULL otherwise.
+ @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer.
+ 0 otherwise.
+ @param[in] DigestLen [Optional] If provided, size of the hash used:
+ SHA1_DIGEST_SIZE
+ SHA256_DIGEST_SIZE
+ SHA384_DIGEST_SIZE
+ SHA512_DIGEST_SIZE
+ 0 to use default (SHA1)
+ @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] EncryptedDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+RsaOaepEncrypt (
+ IN VOID *RsaContext,
+ IN UINT8 *InData,
+ IN UINTN InDataSize,
+ IN CONST UINT8 *PrngSeed OPTIONAL,
+ IN UINTN PrngSeedSize OPTIONAL,
+ IN UINT16 DigestLen OPTIONAL,
+ OUT UINT8 **EncryptedData,
+ OUT UINTN *EncryptedDataSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ decrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - Fail to parse private key.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+
+ @param[in] PrivateKey A pointer to the DER-encoded private key.
+ @param[in] PrivateKeySize Size of the private key buffer.
+ @param[in] EncryptedData Data to be decrypted.
+ @param[in] EncryptedDataSize Size of the encrypted buffer.
+ @param[out] OutData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] OutDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs1v2Decrypt (
+ IN CONST UINT8 *PrivateKey,
+ IN UINTN PrivateKeySize,
+ IN UINT8 *EncryptedData,
+ IN UINTN EncryptedDataSize,
+ OUT UINT8 **OutData,
+ OUT UINTN *OutDataSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ decrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - Fail to parse private key.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+
+ @param[in] RsaContext A pointer to an RSA context created by RsaNew() and
+ provisioned with a private key using RsaSetKey().
+ @param[in] EncryptedData Data to be decrypted.
+ @param[in] EncryptedDataSize Size of the encrypted buffer.
+ @param[in] DigestLen [Optional] If provided, size of the hash used:
+ SHA1_DIGEST_SIZE
+ SHA256_DIGEST_SIZE
+ SHA384_DIGEST_SIZE
+ SHA512_DIGEST_SIZE
+ 0 to use default (SHA1)
+ @param[out] OutData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] OutDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+RsaOaepDecrypt (
+ IN VOID *RsaContext,
+ IN UINT8 *EncryptedData,
+ IN UINTN EncryptedDataSize,
+ IN UINT16 DigestLen OPTIONAL,
+ OUT UINT8 **OutData,
+ OUT UINTN *OutDataSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c
new file mode 100644
index 0000000000..94f1fcfa3b
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs5Pbkdf2.c
@@ -0,0 +1,100 @@
+/** @file
+ PBKDF2 Key Derivation Function Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs5.h>
+
+/**
+ Derives a key from a password using a salt and iteration count, based on PKCS#5 v2.0
+ password based encryption key derivation function PBKDF2, as specified in RFC 2898.
+
+ If Password or Salt or OutKey is NULL, then return FALSE.
+ If the hash algorithm could not be determined, then return FALSE.
+
+ @param[in] PasswordLength Length of input password in bytes.
+ @param[in] Password Pointer to the array for the password.
+ @param[in] SaltLength Size of the Salt in bytes.
+ @param[in] Salt Pointer to the Salt.
+ @param[in] IterationCount Number of iterations to perform. Its value should be
+ greater than or equal to 1.
+ @param[in] DigestSize Size of the message digest to be used (eg. SHA256_DIGEST_SIZE).
+ NOTE: DigestSize will be used to determine the hash algorithm.
+ Only SHA1_DIGEST_SIZE or SHA256_DIGEST_SIZE is supported.
+ @param[in] KeyLength Size of the derived key buffer in bytes.
+ @param[out] OutKey Pointer to the output derived key buffer.
+
+ @retval TRUE A key was derived successfully.
+ @retval FALSE One of the pointers was NULL or one of the sizes was too large.
+ @retval FALSE The hash algorithm could not be determined from the digest size.
+ @retval FALSE The key derivation operation failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs5HashPassword (
+ IN UINTN PasswordLength,
+ IN CONST CHAR8 *Password,
+ IN UINTN SaltLength,
+ IN CONST UINT8 *Salt,
+ IN UINTN IterationCount,
+ IN UINTN DigestSize,
+ IN UINTN KeyLength,
+ OUT UINT8 *OutKey
+ )
+{
+ mbedtls_md_type_t HashAlg;
+
+ //
+ // Parameter Checking.
+ //
+ if ((Password == NULL) || (Salt == NULL) || (OutKey == NULL)) {
+ return FALSE;
+ }
+
+ if ((PasswordLength == 0) || (PasswordLength > INT_MAX) ||
+ (SaltLength == 0) || (SaltLength > INT_MAX) ||
+ (KeyLength == 0) || (KeyLength > INT_MAX) ||
+ (IterationCount < 1) || (IterationCount > INT_MAX))
+ {
+ return FALSE;
+ }
+
+ //
+ // Make sure the digest algorithm is supported.
+ //
+ switch (DigestSize) {
+ case SHA1_DIGEST_SIZE:
+ HashAlg = MBEDTLS_MD_SHA1;
+ break;
+ case SHA256_DIGEST_SIZE:
+ HashAlg = MBEDTLS_MD_SHA256;
+ break;
+ default:
+ return FALSE;
+ break;
+ }
+
+ //
+ // Perform password-based key derivation routines.
+ //
+ if (mbedtls_pkcs5_pbkdf2_hmac_ext (
+ HashAlg,
+ (CONST UINT8 *)Password,
+ (int)PasswordLength,
+ (CONST UINT8 *)Salt,
+ (int)SaltLength,
+ (int)IterationCount,
+ (int)KeyLength,
+ (UINT8 *)OutKey
+ ) != 0)
+ {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
index 207f493cbb..cbdd1dc530 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Internal.h
@@ -4,7 +4,7 @@
RFC 2315 - PKCS #7: Cryptographic Message Syntax Version 1.5
-Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2023-2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -31,10 +31,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define MBEDTLS_OID_PKCS7_DIGESTED_DATA MBEDTLS_OID_PKCS7 "\x05"
#define MBEDTLS_OID_PKCS7_ENCRYPTED_DATA MBEDTLS_OID_PKCS7 "\x06"
-typedef mbedtls_asn1_buf MBEDTLSPKCS7BUF;
-typedef mbedtls_asn1_named_data MBEDTLSPKCS7NAME;
-typedef mbedtls_asn1_sequence MBEDTLSPKCS7SEQUENCE;
-
///
/// PKCS7 SignerInfo type
/// https://tools.ietf.org/html/rfc2315#section-9.2
@@ -48,8 +44,8 @@ typedef struct MbedtlsPkcs7SignerInfo {
mbedtls_x509_buf SigAlgIdentifier;
mbedtls_x509_buf AuthAttr;
mbedtls_x509_buf Sig;
- struct MBEDTLSPKCS7SIGNERINFO *Next;
-} MBEDTLSPKCS7SIGNERINFO;
+ struct MbedtlsPkcs7SignerInfo *Next;
+} MbedtlsPkcs7SignerInfo;
///
/// PKCS7 signed data attached data format
@@ -57,7 +53,7 @@ typedef struct MbedtlsPkcs7SignerInfo {
typedef struct MbedtlsPkcs7Data {
mbedtls_asn1_buf Oid;
mbedtls_asn1_buf Data;
-} MBEDTLSPKCS7DATA;
+} MbedtlsPkcs7Data;
///
/// Signed Data
@@ -66,18 +62,27 @@ typedef struct MbedtlsPkcs7Data {
typedef struct MbedtlsPkcs7SignedData {
INT32 Version;
mbedtls_asn1_buf DigestAlgorithms;
- struct MBEDTLSPKCS7DATA ContentInfo;
+ struct MbedtlsPkcs7Data ContentInfo;
mbedtls_x509_crt Certificates;
mbedtls_x509_crl Crls;
struct MbedtlsPkcs7SignerInfo SignerInfos;
-} MBEDTLSPKCS7SIGNEDDATA;
+} MbedtlsPkcs7SignedData;
///
/// PKCS7 struct, only support SignedData
///
typedef struct MbedtlsPkcs7 {
mbedtls_asn1_buf ContentTypeOid;
- struct MBEDTLSPKCS7SIGNEDDATA SignedData;
-} MBEDTLSPKCS7;
+ struct MbedtlsPkcs7SignedData SignedData;
+} MbedtlsPkcs7;
+
+#define EDKII_ASN1_CHK_ADD(g, f) \
+ do \
+ { \
+ if( ( Ret = (f) ) < 0 ) \
+ return( Ret ); \
+ else \
+ (g) += Ret; \
+ } while( 0 )
#endif
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
new file mode 100644
index 0000000000..e3283dad48
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
@@ -0,0 +1,635 @@
+/** @file
+ PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper
+ Implementation over mbedtls.
+
+ RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites
+ FIPS 186-4 - Digital Signature Standard (DSS)
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CryptPkcs7Internal.h"
+#include <mbedtls/ecdh.h>
+
+///
+/// Enough to store any signature generated by PKCS7
+///
+#define MAX_SIGNATURE_SIZE 1024
+
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidDigestAlgSha256[] = MBEDTLS_OID_DIGEST_ALG_SHA256;
+GLOBAL_REMOVE_IF_UNREFERENCED UINT8 MbedtlsOidPkcs1Rsa[] = MBEDTLS_OID_PKCS1_RSA;
+
+/**
+ Write DigestAlgorithmIdentifier.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] DigestType Digest Type
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteDigestAlgorithm (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ mbedtls_md_type_t DigestType
+ )
+{
+ UINT8 *OidPtr;
+ UINTN OidLen;
+ INT32 Ret;
+
+ Ret = mbedtls_oid_get_oid_by_md (DigestType, (CONST CHAR8 **)&OidPtr, &OidLen);
+ if (Ret == 0) {
+ return mbedtls_asn1_write_oid (Ptr, (CONST UINT8 *)Start, (CONST CHAR8 *)OidPtr, OidLen);
+ }
+
+ return 0;
+}
+
+/**
+ DigestAlgorithmIdentifiers ::=
+ SET OF DigestAlgorithmIdentifier.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] DigestTypes Digest Type array.
+ @param[in] Count The index for Digest Type.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteDigestAlgorithmSet (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ mbedtls_md_type_t *DigestTypes,
+ INTN Count
+ )
+{
+ INTN Idx;
+ INT32 Len;
+ INT32 Ret;
+
+ Len = 0;
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_null (Ptr, Start));
+
+ for (Idx = 0; Idx < Count; Idx++) {
+ EDKII_ASN1_CHK_ADD (
+ Len,
+ MbedTlsPkcs7WriteDigestAlgorithm (Ptr, Start, DigestTypes[Idx])
+ );
+ }
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len));
+
+ EDKII_ASN1_CHK_ADD (
+ Len,
+ mbedtls_asn1_write_tag (
+ Ptr,
+ Start,
+ (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)
+ )
+ );
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, (UINTN)Len));
+
+ EDKII_ASN1_CHK_ADD (
+ Len,
+ mbedtls_asn1_write_tag (
+ Ptr,
+ Start,
+ (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)
+ )
+ );
+
+ return Len;
+}
+
+/**
+ ContentInfo ::= SEQUENCE {
+ contentType ContentType,
+ content
+ [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] Content ContentInfo.
+ @param[in] ContentLen Size of ContentInfo.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteContentInfo (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ UINT8 *Content,
+ INTN ContentLen
+ )
+{
+ INT32 Ret;
+ INT32 Len;
+
+ Len = 0;
+ if (Content != NULL) {
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, Content, ContentLen));
+ }
+
+ EDKII_ASN1_CHK_ADD (
+ Len,
+ mbedtls_asn1_write_oid (
+ Ptr,
+ Start,
+ MBEDTLS_OID_PKCS7_DATA,
+ sizeof (MBEDTLS_OID_PKCS7_DATA) - 1
+ )
+ );
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+ return Len;
+}
+
+/**
+ certificates :: SET OF ExtendedCertificateOrCertificate,
+ ExtendedCertificateOrCertificate ::= CHOICE {
+ certificate Certificate -- x509,
+ extendedCertificate[0] IMPLICIT ExtendedCertificate }.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] Cert Certificate.
+ @param[in] OtherCerts Ohter Certificate.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteCertificates (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ mbedtls_x509_crt *Cert,
+ mbedtls_x509_crt *OtherCerts
+ )
+{
+ INT32 Ret;
+ INT32 Len;
+ mbedtls_x509_crt *TmpCert;
+
+ Len = 0;
+
+ /// Write OtherCerts
+ TmpCert = OtherCerts;
+ while (TmpCert != NULL) {
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, TmpCert->raw.p, TmpCert->raw.len));
+ TmpCert = TmpCert->next;
+ }
+
+ /// Write Cert
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, Cert->raw.p, Cert->raw.len));
+
+ /// Write NextContext
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC));
+ return Len;
+}
+
+/**
+ write Pkcs7 Int.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] SerialRaw SerialRaw.
+ @param[in] SerialRawLen Size of SerialRaw.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteInt (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ UINT8 *SerialRaw,
+ INTN SerialRawLen
+ )
+{
+ INT32 Ret;
+ UINT8 *Pt;
+ INT32 Len;
+
+ Len = 0;
+ Pt = SerialRaw + SerialRawLen;
+ while (Pt > SerialRaw) {
+ *--(*Ptr) = *--Pt;
+ Len++;
+ }
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_INTEGER));
+
+ return Len;
+}
+
+/**
+ write Pkcs7 Issuer And SerialNumber.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] Serial Serial.
+ @param[in] SerialLen Size of Serial.
+ @param[in] IssuerRaw IssuerRawLen.
+ @param[in] IssuerRawLen Size of IssuerRawLen.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteIssuerAndSerialNumber (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ UINT8 *Serial,
+ INTN SerialLen,
+ UINT8 *IssuerRaw,
+ INTN IssuerRawLen
+ )
+{
+ INT32 Ret;
+ INT32 Len;
+
+ Len = 0;
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteInt (Ptr, Start, Serial, SerialLen));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_raw_buffer (Ptr, Start, IssuerRaw, IssuerRawLen));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+ return Len;
+}
+
+/**
+ SignerInfo ::= SEQUENCE {
+ version Version;
+ issuerAndSerialNumber IssuerAndSerialNumber,
+ digestAlgorithm DigestAlgorithmIdentifier,
+ authenticatedAttributes
+ [0] IMPLICIT Attributes OPTIONAL,
+ digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ encryptedDigest EncryptedDigest,
+ unauthenticatedAttributes
+ [1] IMPLICIT Attributes OPTIONAL.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] SignerInfo SignerInfo.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteSignerInfo (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ MbedtlsPkcs7SignerInfo *SignerInfo
+ )
+{
+ INT32 Ret;
+ INT32 Len;
+
+ Len = 0;
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_octet_string (Ptr, Start, SignerInfo->Sig.p, SignerInfo->Sig.len));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, Start, (CONST CHAR8 *)SignerInfo->SigAlgIdentifier.p, SignerInfo->SigAlgIdentifier.len, 0));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_algorithm_identifier (Ptr, Start, (CONST CHAR8 *)SignerInfo->AlgIdentifier.p, SignerInfo->AlgIdentifier.len, 0));
+
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteIssuerAndSerialNumber (Ptr, Start, SignerInfo->Serial.p, SignerInfo->Serial.len, SignerInfo->IssuerRaw.p, SignerInfo->IssuerRaw.len));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, SignerInfo->Version));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+ return Len;
+}
+
+/**
+ write Pkcs7 Signers Info Set.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] SignersSet SignerInfo Set.
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteSignersInfoSet (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ MbedtlsPkcs7SignerInfo *SignersSet
+ )
+{
+ MbedtlsPkcs7SignerInfo *SignerInfo;
+ INT32 Ret;
+ INT32 Len;
+
+ SignerInfo = SignersSet;
+ Len = 0;
+
+ while (SignerInfo != NULL) {
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignerInfo (Ptr, Start, SignerInfo));
+ // move to next
+ SignerInfo = SignerInfo->Next;
+ }
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET));
+
+ return Len;
+}
+
+/**
+ Signed Data Type
+ SignedData ::= SEQUENCE {
+ version Version,
+ digestAlgorithms DigestAlgorithmIdentifiers,
+ contentInfo ContentInfo,
+ certificates
+ [0] IMPLICIT ExtendedCertificatesAndCertificates
+ OPTIONAL,
+ crls
+ [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+ signerInfos SignerInfos }
+
+ DigestAlgorithmIdentifiers ::=
+ SET OF DigestAlgorithmIdentifier
+
+ SignerInfos ::= SET OF SignerInfo.
+
+ @param[in, out] Ptr The reference to the current position pointer.
+ @param[in] Start The start of the buffer, for bounds-checking.
+ @param[in] Pkcs7 MbedtlsPkcs7
+
+ @retval number The number of bytes written to p on success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7WriteDer (
+ UINT8 **Ptr,
+ UINT8 *Start,
+ MbedtlsPkcs7 *Pkcs7
+ )
+{
+ INT32 Ret;
+ INT32 Len;
+ mbedtls_md_type_t DigestAlg[1];
+
+ DigestAlg[0] = MBEDTLS_MD_SHA256;
+ Len = 0;
+
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteSignersInfoSet (Ptr, Start, &(Pkcs7->SignedData.SignerInfos)));
+
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteCertificates (Ptr, Start, &(Pkcs7->SignedData.Certificates), Pkcs7->SignedData.Certificates.next));
+
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteContentInfo (Ptr, Start, NULL, 0));
+
+ EDKII_ASN1_CHK_ADD (Len, MbedTlsPkcs7WriteDigestAlgorithmSet (Ptr, Start, DigestAlg, 1));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_int (Ptr, Start, Pkcs7->SignedData.Version));
+
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_len (Ptr, Start, Len));
+ EDKII_ASN1_CHK_ADD (Len, mbedtls_asn1_write_tag (Ptr, Start, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE));
+
+ return Len;
+}
+
+/**
+ Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message
+ Syntax Standard, version 1.5". This interface is only intended to be used for
+ application to perform PKCS#7 functionality validation.
+
+ If this interface is not supported, then return FALSE.
+
+ @param[in] PrivateKey Pointer to the PEM-formatted private key data for
+ data signing.
+ @param[in] PrivateKeySize Size of the PEM private key data in bytes.
+ @param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM
+ key data.
+ @param[in] InData Pointer to the content to be signed.
+ @param[in] InDataSize Size of InData in bytes.
+ @param[in] SignCert Pointer to signer's DER-encoded certificate to sign with.
+ @param[in] OtherCerts Pointer to an optional additional set of certificates to
+ include in the PKCS#7 signedData (e.g. any intermediate
+ CAs in the chain).
+ @param[out] SignedData Pointer to output PKCS#7 signedData. It's caller's
+ responsibility to free the buffer with FreePool().
+ @param[out] SignedDataSize Size of SignedData in bytes.
+
+ @retval TRUE PKCS#7 data signing succeeded.
+ @retval FALSE PKCS#7 data signing failed.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7Sign (
+ IN CONST UINT8 *PrivateKey,
+ IN UINTN PrivateKeySize,
+ IN CONST UINT8 *KeyPassword,
+ IN UINT8 *InData,
+ IN UINTN InDataSize,
+ IN UINT8 *SignCert,
+ IN UINT8 *OtherCerts OPTIONAL,
+ OUT UINT8 **SignedData,
+ OUT UINTN *SignedDataSize
+ )
+{
+ BOOLEAN Status;
+ INT32 Ret;
+ mbedtls_pk_context Pkey;
+ UINT8 HashValue[SHA256_DIGEST_SIZE];
+ UINT8 Signature[MAX_SIGNATURE_SIZE];
+ UINTN SignatureLen;
+ UINT8 *NewPrivateKey;
+ mbedtls_x509_crt *Crt;
+
+ MbedtlsPkcs7 Pkcs7;
+ MbedtlsPkcs7SignerInfo SignerInfo;
+ UINT8 *Buffer;
+ INTN BufferSize;
+ UINT8 *Ptr;
+ INT32 Len;
+
+ //
+ // Check input parameters.
+ //
+ if ((PrivateKey == NULL) || (KeyPassword == NULL) || (InData == NULL) ||
+ (SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL) || (InDataSize > INT_MAX))
+ {
+ return FALSE;
+ }
+
+ BufferSize = 4096;
+
+ SignatureLen = MAX_SIGNATURE_SIZE;
+ Crt = (mbedtls_x509_crt *)SignCert;
+
+ NewPrivateKey = NULL;
+ if (PrivateKey[PrivateKeySize - 1] != 0) {
+ NewPrivateKey = AllocateZeroPool (PrivateKeySize + 1);
+ if (NewPrivateKey == NULL) {
+ return FALSE;
+ }
+
+ CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);
+ NewPrivateKey[PrivateKeySize] = 0;
+ PrivateKeySize++;
+ } else {
+ NewPrivateKey = AllocateZeroPool (PrivateKeySize);
+ if (NewPrivateKey == NULL) {
+ return FALSE;
+ }
+
+ CopyMem (NewPrivateKey, PrivateKey, PrivateKeySize);
+ }
+
+ mbedtls_pk_init (&Pkey);
+ Ret = mbedtls_pk_parse_key (
+ &Pkey,
+ NewPrivateKey,
+ PrivateKeySize,
+ KeyPassword,
+ KeyPassword == NULL ? 0 : AsciiStrLen ((CONST CHAR8 *)KeyPassword),
+ NULL,
+ NULL
+ );
+ if (Ret != 0) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ /// Calculate InData Digest
+ ZeroMem (HashValue, SHA256_DIGEST_SIZE);
+ Status = Sha256HashAll (InData, InDataSize, HashValue);
+ if (!Status) {
+ goto Cleanup;
+ }
+
+ /// Pk Sign
+ ZeroMem (Signature, MAX_SIGNATURE_SIZE);
+ Ret = mbedtls_pk_sign (
+ &Pkey,
+ MBEDTLS_MD_SHA256,
+ HashValue,
+ SHA256_DIGEST_SIZE,
+ Signature,
+ MAX_SIGNATURE_SIZE,
+ &SignatureLen,
+ MbedtlsRand,
+ NULL
+ );
+ if (Ret != 0) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ ZeroMem (&Pkcs7, sizeof (MbedtlsPkcs7));
+ Pkcs7.SignedData.Version = 1;
+
+ Crt->next = (mbedtls_x509_crt *)OtherCerts;
+ Pkcs7.SignedData.Certificates = *Crt;
+
+ SignerInfo.Next = NULL;
+ SignerInfo.Sig.p = Signature;
+ SignerInfo.Sig.len = SignatureLen;
+ SignerInfo.Version = 1;
+ SignerInfo.AlgIdentifier.p = MbedtlsOidDigestAlgSha256;
+ SignerInfo.AlgIdentifier.len = sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1;
+ if (mbedtls_pk_get_type (&Pkey) == MBEDTLS_PK_RSA) {
+ SignerInfo.SigAlgIdentifier.p = MbedtlsOidPkcs1Rsa;
+ SignerInfo.SigAlgIdentifier.len = sizeof (MBEDTLS_OID_PKCS1_RSA) - 1;
+ } else {
+ Ret = mbedtls_oid_get_oid_by_sig_alg (MBEDTLS_PK_ECDSA, MBEDTLS_MD_SHA256, (CONST CHAR8 **)&SignerInfo.SigAlgIdentifier.p, &SignerInfo.SigAlgIdentifier.len);
+ if (Ret != 0) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+ }
+
+ SignerInfo.Serial = ((mbedtls_x509_crt *)SignCert)->serial;
+ SignerInfo.IssuerRaw = ((mbedtls_x509_crt *)SignCert)->issuer_raw;
+ Pkcs7.SignedData.SignerInfos = SignerInfo;
+
+ Buffer = AllocateZeroPool (BufferSize);
+ if (Buffer == NULL) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ Ptr = Buffer + BufferSize;
+ Len = MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7);
+
+ /// Enlarge buffer if buffer is too small
+ while (Len == MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) {
+ BufferSize = BufferSize * 2;
+ Ptr = Buffer + BufferSize;
+ FreePool (Buffer);
+ Buffer = AllocateZeroPool (BufferSize);
+ if (Buffer == NULL) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ Ptr = Buffer + BufferSize;
+ Len = MbedTlsPkcs7WriteDer (&Ptr, Buffer, &Pkcs7);
+ }
+
+ if (Len <= 0) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ *SignedData = AllocateZeroPool (Len);
+ if (*SignedData == NULL) {
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ *SignedDataSize = Len;
+ CopyMem (*SignedData, Ptr, Len);
+ Status = TRUE;
+
+Cleanup:
+ if (&Pkey != NULL) {
+ mbedtls_pk_free (&Pkey);
+ }
+
+ if (NewPrivateKey != NULL) {
+ memset (NewPrivateKey, 0, PrivateKeySize);
+ FreePool (NewPrivateKey);
+ }
+
+ if (Buffer != NULL) {
+ memset (Buffer, 0, BufferSize);
+ FreePool (Buffer);
+ }
+
+ return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
new file mode 100644
index 0000000000..6b62ee2618
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
@@ -0,0 +1,113 @@
+/** @file
+ Non-runtime specific implementation of PKCS#7 SignedData Verification Wrapper.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
+
+/**
+ Extracts the attached content from a PKCS#7 signed data if existed. The input signed
+ data could be wrapped in a ContentInfo structure.
+
+ If P7Data, Content, or ContentSize is NULL, then return FALSE. If P7Length overflow,
+ then return FALSE. If the P7Data is not correctly formatted, then return FALSE.
+
+ Caution: This function may receive untrusted input. So this function will do
+ basic check for PKCS#7 data structure.
+
+ @param[in] P7Data Pointer to the PKCS#7 signed data to process.
+ @param[in] P7Length Length of the PKCS#7 signed data in bytes.
+ @param[out] Content Pointer to the extracted content from the PKCS#7 signedData.
+ It's caller's responsibility to free the buffer with FreePool().
+ @param[out] ContentSize The size of the extracted content in bytes.
+
+ @retval TRUE The P7Data was correctly formatted for processing.
+ @retval FALSE The P7Data was not correctly formatted for processing.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetAttachedContent (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ OUT VOID **Content,
+ OUT UINTN *ContentSize
+ )
+{
+ BOOLEAN Status;
+ UINT8 *SignedData;
+ UINTN SignedDataSize;
+ BOOLEAN Wrapped;
+ INTN Ret;
+ mbedtls_pkcs7 Pkcs7;
+ mbedtls_pkcs7_data *MbedtlsContent;
+
+ mbedtls_pkcs7_init (&Pkcs7);
+
+ //
+ // Check input parameter.
+ //
+ if ((P7Data == NULL) || (P7Length > INT_MAX) || (Content == NULL) || (ContentSize == NULL)) {
+ return FALSE;
+ }
+
+ *Content = NULL;
+ SignedData = NULL;
+
+ Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
+ if (!Status || (SignedDataSize > INT_MAX)) {
+ goto _Exit;
+ }
+
+ Status = FALSE;
+
+ Ret = mbedtls_pkcs7_parse_der (&Pkcs7, SignedData, (INT32)SignedDataSize);
+
+ //
+ // The type of Pkcs7 must be signedData
+ //
+ if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {
+ goto _Exit;
+ }
+
+ //
+ // Check for detached or attached content
+ //
+ MbedtlsContent = &(Pkcs7.signed_data.content);
+
+ if (MbedtlsContent == NULL) {
+ //
+ // No Content supplied for PKCS7 detached signedData
+ //
+ *Content = NULL;
+ *ContentSize = 0;
+ } else {
+ //
+ // Retrieve the attached content in PKCS7 signedData
+ //
+ if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p != NULL)) {
+ *ContentSize = MbedtlsContent->data.len;
+ *Content = AllocateZeroPool (*ContentSize);
+ if (*Content == NULL) {
+ *ContentSize = 0;
+ goto _Exit;
+ }
+
+ CopyMem (*Content, MbedtlsContent->data.p, *ContentSize);
+ }
+ }
+
+ Status = TRUE;
+
+_Exit:
+ //
+ // Release Resources
+ //
+ mbedtls_pkcs7_free (&Pkcs7);
+
+ return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
new file mode 100644
index 0000000000..e9f1b0efdd
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
@@ -0,0 +1,1354 @@
+/** @file
+ PKCS#7 SignedData Sign Wrapper and PKCS#7 SignedData Verification Wrapper
+ Implementation over mbedtls.
+
+ RFC 8422 - Elliptic Curve Cryptography (ECC) Cipher Suites
+ FIPS 186-4 - Digital Signature Standard (DSS)
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CryptPkcs7Internal.h"
+#include <mbedtls/pkcs7.h>
+
+/* Profile for backward compatibility. Allows RSA 1024, unlike the default
+ profile. */
+STATIC mbedtls_x509_crt_profile gCompatProfile =
+{
+ /* Hashes from SHA-256 and above. Note that this selection
+ * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */
+
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA1) |
+ #endif
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512),
+ 0xFFFFFFF, /* Any PK alg */
+
+ /* Curves at or above 128-bit security level. Note that this selection
+ * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) |
+ 0,
+ 1024,
+};
+
+/**
+ Init MbedtlsPkcs7.
+
+ @param[in] Pkcs7 MbedtlsPkcs7.
+**/
+STATIC
+VOID
+MbedTlsPkcs7Init (
+ MbedtlsPkcs7 *Pkcs7
+ )
+{
+ ZeroMem (Pkcs7, sizeof (MbedtlsPkcs7));
+}
+
+/**
+ Get Pkcs7 Next Content Len.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] Len MbedtlsPkcs7 Content Len.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetNextContentLen (
+ UINT8 **Ptr,
+ UINT8 *End,
+ UINTN *Len
+ )
+{
+ INT32 Ret;
+
+ Ret = mbedtls_asn1_get_tag (Ptr, End, Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+ return Ret;
+}
+
+/**
+ Get Pkcs7 Version..
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] Ver MbedtlsPkcs7 Version.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetVersion (
+ UINT8 **Ptr,
+ UINT8 *End,
+ INT32 *Ver
+ )
+{
+ INT32 Ret;
+
+ Ret = mbedtls_asn1_get_int (Ptr, End, Ver);
+ return Ret;
+}
+
+/**
+ ContentInfo ::= SEQUENCE {
+ contentType ContentType,
+ content
+ [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] Pkcs7 MbedtlsPkcs7.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+Pkcs7GetContentInfoType (
+ UINT8 **Ptr,
+ UINT8 *End,
+ mbedtls_asn1_buf *Pkcs7
+ )
+{
+ UINTN Len;
+ int Ret;
+
+ Len = 0;
+ Ret = mbedtls_asn1_get_tag (
+ Ptr,
+ End,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+ );
+
+ if (Ret == 0) {
+ Ret = mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OID);
+ }
+
+ if (Ret == 0) {
+ Pkcs7->tag = MBEDTLS_ASN1_OID;
+ Pkcs7->len = Len;
+ Pkcs7->p = *Ptr;
+ }
+
+ return Ret;
+}
+
+/**
+ DigestAlgorithmIdentifier ::= AlgorithmIdentifier.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetDigestAlgorithm (
+ UINT8 **Ptr,
+ UINT8 *End,
+ mbedtls_x509_buf *Alg
+ )
+{
+ INT32 Ret;
+
+ Ret = mbedtls_asn1_get_alg_null (Ptr, End, Alg);
+ return Ret;
+}
+
+/**
+ DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] Alg MbedtlsPkcs7 AlgorithmIdentifier.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetDigestAlgorithmSet (
+ UINT8 **Ptr,
+ UINT8 *End,
+ mbedtls_x509_buf *Alg
+ )
+{
+ UINTN Len;
+ INT32 Ret;
+
+ Len = 0;
+ Ret = mbedtls_asn1_get_tag (
+ Ptr,
+ End,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET
+ );
+
+ if (Ret == 0) {
+ End = *Ptr + Len;
+ // assume only one digest algorithm
+ Ret = mbedtls_asn1_get_alg_null (Ptr, End, Alg);
+ }
+
+ return Ret;
+}
+
+/**
+ certificates :: SET OF ExtendedCertificateOrCertificate,
+ ExtendedCertificateOrCertificate ::= CHOICE {
+ certificate Certificate -- x509,
+ extendedCertificate[0] IMPLICIT ExtendedCertificate }.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] Plen The buffer len.
+ @param[out] Certs mbedtls_x509_crt cert.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetCertificates (
+ UINT8 **Ptr,
+ INTN Plen,
+ mbedtls_x509_crt *Certs
+ )
+{
+ INT32 Ret;
+
+ Ret = mbedtls_x509_crt_parse (Certs, *Ptr, Plen);
+ return Ret;
+}
+
+/**
+ EncryptedDigest ::= OCTET STRING.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] Signature Signature.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+Pkcs7GetSignature (
+ UINT8 **Ptr,
+ UINT8 *End,
+ mbedtls_asn1_buf *Signature
+ )
+{
+ INT32 Ret;
+ UINTN Len;
+
+ Len = 0;
+ Ret = mbedtls_asn1_get_tag (Ptr, End, &Len, MBEDTLS_ASN1_OCTET_STRING);
+ if (Ret == 0) {
+ Signature->tag = MBEDTLS_ASN1_OCTET_STRING;
+ Signature->len = Len;
+ Signature->p = *Ptr;
+ }
+
+ return Ret;
+}
+
+/**
+ SignerInfo ::= SEQUENCE {
+ version Version;
+ issuerAndSerialNumber IssuerAndSerialNumber,
+ digestAlgorithm DigestAlgorithmIdentifier,
+ authenticatedAttributes
+ [0] IMPLICIT Attributes OPTIONAL,
+ digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+ encryptedDigest EncryptedDigest,
+ unauthenticatedAttributes
+ [1] IMPLICIT Attributes OPTIONAL.
+
+ @param[in] Ptr The start of the buffer.
+ @param[in] End The end of the buffer.
+ @param[out] SignersSet MbedtlsPkcs7SignerInfo.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedTlsPkcs7GetSignersInfoSet (
+ UINT8 **Ptr,
+ UINT8 *End,
+ MbedtlsPkcs7SignerInfo *SignersSet
+ )
+{
+ UINT8 *EndSet;
+ INT32 Ret;
+ UINTN Len;
+ UINT8 *TempP;
+
+ Len = 0;
+
+ Ret = mbedtls_asn1_get_tag (
+ Ptr,
+ End,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET
+ );
+
+ if (Ret == 0) {
+ EndSet = *Ptr + Len;
+
+ Ret = mbedtls_asn1_get_tag (
+ Ptr,
+ EndSet,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+ );
+ }
+
+ if (Ret == 0) {
+ Ret = mbedtls_asn1_get_int (Ptr, EndSet, &SignersSet->Version);
+ }
+
+ if (Ret == 0) {
+ Ret = mbedtls_asn1_get_tag (
+ Ptr,
+ EndSet,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+ );
+ }
+
+ if (Ret == 0) {
+ SignersSet->IssuerRaw.p = *Ptr;
+ Ret = mbedtls_asn1_get_tag (
+ Ptr,
+ EndSet,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+ );
+ }
+
+ if (Ret == 0) {
+ Ret = mbedtls_x509_get_name (Ptr, *Ptr + Len, &SignersSet->Issuer);
+ }
+
+ if (Ret == 0) {
+ SignersSet->IssuerRaw.len = *Ptr - SignersSet->IssuerRaw.p;
+
+ Ret = mbedtls_x509_get_serial (Ptr, EndSet, &SignersSet->Serial);
+ }
+
+ if (Ret == 0) {
+ Ret = MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->AlgIdentifier);
+ }
+
+ // OPTIONAL AuthenticatedAttributes
+ if (Ret == 0) {
+ TempP = *Ptr;
+ if (mbedtls_asn1_get_tag (&TempP, EndSet, &Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {
+ SignersSet->AuthAttr.len = Len + (TempP - *Ptr);
+ SignersSet->AuthAttr.p = *Ptr;
+ *Ptr = TempP + Len;
+ } else {
+ SignersSet->AuthAttr.p = NULL;
+ }
+ }
+
+ if (Ret == 0) {
+ Ret = MbedTlsPkcs7GetDigestAlgorithm (Ptr, EndSet, &SignersSet->SigAlgIdentifier);
+ }
+
+ if (Ret == 0) {
+ Ret = Pkcs7GetSignature (Ptr, End, &SignersSet->Sig);
+ }
+
+ if (Ret == 0) {
+ SignersSet->Next = NULL;
+ }
+
+ return Ret;
+}
+
+/**
+ SignedData ::= SEQUENCE {
+ version Version,
+ digestAlgorithms DigestAlgorithmIdentifiers,
+ contentInfo ContentInfo,
+ certificates
+ [0] IMPLICIT ExtendedCertificatesAndCertificates
+ OPTIONAL,
+ crls
+ [0] IMPLICIT CertificateRevocationLists OPTIONAL,
+ signerInfos SignerInfos }.
+
+ @param[in] Buffer The start of the buffer.
+ @param[in] BufferLen The len the buffer.
+ @param[out] SignedData MbedtlsPkcs7SignedData.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+Pkcs7GetSignedData (
+ UINT8 *Buffer,
+ INTN BufferLen,
+ MbedtlsPkcs7SignedData *SignedData
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *End;
+ UINTN Len;
+ INT32 Ret;
+ UINT8 *CertP;
+ UINTN CertLen;
+ UINT8 *OldCertP;
+ UINTN TotalCertLen;
+ mbedtls_x509_crt *MoreCert;
+ UINT8 CertNum;
+ mbedtls_x509_crt *LastCert;
+ mbedtls_x509_crt *TempCrt;
+
+ Len = 0;
+ Ptr = Buffer;
+ End = Buffer + BufferLen;
+ MoreCert = NULL;
+
+ Ret = mbedtls_asn1_get_tag (
+ &Ptr,
+ End,
+ &Len,
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE
+ );
+
+ if (Ret == 0) {
+ // version
+ Ret = MbedTlsPkcs7GetVersion (&Ptr, End, &SignedData->Version);
+ }
+
+ if ((Ret == 0) && (SignedData->Version != 1)) {
+ Ret = -1;
+ }
+
+ if (Ret == 0) {
+ // digest algorithm
+ Ret = MbedTlsPkcs7GetDigestAlgorithmSet (
+ &Ptr,
+ End,
+ &SignedData->DigestAlgorithms
+ );
+ }
+
+ if (Ret == 0) {
+ if (
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+ ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA1) - 1) &&
+ (CompareMem (
+ SignedData->DigestAlgorithms.p,
+ MBEDTLS_OID_DIGEST_ALG_SHA1,
+ SignedData->DigestAlgorithms.len
+ ) == 0)) ||
+ #endif
+ ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA256) - 1) &&
+ (CompareMem (
+ SignedData->DigestAlgorithms.p,
+ MBEDTLS_OID_DIGEST_ALG_SHA256,
+ SignedData->DigestAlgorithms.len
+ ) == 0)) ||
+ ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA384) - 1) &&
+ (CompareMem (
+ SignedData->DigestAlgorithms.p,
+ MBEDTLS_OID_DIGEST_ALG_SHA384,
+ SignedData->DigestAlgorithms.len
+ ) == 0)) ||
+ ((SignedData->DigestAlgorithms.len == sizeof (MBEDTLS_OID_DIGEST_ALG_SHA512) - 1) &&
+ (CompareMem (
+ SignedData->DigestAlgorithms.p,
+ MBEDTLS_OID_DIGEST_ALG_SHA512,
+ SignedData->DigestAlgorithms.len
+ ) == 0)))
+ {
+ Ret = 0;
+ } else {
+ Ret = -1;
+ }
+ }
+
+ if (Ret == 0) {
+ Ret = Pkcs7GetContentInfoType (&Ptr, End, &SignedData->ContentInfo.Oid);
+ }
+
+ if (Ret == 0) {
+ // move to next
+ Ptr = Ptr + SignedData->ContentInfo.Oid.len;
+ Ret = MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len);
+ CertP = Ptr + Len;
+
+ // move to actual cert, if there are more [0]
+ if (MbedTlsPkcs7GetNextContentLen (&CertP, End, &CertLen) == 0) {
+ Len = CertLen;
+ Ptr = CertP;
+ }
+ }
+
+ // certificates: may have many certs
+ CertP = Ptr;
+
+ TotalCertLen = 0;
+
+ MoreCert = &SignedData->Certificates;
+ CertNum = 0;
+
+ while (TotalCertLen < Len) {
+ OldCertP = CertP;
+
+ Ret = mbedtls_asn1_get_tag (&CertP, End, &CertLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (Ret != 0) {
+ goto Out;
+ }
+
+ // cert total len
+ CertLen = CertLen + (CertP - OldCertP);
+
+ // move to next cert
+ CertP = OldCertP + CertLen;
+
+ // change TotalCertLen
+ TotalCertLen += CertLen;
+
+ mbedtls_x509_crt_init (MoreCert);
+ Ret = MbedTlsPkcs7GetCertificates (&OldCertP, CertLen, MoreCert);
+ if (Ret != 0) {
+ goto Out;
+ }
+
+ CertNum++;
+ MoreCert->next = mbedtls_calloc (1, sizeof (mbedtls_x509_crt));
+ MoreCert = MoreCert->next;
+ }
+
+ if (TotalCertLen != Len) {
+ Ret = -1;
+ goto Out;
+ }
+
+ LastCert = &(SignedData->Certificates);
+
+ while (CertNum--) {
+ if (CertNum == 0) {
+ LastCert->next = NULL;
+ break;
+ } else {
+ LastCert = LastCert->next;
+ }
+ }
+
+ // signers info
+ if (Ret == 0) {
+ Ptr = Ptr + Len;
+ Ret = MbedTlsPkcs7GetSignersInfoSet (&Ptr, End, &SignedData->SignerInfos);
+ }
+
+Out:
+ if (Ret == 0) {
+ if (MoreCert != NULL) {
+ mbedtls_x509_crt_free (MoreCert);
+ MoreCert = NULL;
+ }
+ } else {
+ if (SignedData->Certificates.next != NULL) {
+ TempCrt = SignedData->Certificates.next;
+ mbedtls_x509_crt_free (TempCrt);
+ }
+ }
+
+ return Ret;
+}
+
+/**
+ Parse MbedtlsPkcs7 to Der format.
+ @param[in] Buffer The start of the buffer.
+ @param[in] BufferLen The len the buffer.
+ @param[out] Pkcs7 MbedtlsPkcs7.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedtlsPkcs7ParseDer (
+ CONST UINT8 *Buffer,
+ INTN BufferLen,
+ MbedtlsPkcs7 *Pkcs7
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *End;
+ UINTN Len;
+ INT32 Ret;
+
+ if (Pkcs7 == NULL) {
+ return -1;
+ }
+
+ Len = 0;
+ Ptr = (UINT8 *)Buffer;
+ End = Ptr + BufferLen;
+
+ Ret = Pkcs7GetContentInfoType (&Ptr, End, &Pkcs7->ContentTypeOid);
+ if (Ret != 0) {
+ goto Out;
+ }
+
+ if ((CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DATA, Pkcs7->ContentTypeOid.len) == 0) ||
+ (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, Pkcs7->ContentTypeOid.len) == 0) ||
+ (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) ||
+ (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, Pkcs7->ContentTypeOid.len) == 0) ||
+ (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_DIGESTED_DATA, Pkcs7->ContentTypeOid.len) == 0))
+ {
+ // Invalid PKCS7 data type;
+ Ret = -1;
+ goto Out;
+ }
+
+ if (CompareMem (Pkcs7->ContentTypeOid.p, MBEDTLS_OID_PKCS7_SIGNED_DATA, Pkcs7->ContentTypeOid.len) != 0) {
+ // Invalid PKCS7 data type;
+ Ret = -1;
+ goto Out;
+ }
+
+ // Content type is SignedData
+ Ptr = Ptr + Pkcs7->ContentTypeOid.len;
+
+ Ret = MbedTlsPkcs7GetNextContentLen (&Ptr, End, &Len);
+ if (Ret != 0) {
+ goto Out;
+ }
+
+ Ret = Pkcs7GetSignedData (Ptr, Len, &Pkcs7->SignedData);
+ if (Ret != 0) {
+ goto Out;
+ }
+
+Out:
+ return Ret;
+}
+
+/**
+ MbedtlsPkcs7 verify MbedtlsPkcs7SignerInfo.
+ @param[in] SignerInfo MbedtlsPkcs7 SignerInfo.
+ @param[in] Cert cert.
+ @param[in] Data Pointer for data.
+ @param[in] DataLen The len the buffer.
+
+ @retval 0 Success.
+ @retval negative A negative MBEDTLS_ERR_ASN1_XXX error code on failure.
+**/
+STATIC
+INT32
+MbedtlsPkcs7SignedDataVerifySigners (
+ MbedtlsPkcs7SignerInfo *SignerInfo,
+ mbedtls_x509_crt *Cert,
+ CONST UINT8 *Data,
+ INTN DataLen
+ )
+{
+ INT32 Ret;
+ UINT8 Hash[MBEDTLS_MD_MAX_SIZE];
+ mbedtls_pk_context Pk;
+ CONST mbedtls_md_info_t *MdInfo;
+ INTN HashLen;
+ UINT8 TempAuthAttr;
+
+ Pk = Cert->pk;
+ ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+
+ // all the hash algo
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+ MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA1);
+ HashLen = mbedtls_md_get_size (MdInfo);
+ mbedtls_md (MdInfo, Data, DataLen, Hash);
+ if (SignerInfo->AuthAttr.p != NULL) {
+ TempAuthAttr = *(SignerInfo->AuthAttr.p);
+ *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+ mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+ // Restore content
+ *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+ }
+
+ Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA1, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+
+ if (Ret == 0) {
+ return Ret;
+ }
+
+ #endif
+
+ MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA256);
+ HashLen = mbedtls_md_get_size (MdInfo);
+ ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+ mbedtls_md (MdInfo, Data, DataLen, Hash);
+ if (SignerInfo->AuthAttr.p != NULL) {
+ TempAuthAttr = *(SignerInfo->AuthAttr.p);
+ *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+ mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+ // Restore content
+ *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+ }
+
+ Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA256, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+ if (Ret == 0) {
+ return Ret;
+ }
+
+ MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA384);
+ HashLen = mbedtls_md_get_size (MdInfo);
+ ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+ mbedtls_md (MdInfo, Data, DataLen, Hash);
+ if (SignerInfo->AuthAttr.p != NULL) {
+ TempAuthAttr = *(SignerInfo->AuthAttr.p);
+ *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+ mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+ // Restore content
+ *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+ }
+
+ Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA384, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+ if (Ret == 0) {
+ return Ret;
+ }
+
+ MdInfo = mbedtls_md_info_from_type (MBEDTLS_MD_SHA512);
+ HashLen = mbedtls_md_get_size (MdInfo);
+ ZeroMem (Hash, MBEDTLS_MD_MAX_SIZE);
+ mbedtls_md (MdInfo, Data, DataLen, Hash);
+ if (SignerInfo->AuthAttr.p != NULL) {
+ TempAuthAttr = *(SignerInfo->AuthAttr.p);
+ *(SignerInfo->AuthAttr.p) = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET;
+ mbedtls_md (MdInfo, SignerInfo->AuthAttr.p, SignerInfo->AuthAttr.len, Hash);
+ // Restore content
+ *(SignerInfo->AuthAttr.p) = TempAuthAttr;
+ }
+
+ Ret = mbedtls_pk_verify (&Pk, MBEDTLS_MD_SHA512, Hash, HashLen, SignerInfo->Sig.p, SignerInfo->Sig.len);
+ if (Ret == 0) {
+ return Ret;
+ }
+
+ return Ret;
+}
+
+/**
+ Find signer cert in MbedtlsPkcs7SignerInfo.
+
+ @param[in] SignerInfo MbedtlsPkcs7 SignerInfo.
+ @param[in] Certs MbedtlsPkcs7 SignerInfo certs.
+
+ @retval cert Signer Cert.
+**/
+STATIC
+mbedtls_x509_crt *
+MbedTlsPkcs7FindSignerCert (
+ MbedtlsPkcs7SignerInfo *SignerInfo,
+ mbedtls_x509_crt *Certs
+ )
+{
+ mbedtls_x509_crt *Cert;
+
+ Cert = Certs;
+ while (Cert != NULL) {
+ if ((Cert->serial.p == NULL) || (Cert->issuer_raw.p == NULL)) {
+ return NULL;
+ }
+
+ if ((Cert->issuer_raw.len == SignerInfo->IssuerRaw.len) &&
+ (CompareMem (Cert->issuer_raw.p, SignerInfo->IssuerRaw.p, Cert->issuer_raw.len) == 0) &&
+ (Cert->serial.len == SignerInfo->Serial.len) &&
+ (CompareMem (Cert->serial.p, SignerInfo->Serial.p, Cert->serial.len) == 0))
+ {
+ break;
+ }
+
+ Cert = Cert->next;
+ }
+
+ return Cert;
+}
+
+/**
+ verify cert.
+
+ @param[in] Ca CA cert.
+ @param[in] CaCrl CRL.
+ @param[in] End Cert which need be verified.
+
+ @retval TRUE Verify successfully.
+ @retval FALSE Verify failed.
+**/
+STATIC
+BOOLEAN
+MbedTlsPkcs7VerifyCert (
+ mbedtls_x509_crt *Ca,
+ mbedtls_x509_crl *CaCrl,
+ mbedtls_x509_crt *End
+ )
+{
+ INT32 Ret;
+ UINT32 VFlag;
+ mbedtls_x509_crt_profile Profile;
+
+ VFlag = 0;
+ CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile));
+
+ Ret = mbedtls_x509_crt_verify_with_profile (End, Ca, CaCrl, &Profile, NULL, &VFlag, NULL, NULL);
+
+ return Ret == 0;
+}
+
+/**
+ verify cert chain.
+
+ @param[in] Pkcs7 MbedtlsPkcs7.
+ @param[in] Ca CA cert.
+ @param[in] End Cert which need be verified.
+
+ @retval TRUE Verify successfully.
+ @retval FALSE Verify failed.
+**/
+STATIC
+BOOLEAN
+MbedTlsPkcs7VerifyCertChain (
+ MbedtlsPkcs7 *Pkcs7,
+ mbedtls_x509_crt *Ca,
+ mbedtls_x509_crt *End
+ )
+{
+ mbedtls_x509_crt *AllCert;
+ mbedtls_x509_crt *InterCert;
+
+ AllCert = &(Pkcs7->SignedData.Certificates);
+ InterCert = NULL;
+
+ while (AllCert != NULL) {
+ if ((AllCert->next == End) && (MbedTlsPkcs7VerifyCert (AllCert, NULL, End))) {
+ InterCert = AllCert;
+ break;
+ }
+
+ AllCert = AllCert->next;
+ }
+
+ if (InterCert == NULL) {
+ return FALSE;
+ }
+
+ if (MbedTlsPkcs7VerifyCert (Ca, &(Pkcs7->SignedData.Crls), InterCert)) {
+ return TRUE;
+ } else {
+ return MbedTlsPkcs7VerifyCertChain (Pkcs7, Ca, InterCert);
+ }
+}
+
+/**
+ MbedTlsPkcs7 Verify SignedData.
+
+ @param[in] Pkcs7 MbedtlsPkcs7.
+ @param[in] TrustCert CA cert.
+ @param[in] Data Pointer for data.
+ @param[in] DataLen The len the buffer.
+
+ @retval TRUE Verify successfully.
+ @retval FALSE Verify failed.
+**/
+STATIC
+BOOLEAN
+MbedTlsPkcs7SignedDataVerify (
+ MbedtlsPkcs7 *Pkcs7,
+ mbedtls_x509_crt *TrustCert,
+ CONST UINT8 *Data,
+ INTN DataLen
+ )
+{
+ MbedtlsPkcs7SignerInfo *SignerInfo;
+ mbedtls_x509_crt *Cert;
+ mbedtls_x509_crt *AllCert;
+ BOOLEAN Result;
+
+ SignerInfo = &(Pkcs7->SignedData.SignerInfos);
+ Result = TRUE;
+
+ //
+ // Traverse signers and verify each signers
+ //
+ while (SignerInfo != NULL) {
+ Result = FALSE;
+ // 1. Find signers cert
+ Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7->SignedData.Certificates));
+ if (Cert != NULL) {
+ // 2. Check signer cert is trusted by trustCert
+ if (MbedTlsPkcs7VerifyCert (TrustCert, &(Pkcs7->SignedData.Crls), Cert)) {
+ // root cert verify pass
+ Result = TRUE;
+ } else {
+ if (MbedTlsPkcs7VerifyCertChain (Pkcs7, TrustCert, Cert)) {
+ Result = TRUE;
+ } else {
+ Result = FALSE;
+ }
+ }
+
+ if (Result == TRUE) {
+ // 3. Check signed data
+ AllCert = &(Pkcs7->SignedData.Certificates);
+ while (AllCert != NULL) {
+ if (MbedtlsPkcs7SignedDataVerifySigners (SignerInfo, AllCert, Data, DataLen) == 0) {
+ return TRUE;
+ }
+
+ AllCert = AllCert->next;
+ }
+
+ Result = FALSE;
+ }
+ }
+
+ // move to next
+ SignerInfo = SignerInfo->Next;
+ }
+
+ return Result;
+}
+
+/**
+ Check input P7Data is a wrapped ContentInfo structure or not. If not construct
+ a new structure to wrap P7Data.
+
+ Caution: This function may receive untrusted input.
+ UEFI Authenticated Variable is external input, so this function will do basic
+ check for PKCS#7 data structure.
+
+ @param[in] P7Data Pointer to the PKCS#7 message to verify.
+ @param[in] P7Length Length of the PKCS#7 message in bytes.
+ @param[out] WrapFlag If TRUE P7Data is a ContentInfo structure, otherwise
+ return FALSE.
+ @param[out] WrapData If return status of this function is TRUE:
+ 1) when WrapFlag is TRUE, pointer to P7Data.
+ 2) when WrapFlag is FALSE, pointer to a new ContentInfo
+ structure. It's caller's responsibility to free this
+ buffer.
+ @param[out] WrapDataSize Length of ContentInfo structure in bytes.
+
+ @retval TRUE The operation is finished successfully.
+ @retval FALSE The operation is failed due to lack of resources.
+
+**/
+BOOLEAN
+WrapPkcs7Data (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ OUT BOOLEAN *WrapFlag,
+ OUT UINT8 **WrapData,
+ OUT UINTN *WrapDataSize
+ )
+{
+ BOOLEAN Wrapped;
+ UINT8 *SignedData;
+
+ //
+ // Check whether input P7Data is a wrapped ContentInfo structure or not.
+ //
+ Wrapped = FALSE;
+ if ((P7Data[4] == MBEDTLS_ASN1_OID) && (P7Data[5] == sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1)) {
+ if (CompareMem (P7Data + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1) == 0) {
+ if ((P7Data[15] == (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) && (P7Data[16] == 0x82)) {
+ Wrapped = TRUE;
+ }
+ }
+ }
+
+ if (Wrapped) {
+ *WrapData = (UINT8 *)P7Data;
+ *WrapDataSize = P7Length;
+ } else {
+ //
+ // Wrap PKCS#7 signeddata to a ContentInfo structure - add a header in 19 bytes.
+ //
+ *WrapDataSize = P7Length + 19;
+ *WrapData = AllocateZeroPool (*WrapDataSize);
+ if (*WrapData == NULL) {
+ *WrapFlag = Wrapped;
+ return FALSE;
+ }
+
+ SignedData = *WrapData;
+
+ //
+ // Part1: 0x30, 0x82.
+ //
+ SignedData[0] = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE;
+ SignedData[1] = 0x82;
+
+ //
+ // Part2: Length1 = P7Length + 19 - 4, in big endian.
+ //
+ SignedData[2] = (UINT8)(((UINT16)(*WrapDataSize - 4)) >> 8);
+ SignedData[3] = (UINT8)(((UINT16)(*WrapDataSize - 4)) & 0xff);
+
+ //
+ // Part3: 0x06, 0x09.
+ //
+ SignedData[4] = MBEDTLS_ASN1_OID;
+ SignedData[5] = sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1;
+
+ //
+ // Part4: OID value -- 0x2A 0x86 0x48 0x86 0xF7 0x0D 0x01 0x07 0x02.
+ //
+ CopyMem (SignedData + 6, MBEDTLS_OID_PKCS7_SIGNED_DATA, sizeof (MBEDTLS_OID_PKCS7_SIGNED_DATA) - 1);
+
+ //
+ // Part5: 0xA0, 0x82.
+ //
+ SignedData[15] = MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC;
+ SignedData[16] = 0x82;
+
+ //
+ // Part6: Length2 = P7Length, in big endian.
+ //
+ SignedData[17] = (UINT8)(((UINT16)P7Length) >> 8);
+ SignedData[18] = (UINT8)(((UINT16)P7Length) & 0xff);
+
+ //
+ // Part7: P7Data.
+ //
+ CopyMem (SignedData + 19, P7Data, P7Length);
+ }
+
+ *WrapFlag = Wrapped;
+ return TRUE;
+}
+
+/**
+ Verifies the validity of a PKCS#7 signed data as described in "PKCS #7:
+ Cryptographic Message Syntax Standard". The input signed data could be wrapped
+ in a ContentInfo structure.
+
+ If P7Data, TrustedCert or InData is NULL, then return FALSE.
+ If P7Length, CertLength or DataLength overflow, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] P7Data Pointer to the PKCS#7 message to verify.
+ @param[in] P7Length Length of the PKCS#7 message in bytes.
+ @param[in] TrustedCert Pointer to a trusted/root certificate encoded in DER, which
+ is used for certificate chain verification.
+ @param[in] CertLength Length of the trusted certificate in bytes.
+ @param[in] InData Pointer to the content to be verified.
+ @param[in] DataLength Length of InData in bytes.
+
+ @retval TRUE The specified PKCS#7 signed data is valid.
+ @retval FALSE Invalid PKCS#7 signed data.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7Verify (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ IN CONST UINT8 *TrustedCert,
+ IN UINTN CertLength,
+ IN CONST UINT8 *InData,
+ IN UINTN DataLength
+ )
+{
+ BOOLEAN Status;
+ UINT8 *WrapData;
+ UINTN WrapDataSize;
+ BOOLEAN Wrapped;
+ MbedtlsPkcs7 Pkcs7;
+ INT32 Ret;
+ mbedtls_x509_crt Crt;
+ mbedtls_x509_crt *TempCrt;
+
+ //
+ // Check input parameters.
+ //
+ if ((P7Data == NULL) || (TrustedCert == NULL) || (InData == NULL) ||
+ (P7Length > INT_MAX) || (CertLength > INT_MAX) || (DataLength > INT_MAX))
+ {
+ return FALSE;
+ }
+
+ Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);
+
+ if (!Status) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+ MbedTlsPkcs7Init (&Pkcs7);
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7);
+ if (Ret != 0) {
+ goto Cleanup;
+ }
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, TrustedCert, CertLength);
+ if (Ret != 0) {
+ goto Cleanup;
+ }
+
+ Status = MbedTlsPkcs7SignedDataVerify (&Pkcs7, &Crt, InData, (INT32)DataLength);
+
+Cleanup:
+ if (&Crt != NULL) {
+ mbedtls_x509_crt_free (&Crt);
+ }
+
+ if (Pkcs7.SignedData.Certificates.next != NULL) {
+ TempCrt = Pkcs7.SignedData.Certificates.next;
+ mbedtls_x509_crt_free (TempCrt);
+ }
+
+ return Status;
+}
+
+/**
+ Wrap function to use free() to free allocated memory for certificates.
+
+ @param[in] Certs Pointer to the certificates to be freed.
+
+**/
+VOID
+EFIAPI
+Pkcs7FreeSigners (
+ IN UINT8 *Certs
+ )
+{
+ if (Certs == NULL) {
+ return;
+ }
+
+ FreePool (Certs);
+}
+
+/**
+ Get the signer's certificates from PKCS#7 signed data as described in "PKCS #7:
+ Cryptographic Message Syntax Standard". The input signed data could be wrapped
+ in a ContentInfo structure.
+
+ If P7Data, CertStack, StackLength, TrustedCert or CertLength is NULL, then
+ return FALSE. If P7Length overflow, then return FALSE.
+
+ Caution: This function may receive untrusted input.
+ UEFI Authenticated Variable is external input, so this function will do basic
+ check for PKCS#7 data structure.
+
+ @param[in] P7Data Pointer to the PKCS#7 message to verify.
+ @param[in] P7Length Length of the PKCS#7 message in bytes.
+ @param[out] CertStack Pointer to Signer's certificates retrieved from P7Data.
+ It's caller's responsibility to free the buffer with
+ Pkcs7FreeSigners().
+ This data structure is EFI_CERT_STACK type.
+ @param[out] StackLength Length of signer's certificates in bytes.
+ @param[out] TrustedCert Pointer to a trusted certificate from Signer's certificates.
+ It's caller's responsibility to free the buffer with
+ Pkcs7FreeSigners().
+ @param[out] CertLength Length of the trusted certificate in bytes.
+
+ @retval TRUE The operation is finished successfully.
+ @retval FALSE Error occurs during the operation.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetSigners (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ OUT UINT8 **CertStack,
+ OUT UINTN *StackLength,
+ OUT UINT8 **TrustedCert,
+ OUT UINTN *CertLength
+ )
+{
+ MbedtlsPkcs7SignerInfo *SignerInfo;
+ mbedtls_x509_crt *Cert;
+ MbedtlsPkcs7 Pkcs7;
+ BOOLEAN Status;
+ UINT8 *WrapData;
+ UINTN WrapDataSize;
+ BOOLEAN Wrapped;
+ mbedtls_x509_crt *TempCrt;
+
+ UINTN CertSize;
+ UINT8 Index;
+ UINT8 *CertBuf;
+ UINT8 *OldBuf;
+ UINTN BufferSize;
+ UINTN OldSize;
+
+ if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) ||
+ (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX))
+ {
+ return FALSE;
+ }
+
+ Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);
+
+ if (!Status) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+ CertBuf = NULL;
+ OldBuf = NULL;
+ Cert = NULL;
+
+ MbedTlsPkcs7Init (&Pkcs7);
+ if (MbedtlsPkcs7ParseDer (WrapData, (INT32)WrapDataSize, &Pkcs7) != 0) {
+ goto _Exit;
+ }
+
+ SignerInfo = &(Pkcs7.SignedData.SignerInfos);
+
+ //
+ // Traverse each signers
+ //
+ // Convert CertStack to buffer in following format:
+ // UINT8 CertNumber;
+ // UINT32 Cert1Length;
+ // UINT8 Cert1[];
+ // UINT32 Cert2Length;
+ // UINT8 Cert2[];
+ // ...
+ // UINT32 CertnLength;
+ // UINT8 Certn[];
+ //
+ BufferSize = sizeof (UINT8);
+ OldSize = BufferSize;
+ Index = 0;
+
+ while (SignerInfo != NULL) {
+ // Find signers cert
+ Cert = MbedTlsPkcs7FindSignerCert (SignerInfo, &(Pkcs7.SignedData.Certificates));
+ if (Cert == NULL) {
+ goto _Exit;
+ }
+
+ CertSize = Cert->raw.len;
+ OldSize = BufferSize;
+ OldBuf = CertBuf;
+ BufferSize = OldSize + CertSize + sizeof (UINT32);
+
+ CertBuf = AllocateZeroPool (BufferSize);
+ if (CertBuf == NULL) {
+ goto _Exit;
+ }
+
+ if (OldBuf != NULL) {
+ CopyMem (CertBuf, OldBuf, OldSize);
+ FreePool (OldBuf);
+ OldBuf = NULL;
+ }
+
+ WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)CertSize);
+ CopyMem (CertBuf + OldSize + sizeof (UINT32), Cert->raw.p, CertSize);
+
+ Index++;
+
+ // move to next
+ SignerInfo = SignerInfo->Next;
+ }
+
+ if (CertBuf != NULL) {
+ //
+ // Update CertNumber.
+ //
+ CertBuf[0] = Index;
+
+ *CertLength = BufferSize - OldSize - sizeof (UINT32);
+ *TrustedCert = AllocateZeroPool (*CertLength);
+ if (*TrustedCert == NULL) {
+ goto _Exit;
+ }
+
+ CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength);
+ *CertStack = CertBuf;
+ *StackLength = BufferSize;
+ Status = TRUE;
+ }
+
+_Exit:
+ //
+ // Release Resources
+ //
+ if (!Status && (CertBuf != NULL)) {
+ FreePool (CertBuf);
+ *CertStack = NULL;
+ }
+
+ if (Status) {
+ if (Pkcs7.SignedData.Certificates.next != NULL) {
+ TempCrt = Pkcs7.SignedData.Certificates.next;
+ mbedtls_x509_crt_free (TempCrt);
+ }
+ }
+
+ if (OldBuf != NULL) {
+ FreePool (OldBuf);
+ }
+
+ return Status;
+}
+
+/**
+ Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:
+ Cryptographic Message Syntax Standard", and outputs two certificate lists chained and
+ unchained to the signer's certificates.
+ The input signed data could be wrapped in a ContentInfo structure.
+
+ @param[in] P7Data Pointer to the PKCS#7 message.
+ @param[in] P7Length Length of the PKCS#7 message in bytes.
+ @param[out] SignerChainCerts Pointer to the certificates list chained to signer's
+ certificate. It's caller's responsibility to free the buffer
+ with Pkcs7FreeSigners().
+ This data structure is EFI_CERT_STACK type.
+ @param[out] ChainLength Length of the chained certificates list buffer in bytes.
+ @param[out] UnchainCerts Pointer to the unchained certificates lists. It's caller's
+ responsibility to free the buffer with Pkcs7FreeSigners().
+ This data structure is EFI_CERT_STACK type.
+ @param[out] UnchainLength Length of the unchained certificates list buffer in bytes.
+
+ @retval TRUE The operation is finished successfully.
+ @retval FALSE Error occurs during the operation.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetCertificatesList (
+ IN CONST UINT8 *P7Data,
+ IN UINTN P7Length,
+ OUT UINT8 **SignerChainCerts,
+ OUT UINTN *ChainLength,
+ OUT UINT8 **UnchainCerts,
+ OUT UINTN *UnchainLength
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
new file mode 100644
index 0000000000..47a8230cf6
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
@@ -0,0 +1,689 @@
+/** @file
+ This module verifies that Enhanced Key Usages (EKU's) are present within
+ a PKCS7 signature blob using MbedTLS.
+
+ Copyright (C) Microsoft Corporation. All Rights Reserved.
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Base.h>
+#include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
+#include <mbedtls/asn1write.h>
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 EkuOID[] = { 0x55, 0x1D, 0x25 };
+
+/*leaf Cert basic_constraints case1: CA: false and CA object is excluded */
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase1[] = { 0x30, 0x00 };
+
+/*leaf Cert basic_constraints case2: CA: false */
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gBasicConstraintsCase2[] = { 0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x00 };
+
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8 gOidBasicConstraints[] = { 0x55, 0x1D, 0x13 };
+
+/**
+ Find first Extension data match with given OID
+
+ @param[in] Start Pointer to the DER-encoded extensions data
+ @param[in] End extensions data size in bytes
+ @param[in ] Oid OID for match
+ @param[in ] OidSize OID size in bytes
+ @param[out] FindExtensionData output matched extension data.
+ @param[out] FindExtensionDataLen matched extension data size.
+
+**/
+STATIC
+BOOLEAN
+InternalX509FindExtensionData (
+ UINT8 *Start,
+ UINT8 *End,
+ CONST UINT8 *Oid,
+ UINTN OidSize,
+ UINT8 **FindExtensionData,
+ UINTN *FindExtensionDataLen
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *ExtensionPtr;
+ UINTN ObjLen;
+ INT32 Ret;
+ BOOLEAN Status;
+ UINTN FindExtensionLen;
+ UINTN HeaderLen;
+
+ /*If no Extension entry match Oid*/
+ Status = FALSE;
+ Ptr = Start;
+
+ Ret = 0;
+
+ while (TRUE) {
+ //
+ // Extension ::= SEQUENCE {
+ // extnID OBJECT IDENTIFIER,
+ // critical BOOLEAN DEFAULT FALSE,
+ // extnValue OCTET STRING }
+ //
+ ExtensionPtr = Ptr;
+ Ret = mbedtls_asn1_get_tag (
+ &Ptr,
+ End,
+ &ObjLen,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE
+ );
+ if (Ret == 0) {
+ HeaderLen = (UINTN)(Ptr - ExtensionPtr);
+ FindExtensionLen = ObjLen;
+ /* Get Object Identifier*/
+ Ret = mbedtls_asn1_get_tag (
+ &Ptr,
+ End,
+ &ObjLen,
+ MBEDTLS_ASN1_OID
+ );
+ } else {
+ break;
+ }
+
+ if ((Ret == 0) && !CompareMem (Ptr, Oid, OidSize)) {
+ Ptr += ObjLen;
+
+ Ret = mbedtls_asn1_get_tag (
+ &Ptr,
+ End,
+ &ObjLen,
+ MBEDTLS_ASN1_BOOLEAN
+ );
+ if (Ret == 0) {
+ Ptr += ObjLen;
+ }
+
+ Ret = mbedtls_asn1_get_tag (
+ &Ptr,
+ End,
+ &ObjLen,
+ MBEDTLS_ASN1_OCTET_STRING
+ );
+ } else {
+ Ret = 1;
+ }
+
+ if (Ret == 0) {
+ *FindExtensionData = Ptr;
+ *FindExtensionDataLen = ObjLen;
+ Status = TRUE;
+ break;
+ }
+
+ /* move to next*/
+ Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;
+ Ret = 0;
+ }
+
+ return Status;
+}
+
+/**
+ Retrieve Extension data from one X.509 certificate.
+
+ @param[in] Cert Pointer to the X509 certificate.
+ @param[in] Oid Object identifier buffer
+ @param[in] OidSize Object identifier buffer size
+ @param[out] ExtensionData Extension bytes.
+ @param[in, out] ExtensionDataSize Extension bytes size.
+
+ @retval RETURN_SUCCESS The certificate Extension data retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If ExtensionDataSize is NULL.
+ If ExtensionData is not NULL and *ExtensionDataSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no Extension entry match Oid.
+ @retval RETURN_BUFFER_TOO_SMALL If the ExtensionData is NULL. The required buffer size
+ is returned in the ExtensionDataSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+**/
+STATIC
+BOOLEAN
+GetExtensionData (
+ CONST mbedtls_x509_crt *Cert,
+ CONST UINT8 *Oid,
+ UINTN OidSize,
+ UINT8 *ExtensionData,
+ UINTN *ExtensionDataSize
+ )
+{
+ CONST mbedtls_x509_crt *Crt;
+ INT32 Ret;
+ BOOLEAN Status;
+ UINT8 *Ptr;
+ UINT8 *End;
+ UINTN ObjLen;
+
+ Ptr = NULL;
+ End = NULL;
+ ObjLen = 0;
+
+ if ((Cert == NULL) || (Oid == NULL) || (OidSize == 0) ||
+ (ExtensionDataSize == NULL))
+ {
+ return FALSE;
+ }
+
+ Status = FALSE;
+
+ Crt = Cert;
+
+ Ptr = Crt->v3_ext.p;
+ End = Crt->v3_ext.p + Crt->v3_ext.len;
+ Ret = mbedtls_asn1_get_tag (
+ &Ptr,
+ End,
+ &ObjLen,
+ MBEDTLS_ASN1_CONSTRUCTED |
+ MBEDTLS_ASN1_SEQUENCE
+ );
+
+ if (Ret == 0) {
+ Status = InternalX509FindExtensionData (
+ Ptr,
+ End,
+ Oid,
+ OidSize,
+ &Ptr,
+ &ObjLen
+ );
+ }
+
+ if (Status) {
+ if (*ExtensionDataSize < ObjLen) {
+ *ExtensionDataSize = ObjLen;
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ if (Oid != NULL) {
+ if (ExtensionData == NULL) {
+ return FALSE;
+ }
+
+ CopyMem (ExtensionData, Ptr, ObjLen);
+ }
+
+ *ExtensionDataSize = ObjLen;
+ } else {
+ *ExtensionDataSize = 0;
+ }
+
+Cleanup:
+ return Status;
+}
+
+/**
+ Determines if the specified EKU represented in ASN1 form is present
+ in a given certificate.
+
+ @param[in] Cert The certificate to check.
+ @param[in] EKU The EKU to look for.
+ @param[in] EkuLen The size of EKU.
+
+ @retval EFI_SUCCESS We successfully identified the signing type.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
+
+**/
+STATIC
+EFI_STATUS
+IsEkuInCertificate (
+ IN CONST mbedtls_x509_crt *Cert,
+ IN UINT8 *EKU,
+ IN UINTN EkuLen
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Ret;
+ UINT8 *Buffer;
+ UINTN Index;
+ UINTN Len;
+
+ if ((Cert == NULL) || (EKU == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ Len = 0;
+ Buffer = NULL;
+ Ret = GetExtensionData (
+ Cert,
+ (CONST UINT8 *)EkuOID,
+ sizeof (EkuOID),
+ NULL,
+ &Len
+ );
+ if (Len == 0) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ Buffer = AllocateZeroPool (Len);
+ if (Buffer == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ Ret = GetExtensionData (
+ Cert,
+ (CONST UINT8 *)EkuOID,
+ sizeof (EkuOID),
+ Buffer,
+ &Len
+ );
+
+ if ((Len == 0) || (!Ret)) {
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ Status = EFI_NOT_FOUND;
+ /*find the spdm hardware identity OID*/
+ for (Index = 0; Index <= Len - EkuLen; Index++) {
+ if (!CompareMem (Buffer + Index, EKU, EkuLen)) {
+ // check sub EKU
+ if (Index == Len - EkuLen) {
+ Status = EFI_SUCCESS;
+ break;
+ // Ensure that the OID is complete
+ } else if (Buffer[Index + EkuLen] == 0x06) {
+ Status = EFI_SUCCESS;
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+
+Exit:
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+
+ return Status;
+}
+
+/**
+ Get OID from txt.
+
+ @param[in] RequiredEKUs Array of null-terminated strings listing OIDs of
+ required EKUs that must be present in the signature.
+ @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array.
+ @param[in,out] CheckOid OID.
+ @param[out] OidLen The size of OID.
+
+**/
+VOID
+GetOidFromTxt (
+ IN CONST CHAR8 *RequiredEKUs,
+ IN UINTN RequiredEKUsSize,
+ IN OUT UINT8 *CheckOid,
+ OUT UINT8 *OidLen
+ )
+{
+ UINT8 *Ptr;
+ UINT16 Index;
+ UINT32 Data;
+ UINT8 OidIndex;
+ UINTN EKUsSize;
+
+ EKUsSize = RequiredEKUsSize;
+ // https://learn.microsoft.com/en-us/windows/win32/seccertenroll/about-object-identifier?redirectedfrom=MSDN
+ CheckOid[0] = (UINT8)((RequiredEKUs[0] - '0') * 40 + (RequiredEKUs[2] - '0'));
+
+ EKUsSize = EKUsSize - 4;
+ Ptr = (UINT8 *)(RequiredEKUs + 4);
+
+ OidIndex = 1;
+
+ while (EKUsSize) {
+ Index = 0;
+ Data = 0;
+
+ while ((*Ptr != '.') && (*Ptr != '\0')) {
+ Index++;
+ Ptr++;
+ EKUsSize--;
+ }
+
+ while (Index) {
+ Data = 10 * Data + (*(Ptr - Index) - '0');
+ Index--;
+ }
+
+ if (EKUsSize != 0) {
+ Ptr++;
+ EKUsSize--;
+ }
+
+ if (Data < 128) {
+ CheckOid[OidIndex] = (UINT8)Data;
+ OidIndex++;
+ } else {
+ CheckOid[OidIndex + 1] = (UINT8)(Data & 0xFF);
+ CheckOid[OidIndex] = (UINT8)(((((Data & 0xFF00) << 1) | 0x8000) >> 8) & 0xFF);
+ OidIndex = OidIndex + 2;
+ }
+ }
+
+ *OidLen = OidIndex;
+}
+
+/**
+ Verify the Cert is signer cert
+
+ @param[in] Start Pointer to the DER-encoded certificate data Start.
+ @param[in] End Pointer to the DER-encoded certificate data End.
+
+ @retval true verify pass
+ @retval false verify fail
+**/
+STATIC
+BOOLEAN
+IsCertSignerCert (
+ UINT8 *Start,
+ UINT8 *End
+ )
+{
+ BOOLEAN Status;
+ UINT8 *Buffer;
+ UINTN Len;
+ mbedtls_x509_crt Cert;
+ UINTN ObjLen;
+
+ mbedtls_x509_crt_init (&Cert);
+
+ ObjLen = End - Start;
+
+ if (mbedtls_x509_crt_parse_der (&Cert, Start, ObjLen) != 0) {
+ return FALSE;
+ }
+
+ Len = 0;
+ Buffer = NULL;
+ Status = GetExtensionData (
+ &Cert,
+ (CONST UINT8 *)gOidBasicConstraints,
+ sizeof (gOidBasicConstraints),
+ NULL,
+ &Len
+ );
+ if (Len == 0) {
+ /* basic constraints is not present in Cert */
+ return TRUE;
+ }
+
+ Buffer = AllocateZeroPool (Len);
+ if (Buffer == NULL) {
+ return FALSE;
+ }
+
+ Status = GetExtensionData (
+ &Cert,
+ (CONST UINT8 *)gOidBasicConstraints,
+ sizeof (gOidBasicConstraints),
+ Buffer,
+ &Len
+ );
+
+ if (Len == 0) {
+ /* basic constraints is not present in Cert */
+ Status = TRUE;
+ goto Exit;
+ } else if (!Status) {
+ Status = FALSE;
+ goto Exit;
+ }
+
+ if ((Len == sizeof (gBasicConstraintsCase1)) &&
+ (!CompareMem (Buffer, gBasicConstraintsCase1, sizeof (gBasicConstraintsCase1))))
+ {
+ Status = TRUE;
+ goto Exit;
+ }
+
+ if ((Len == sizeof (gBasicConstraintsCase2)) &&
+ (!CompareMem (Buffer, gBasicConstraintsCase2, sizeof (gBasicConstraintsCase2))))
+ {
+ Status = TRUE;
+ goto Exit;
+ }
+
+ Status = FALSE;
+
+Exit:
+ mbedtls_x509_crt_free (&Cert);
+
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+
+ return Status;
+}
+
+/**
+ Determines if the specified EKUs are present in a signing certificate.
+
+ @param[in] SignerCert The certificate to check.
+ @param[in] RequiredEKUs The EKUs to look for.
+ @param[in] RequiredEKUsSize The number of EKUs
+ @param[in] RequireAllPresent If TRUE, then all the specified EKUs
+ must be present in the certificate.
+
+ @retval EFI_SUCCESS We successfully identified the signing type.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
+**/
+STATIC
+EFI_STATUS
+CheckEKUs (
+ IN CONST mbedtls_x509_crt *SignerCert,
+ IN CONST CHAR8 *RequiredEKUs[],
+ IN CONST UINT32 RequiredEKUsSize,
+ IN BOOLEAN RequireAllPresent
+ )
+{
+ EFI_STATUS Status;
+ UINT32 NumEkusFound;
+ UINT32 Index;
+ UINT8 *EKU;
+ UINTN EkuLen;
+ UINT8 CheckOid[20];
+ UINT8 OidLen;
+
+ Status = EFI_SUCCESS;
+ NumEkusFound = 0;
+
+ if ((SignerCert == NULL) || (RequiredEKUs == NULL) || (RequiredEKUsSize == 0)) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Exit;
+ }
+
+ for (Index = 0; Index < RequiredEKUsSize; Index++) {
+ //
+ // Finding required EKU in Cert.
+ //
+ GetOidFromTxt (RequiredEKUs[Index], strlen (RequiredEKUs[Index]), CheckOid, &OidLen);
+
+ EKU = CheckOid;
+ EkuLen = OidLen;
+
+ Status = IsEkuInCertificate (SignerCert, EKU, EkuLen);
+ if (Status == EFI_SUCCESS) {
+ NumEkusFound++;
+ if (!RequireAllPresent) {
+ //
+ // Found at least one, so we are done.
+ //
+ goto Exit;
+ }
+ } else {
+ //
+ // Fail to find Eku in Cert
+ break;
+ }
+ }
+
+Exit:
+ if (RequireAllPresent &&
+ (NumEkusFound == RequiredEKUsSize))
+ {
+ //
+ // Found all required EKUs in certificate.
+ //
+ Status = EFI_SUCCESS;
+ }
+
+ return Status;
+}
+
+/**
+ This function receives a PKCS#7 formatted signature blob,
+ looks for the EKU SEQUENCE blob, and if found then looks
+ for all the required EKUs. This function was created so that
+ the Surface team can cut down on the number of Certificate
+ Authorities (CA's) by checking EKU's on leaf signers for
+ a specific product. This prevents one product's certificate
+ from signing another product's firmware or unlock blobs.
+
+ Note that this function does not validate the certificate chain.
+ That needs to be done before using this function.
+
+ @param[in] Pkcs7Signature The PKCS#7 signed information content block. An array
+ containing the content block with both the signature,
+ the signer's certificate, and any necessary intermediate
+ certificates.
+ @param[in] Pkcs7SignatureSize Number of bytes in Pkcs7Signature.
+ @param[in] RequiredEKUs Array of null-terminated strings listing OIDs of
+ required EKUs that must be present in the signature.
+ @param[in] RequiredEKUsSize Number of elements in the RequiredEKUs string array.
+ @param[in] RequireAllPresent If this is TRUE, then all of the specified EKU's
+ must be present in the leaf signer. If it is
+ FALSE, then we will succeed if we find any
+ of the specified EKU's.
+
+ @retval EFI_SUCCESS The required EKUs were found in the signature.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_NOT_FOUND One or more EKU's were not found in the signature.
+
+**/
+EFI_STATUS
+EFIAPI
+VerifyEKUsInPkcs7Signature (
+ IN CONST UINT8 *Pkcs7Signature,
+ IN CONST UINT32 SignatureSize,
+ IN CONST CHAR8 *RequiredEKUs[],
+ IN CONST UINT32 RequiredEKUsSize,
+ IN BOOLEAN RequireAllPresent
+ )
+{
+ EFI_STATUS Status;
+ mbedtls_x509_crt Cert;
+ UINT8 *Ptr;
+ UINT8 *End;
+ INT32 Len;
+ UINTN ObjLen;
+ UINT8 *OldEnd;
+
+ //
+ // Check input parameter.
+ //
+ if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL)) {
+ Status = EFI_INVALID_PARAMETER;
+ return Status;
+ }
+
+ mbedtls_x509_crt_init (&Cert);
+
+ Ptr = (UINT8 *)(UINTN)Pkcs7Signature;
+ Len = (UINT32)SignatureSize;
+ End = Ptr + Len;
+
+ // Cert
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // tbscert
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // signature algo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // signature
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ OldEnd = Ptr;
+ // Cert
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ End = Ptr + ObjLen;
+
+ // leaf Cert
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ while ((Ptr != End) && (Ptr < End)) {
+ if (IsCertSignerCert (OldEnd, Ptr)) {
+ break;
+ }
+
+ OldEnd = Ptr;
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ }
+
+ if (Ptr != End) {
+ return FALSE;
+ } else {
+ Ptr = End - ObjLen;
+ }
+
+ // leaf Cert
+ ObjLen += Ptr - OldEnd;
+ Ptr = OldEnd;
+
+ if (mbedtls_x509_crt_parse_der (&Cert, Ptr, ObjLen) != 0) {
+ return FALSE;
+ }
+
+ Status = CheckEKUs (&Cert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent);
+ if (Status != EFI_SUCCESS) {
+ goto Exit;
+ }
+
+Exit:
+ //
+ // Release Resources
+ //
+ mbedtls_x509_crt_free (&Cert);
+
+ return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
new file mode 100644
index 0000000000..5fe76f146d
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
@@ -0,0 +1,352 @@
+/** @file
+ RSA Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+ This file implements following APIs which provide more capabilities for RSA:
+ 1) RsaGetKey
+ 2) RsaGenerateKey
+ 3) RsaCheckKey
+ 4) RsaPkcs1Sign
+
+ RFC 8017 - PKCS #1: RSA Cryptography Specifications Version 2.2
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+
+/**
+ Gets the tag-designated RSA key component from the established RSA context.
+
+ This function retrieves the tag-designated RSA key component from the
+ established RSA context as a non-negative integer (octet string format
+ represented in RSA PKCS#1).
+ If specified key component has not been set or has been cleared, then returned
+ BnSize is set to 0.
+ If the BigNumber buffer is too small to hold the contents of the key, FALSE
+ is returned and BnSize is set to the required buffer size to obtain the key.
+
+ If RsaContext is NULL, then return FALSE.
+ If BnSize is NULL, then return FALSE.
+ If BnSize is large enough but BigNumber is NULL, then return FALSE.
+
+ @param[in, out] RsaContext Pointer to RSA context being set.
+ @param[in] KeyTag Tag of RSA key component being set.
+ @param[out] BigNumber Pointer to octet integer buffer.
+ @param[in, out] BnSize On input, the size of big number buffer in bytes.
+ On output, the size of data returned in big number buffer in bytes.
+
+ @retval TRUE RSA key component was retrieved successfully.
+ @retval FALSE Invalid RSA key component tag.
+ @retval FALSE BnSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetKey (
+ IN OUT VOID *RsaContext,
+ IN RSA_KEY_TAG KeyTag,
+ OUT UINT8 *BigNumber,
+ IN OUT UINTN *BnSize
+ )
+{
+ mbedtls_rsa_context *RsaKey;
+ INT32 Ret;
+ mbedtls_mpi Value;
+ UINTN Size;
+
+ //
+ // Check input parameters.
+ //
+ if ((RsaContext == NULL) || (*BnSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ //
+ // Init mbedtls_mpi
+ //
+ mbedtls_mpi_init (&Value);
+ Size = *BnSize;
+ *BnSize = 0;
+
+ RsaKey = (mbedtls_rsa_context *)RsaContext;
+
+ switch (KeyTag) {
+ case RsaKeyN:
+ Ret = mbedtls_rsa_export (RsaKey, &Value, NULL, NULL, NULL, NULL);
+ break;
+ case RsaKeyE:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, NULL, &Value);
+ break;
+ case RsaKeyD:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, &Value, NULL);
+ break;
+ case RsaKeyQ:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, &Value, NULL, NULL);
+ break;
+ case RsaKeyP:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, &Value, NULL, NULL, NULL);
+ break;
+ case RsaKeyDp:
+ case RsaKeyDq:
+ case RsaKeyQInv:
+ default:
+ Ret = -1;
+ break;
+ }
+
+ if (Ret != 0) {
+ goto End;
+ }
+
+ if (mbedtls_mpi_size (&Value) == 0) {
+ Ret = 0;
+ goto End;
+ }
+
+ *BnSize = Size;
+
+ Size = mbedtls_mpi_size (&Value);
+ if (*BnSize < Size) {
+ Ret = 1;
+ *BnSize = Size;
+ goto End;
+ }
+
+ if (BigNumber == NULL) {
+ Ret = 0;
+ *BnSize = Size;
+ goto End;
+ }
+
+ if ((BigNumber != NULL) && (Ret == 0)) {
+ Ret = mbedtls_mpi_write_binary (&Value, BigNumber, Size);
+ *BnSize = Size;
+ }
+
+End:
+ mbedtls_mpi_free (&Value);
+ return Ret == 0;
+}
+
+/**
+ Generates RSA key components.
+
+ This function generates RSA key components. It takes RSA public exponent Pe and
+ length in bits of RSA modulus N as input, and generates all key components.
+ If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
+
+ Before this function can be invoked, pseudorandom number generator must be correctly
+ initialized by RandomSeed().
+
+ If RsaContext is NULL, then return FALSE.
+
+ @param[in, out] RsaContext Pointer to RSA context being set.
+ @param[in] ModulusLength Length of RSA modulus N in bits.
+ @param[in] PublicExponent Pointer to RSA public exponent.
+ @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes.
+
+ @retval TRUE RSA key component was generated successfully.
+ @retval FALSE Invalid RSA key component tag.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGenerateKey (
+ IN OUT VOID *RsaContext,
+ IN UINTN ModulusLength,
+ IN CONST UINT8 *PublicExponent,
+ IN UINTN PublicExponentSize
+ )
+{
+ INT32 Ret;
+ mbedtls_rsa_context *Rsa;
+ INT32 Pe;
+
+ //
+ // Check input parameters.
+ //
+ if ((RsaContext == NULL) || (ModulusLength > INT_MAX) || (PublicExponentSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ Rsa = (mbedtls_rsa_context *)RsaContext;
+
+ if (PublicExponent == NULL) {
+ Pe = 0x10001;
+ } else {
+ if (PublicExponentSize == 0) {
+ return FALSE;
+ }
+
+ switch (PublicExponentSize) {
+ case 1:
+ Pe = PublicExponent[0];
+ break;
+ case 2:
+ Pe = PublicExponent[0] << 8 | PublicExponent[1];
+ break;
+ case 3:
+ Pe = PublicExponent[0] << 16 | PublicExponent[1] << 8 |
+ PublicExponent[2];
+ break;
+ case 4:
+ Pe = PublicExponent[0] << 24 | PublicExponent[1] << 16 |
+ PublicExponent[2] << 8 | PublicExponent[3];
+ break;
+ default:
+ return FALSE;
+ }
+ }
+
+ Ret = mbedtls_rsa_gen_key (
+ Rsa,
+ MbedtlsRand,
+ NULL,
+ (UINT32)ModulusLength,
+ Pe
+ );
+
+ return Ret == 0;
+}
+
+/**
+ Validates key components of RSA context.
+ NOTE: This function performs integrity checks on all the RSA key material, so
+ the RSA key structure must contain all the private key data.
+
+ This function validates key components of RSA context in following aspects:
+ - Whether p is a prime
+ - Whether q is a prime
+ - Whether n = p * q
+ - Whether d*e = 1 mod lcm(p-1,q-1)
+
+ If RsaContext is NULL, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context to check.
+
+ @retval TRUE RSA key components are valid.
+ @retval FALSE RSA key components are not valid.
+
+**/
+BOOLEAN
+EFIAPI
+RsaCheckKey (
+ IN VOID *RsaContext
+ )
+{
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+
+ UINT32 Ret;
+
+ Ret = mbedtls_rsa_complete (RsaContext);
+ if (Ret == 0) {
+ Ret = mbedtls_rsa_check_privkey (RsaContext);
+ }
+
+ return Ret == 0;
+}
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
+ RSA PKCS#1.
+ 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 MessageHash is NULL, then return FALSE.
+ If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-384 or SHA-512 digest, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 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 PKCS1-v1_5.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPkcs1Sign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ INT32 Ret;
+ mbedtls_md_type_t MdAlg;
+
+ if ((RsaContext == NULL) || (MessageHash == NULL)) {
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+ return FALSE;
+ }
+
+ switch (HashSize) {
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+ case SHA1_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA1;
+ break;
+ #endif
+
+ case SHA256_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA256;
+ break;
+
+ case SHA384_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA384;
+ break;
+
+ case SHA512_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA512;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_get_len (RsaContext) > *SigSize) {
+ *SigSize = mbedtls_rsa_get_len (RsaContext);
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, MdAlg);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_pkcs1_sign (
+ RsaContext,
+ MbedtlsRand,
+ NULL,
+ MdAlg,
+ (UINT32)HashSize,
+ MessageHash,
+ Signature
+ );
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ *SigSize = mbedtls_rsa_get_len (RsaContext);
+ return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
new file mode 100644
index 0000000000..5555f9261e
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
@@ -0,0 +1,140 @@
+/** @file
+ RSA PSS Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+ This file implements following APIs which provide basic capabilities for RSA:
+ 1) RsaPssSign
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/sha512.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 not equal to 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
+ )
+{
+ INT32 Ret;
+ mbedtls_md_type_t MdAlg;
+ UINT8 HashValue[SHA512_DIGEST_SIZE];
+
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+ return FALSE;
+ }
+
+ if ((Message == NULL) || (MsgSize == 0) || (MsgSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ if (SaltLen != DigestLen) {
+ return FALSE;
+ }
+
+ ZeroMem (HashValue, DigestLen);
+
+ switch (DigestLen) {
+ case SHA256_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA256;
+ if (mbedtls_sha256 (Message, MsgSize, HashValue, FALSE) != 0) {
+ return FALSE;
+ }
+
+ break;
+
+ case SHA384_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA384;
+ if (mbedtls_sha512 (Message, MsgSize, HashValue, TRUE) != 0) {
+ return FALSE;
+ }
+
+ break;
+
+ case SHA512_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA512;
+ if (mbedtls_sha512 (Message, MsgSize, HashValue, FALSE) != 0) {
+ return FALSE;
+ }
+
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ //
+ // If Signature is NULL, return safe SignatureSize
+ //
+ *SigSize = MBEDTLS_MPI_MAX_SIZE;
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V21, MdAlg);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_rsassa_pss_sign (
+ RsaContext,
+ MbedtlsRand,
+ NULL,
+ MdAlg,
+ (UINT32)DigestLen,
+ HashValue,
+ Signature
+ );
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ *SigSize = ((mbedtls_rsa_context *)RsaContext)->len;
+ return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c
new file mode 100644
index 0000000000..d3fa205f9c
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptTs.c
@@ -0,0 +1,381 @@
+/** @file
+ RFC3161 Timestamp Countersignature Verification Wrapper Implementation which does
+ not provide real capabilities.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/asn1.h>
+
+//
+// OID ASN.1 Value for SPC_RFC3161_OBJID ("1.3.6.1.4.1.311.3.3.1")
+//
+GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 mSpcRFC3161OidValue[] = {
+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x03, 0x03, 0x01
+};
+
+/**
+ Convert ASN.1 GeneralizedTime to EFI Time.
+
+ @param[in] Ptr Pointer to the ASN.1 GeneralizedTime to be converted.
+ @param[out] EfiTime Return the corresponding EFI Time.
+
+ @retval TRUE The time conversion succeeds.
+ @retval FALSE Invalid parameters.
+
+**/
+STATIC
+BOOLEAN
+ConvertAsn1TimeToEfiTime (
+ IN UINT8 *Ptr,
+ OUT EFI_TIME *EfiTime
+ )
+{
+ CONST CHAR8 *Str;
+ UINTN Index;
+
+ if ((Ptr == NULL) || (EfiTime == NULL)) {
+ return FALSE;
+ }
+
+ Str = (CONST CHAR8 *)Ptr;
+ SetMem (EfiTime, sizeof (EFI_TIME), 0);
+
+ Index = 0;
+
+ /* four digit year */
+ EfiTime->Year = (Str[Index++] - '0') * 1000;
+ EfiTime->Year += (Str[Index++] - '0') * 100;
+ EfiTime->Year += (Str[Index++] - '0') * 10;
+ EfiTime->Year += (Str[Index++] - '0');
+ if ((EfiTime->Year < 1900) || (EfiTime->Year > 9999)) {
+ return FALSE;
+ }
+
+ EfiTime->Month = (Str[Index++] - '0') * 10;
+ EfiTime->Month += (Str[Index++] - '0');
+ if ((EfiTime->Month < 1) || (EfiTime->Month > 12)) {
+ return FALSE;
+ }
+
+ EfiTime->Day = (Str[Index++] - '0') * 10;
+ EfiTime->Day += (Str[Index++] - '0');
+ if ((EfiTime->Day < 1) || (EfiTime->Day > 31)) {
+ return FALSE;
+ }
+
+ EfiTime->Hour = (Str[Index++] - '0') * 10;
+ EfiTime->Hour += (Str[Index++] - '0');
+ if (EfiTime->Hour > 23) {
+ return FALSE;
+ }
+
+ EfiTime->Minute = (Str[Index++] - '0') * 10;
+ EfiTime->Minute += (Str[Index++] - '0');
+ if (EfiTime->Minute > 59) {
+ return FALSE;
+ }
+
+ EfiTime->Second = (Str[Index++] - '0') * 10;
+ EfiTime->Second += (Str[Index++] - '0');
+ if (EfiTime->Second > 59) {
+ return FALSE;
+ }
+
+ /* Note: we did not adjust the time based on time zone information */
+
+ return TRUE;
+}
+
+/**
+ Verifies the validity of a RFC3161 Timestamp CounterSignature embedded in PE/COFF Authenticode
+ signature.
+
+ Return FALSE to indicate this interface is not supported.
+
+ @param[in] AuthData Pointer to the Authenticode Signature retrieved from signed
+ PE/COFF image to be verified.
+ @param[in] DataSize Size of the Authenticode Signature in bytes.
+ @param[in] TsaCert Pointer to a trusted/root TSA certificate encoded in DER, which
+ is used for TSA certificate chain verification.
+ @param[in] CertSize Size of the trusted certificate in bytes.
+ @param[out] SigningTime Return the time of timestamp generation time if the timestamp
+ signature is valid.
+
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ImageTimestampVerify (
+ IN CONST UINT8 *AuthData,
+ IN UINTN DataSize,
+ IN CONST UINT8 *TsaCert,
+ IN UINTN CertSize,
+ OUT EFI_TIME *SigningTime
+ )
+{
+ BOOLEAN Status;
+ UINT8 *Ptr;
+ UINT8 *End;
+ INT32 Len;
+ UINTN ObjLen;
+ UINT8 *TempPtr;
+
+ //
+ // Initializations
+ //
+ if (SigningTime != NULL) {
+ SetMem (SigningTime, sizeof (EFI_TIME), 0);
+ }
+
+ //
+ // Input Parameters Checking.
+ //
+ if ((AuthData == NULL) || (TsaCert == NULL)) {
+ return FALSE;
+ }
+
+ if ((DataSize > INT_MAX) || (CertSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ Ptr = (UINT8 *)(UINTN)AuthData;
+ Len = (UINT32)DataSize;
+ End = Ptr + Len;
+
+ // ContentInfo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // ContentType
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // content
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ End = Ptr + ObjLen;
+ // signedData
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // version
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // digestAlgo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // encapContentInfo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // cert
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ TempPtr = Ptr;
+ // OPTIONAL CRLs
+ if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {
+ Ptr = TempPtr + ObjLen;
+ }
+
+ // signerInfo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+ return FALSE;
+ }
+
+ // sub parse
+ // signerInfo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ End = Ptr + ObjLen;
+
+ // version
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // sid
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // digestalgo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // OPTIONAL AuthenticatedAttributes
+ TempPtr = Ptr;
+ if (mbedtls_asn1_get_tag (&TempPtr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) == 0) {
+ Ptr = TempPtr + ObjLen;
+ }
+
+ // signaturealgo
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // signature
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // OPTIONAL UnauthenticatedAttributes
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, 0xA1) != 0) {
+ return FALSE;
+ }
+
+ // Attribute
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // type
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ if (CompareMem (Ptr, mSpcRFC3161OidValue, sizeof (mSpcRFC3161OidValue)) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // values
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+ return FALSE;
+ }
+
+ // values
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // signedData OID
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // [0]
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // integer
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // SET
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // tST OID
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
+ return FALSE;
+ }
+
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING) != 0) {
+ return FALSE;
+ }
+
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ // Integer
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // policy OID
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // sequence
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+ // Integer
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_INTEGER) != 0) {
+ return FALSE;
+ }
+
+ Ptr += ObjLen;
+
+ // GeneralizedTime
+ if (mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_GENERALIZED_TIME) != 0) {
+ return FALSE;
+ }
+
+ //
+ // Retrieve the signing time from TS_TST_INFO structure.
+ //
+ if (SigningTime != NULL) {
+ SetMem (SigningTime, sizeof (EFI_TIME), 0);
+ Status = ConvertAsn1TimeToEfiTime (Ptr, SigningTime);
+ }
+
+ return Status;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c
new file mode 100644
index 0000000000..84b67c8f0a
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptX509.c
@@ -0,0 +1,1940 @@
+/** @file
+ X.509 Certificate Handler Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_crt.h>
+#include <mbedtls/rsa.h>
+#include <mbedtls/ecp.h>
+#include <mbedtls/ecdh.h>
+#include <mbedtls/ecdsa.h>
+
+///
+/// OID
+///
+STATIC CONST UINT8 OID_commonName[] = {
+ 0x55, 0x04, 0x03
+};
+STATIC CONST UINT8 OID_organizationName[] = {
+ 0x55, 0x04, 0x0A
+};
+STATIC CONST UINT8 OID_extKeyUsage[] = {
+ 0x55, 0x1D, 0x25
+};
+STATIC CONST UINT8 OID_BasicConstraints[] = {
+ 0x55, 0x1D, 0x13
+};
+
+/* Profile for backward compatibility. Allows RSA 1024, unlike the default
+ profile. */
+STATIC mbedtls_x509_crt_profile gCompatProfile =
+{
+ /* Hashes from SHA-256 and above. Note that this selection
+ * should be aligned with ssl_preset_default_hashes in ssl_tls.c. */
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA256) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA384) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_MD_SHA512),
+ 0xFFFFFFF, /* Any PK alg */
+
+ /* Curves at or above 128-bit security level. Note that this selection
+ * should be aligned with ssl_preset_default_curves in ssl_tls.c. */
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP256R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP384R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_SECP521R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP256R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP384R1) |
+ MBEDTLS_X509_ID_FLAG (MBEDTLS_ECP_DP_BP512R1) |
+ 0,
+ 1024,
+};
+
+/**
+ Construct a X509 object from DER-encoded certificate data.
+
+ If Cert is NULL, then return FALSE.
+ If SingleX509Cert is NULL, then return FALSE.
+
+ @param[in] Cert Pointer to the DER-encoded certificate data.
+ @param[in] CertSize The size of certificate data in bytes.
+ @param[out] SingleX509Cert The generated X509 object.
+
+ @retval TRUE The X509 object generation succeeded.
+ @retval FALSE The operation failed.
+
+**/
+BOOLEAN
+EFIAPI
+X509ConstructCertificate (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 **SingleX509Cert
+ )
+{
+ mbedtls_x509_crt *MbedTlsCert;
+ INT32 Ret;
+
+ if ((Cert == NULL) || (SingleX509Cert == NULL) || (CertSize == 0)) {
+ return FALSE;
+ }
+
+ MbedTlsCert = AllocateZeroPool (sizeof (mbedtls_x509_crt));
+ if (MbedTlsCert == NULL) {
+ return FALSE;
+ }
+
+ mbedtls_x509_crt_init (MbedTlsCert);
+
+ *SingleX509Cert = (UINT8 *)(VOID *)MbedTlsCert;
+ Ret = mbedtls_x509_crt_parse_der (MbedTlsCert, Cert, CertSize);
+ if (Ret == 0) {
+ return TRUE;
+ } else {
+ mbedtls_x509_crt_free (MbedTlsCert);
+ FreePool (MbedTlsCert);
+ return FALSE;
+ }
+}
+
+/**
+ Construct a X509 stack object from a list of DER-encoded certificate data.
+
+ If X509Stack is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object.
+ On output, pointer to the X509 stack object with new
+ inserted X509 certificate.
+ @param[in] Args VA_LIST marker for the variable argument list.
+ A list of DER-encoded single certificate data followed
+ by certificate size. A NULL terminates the list. The
+ pairs are the arguments to X509ConstructCertificate().
+
+ @retval TRUE The X509 stack construction succeeded.
+ @retval FALSE The construction operation failed.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+X509ConstructCertificateStackV (
+ IN OUT UINT8 **X509Stack,
+ IN VA_LIST Args
+ )
+{
+ UINT8 *Cert;
+ UINTN CertSize;
+ INT32 Index;
+ INT32 Ret;
+ mbedtls_x509_crt *Crt;
+
+ if (X509Stack == NULL) {
+ return FALSE;
+ }
+
+ Ret = 0;
+ Crt = NULL;
+ if (*X509Stack == NULL) {
+ Crt = AllocateZeroPool (sizeof (mbedtls_x509_crt));
+ if (Crt == NULL) {
+ return FALSE;
+ }
+
+ mbedtls_x509_crt_init (Crt);
+ *X509Stack = (UINT8 *)Crt;
+ }
+
+ for (Index = 0; ; Index++) {
+ //
+ // If Cert is NULL, then it is the end of the list.
+ //
+ Cert = VA_ARG (Args, UINT8 *);
+ if (Cert == NULL) {
+ break;
+ }
+
+ CertSize = VA_ARG (Args, UINTN);
+ if (CertSize == 0) {
+ break;
+ }
+
+ Ret = mbedtls_x509_crt_parse_der ((mbedtls_x509_crt *)*X509Stack, Cert, CertSize);
+
+ if (Ret != 0) {
+ break;
+ }
+ }
+
+ if (Ret == 0) {
+ return TRUE;
+ } else {
+ if (Crt != NULL) {
+ mbedtls_x509_crt_free (Crt);
+ FreePool (Crt);
+ *X509Stack = NULL;
+ }
+
+ return FALSE;
+ }
+}
+
+/**
+ Construct a X509 stack object from a list of DER-encoded certificate data.
+
+ If X509Stack is NULL, then return FALSE.
+
+ @param[in, out] X509Stack On input, pointer to an existing or NULL X509 stack object.
+ On output, pointer to the X509 stack object with new
+ inserted X509 certificate.
+ @param ... A list of DER-encoded single certificate data followed
+ by certificate size. A NULL terminates the list. The
+ pairs are the arguments to X509ConstructCertificate().
+
+ @retval TRUE The X509 stack construction succeeded.
+ @retval FALSE The construction operation failed.
+
+**/
+BOOLEAN
+EFIAPI
+X509ConstructCertificateStack (
+ IN OUT UINT8 **X509Stack,
+ ...
+ )
+{
+ VA_LIST Args;
+ BOOLEAN Result;
+
+ VA_START (Args, X509Stack);
+ Result = X509ConstructCertificateStackV (X509Stack, Args);
+ VA_END (Args);
+ return Result;
+}
+
+/**
+ Release the specified X509 object.
+
+ If X509Cert is NULL, then return FALSE.
+
+ @param[in] X509Cert Pointer to the X509 object to be released.
+
+**/
+VOID
+EFIAPI
+X509Free (
+ IN VOID *X509Cert
+ )
+{
+ if (X509Cert != NULL) {
+ mbedtls_x509_crt_free (X509Cert);
+ FreePool (X509Cert);
+ }
+}
+
+/**
+ Release the specified X509 stack object.
+
+ If X509Stack is NULL, then return FALSE.
+
+ @param[in] X509Stack Pointer to the X509 stack object to be released.
+
+**/
+VOID
+EFIAPI
+X509StackFree (
+ IN VOID *X509Stack
+ )
+{
+ if (X509Stack == NULL) {
+ return;
+ }
+
+ mbedtls_x509_crt_free (X509Stack);
+}
+
+/**
+ Retrieve the tag and length of the tag.
+
+ @param Ptr The position in the ASN.1 data
+ @param End End of data
+ @param Length The variable that will receive the length
+ @param Tag The expected tag
+
+ @retval TRUE Get tag successful
+ @retval FALSe Failed to get tag or tag not match
+**/
+BOOLEAN
+EFIAPI
+Asn1GetTag (
+ IN OUT UINT8 **Ptr,
+ IN CONST UINT8 *End,
+ OUT UINTN *Length,
+ IN UINT32 Tag
+ )
+{
+ if (mbedtls_asn1_get_tag (Ptr, End, Length, (INT32)Tag) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ Retrieve the subject bytes from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] CertSubject Pointer to the retrieved certificate subject bytes.
+ @param[in, out] SubjectSize The size in bytes of the CertSubject buffer on input,
+ and the size of buffer returned CertSubject on output.
+
+ If Cert is NULL, then return FALSE.
+ If SubjectSize is NULL, then return FALSE.
+
+ @retval TRUE The certificate subject retrieved successfully.
+ @retval FALSE Invalid certificate, or the SubjectSize is too small for the result.
+ The SubjectSize will be updated with the required size.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetSubjectName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 *CertSubject,
+ IN OUT UINTN *SubjectSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ if (CertSubject != NULL) {
+ CopyMem (CertSubject, Crt.subject_raw.p, Crt.subject_raw.len);
+ }
+
+ *SubjectSize = Crt.subject_raw.len;
+ }
+
+ mbedtls_x509_crt_free (&Crt);
+
+ return Ret == 0;
+}
+
+/**
+ Retrieve a string from one X.509 certificate base on the Request_NID.
+
+ @param[in] Name mbedtls_x509_name
+ @param[in] Oid Oid
+ @param[in] OidSize Size of Oid
+ @param[in,out] CommonName Buffer to contain the retrieved certificate common
+ name string (UTF8). At most CommonNameSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
+ and the size of buffer returned CommonName on output.
+ If CommonName is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate CommonName retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If CommonNameSize is NULL.
+ If CommonName is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no NID Name entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalX509GetNIDName (
+ IN mbedtls_x509_name *Name,
+ IN CHAR8 *Oid,
+ IN UINTN OidSize,
+ IN OUT CHAR8 *CommonName OPTIONAL,
+ IN OUT UINTN *CommonNameSize
+ )
+{
+ CONST mbedtls_asn1_named_data *data;
+
+ data = mbedtls_asn1_find_named_data (Name, Oid, OidSize);
+ if (data != NULL) {
+ if (*CommonNameSize <= data->val.len) {
+ *CommonNameSize = data->val.len + 1;
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ if (CommonName != NULL) {
+ CopyMem (CommonName, data->val.p, data->val.len);
+ CommonName[data->val.len] = '\0';
+ }
+
+ *CommonNameSize = data->val.len + 1;
+ return RETURN_SUCCESS;
+ } else {
+ return RETURN_NOT_FOUND;
+ }
+}
+
+/**
+ Get X509 SubjectNIDName by OID.
+
+ @param[in] Cert certificate
+ @param[in] CertSize certificate size.
+ @param[in] Oid Oid
+ @param[in] OidSize Size of Oid
+ @param[in,out] CommonName Buffer to contain the retrieved certificate common
+ name string (UTF8). At most CommonNameSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
+ and the size of buffer returned CommonName on output.
+ If CommonName is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate CommonName retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If CommonNameSize is NULL.
+ If CommonName is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no NID Name entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalX509GetSubjectNIDName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ IN CHAR8 *Oid,
+ IN UINTN OidSize,
+ IN OUT CHAR8 *CommonName OPTIONAL,
+ IN OUT UINTN *CommonNameSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ mbedtls_x509_name *Name;
+ RETURN_STATUS ReturnStatus;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ ReturnStatus = RETURN_INVALID_PARAMETER;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ Name = &(Crt.subject);
+ ReturnStatus = InternalX509GetNIDName (Name, Oid, OidSize, CommonName, CommonNameSize);
+ }
+
+ mbedtls_x509_crt_free (&Crt);
+
+ return ReturnStatus;
+}
+
+/**
+ Get X509 IssuerNIDName by OID.
+
+ @param[in] Cert certificate
+ @param[in] CertSize certificate size.
+ @param[in] Oid Oid
+ @param[in] OidSize Size of Oid
+ @param[out] CommonName Buffer to contain the retrieved certificate common
+ name string (UTF8). At most CommonNameSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
+ and the size of buffer returned CommonName on output.
+ If CommonName is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate CommonName retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If CommonNameSize is NULL.
+ If CommonName is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no NID Name entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+InternalX509GetIssuerNIDName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ IN CHAR8 *Oid,
+ IN UINTN OidSize,
+ OUT CHAR8 *CommonName OPTIONAL,
+ IN OUT UINTN *CommonNameSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ mbedtls_x509_name *Name;
+ RETURN_STATUS ReturnStatus;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ ReturnStatus = RETURN_INVALID_PARAMETER;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ Name = &(Crt.issuer);
+ ReturnStatus = InternalX509GetNIDName (Name, Oid, OidSize, CommonName, CommonNameSize);
+ }
+
+ mbedtls_x509_crt_free (&Crt);
+
+ return ReturnStatus;
+}
+
+/**
+ Retrieve the common name (CN) string from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] CommonName Buffer to contain the retrieved certificate common
+ name string. At most CommonNameSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
+ and the size of buffer returned CommonName on output.
+ If CommonName is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate CommonName retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If CommonNameSize is NULL.
+ If CommonName is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no CommonName entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetCommonName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT CHAR8 *CommonName OPTIONAL,
+ IN OUT UINTN *CommonNameSize
+ )
+{
+ return InternalX509GetSubjectNIDName (Cert, CertSize, (CHAR8 *)OID_commonName, sizeof (OID_commonName), CommonName, CommonNameSize);
+}
+
+/**
+ Retrieve the organization name (O) string from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] NameBuffer Buffer to contain the retrieved certificate organization
+ name string. At most NameBufferSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] NameBufferSize The size in bytes of the Name buffer on input,
+ and the size of buffer returned Name on output.
+ If NameBuffer is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate Organization Name retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If NameBufferSize is NULL.
+ If NameBuffer is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no Organization Name entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the NameBuffer is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetOrganizationName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT CHAR8 *NameBuffer OPTIONAL,
+ IN OUT UINTN *NameBufferSize
+ )
+{
+ return InternalX509GetSubjectNIDName (Cert, CertSize, (CHAR8 *)OID_organizationName, sizeof (OID_organizationName), NameBuffer, NameBufferSize);
+}
+
+/**
+ Retrieve the RSA Public Key from one DER-encoded X509 certificate.
+
+ @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.
+
+ If Cert is NULL, then return FALSE.
+ If RsaContext is NULL, then return FALSE.
+
+ @retval TRUE RSA Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve RSA public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **RsaContext
+ )
+{
+ mbedtls_x509_crt Crt;
+ mbedtls_rsa_context *Rsa;
+ INT32 Ret;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ if (mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize) != 0) {
+ return FALSE;
+ }
+
+ if (mbedtls_pk_get_type (&Crt.pk) != MBEDTLS_PK_RSA) {
+ mbedtls_x509_crt_free (&Crt);
+ return FALSE;
+ }
+
+ Rsa = RsaNew ();
+ if (Rsa == NULL) {
+ mbedtls_x509_crt_free (&Crt);
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_copy (Rsa, mbedtls_pk_rsa (Crt.pk));
+ if (Ret != 0) {
+ RsaFree (Rsa);
+ mbedtls_x509_crt_free (&Crt);
+ return FALSE;
+ }
+
+ mbedtls_x509_crt_free (&Crt);
+
+ *RsaContext = Rsa;
+ return TRUE;
+}
+
+/**
+ Retrieve the EC Public Key from one DER-encoded X509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] EcContext Pointer to new-generated EC DSA context which contain the retrieved
+ EC public key component. Use EcFree() function to free the
+ resource.
+
+ If Cert is NULL, then return FALSE.
+ If EcContext is NULL, then return FALSE.
+
+ @retval TRUE EC Public Key was retrieved successfully.
+ @retval FALSE Fail to retrieve EC public key from X509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+EcGetPublicKeyFromX509 (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT VOID **EcContext
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Verify one X509 certificate was issued by the trusted CA.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate to be verified.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[in] CACert Pointer to the DER-encoded trusted CA certificate.
+ @param[in] CACertSize Size of the CA Certificate in bytes.
+
+ If Cert is NULL, then return FALSE.
+ If CACert is NULL, then return FALSE.
+
+ @retval TRUE The certificate was issued by the trusted CA.
+ @retval FALSE Invalid certificate or the certificate was not issued by the given
+ trusted CA.
+
+**/
+BOOLEAN
+EFIAPI
+X509VerifyCert (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ IN CONST UINT8 *CACert,
+ IN UINTN CACertSize
+ )
+{
+ INT32 Ret;
+ mbedtls_x509_crt Ca;
+ mbedtls_x509_crt End;
+ UINT32 VFlag;
+ mbedtls_x509_crt_profile Profile;
+
+ if ((Cert == NULL) || (CACert == NULL)) {
+ return FALSE;
+ }
+
+ VFlag = 0;
+ CopyMem (&Profile, &gCompatProfile, sizeof (mbedtls_x509_crt_profile));
+
+ mbedtls_x509_crt_init (&Ca);
+ mbedtls_x509_crt_init (&End);
+
+ Ret = mbedtls_x509_crt_parse_der (&Ca, CACert, CACertSize);
+
+ if (Ret == 0) {
+ Ret = mbedtls_x509_crt_parse_der (&End, Cert, CertSize);
+ }
+
+ if (Ret == 0) {
+ Ret = mbedtls_x509_crt_verify_with_profile (&End, &Ca, NULL, &Profile, NULL, &VFlag, NULL, NULL);
+ }
+
+ mbedtls_x509_crt_free (&Ca);
+ mbedtls_x509_crt_free (&End);
+
+ return Ret == 0;
+}
+
+/**
+ Verify one X509 certificate was issued by the trusted CA.
+
+ @param[in] RootCert Trusted Root Certificate buffer
+ @param[in] RootCertLength Trusted Root Certificate buffer length
+ @param[in] CertChain One or more ASN.1 DER-encoded X.509 certificates
+ where the first certificate is signed by the Root
+ Certificate or is the Root Cerificate itself. and
+ subsequent cerificate is signed by the preceding
+ cerificate.
+ @param[in] CertChainLength Total length of the certificate chain, in bytes.
+
+ @retval TRUE All cerificates was issued by the first certificate in X509Certchain.
+ @retval FALSE Invalid certificate or the certificate was not issued by the given
+ trusted CA.
+**/
+BOOLEAN
+EFIAPI
+X509VerifyCertChain (
+ IN CONST UINT8 *RootCert,
+ IN UINTN RootCertLength,
+ IN CONST UINT8 *CertChain,
+ IN UINTN CertChainLength
+ )
+{
+ UINTN Asn1Len;
+ UINTN PrecedingCertLen;
+ CONST UINT8 *PrecedingCert;
+ UINTN CurrentCertLen;
+ CONST UINT8 *CurrentCert;
+ CONST UINT8 *TmpPtr;
+ UINT32 Ret;
+ BOOLEAN VerifyFlag;
+
+ VerifyFlag = FALSE;
+ PrecedingCert = RootCert;
+ PrecedingCertLen = RootCertLength;
+
+ CurrentCert = CertChain;
+
+ //
+ // Get Current certificate from Certificates buffer and Verify with preciding cert
+ //
+ do {
+ TmpPtr = CurrentCert;
+ Ret = mbedtls_asn1_get_tag ((UINT8 **)&TmpPtr, CertChain + CertChainLength, &Asn1Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (Ret != 0) {
+ break;
+ }
+
+ CurrentCertLen = Asn1Len + (TmpPtr - CurrentCert);
+
+ if (!X509VerifyCert (CurrentCert, CurrentCertLen, PrecedingCert, PrecedingCertLen)) {
+ VerifyFlag = FALSE;
+ break;
+ } else {
+ VerifyFlag = TRUE;
+ }
+
+ //
+ // Save preceding certificate
+ //
+ PrecedingCert = CurrentCert;
+ PrecedingCertLen = CurrentCertLen;
+
+ //
+ // Move current certificate to next;
+ //
+ CurrentCert = CurrentCert + CurrentCertLen;
+ } while (1);
+
+ return VerifyFlag;
+}
+
+/**
+ Get one X509 certificate from CertChain.
+
+ @param[in] CertChain One or more ASN.1 DER-encoded X.509 certificates
+ where the first certificate is signed by the Root
+ Certificate or is the Root Cerificate itself. and
+ subsequent cerificate is signed by the preceding
+ cerificate.
+ @param[in] CertChainLength Total length of the certificate chain, in bytes.
+
+ @param[in] CertIndex Index of certificate.
+
+ @param[out] Cert The certificate at the index of CertChain.
+ @param[out] CertLength The length certificate at the index of CertChain.
+
+ @retval TRUE Success.
+ @retval FALSE Failed to get certificate from certificate chain.
+**/
+BOOLEAN
+EFIAPI
+X509GetCertFromCertChain (
+ IN CONST UINT8 *CertChain,
+ IN UINTN CertChainLength,
+ IN CONST INT32 CertIndex,
+ OUT CONST UINT8 **Cert,
+ OUT UINTN *CertLength
+ )
+{
+ UINTN Asn1Len;
+ INT32 CurrentIndex;
+ UINTN CurrentCertLen;
+ CONST UINT8 *CurrentCert;
+ CONST UINT8 *TmpPtr;
+ INT32 Ret;
+
+ //
+ // Check input parameters.
+ //
+ if ((CertChain == NULL) || (Cert == NULL) ||
+ (CertIndex < -1) || (CertLength == NULL))
+ {
+ return FALSE;
+ }
+
+ CurrentCert = CertChain;
+ CurrentIndex = -1;
+
+ //
+ // Traverse the certificate chain
+ //
+ while (TRUE) {
+ //
+ // Get asn1 tag len
+ //
+ TmpPtr = CurrentCert;
+ Ret = mbedtls_asn1_get_tag ((UINT8 **)&TmpPtr, CertChain + CertChainLength, &Asn1Len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (Ret != 0) {
+ break;
+ }
+
+ CurrentCertLen = Asn1Len + (TmpPtr - CurrentCert);
+ CurrentIndex++;
+
+ if (CurrentIndex == CertIndex) {
+ *Cert = CurrentCert;
+ *CertLength = CurrentCertLen;
+ return TRUE;
+ }
+
+ //
+ // Move to next
+ //
+ CurrentCert = CurrentCert + CurrentCertLen;
+ }
+
+ //
+ // If CertIndex is -1, Return the last certificate
+ //
+ if ((CertIndex == -1) && (CurrentIndex >= 0)) {
+ *Cert = CurrentCert - CurrentCertLen;
+ *CertLength = CurrentCertLen;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Retrieve the TBSCertificate from one given X.509 certificate.
+
+ @param[in] Cert Pointer to the given DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] TBSCert DER-Encoded To-Be-Signed certificate.
+ @param[out] TBSCertSize Size of the TBS certificate in bytes.
+
+ If Cert is NULL, then return FALSE.
+ If TBSCert is NULL, then return FALSE.
+ If TBSCertSize is NULL, then return FALSE.
+
+ @retval TRUE The TBSCertificate was retrieved successfully.
+ @retval FALSE Invalid X.509 certificate.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetTBSCert (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 **TBSCert,
+ OUT UINTN *TBSCertSize
+ )
+{
+ UINTN Length;
+ UINTN Ret;
+ UINT8 *Ptr;
+ CONST UINT8 *Temp;
+ CONST UINT8 *End;
+
+ //
+ // Check input parameters.
+ //
+ if ((Cert == NULL) || (TBSCert == NULL) ||
+ (TBSCertSize == NULL) || (CertSize > INT_MAX))
+ {
+ return FALSE;
+ }
+
+ //
+ // An X.509 Certificate is: (defined in RFC3280)
+ // Certificate ::= SEQUENCE {
+ // tbsCertificate TBSCertificate,
+ // signatureAlgorithm AlgorithmIdentifier,
+ // signature BIT STRING }
+ //
+ // and
+ //
+ // TBSCertificate ::= SEQUENCE {
+ // version [0] Version DEFAULT v1,
+ // ...
+ // }
+ //
+ // So we can just ASN1-parse the x.509 DER-encoded data. If we strip
+ // the first SEQUENCE, the second SEQUENCE is the TBSCertificate.
+ //
+
+ Length = 0;
+
+ Ptr = (UINT8 *)Cert;
+ End = Cert + CertSize;
+
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &Length, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Temp = Ptr;
+ End = Ptr + Length;
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &Length, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ *TBSCert = (UINT8 *)Temp;
+ *TBSCertSize = Length + (Ptr - Temp);
+
+ return TRUE;
+}
+
+/**
+ Retrieve the version from one X.509 certificate.
+
+ If Cert is NULL, then return FALSE.
+ If CertSize is 0, 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] Version Pointer to the retrieved version integer.
+
+ @retval TRUE The certificate version retrieved successfully.
+ @retval FALSE If Cert is NULL or CertSize is Zero.
+ @retval FALSE The operation is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetVersion (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINTN *Version
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ BOOLEAN ReturnStatus;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ ReturnStatus = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ *Version = Crt.version - 1;
+ ReturnStatus = TRUE;
+ }
+
+ mbedtls_x509_crt_free (&Crt);
+
+ return ReturnStatus;
+}
+
+/**
+ Retrieve the serialNumber from one X.509 certificate.
+
+ If Cert is NULL, then return FALSE.
+ If CertSize is 0, 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] SerialNumber Pointer to the retrieved certificate SerialNumber bytes.
+ @param[in, out] SerialNumberSize The size in bytes of the SerialNumber buffer on input,
+ and the size of buffer returned SerialNumber on output.
+
+ @retval TRUE The certificate serialNumber retrieved successfully.
+ @retval FALSE If Cert is NULL or CertSize is Zero.
+ If SerialNumberSize is NULL.
+ If Certificate is invalid.
+ @retval FALSE If no SerialNumber exists.
+ @retval FALSE If the SerialNumber is NULL. The required buffer size
+ (including the final null) is returned in the
+ SerialNumberSize parameter.
+ @retval FALSE The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetSerialNumber (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 *SerialNumber OPTIONAL,
+ IN OUT UINTN *SerialNumberSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ BOOLEAN ReturnStatus;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ ReturnStatus = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ if (*SerialNumberSize <= Crt.serial.len) {
+ *SerialNumberSize = Crt.serial.len + 1;
+ ReturnStatus = FALSE;
+ goto Cleanup;
+ }
+
+ if (SerialNumber != NULL) {
+ CopyMem (SerialNumber, Crt.serial.p, Crt.serial.len);
+ SerialNumber[Crt.serial.len] = '\0';
+ }
+
+ *SerialNumberSize = Crt.serial.len + 1;
+ ReturnStatus = TRUE;
+ }
+
+Cleanup:
+ mbedtls_x509_crt_free (&Crt);
+
+ return ReturnStatus;
+}
+
+/**
+ Retrieve the issuer bytes from one X.509 certificate.
+
+ If Cert is NULL, then return FALSE.
+ If CertIssuerSize 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] CertIssuer Pointer to the retrieved certificate subject bytes.
+ @param[in, out] CertIssuerSize The size in bytes of the CertIssuer buffer on input,
+ and the size of buffer returned CertSubject on output.
+
+ @retval TRUE The certificate issuer retrieved successfully.
+ @retval FALSE Invalid certificate, or the CertIssuerSize is too small for the result.
+ The CertIssuerSize will be updated with the required size.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+X509GetIssuerName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 *CertIssuer,
+ IN OUT UINTN *CertIssuerSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ BOOLEAN Status;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ if (*CertIssuerSize < Crt.serial.len) {
+ *CertIssuerSize = Crt.serial.len;
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ if (CertIssuer != NULL) {
+ CopyMem (CertIssuer, Crt.serial.p, Crt.serial.len);
+ }
+
+ *CertIssuerSize = Crt.serial.len;
+ Status = TRUE;
+ }
+
+Cleanup:
+ mbedtls_x509_crt_free (&Crt);
+
+ return Status;
+}
+
+/**
+ Retrieve the issuer common name (CN) string from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] CommonName Buffer to contain the retrieved certificate issuer common
+ name string. At most CommonNameSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] CommonNameSize The size in bytes of the CommonName buffer on input,
+ and the size of buffer returned CommonName on output.
+ If CommonName is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate Issuer CommonName retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If CommonNameSize is NULL.
+ If CommonName is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no CommonName entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the CommonName is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetIssuerCommonName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT CHAR8 *CommonName OPTIONAL,
+ IN OUT UINTN *CommonNameSize
+ )
+{
+ return InternalX509GetIssuerNIDName (Cert, CertSize, (CHAR8 *)OID_commonName, sizeof (OID_commonName), CommonName, CommonNameSize);
+}
+
+/**
+ Retrieve the issuer organization name (O) string from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] NameBuffer Buffer to contain the retrieved certificate issuer organization
+ name string. At most NameBufferSize bytes will be
+ written and the string will be null terminated. May be
+ NULL in order to determine the size buffer needed.
+ @param[in,out] NameBufferSize The size in bytes of the Name buffer on input,
+ and the size of buffer returned Name on output.
+ If NameBuffer is NULL then the amount of space needed
+ in buffer (including the final null) is returned.
+
+ @retval RETURN_SUCCESS The certificate issuer Organization Name retrieved successfully.
+ @retval RETURN_INVALID_PARAMETER If Cert is NULL.
+ If NameBufferSize is NULL.
+ If NameBuffer is not NULL and *CommonNameSize is 0.
+ If Certificate is invalid.
+ @retval RETURN_NOT_FOUND If no Organization Name entry exists.
+ @retval RETURN_BUFFER_TOO_SMALL If the NameBuffer is NULL. The required buffer size
+ (including the final null) is returned in the
+ CommonNameSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+
+**/
+RETURN_STATUS
+EFIAPI
+X509GetIssuerOrganizationName (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT CHAR8 *NameBuffer OPTIONAL,
+ IN OUT UINTN *NameBufferSize
+ )
+{
+ return InternalX509GetIssuerNIDName (Cert, CertSize, (CHAR8 *)OID_organizationName, sizeof (OID_organizationName), NameBuffer, NameBufferSize);
+}
+
+/**
+ Retrieve the Signature Algorithm from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] Oid Signature Algorithm Object identifier buffer.
+ @param[in,out] OidSize Signature Algorithm Object identifier buffer size
+
+ @retval TRUE The certificate Extension data retrieved successfully.
+ @retval FALSE If Cert is NULL.
+ If OidSize is NULL.
+ If Oid is not NULL and *OidSize is 0.
+ If Certificate is invalid.
+ @retval FALSE If no SignatureType.
+ @retval FALSE If the Oid is NULL. The required buffer size
+ is returned in the OidSize.
+ @retval FALSE The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetSignatureAlgorithm (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 *Oid OPTIONAL,
+ IN OUT UINTN *OidSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ BOOLEAN ReturnStatus;
+
+ if ((Cert == NULL) || (CertSize == 0) || (OidSize == NULL)) {
+ return FALSE;
+ }
+
+ ReturnStatus = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ if (*OidSize < Crt.sig_oid.len) {
+ *OidSize = Crt.serial.len;
+ ReturnStatus = FALSE;
+ goto Cleanup;
+ }
+
+ if (Oid != NULL) {
+ CopyMem (Oid, Crt.sig_oid.p, Crt.sig_oid.len);
+ }
+
+ *OidSize = Crt.sig_oid.len;
+ ReturnStatus = TRUE;
+ }
+
+Cleanup:
+ mbedtls_x509_crt_free (&Crt);
+
+ return ReturnStatus;
+}
+
+/**
+ Find first Extension data match with given OID
+
+ @param[in] Start Pointer to the DER-encoded Extensions Data
+ @param[in] End Extensions Data size in bytes
+ @param[in ] Oid OID for match
+ @param[in ] OidSize OID size in bytes
+ @param[out] FindExtensionData output matched extension data.
+ @param[out] FindExtensionDataLen matched extension data size.
+
+ **/
+STATIC
+RETURN_STATUS
+InternalX509FindExtensionData (
+ UINT8 *Start,
+ UINT8 *End,
+ CONST UINT8 *Oid,
+ UINTN OidSize,
+ UINT8 **FindExtensionData,
+ UINTN *FindExtensionDataLen
+ )
+{
+ UINT8 *Ptr;
+ UINT8 *ExtensionPtr;
+ size_t ObjLen;
+ INT32 Ret;
+ RETURN_STATUS ReturnStatus;
+ size_t FindExtensionLen;
+ size_t HeaderLen;
+
+ ReturnStatus = RETURN_INVALID_PARAMETER;
+ Ptr = Start;
+
+ Ret = 0;
+
+ while (TRUE) {
+ /*
+ * Extension ::= SEQUENCE {
+ * extnID OBJECT IDENTIFIER,
+ * critical BOOLEAN DEFAULT FALSE,
+ * extnValue OCTET STRING }
+ */
+ ExtensionPtr = Ptr;
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ if (Ret == 0) {
+ HeaderLen = (size_t)(Ptr - ExtensionPtr);
+ FindExtensionLen = ObjLen;
+ // Get Object Identifier
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OID);
+ } else {
+ break;
+ }
+
+ if ((Ret == 0) && (CompareMem (Ptr, Oid, OidSize) == 0)) {
+ Ptr += ObjLen;
+
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_BOOLEAN);
+ if (Ret == 0) {
+ Ptr += ObjLen;
+ }
+
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_OCTET_STRING);
+ } else {
+ Ret = 1;
+ }
+
+ if (Ret == 0) {
+ *FindExtensionData = Ptr;
+ *FindExtensionDataLen = ObjLen;
+ ReturnStatus = RETURN_SUCCESS;
+ break;
+ }
+
+ // move to next
+ Ptr = ExtensionPtr + HeaderLen + FindExtensionLen;
+ Ret = 0;
+ }
+
+ return ReturnStatus;
+}
+
+/**
+ Retrieve Extension data from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[in] Oid Object identifier buffer
+ @param[in] OidSize Object identifier buffer size
+ @param[out] ExtensionData Extension bytes.
+ @param[in, out] ExtensionDataSize Extension bytes size.
+
+ @retval TRUE The certificate Extension data retrieved successfully.
+ @retval FALSE If Cert is NULL.
+ If ExtensionDataSize is NULL.
+ If ExtensionData is not NULL and *ExtensionDataSize is 0.
+ If Certificate is invalid.
+ @retval FALSE If no Extension entry match Oid.
+ @retval FALSE If the ExtensionData is NULL. The required buffer size
+ is returned in the ExtensionDataSize parameter.
+ @retval FALSE The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetExtensionData (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ IN CONST UINT8 *Oid,
+ IN UINTN OidSize,
+ OUT UINT8 *ExtensionData,
+ IN OUT UINTN *ExtensionDataSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ RETURN_STATUS ReturnStatus;
+ BOOLEAN Status;
+ UINT8 *Ptr;
+ UINT8 *End;
+ size_t ObjLen;
+
+ if ((Cert == NULL) ||
+ (CertSize == 0) ||
+ (Oid == NULL) ||
+ (OidSize == 0) ||
+ (ExtensionDataSize == NULL))
+ {
+ return FALSE;
+ }
+
+ ReturnStatus = RETURN_INVALID_PARAMETER;
+ Status = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ Ptr = Crt.v3_ext.p;
+ End = Crt.v3_ext.p + Crt.v3_ext.len;
+ Ret = mbedtls_asn1_get_tag (&Ptr, End, &ObjLen, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+ }
+
+ if (Ret == 0) {
+ ReturnStatus = InternalX509FindExtensionData (Ptr, End, Oid, OidSize, &Ptr, &ObjLen);
+ }
+
+ if (ReturnStatus == RETURN_SUCCESS) {
+ if (*ExtensionDataSize < ObjLen) {
+ *ExtensionDataSize = ObjLen;
+ Status = FALSE;
+ goto Cleanup;
+ }
+
+ if (Oid != NULL) {
+ CopyMem (ExtensionData, Ptr, ObjLen);
+ }
+
+ *ExtensionDataSize = ObjLen;
+ Status = TRUE;
+ }
+
+Cleanup:
+ mbedtls_x509_crt_free (&Crt);
+
+ return Status;
+}
+
+/**
+ Retrieve the Validity from one X.509 certificate
+
+ If Cert is NULL, then return FALSE.
+ If CertIssuerSize 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[in] From notBefore Pointer to DateTime object.
+ @param[in,out] FromSize notBefore DateTime object size.
+ @param[in] To notAfter Pointer to DateTime object.
+ @param[in,out] ToSize notAfter DateTime object size.
+
+ Note: X509CompareDateTime to compare DateTime oject
+ x509SetDateTime to get a DateTime object from a DateTimeStr
+
+ @retval TRUE The certificate Validity retrieved successfully.
+ @retval FALSE Invalid certificate, or Validity retrieve failed.
+ @retval FALSE This interface is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetValidity (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ IN UINT8 *From,
+ IN OUT UINTN *FromSize,
+ IN UINT8 *To,
+ IN OUT UINTN *ToSize
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ BOOLEAN Status;
+ UINTN TSize;
+ UINTN FSize;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ FSize = sizeof (mbedtls_x509_time);
+ if (*FromSize < FSize) {
+ *FromSize = FSize;
+ goto _Exit;
+ }
+
+ *FromSize = FSize;
+ if (From != NULL) {
+ CopyMem (From, &(Crt.valid_from), FSize);
+ }
+
+ TSize = sizeof (mbedtls_x509_time);
+ if (*ToSize < TSize) {
+ *ToSize = TSize;
+ goto _Exit;
+ }
+
+ *ToSize = TSize;
+ if (To != NULL) {
+ CopyMem (To, &(Crt.valid_to), sizeof (mbedtls_x509_time));
+ }
+
+ Status = TRUE;
+ }
+
+_Exit:
+ mbedtls_x509_crt_free (&Crt);
+
+ return Status;
+}
+
+/**
+ Retrieve the Key Usage from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] Usage Key Usage (CRYPTO_X509_KU_*)
+
+ @retval TRUE The certificate Key Usage retrieved successfully.
+ @retval FALSE Invalid certificate, or Usage is NULL
+ @retval FALSE This interface is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetKeyUsage (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINTN *Usage
+ )
+{
+ mbedtls_x509_crt Crt;
+ INT32 Ret;
+ BOOLEAN Status;
+
+ if (Cert == NULL) {
+ return FALSE;
+ }
+
+ Status = FALSE;
+
+ mbedtls_x509_crt_init (&Crt);
+
+ Ret = mbedtls_x509_crt_parse_der (&Crt, Cert, CertSize);
+
+ if (Ret == 0) {
+ *Usage = Crt.key_usage;
+ Status = TRUE;
+ }
+
+ mbedtls_x509_crt_free (&Crt);
+
+ return Status;
+}
+
+/**
+ Retrieve the Extended Key Usage from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize Size of the X509 certificate in bytes.
+ @param[out] Usage Key Usage bytes.
+ @param[in, out] UsageSize Key Usage buffer sizs in bytes.
+
+ @retval TRUE The Usage bytes retrieve successfully.
+ @retval FALSE If Cert is NULL.
+ If CertSize is NULL.
+ If Usage is not NULL and *UsageSize is 0.
+ If Cert is invalid.
+ @retval FALSE If the Usage is NULL. The required buffer size
+ is returned in the UsageSize parameter.
+ @retval FALSE The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509GetExtendedKeyUsage (
+ IN CONST UINT8 *Cert,
+ IN UINTN CertSize,
+ OUT UINT8 *Usage,
+ IN OUT UINTN *UsageSize
+ )
+{
+ BOOLEAN ReturnStatus;
+
+ if ((Cert == NULL) || (CertSize == 0) || (UsageSize == NULL)) {
+ return FALSE;
+ }
+
+ ReturnStatus = X509GetExtensionData ((UINT8 *)Cert, CertSize, (UINT8 *)OID_extKeyUsage, sizeof (OID_extKeyUsage), Usage, UsageSize);
+
+ return ReturnStatus;
+}
+
+/**
+ Compare DateTime1 object and DateTime2 object time.
+
+ @param[in] Before Pointer to a DateTime Ojbect
+ @param[in] After Pointer to a DateTime Object
+
+ @retval 0 If DateTime1 <= DateTime2
+ @retval 1 If DateTime1 > DateTime2
+**/
+STATIC
+INTN
+InternalX509CheckTime (
+ CONST mbedtls_x509_time *Before,
+ CONST mbedtls_x509_time *After
+ )
+{
+ if (Before->year > After->year) {
+ return (1);
+ }
+
+ if ((Before->year == After->year) &&
+ (Before->mon > After->mon))
+ {
+ return (1);
+ }
+
+ if ((Before->year == After->year) &&
+ (Before->mon == After->mon) &&
+ (Before->day > After->day))
+ {
+ return (1);
+ }
+
+ if ((Before->year == After->year) &&
+ (Before->mon == After->mon) &&
+ (Before->day == After->day) &&
+ (Before->hour > After->hour))
+ {
+ return (1);
+ }
+
+ if ((Before->year == After->year) &&
+ (Before->mon == After->mon) &&
+ (Before->day == After->day) &&
+ (Before->hour == After->hour) &&
+ (Before->min > After->min))
+ {
+ return (1);
+ }
+
+ if ((Before->year == After->year) &&
+ (Before->mon == After->mon) &&
+ (Before->day == After->day) &&
+ (Before->hour == After->hour) &&
+ (Before->min == After->min) &&
+ (Before->sec > After->sec))
+ {
+ return (1);
+ }
+
+ return (0);
+}
+
+/**
+ change string to int.
+
+ @param[in] PStart Pointer to a string Start
+ @param[in] PEnd Pointer to a string End
+
+ @return number
+**/
+STATIC
+INT32
+InternalAtoI (
+ CHAR8 *PStart,
+ CHAR8 *PEnd
+ )
+{
+ CHAR8 *Ptr;
+ INT32 Knum;
+
+ Knum = 0;
+ Ptr = PStart;
+
+ while (Ptr < PEnd) {
+ ///
+ /// k = k * 2^3 + k * 2^1 = k * 8 + k * 2 = k * 10
+ ///
+ Knum = (Knum << 3) + (Knum << 1) + (*Ptr) - '0';
+ Ptr++;
+ }
+
+ return Knum;
+}
+
+/**
+ Format a DateTime object into DataTime Buffer
+
+ If DateTimeStr is NULL, then return FALSE.
+ If DateTimeSize is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] DateTimeStr DateTime string like YYYYMMDDhhmmssZ
+ Ref: https://www.w3.org/TR/NOTE-datetime
+ Z stand for UTC time
+ @param[in,out] DateTime Pointer to a DateTime object.
+ @param[in,out] DateTimeSize DateTime object buffer size.
+
+ @retval RETURN_SUCCESS The DateTime object create successfully.
+ @retval RETURN_INVALID_PARAMETER If DateTimeStr is NULL.
+ If DateTimeSize is NULL.
+ If DateTime is not NULL and *DateTimeSize is 0.
+ If Year Month Day Hour Minute Second combination is invalid datetime.
+ @retval RETURN_BUFFER_TOO_SMALL If the DateTime is NULL. The required buffer size
+ (including the final null) is returned in the
+ DateTimeSize parameter.
+ @retval RETURN_UNSUPPORTED The operation is not supported.
+**/
+RETURN_STATUS
+EFIAPI
+X509SetDateTime (
+ CHAR8 *DateTimeStr,
+ IN OUT VOID *DateTime,
+ IN OUT UINTN *DateTimeSize
+ )
+{
+ mbedtls_x509_time Dt;
+
+ INT32 Year;
+ INT32 Month;
+ INT32 Day;
+ INT32 Hour;
+ INT32 Minute;
+ INT32 Second;
+ RETURN_STATUS ReturnStatus;
+ CHAR8 *Ptr;
+
+ Ptr = DateTimeStr;
+
+ Year = InternalAtoI (Ptr, Ptr + 4);
+ Ptr += 4;
+ Month = InternalAtoI (Ptr, Ptr + 2);
+ Ptr += 2;
+ Day = InternalAtoI (Ptr, Ptr + 2);
+ Ptr += 2;
+ Hour = InternalAtoI (Ptr, Ptr + 2);
+ Ptr += 2;
+ Minute = InternalAtoI (Ptr, Ptr + 2);
+ Ptr += 2;
+ Second = InternalAtoI (Ptr, Ptr + 2);
+ Ptr += 2;
+ Dt.year = (int)Year;
+ Dt.mon = (int)Month;
+ Dt.day = (int)Day;
+ Dt.hour = (int)Hour;
+ Dt.min = (int)Minute;
+ Dt.sec = (int)Second;
+
+ if (*DateTimeSize < sizeof (mbedtls_x509_time)) {
+ *DateTimeSize = sizeof (mbedtls_x509_time);
+ ReturnStatus = RETURN_BUFFER_TOO_SMALL;
+ goto Cleanup;
+ }
+
+ if (DateTime != NULL) {
+ CopyMem (DateTime, &Dt, sizeof (mbedtls_x509_time));
+ }
+
+ *DateTimeSize = sizeof (mbedtls_x509_time);
+ ReturnStatus = RETURN_SUCCESS;
+Cleanup:
+ return ReturnStatus;
+}
+
+/**
+ Compare DateTime1 object and DateTime2 object.
+
+ If DateTime1 is NULL, then return -2.
+ If DateTime2 is NULL, then return -2.
+ If DateTime1 == DateTime2, then return 0
+ If DateTime1 > DateTime2, then return 1
+ If DateTime1 < DateTime2, then return -1
+
+ @param[in] DateTime1 Pointer to a DateTime Ojbect
+ @param[in] DateTime2 Pointer to a DateTime Object
+
+ @retval 0 If DateTime1 == DateTime2
+ @retval 1 If DateTime1 > DateTime2
+ @retval -1 If DateTime1 < DateTime2
+**/
+INT32
+EFIAPI
+X509CompareDateTime (
+ IN CONST VOID *DateTime1,
+ IN CONST VOID *DateTime2
+ )
+{
+ if ((DateTime1 == NULL) || (DateTime2 == NULL)) {
+ return -2;
+ }
+
+ if (CompareMem (DateTime2, DateTime1, sizeof (mbedtls_x509_time)) == 0) {
+ return 0;
+ }
+
+ if (InternalX509CheckTime ((mbedtls_x509_time *)DateTime1, (mbedtls_x509_time *)DateTime2) == 0) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+/**
+ Retrieve the basic constraints from one X.509 certificate.
+
+ @param[in] Cert Pointer to the DER-encoded X509 certificate.
+ @param[in] CertSize size of the X509 certificate in bytes.
+ @param[out] BasicConstraints basic constraints bytes.
+ @param[in, out] BasicConstraintsSize basic constraints buffer sizs in bytes.
+
+ @retval TRUE The basic constraints retrieve successfully.
+ @retval FALSE If cert is NULL.
+ If cert_size is NULL.
+ If basic_constraints is not NULL and *basic_constraints_size is 0.
+ If cert is invalid.
+ @retval FALSE The required buffer size is small.
+ The return buffer size is basic_constraints_size parameter.
+ @retval FALSE If no Extension entry match oid.
+ @retval FALSE The operation is not supported.
+ **/
+BOOLEAN
+EFIAPI
+X509GetExtendedBasicConstraints (
+ CONST UINT8 *Cert,
+ UINTN CertSize,
+ UINT8 *BasicConstraints,
+ UINTN *BasicConstraintsSize
+ )
+{
+ BOOLEAN Status;
+
+ if ((Cert == NULL) || (CertSize == 0) || (BasicConstraintsSize == NULL)) {
+ return FALSE;
+ }
+
+ Status = X509GetExtensionData (
+ (UINT8 *)Cert,
+ CertSize,
+ OID_BasicConstraints,
+ sizeof (OID_BasicConstraints),
+ BasicConstraints,
+ BasicConstraintsSize
+ );
+
+ return Status;
+}
+
+/**
+ Format a DateTimeStr to DataTime object in DataTime Buffer
+
+ If DateTimeStr is NULL, then return FALSE.
+ If DateTimeSize is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] DateTimeStr DateTime string like YYYYMMDDhhmmssZ
+ Ref: https://www.w3.org/TR/NOTE-datetime
+ Z stand for UTC time
+ @param[out] DateTime Pointer to a DateTime object.
+ @param[in,out] DateTimeSize DateTime object buffer size.
+
+ @retval TRUE The DateTime object create successfully.
+ @retval FALSE If DateTimeStr is NULL.
+ If DateTimeSize is NULL.
+ If DateTime is not NULL and *DateTimeSize is 0.
+ If Year Month Day Hour Minute Second combination is invalid datetime.
+ @retval FALSE If the DateTime is NULL. The required buffer size
+ (including the final null) is returned in the
+ DateTimeSize parameter.
+ @retval FALSE The operation is not supported.
+**/
+BOOLEAN
+EFIAPI
+X509FormatDateTime (
+ IN CONST CHAR8 *DateTimeStr,
+ OUT VOID *DateTime,
+ IN OUT UINTN *DateTimeSize
+ )
+{
+ mbedtls_x509_time *Tm;
+
+ if (*DateTimeSize < sizeof (mbedtls_x509_time)) {
+ return FALSE;
+ }
+
+ if (DateTime == NULL) {
+ return FALSE;
+ }
+
+ Tm = (mbedtls_x509_time *)DateTime;
+
+ Tm->year = (DateTimeStr[0] + '0') * 1000 + (DateTimeStr[1] + '0') * 100 +
+ (DateTimeStr[2] + '0') * 10 + (DateTimeStr[3] + '0') * 1;
+
+ Tm->mon = (DateTimeStr[4] + '0') * 10 + (DateTimeStr[5] + '0') * 1;
+
+ Tm->day = (DateTimeStr[6] + '0') * 10 + (DateTimeStr[7] + '0') * 1;
+
+ Tm->hour = (DateTimeStr[8] + '0') * 10 + (DateTimeStr[9] + '0') * 1;
+
+ Tm->min = (DateTimeStr[10] + '0') * 10 + (DateTimeStr[11] + '0') * 1;
+
+ Tm->sec = (DateTimeStr[12] + '0') * 10 + (DateTimeStr[13] + '0') * 1;
+
+ return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
new file mode 100644
index 0000000000..e01aabc0de
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRand.c
@@ -0,0 +1,114 @@
+/** @file
+ Pseudorandom Number Generator Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <Library/RngLib.h>
+
+/**
+ Sets up the seed value for the pseudorandom number generator.
+
+ This function sets up the seed value for the pseudorandom number generator.
+ If Seed is not NULL, then the seed passed in is used.
+ If Seed is NULL, then default seed is used.
+
+ @param[in] Seed Pointer to seed value.
+ If NULL, default seed is used.
+ @param[in] SeedSize Size of seed value.
+ If Seed is NULL, this parameter is ignored.
+
+ @retval TRUE Pseudorandom number generator has enough entropy for random generation.
+ @retval FALSE Pseudorandom number generator does not have enough entropy for random generation.
+
+**/
+BOOLEAN
+EFIAPI
+RandomSeed (
+ IN CONST UINT8 *Seed OPTIONAL,
+ IN UINTN SeedSize
+ )
+{
+ return TRUE;
+}
+
+/**
+ Generates a pseudorandom byte stream of the specified size.
+
+ If Output is NULL, then return FALSE.
+
+ @param[out] Output Pointer to buffer to receive random value.
+ @param[in] Size Size of random bytes to generate.
+
+ @retval TRUE Pseudorandom byte stream generated successfully.
+ @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy.
+
+**/
+BOOLEAN
+EFIAPI
+RandomBytes (
+ OUT UINT8 *Output,
+ IN UINTN Size
+ )
+{
+ BOOLEAN Ret;
+ volatile UINT64 TempRand;
+
+ //
+ // Check input parameters.
+ //
+ if ((Output == NULL) || (Size > INT_MAX)) {
+ return FALSE;
+ }
+
+ Ret = FALSE;
+
+ while (Size > 0) {
+ // Use RngLib to get random number
+ Ret = GetRandomNumber64 ((UINT64 *)&TempRand);
+
+ if (!Ret) {
+ TempRand = 0;
+ return Ret;
+ }
+
+ if (Size >= sizeof (TempRand)) {
+ *((UINT64 *)Output) = TempRand;
+ Output += sizeof (UINT64);
+ Size -= sizeof (TempRand);
+ } else {
+ CopyMem (Output, (VOID *)&TempRand, Size);
+ Size = 0;
+ }
+ }
+
+ TempRand = 0;
+ return Ret;
+}
+
+/**
+ The MbedTLS function f_rng, which MbedtlsRand implements.
+
+ @param[in] RngState Not used, just for compatibility with mbedlts.
+ @param[out] Output Pointer to buffer to receive random value.
+ @param[in] Len Size of random bytes to generate.
+
+ @retval 0 Pseudorandom byte stream generated successfully.
+ @retval Non-0 Pseudorandom number generator fails to generate due to lack of entropy.
+**/
+INT32
+MbedtlsRand (
+ VOID *RngState,
+ UINT8 *Output,
+ UINTN Len
+ )
+{
+ BOOLEAN Result;
+
+ Result = RandomBytes (Output, Len);
+
+ return Result ? 0 : -1;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c
new file mode 100644
index 0000000000..e01aabc0de
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Rand/CryptRandTsc.c
@@ -0,0 +1,114 @@
+/** @file
+ Pseudorandom Number Generator Wrapper Implementation over MbedTLS.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <Library/RngLib.h>
+
+/**
+ Sets up the seed value for the pseudorandom number generator.
+
+ This function sets up the seed value for the pseudorandom number generator.
+ If Seed is not NULL, then the seed passed in is used.
+ If Seed is NULL, then default seed is used.
+
+ @param[in] Seed Pointer to seed value.
+ If NULL, default seed is used.
+ @param[in] SeedSize Size of seed value.
+ If Seed is NULL, this parameter is ignored.
+
+ @retval TRUE Pseudorandom number generator has enough entropy for random generation.
+ @retval FALSE Pseudorandom number generator does not have enough entropy for random generation.
+
+**/
+BOOLEAN
+EFIAPI
+RandomSeed (
+ IN CONST UINT8 *Seed OPTIONAL,
+ IN UINTN SeedSize
+ )
+{
+ return TRUE;
+}
+
+/**
+ Generates a pseudorandom byte stream of the specified size.
+
+ If Output is NULL, then return FALSE.
+
+ @param[out] Output Pointer to buffer to receive random value.
+ @param[in] Size Size of random bytes to generate.
+
+ @retval TRUE Pseudorandom byte stream generated successfully.
+ @retval FALSE Pseudorandom number generator fails to generate due to lack of entropy.
+
+**/
+BOOLEAN
+EFIAPI
+RandomBytes (
+ OUT UINT8 *Output,
+ IN UINTN Size
+ )
+{
+ BOOLEAN Ret;
+ volatile UINT64 TempRand;
+
+ //
+ // Check input parameters.
+ //
+ if ((Output == NULL) || (Size > INT_MAX)) {
+ return FALSE;
+ }
+
+ Ret = FALSE;
+
+ while (Size > 0) {
+ // Use RngLib to get random number
+ Ret = GetRandomNumber64 ((UINT64 *)&TempRand);
+
+ if (!Ret) {
+ TempRand = 0;
+ return Ret;
+ }
+
+ if (Size >= sizeof (TempRand)) {
+ *((UINT64 *)Output) = TempRand;
+ Output += sizeof (UINT64);
+ Size -= sizeof (TempRand);
+ } else {
+ CopyMem (Output, (VOID *)&TempRand, Size);
+ Size = 0;
+ }
+ }
+
+ TempRand = 0;
+ return Ret;
+}
+
+/**
+ The MbedTLS function f_rng, which MbedtlsRand implements.
+
+ @param[in] RngState Not used, just for compatibility with mbedlts.
+ @param[out] Output Pointer to buffer to receive random value.
+ @param[in] Len Size of random bytes to generate.
+
+ @retval 0 Pseudorandom byte stream generated successfully.
+ @retval Non-0 Pseudorandom number generator fails to generate due to lack of entropy.
+**/
+INT32
+MbedtlsRand (
+ VOID *RngState,
+ UINT8 *Output,
+ UINTN Len
+ )
+{
+ BOOLEAN Result;
+
+ Result = RandomBytes (Output, Len);
+
+ return Result ? 0 : -1;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf
index 9f17ef00bf..824aa4fa5d 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/RuntimeCryptLib.inf
@@ -37,32 +37,35 @@
Hash/CryptMd5.c
Hash/CryptSha1.c
Hash/CryptSha256.c
- Hash/CryptSm3Null.c
Hash/CryptSha512.c
Hash/CryptParallelHashNull.c
+ Hash/CryptSm3.c
Hmac/CryptHmac.c
Kdf/CryptHkdf.c
Cipher/CryptAes.c
Cipher/CryptAeadAesGcmNull.c
Pk/CryptRsaBasic.c
Pk/CryptRsaExtNull.c
- Pk/CryptRsaPssNull.c
- Pk/CryptRsaPssSignNull.c
- Bn/CryptBnNull.c
- Pem/CryptPemNull.c
- Pk/CryptDhNull.c
- Pk/CryptEcNull.c
Pk/CryptPkcs1OaepNull.c
Pk/CryptPkcs5Pbkdf2Null.c
Pk/CryptPkcs7SignNull.c
- Pk/CryptPkcs7VerifyNull.c
- Pk/CryptPkcs7VerifyEkuNull.c
- Pk/CryptX509Null.c
+ Pk/CryptPkcs7VerifyCommon.c
+ Pk/CryptPkcs7VerifyRuntime.c
+ Pk/CryptPkcs7VerifyEkuRuntime.c
+ Pk/CryptDhNull.c
+ Pk/CryptX509.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
- Rand/CryptRandNull.c
+ Pk/CryptRsaPssNull.c
+ Pk/CryptRsaPssSignNull.c
+ Pk/CryptEcNull.c
+ Pem/CryptPem.c
+ Bn/CryptBnNull.c
+ Rand/CryptRand.c
+
SysCall/CrtWrapper.c
SysCall/TimerWrapper.c
+ SysCall/DummyOpensslSupport.c
SysCall/RuntimeMemAllocation.c
[Packages]
@@ -75,8 +78,10 @@
UefiRuntimeServicesTableLib
DebugLib
MbedTlsLib
+ OpensslLib
IntrinsicLib
PrintLib
+ RngLib
#
# Remove these [BuildOptions] after this library is cleaned up
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SecCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/SecCryptLib.inf
index 6fc073aac6..e61e07dfa4 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/SecCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SecCryptLib.inf
@@ -29,7 +29,6 @@
[Sources]
InternalCryptLib.h
Hash/CryptSha512.c
-
Hash/CryptMd5Null.c
Hash/CryptSha1Null.c
Hash/CryptSha256Null.c
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf
index 40c56d1b7d..649c2a3c0c 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SmmCryptLib.inf
@@ -36,31 +36,35 @@
Hash/CryptMd5.c
Hash/CryptSha1.c
Hash/CryptSha256.c
- Hash/CryptSm3Null.c
Hash/CryptSha512.c
Hash/CryptParallelHashNull.c
+ Hash/CryptSm3.c
Hmac/CryptHmac.c
Kdf/CryptHkdf.c
Cipher/CryptAes.c
Cipher/CryptAeadAesGcmNull.c
Pk/CryptRsaBasic.c
Pk/CryptRsaExtNull.c
- Pk/CryptRsaPss.c
- Pk/CryptRsaPssSignNull.c
- Bn/CryptBnNull.c
- Pem/CryptPemNull.c
- Pk/CryptDhNull.c
- Pk/CryptEcNull.c
- Pk/CryptPkcs1OaepNull.c
- Pk/CryptPkcs5Pbkdf2Null.c
+ Pk/CryptPkcs1Oaep.c
+ Pk/CryptPkcs5Pbkdf2.c
Pk/CryptPkcs7SignNull.c
- Pk/CryptPkcs7VerifyNull.c
- Pk/CryptPkcs7VerifyEkuNull.c
- Pk/CryptX509Null.c
+ Pk/CryptPkcs7VerifyCommon.c
+ Pk/CryptPkcs7VerifyBase.c
+ Pk/CryptPkcs7VerifyEku.c
+ Pk/CryptDhNull.c
+ Pk/CryptX509.c
Pk/CryptAuthenticodeNull.c
Pk/CryptTsNull.c
- Rand/CryptRandNull.c
+ Pk/CryptRsaPss.c
+ Pk/CryptRsaPssSignNull.c
+ Pk/CryptEcNull.c
+ Pem/CryptPem.c
+ Bn/CryptBnNull.c
+ Rand/CryptRand.c
+
SysCall/CrtWrapper.c
+ SysCall/DummyOpensslSupport.c
+ SysCall/BaseMemAllocation.c
SysCall/ConstantTimeClock.c
[Packages]
@@ -72,9 +76,11 @@
BaseMemoryLib
MemoryAllocationLib
MbedTlsLib
+ OpensslLib
IntrinsicLib
PrintLib
MmServicesTableLib
+ RngLib
SynchronizationLib
#
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/BaseMemAllocation.c b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/BaseMemAllocation.c
new file mode 100644
index 0000000000..10fb75cd98
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/BaseMemAllocation.c
@@ -0,0 +1,122 @@
+/** @file
+ Base Memory Allocation Routines Wrapper for Crypto library over OpenSSL
+ during PEI & DXE phases.
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <CrtLibSupport.h>
+#include <Library/MemoryAllocationLib.h>
+
+//
+// Extra header to record the memory buffer size from malloc routine.
+//
+#define CRYPTMEM_HEAD_SIGNATURE SIGNATURE_32('c','m','h','d')
+typedef struct {
+ UINT32 Signature;
+ UINT32 Reserved;
+ UINTN Size;
+} CRYPTMEM_HEAD;
+
+#define CRYPTMEM_OVERHEAD sizeof(CRYPTMEM_HEAD)
+
+//
+// -- Memory-Allocation Routines --
+//
+
+/* Allocates memory blocks */
+void *
+malloc (
+ size_t size
+ )
+{
+ CRYPTMEM_HEAD *PoolHdr;
+ UINTN NewSize;
+ VOID *Data;
+
+ //
+ // Adjust the size by the buffer header overhead
+ //
+ NewSize = (UINTN)(size) + CRYPTMEM_OVERHEAD;
+
+ Data = AllocatePool (NewSize);
+ if (Data != NULL) {
+ PoolHdr = (CRYPTMEM_HEAD *)Data;
+ //
+ // Record the memory brief information
+ //
+ PoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE;
+ PoolHdr->Size = size;
+
+ return (VOID *)(PoolHdr + 1);
+ } else {
+ //
+ // The buffer allocation failed.
+ //
+ return NULL;
+ }
+}
+
+/* Reallocate memory blocks */
+void *
+realloc (
+ void *ptr,
+ size_t size
+ )
+{
+ CRYPTMEM_HEAD *OldPoolHdr;
+ CRYPTMEM_HEAD *NewPoolHdr;
+ UINTN OldSize;
+ UINTN NewSize;
+ VOID *Data;
+
+ NewSize = (UINTN)size + CRYPTMEM_OVERHEAD;
+ Data = AllocatePool (NewSize);
+ if (Data != NULL) {
+ NewPoolHdr = (CRYPTMEM_HEAD *)Data;
+ NewPoolHdr->Signature = CRYPTMEM_HEAD_SIGNATURE;
+ NewPoolHdr->Size = size;
+ if (ptr != NULL) {
+ //
+ // Retrieve the original size from the buffer header.
+ //
+ OldPoolHdr = (CRYPTMEM_HEAD *)ptr - 1;
+ ASSERT (OldPoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE);
+ OldSize = OldPoolHdr->Size;
+
+ //
+ // Duplicate the buffer content.
+ //
+ CopyMem ((VOID *)(NewPoolHdr + 1), ptr, MIN (OldSize, size));
+ FreePool ((VOID *)OldPoolHdr);
+ }
+
+ return (VOID *)(NewPoolHdr + 1);
+ } else {
+ //
+ // The buffer allocation failed.
+ //
+ return NULL;
+ }
+}
+
+/* De-allocates or frees a memory block */
+void
+free (
+ void *ptr
+ )
+{
+ CRYPTMEM_HEAD *PoolHdr;
+
+ //
+ // In Standard C, free() handles a null pointer argument transparently. This
+ // is not true of FreePool() below, so protect it.
+ //
+ if (ptr != NULL) {
+ PoolHdr = (CRYPTMEM_HEAD *)ptr - 1;
+ ASSERT (PoolHdr->Signature == CRYPTMEM_HEAD_SIGNATURE);
+ FreePool (PoolHdr);
+ }
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/DummyOpensslSupport.c b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/DummyOpensslSupport.c
new file mode 100644
index 0000000000..d3786f0e2a
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/DummyOpensslSupport.c
@@ -0,0 +1,571 @@
+/**
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <CrtLibSupport.h>
+
+int errno = 0;
+
+FILE *stderr = NULL;
+FILE *stdin = NULL;
+FILE *stdout = NULL;
+
+typedef
+ int
+(*SORT_COMPARE)(
+ IN VOID *Buffer1,
+ IN VOID *Buffer2
+ );
+
+//
+// Duplicated from EDKII BaseSortLib for qsort() wrapper
+//
+STATIC
+VOID
+QuickSortWorker (
+ IN OUT VOID *BufferToSort,
+ IN CONST UINTN Count,
+ IN CONST UINTN ElementSize,
+ IN SORT_COMPARE CompareFunction,
+ IN VOID *Buffer
+ )
+{
+ VOID *Pivot;
+ UINTN LoopCount;
+ UINTN NextSwapLocation;
+
+ ASSERT (BufferToSort != NULL);
+ ASSERT (CompareFunction != NULL);
+ ASSERT (Buffer != NULL);
+
+ if ((Count < 2) || (ElementSize < 1)) {
+ return;
+ }
+
+ NextSwapLocation = 0;
+
+ //
+ // Pick a pivot (we choose last element)
+ //
+ Pivot = ((UINT8 *)BufferToSort + ((Count - 1) * ElementSize));
+
+ //
+ // Now get the pivot such that all on "left" are below it
+ // and everything "right" are above it
+ //
+ for (LoopCount = 0; LoopCount < Count - 1; LoopCount++) {
+ //
+ // If the element is less than the pivot
+ //
+ if (CompareFunction ((VOID *)((UINT8 *)BufferToSort + ((LoopCount) * ElementSize)), Pivot) <= 0) {
+ //
+ // Swap
+ //
+ CopyMem (Buffer, (UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), ElementSize);
+ CopyMem ((UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), (UINT8 *)BufferToSort + ((LoopCount) * ElementSize), ElementSize);
+ CopyMem ((UINT8 *)BufferToSort + ((LoopCount) * ElementSize), Buffer, ElementSize);
+
+ //
+ // Increment NextSwapLocation
+ //
+ NextSwapLocation++;
+ }
+ }
+
+ //
+ // Swap pivot to its final position (NextSwapLocation)
+ //
+ CopyMem (Buffer, Pivot, ElementSize);
+ CopyMem (Pivot, (UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), ElementSize);
+ CopyMem ((UINT8 *)BufferToSort + (NextSwapLocation * ElementSize), Buffer, ElementSize);
+
+ //
+ // Now recurse on 2 partial lists. Neither of these will have the 'pivot' element.
+ // IE list is sorted left half, pivot element, sorted right half...
+ //
+ QuickSortWorker (
+ BufferToSort,
+ NextSwapLocation,
+ ElementSize,
+ CompareFunction,
+ Buffer
+ );
+
+ QuickSortWorker (
+ (UINT8 *)BufferToSort + (NextSwapLocation + 1) * ElementSize,
+ Count - NextSwapLocation - 1,
+ ElementSize,
+ CompareFunction,
+ Buffer
+ );
+
+ return;
+}
+
+// ---------------------------------------------------------
+// Standard C Run-time Library Interface Wrapper
+// ---------------------------------------------------------
+
+//
+// -- String Manipulation Routines --
+//
+
+/* Scan a string for the last occurrence of a character */
+char *
+strrchr (
+ const char *str,
+ int c
+ )
+{
+ char *save;
+
+ for (save = NULL; ; ++str) {
+ if (*str == c) {
+ save = (char *)str;
+ }
+
+ if (*str == 0) {
+ return (save);
+ }
+ }
+}
+
+/* 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;
+}
+
+/* Maps errnum to an error-message string */
+char *
+strerror (
+ int errnum
+ )
+{
+ return NULL;
+}
+
+/* Computes the length of the maximum initial segment of the string pointed to by s1
+ which consists entirely of characters from the string pointed to by s2. */
+size_t
+strspn (
+ const char *s1,
+ const char *s2
+ )
+{
+ UINT8 Map[32];
+ UINT32 Index;
+ size_t Count;
+
+ for (Index = 0; Index < 32; Index++) {
+ Map[Index] = 0;
+ }
+
+ while (*s2) {
+ Map[*s2 >> 3] |= (1 << (*s2 & 7));
+ s2++;
+ }
+
+ if (*s1) {
+ Count = 0;
+ while (Map[*s1 >> 3] & (1 << (*s1 & 7))) {
+ Count++;
+ s1++;
+ }
+
+ return Count;
+ }
+
+ return 0;
+}
+
+/* Computes the length of the maximum initial segment of the string pointed to by s1
+ which consists entirely of characters not from the string pointed to by s2. */
+size_t
+strcspn (
+ const char *s1,
+ const char *s2
+ )
+{
+ UINT8 Map[32];
+ UINT32 Index;
+ size_t Count;
+
+ for (Index = 0; Index < 32; Index++) {
+ Map[Index] = 0;
+ }
+
+ while (*s2) {
+ Map[*s2 >> 3] |= (1 << (*s2 & 7));
+ s2++;
+ }
+
+ Map[0] |= 1;
+
+ Count = 0;
+ while (!(Map[*s1 >> 3] & (1 << (*s1 & 7)))) {
+ Count++;
+ s1++;
+ }
+
+ return Count;
+}
+
+char *
+strcpy (
+ char *strDest,
+ const char *strSource
+ )
+{
+ // AsciiStrCpyS (strDest, MAX_STRING_SIZE, strSource);
+ // return strDest;
+ return NULL;
+}
+
+//
+// -- Character Classification Routines --
+//
+
+/* Determines if a particular character is a decimal-digit character */
+int
+isdigit (
+ int c
+ )
+{
+ //
+ // <digit> ::= [0-9]
+ //
+ return (('0' <= (c)) && ((c) <= '9'));
+}
+
+/* Determine if an integer represents character that is a hex digit */
+int
+isxdigit (
+ int c
+ )
+{
+ //
+ // <hexdigit> ::= [0-9] | [a-f] | [A-F]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (('a' <= (c)) && ((c) <= 'f')) ||
+ (('A' <= (c)) && ((c) <= 'F')));
+}
+
+/* Determines if a particular character represents a space character */
+int
+isspace (
+ int c
+ )
+{
+ //
+ // <space> ::= [ ]
+ //
+ return ((c) == ' ');
+}
+
+/* Determine if a particular character is an alphanumeric character */
+int
+isalnum (
+ int c
+ )
+{
+ //
+ // <alnum> ::= [0-9] | [a-z] | [A-Z]
+ //
+ return ((('0' <= (c)) && ((c) <= '9')) ||
+ (('a' <= (c)) && ((c) <= 'z')) ||
+ (('A' <= (c)) && ((c) <= 'Z')));
+}
+
+/* Determines if a particular character is in upper case */
+int
+isupper (
+ int c
+ )
+{
+ //
+ // <uppercase letter> := [A-Z]
+ //
+ return (('A' <= (c)) && ((c) <= 'Z'));
+}
+
+//
+// -- Data Conversion Routines --
+//
+
+/* Convert strings to a long-integer value */
+long
+strtol (
+ const char *nptr,
+ char **endptr,
+ int base
+ )
+{
+ //
+ // Null strtol() function implementation to satisfy the linker, since there is
+ // no direct functionality logic dependency in present UEFI cases.
+ //
+ return 0;
+}
+
+/* Convert strings to an unsigned long-integer value */
+unsigned long
+strtoul (
+ const char *nptr,
+ char **endptr,
+ int base
+ )
+{
+ //
+ // Null strtoul() function implementation to satisfy the linker, since there is
+ // no direct functionality logic dependency in present UEFI cases.
+ //
+ return 0;
+}
+
+/* Convert character to lowercase */
+int
+tolower (
+ int c
+ )
+{
+ if (('A' <= (c)) && ((c) <= 'Z')) {
+ return (c - ('A' - 'a'));
+ }
+
+ return (c);
+}
+
+//
+// -- Searching and Sorting Routines --
+//
+
+/* Performs a quick sort */
+void
+qsort (
+ void *base,
+ size_t num,
+ size_t width,
+ int ( *compare )(const void *, const void *)
+ )
+{
+ VOID *Buffer;
+
+ ASSERT (base != NULL);
+ ASSERT (compare != NULL);
+
+ //
+ // Use CRT-style malloc to cover BS and RT memory allocation.
+ //
+ Buffer = malloc (width);
+ ASSERT (Buffer != NULL);
+
+ //
+ // Re-use PerformQuickSort() function Implementation in EDKII BaseSortLib.
+ //
+ QuickSortWorker (base, (UINTN)num, (UINTN)width, (SORT_COMPARE)compare, Buffer);
+
+ free (Buffer);
+ return;
+}
+
+//
+// -- Process and Environment Control Routines --
+//
+
+/* Get a value from the current environment */
+char *
+getenv (
+ const char *varname
+ )
+{
+ //
+ // Null getenv() function implementation to satisfy the linker, since there is
+ // no direct functionality logic dependency in present UEFI cases.
+ //
+ return NULL;
+}
+
+/* Get a value from the current environment */
+char *
+secure_getenv (
+ const char *varname
+ )
+{
+ //
+ // Null secure_getenv() function implementation to satisfy the linker, since
+ // there is no direct functionality logic dependency in present UEFI cases.
+ //
+ // From the secure_getenv() manual: 'just like getenv() except that it
+ // returns NULL in cases where "secure execution" is required'.
+ //
+ return NULL;
+}
+
+//
+// -- Stream I/O Routines --
+//
+
+/* Write data to a stream */
+size_t
+fwrite (
+ const void *buffer,
+ size_t size,
+ size_t count,
+ FILE *stream
+ )
+{
+ return 0;
+}
+
+#ifdef __GNUC__
+
+typedef
+ VOID
+(EFIAPI *NoReturnFuncPtr)(
+ VOID
+ ) __attribute__ ((__noreturn__));
+
+STATIC
+VOID
+EFIAPI
+NopFunction (
+ VOID
+ )
+{
+}
+
+void
+abort (
+ void
+ )
+{
+ NoReturnFuncPtr NoReturnFunc;
+
+ NoReturnFunc = (NoReturnFuncPtr)NopFunction;
+
+ NoReturnFunc ();
+}
+
+#else
+
+void
+abort (
+ void
+ )
+{
+ // Do nothing
+}
+
+#endif
+
+int
+fclose (
+ FILE *f
+ )
+{
+ return 0;
+}
+
+FILE *
+fopen (
+ const char *c,
+ const char *m
+ )
+{
+ return NULL;
+}
+
+size_t
+fread (
+ void *b,
+ size_t c,
+ size_t i,
+ FILE *f
+ )
+{
+ 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
+printf (
+ char const *fmt,
+ ...
+ )
+{
+ return 0;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/UnitTestHostCrtWrapper.c b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/UnitTestHostCrtWrapper.c
new file mode 100644
index 0000000000..cd20309a6d
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/SysCall/UnitTestHostCrtWrapper.c
@@ -0,0 +1,63 @@
+/** @file
+ C Run-Time Libraries (CRT) Wrapper Implementation for OpenSSL-based
+ Cryptographic Library.
+
+Copyright (c) 2024, 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>
+
+/* 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;
+}
+
+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/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf
index def990b996..30d15a8eff 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/TestBaseCryptLib.inf
@@ -27,33 +27,36 @@
[Sources]
InternalCryptLib.h
- Cipher/CryptAeadAesGcmNull.c
- Cipher/CryptAes.c
- Hash/CryptSha256.c
- Hash/CryptSha512.c
- Hash/CryptSm3Null.c
Hash/CryptMd5.c
Hash/CryptSha1.c
+ Hash/CryptSha256.c
+ Hash/CryptSha512.c
+ Hash/CryptSm3.c
+ Hash/CryptParallelHashNull.c
Hmac/CryptHmac.c
Kdf/CryptHkdf.c
+ Cipher/CryptAes.c
+ Cipher/CryptAeadAesGcm.c
Pk/CryptRsaBasic.c
- Pk/CryptRsaExtNull.c
+ Pk/CryptRsaExt.c
+ Pk/CryptPkcs1Oaep.c
+ Pk/CryptPkcs5Pbkdf2.c
+ Pk/CryptPkcs7Sign.c
+ Pk/CryptPkcs7VerifyCommon.c
+ Pk/CryptPkcs7VerifyBase.c
+ Pk/CryptPkcs7VerifyEku.c
+ Pk/CryptDhNull.c
+ Pk/CryptX509.c
+ Pk/CryptAuthenticode.c
+ Pk/CryptTs.c
+ Pem/CryptPem.c
Pk/CryptRsaPss.c
- Pk/CryptRsaPssSignNull.c
+ Pk/CryptRsaPssSign.c
Bn/CryptBnNull.c
- Pem/CryptPemNull.c
- Pk/CryptDhNull.c
Pk/CryptEcNull.c
- Pk/CryptPkcs1OaepNull.c
- Pk/CryptPkcs5Pbkdf2Null.c
- Pk/CryptPkcs7SignNull.c
- Pk/CryptPkcs7VerifyNull.c
- Pk/CryptPkcs7VerifyEkuNull.c
- Pk/CryptX509Null.c
- Pk/CryptAuthenticodeNull.c
- Pk/CryptTsNull.c
- Rand/CryptRandNull.c
+ Rand/CryptRand.c
SysCall/CrtWrapper.c
+ SysCall/UnitTestHostCrtWrapper.c
[Packages]
MdePkg/MdePkg.dec
@@ -66,6 +69,7 @@
UefiRuntimeServicesTableLib
DebugLib
MbedTlsLib
+ OpensslLib
PrintLib
RngLib
diff --git a/CryptoPkg/Library/OpensslLib/OpensslStub/uefiprov.c b/CryptoPkg/Library/OpensslLib/OpensslStub/uefiprov.c
index 40ab7e937c..f2af6a49d8 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslStub/uefiprov.c
+++ b/CryptoPkg/Library/OpensslLib/OpensslStub/uefiprov.c
@@ -141,6 +141,17 @@ static const OSSL_ALGORITHM_CAPABLE deflt_ciphers[] = {
ALG(PROV_NAMES_AES_192_GCM, ossl_aes192gcm_functions),
ALG(PROV_NAMES_AES_128_GCM, ossl_aes128gcm_functions),
+ ALGC (
+ PROV_NAMES_AES_128_CBC_HMAC_SHA256,
+ ossl_aes128cbc_hmac_sha256_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha256
+ ),
+ ALGC (
+ PROV_NAMES_AES_256_CBC_HMAC_SHA256,
+ ossl_aes256cbc_hmac_sha256_functions,
+ ossl_cipher_capable_aes_cbc_hmac_sha256
+ ),
+
{ { NULL, NULL, NULL }, NULL }
};
static OSSL_ALGORITHM exported_ciphers[OSSL_NELEM(deflt_ciphers)];
diff --git a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
index 82d5464084..4427ab68fa 100644
--- a/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
+++ b/DynamicTablesPkg/Include/Library/AmlLib/AmlLib.h
@@ -2,7 +2,7 @@
AML Lib.
Copyright (c) 2019 - 2023, Arm Limited. All rights reserved.<BR>
- Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ Copyright (C) 2023 - 2024, Advanced Micro Devices, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1743,6 +1743,45 @@ AmlAddNameStringToNamedPackage (
IN AML_OBJECT_NODE_HANDLE NamedNode
);
+/** Add an integer value to the named package node.
+
+ AmlCodeGenNamePackage ("_CID", NULL, &PackageNode);
+ AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+ AmlAddIntegerToNamedPackage (EisaId, NameNode);
+ AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+ AmlAddIntegerToNamedPackage (EisaId, NameNode);
+
+ equivalent of the following ASL code:
+ Name (_CID, Package (0x02) // _CID: Compatible ID
+ {
+ EisaId ("PNP0A03"),
+ EisaId ("PNP0A08")
+ })
+
+ The package is added at the tail of the list of the input package node
+ name:
+ Name ("NamePackageNode", Package () {
+ [Pre-existing package entries],
+ [Newly created integer entry]
+ })
+
+
+ @ingroup CodeGenApis
+
+ @param [in] Integer Integer value that need to be added to package node.
+ @param [in, out] NameNode Package named node to add the object to.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Error occurred during the operation.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddIntegerToNamedPackage (
+ IN UINT32 Integer,
+ IN OUT AML_OBJECT_NODE_HANDLE NameNode
+ );
+
/** AML code generation to invoke/call another method.
This method is a subset implementation of MethodInvocation
diff --git a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
index 22c2d598d0..89fa4e06f8 100644
--- a/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
+++ b/DynamicTablesPkg/Library/Common/AmlLib/CodeGen/AmlCodeGen.c
@@ -3871,6 +3871,73 @@ exit_handler:
return Status;
}
+/** Add an integer value to the named package node.
+
+ AmlCodeGenNamePackage ("_CID", NULL, &PackageNode);
+ AmlGetEisaIdFromString ("PNP0A03", &EisaId);
+ AmlAddIntegerToNamedPackage (EisaId, NameNode);
+ AmlGetEisaIdFromString ("PNP0A08", &EisaId);
+ AmlAddIntegerToNamedPackage (EisaId, NameNode);
+
+ equivalent of the following ASL code:
+ Name (_CID, Package (0x02) // _CID: Compatible ID
+ {
+ EisaId ("PNP0A03"),
+ EisaId ("PNP0A08")
+ })
+
+ The package is added at the tail of the list of the input package node
+ name:
+ Name ("NamePackageNode", Package () {
+ [Pre-existing package entries],
+ [Newly created integer entry]
+ })
+
+
+ @ingroup CodeGenApis
+
+ @param [in] Integer Integer value that need to be added to package node.
+ @param [in, out] NameNode Package named node to add the object to.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval Others Error occurred during the operation.
+**/
+EFI_STATUS
+EFIAPI
+AmlAddIntegerToNamedPackage (
+ IN UINT32 Integer,
+ IN OUT AML_OBJECT_NODE_HANDLE NameNode
+ )
+{
+ EFI_STATUS Status;
+ AML_OBJECT_NODE *PackageNode;
+
+ if (NameNode == NULL) {
+ ASSERT_EFI_ERROR (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PackageNode = (AML_OBJECT_NODE_HANDLE)AmlGetFixedArgument (
+ NameNode,
+ EAmlParseIndexTerm1
+ );
+ if ((PackageNode == NULL) ||
+ (AmlGetNodeType ((AML_NODE_HANDLE)PackageNode) != EAmlNodeObject) ||
+ (!AmlNodeHasOpCode (PackageNode, AML_PACKAGE_OP, 0)))
+ {
+ ASSERT_EFI_ERROR (FALSE);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = AmlAddRegisterOrIntegerToPackage (NULL, Integer, PackageNode);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ }
+
+ return Status;
+}
+
/** AML code generation to invoke/call another method.
This method is a subset implementation of MethodInvocation
diff --git a/EmulatorPkg/EmulatorPkg.dsc b/EmulatorPkg/EmulatorPkg.dsc
index 5fa1ed345a..1c356bc8c7 100644
--- a/EmulatorPkg/EmulatorPkg.dsc
+++ b/EmulatorPkg/EmulatorPkg.dsc
@@ -127,11 +127,12 @@
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
-
-!if $(SECURE_BOOT_ENABLE) == TRUE
RngLib|MdeModulePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf
IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf
+ BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+
+!if $(SECURE_BOOT_ENABLE) == TRUE
PlatformSecureLib|SecurityPkg/Library/PlatformSecureLibNull/PlatformSecureLibNull.inf
AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
@@ -398,6 +399,15 @@
EmulatorPkg/PlatformSmbiosDxe/PlatformSmbiosDxe.inf
EmulatorPkg/TimerDxe/Timer.inf
+ #
+ # Rng Protocol producer
+ #
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+ #
+ # Hash2 Protocol producer
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
!if $(SECURE_BOOT_ENABLE) == TRUE
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
!endif
diff --git a/EmulatorPkg/EmulatorPkg.fdf b/EmulatorPkg/EmulatorPkg.fdf
index 5420756eaa..73d5b0068d 100644
--- a/EmulatorPkg/EmulatorPkg.fdf
+++ b/EmulatorPkg/EmulatorPkg.fdf
@@ -194,6 +194,16 @@ INF MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
INF MdeModulePkg/Universal/DriverSampleDxe/DriverSampleDxe.inf
#
+# Rng Protocol producer
+#
+INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
+
+#
+# Hash2 Protocol producer
+#
+INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+#
# Secure Boot Key Enroll
#
!if $(SECURE_BOOT_ENABLE) == TRUE
@@ -320,4 +330,3 @@ INF ShellPkg/Application/Shell/Shell.inf
UI STRING="$(MODULE_NAME)" Optional
VERSION STRING="$(INF_VERSION)" Optional BUILD_NUM=$(BUILD_NUMBER)
}
-
diff --git a/EmulatorPkg/Unix/Host/Gasket.h b/EmulatorPkg/Unix/Host/Gasket.h
index 6dafc903cf..71b459ddd8 100644
--- a/EmulatorPkg/Unix/Host/Gasket.h
+++ b/EmulatorPkg/Unix/Host/Gasket.h
@@ -140,7 +140,7 @@ GasketSecGetTime (
OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL
);
-VOID
+EFI_STATUS
EFIAPI
GasketSecSetTime (
IN EFI_TIME *Time
diff --git a/IntelFsp2Pkg/Tools/PatchFv.py b/IntelFsp2Pkg/Tools/PatchFv.py
index bd9aa71e3c..d35aa1dc9f 100644
--- a/IntelFsp2Pkg/Tools/PatchFv.py
+++ b/IntelFsp2Pkg/Tools/PatchFv.py
@@ -432,7 +432,7 @@ class Symbols:
if reportLine.strip().find("Archive member included") != -1:
#GCC
# 0x0000000000001d55 IoRead8
- patchMapFileMatchString = r"\s+(0x[0-9a-fA-F]{16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
+ patchMapFileMatchString = r"\s+(0x[0-9a-fA-F]{8,16})\s+([^\s][^0x][_a-zA-Z0-9\-]+)\s"
matchKeyGroupIndex = 2
matchSymbolGroupIndex = 1
prefix = '_'
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
index f4e61d223c..cf6b32959e 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.c
@@ -825,7 +825,10 @@ XhcTransfer (
*TransferResult = Urb->Result;
*DataLength = Urb->Completed;
- if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE)) {
+ //
+ // Based on XHCI spec 4.8.3, software should do the reset endpoint while USB Transaction occur.
+ //
+ if ((*TransferResult == EFI_USB_ERR_STALL) || (*TransferResult == EFI_USB_ERR_BABBLE) || (*TransferResult == EDKII_USB_ERR_TRANSACTION)) {
ASSERT (Status == EFI_DEVICE_ERROR);
RecoveryStatus = XhcRecoverHaltedEndpoint (Xhc, Urb);
if (EFI_ERROR (RecoveryStatus)) {
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
index 4401675872..c9a12095c2 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/Xhci.h
@@ -28,6 +28,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DebugLib.h>
#include <Library/ReportStatusCodeLib.h>
#include <Library/TimerLib.h>
+#include <Library/PcdLib.h>
#include <IndustryStandard/Pci.h>
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf b/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
index 18ef87916a..4ab986a019 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
@@ -45,6 +45,7 @@
[Packages]
MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
MemoryAllocationLib
@@ -56,6 +57,7 @@
DebugLib
ReportStatusCodeLib
TimerLib
+ PcdLib
[Guids]
gEfiEventExitBootServicesGuid ## SOMETIMES_CONSUMES ## Event
@@ -64,6 +66,9 @@
gEfiPciIoProtocolGuid ## TO_START
gEfiUsb2HcProtocolGuid ## BY_START
+[Pcd]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDelayXhciHCReset ## CONSUMES
+
# [Event]
# EVENT_TYPE_PERIODIC_TIMER ## CONSUMES
#
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
index 40f2f1f227..525942a167 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciReg.c
@@ -864,7 +864,7 @@ XhcResetHC (
// Otherwise there may have the timeout case happened.
// The below is a workaround to solve such problem.
//
- gBS->Stall (XHC_1_MILLISECOND);
+ gBS->Stall (PcdGet16 (PcdDelayXhciHCReset));
Status = XhcWaitOpRegBit (Xhc, XHC_USBCMD_OFFSET, XHC_USBCMD_RESET, FALSE, Timeout);
if (!EFI_ERROR (Status)) {
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
index 5d735008ba..a97ed44dbf 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.c
@@ -1192,8 +1192,11 @@ XhcCheckUrbResult (
DEBUG ((DEBUG_ERROR, "XhcCheckUrbResult: ERR_BUFFER! Completecode = %x\n", EvtTrb->Completecode));
goto EXIT;
+ //
+ // Based on XHCI spec 4.8.3, software should do the reset endpoint while USB Transaction occur.
+ //
case TRB_COMPLETION_USB_TRANSACTION_ERROR:
- CheckedUrb->Result |= EFI_USB_ERR_TIMEOUT;
+ CheckedUrb->Result |= EDKII_USB_ERR_TRANSACTION;
CheckedUrb->Finished = TRUE;
DEBUG ((DEBUG_ERROR, "XhcCheckUrbResult: TRANSACTION_ERROR! Completecode = %x\n", EvtTrb->Completecode));
goto EXIT;
diff --git a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
index 7c85f7993b..e606e212a1 100644
--- a/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
+++ b/MdeModulePkg/Bus/Pci/XhciDxe/XhciSched.h
@@ -79,6 +79,13 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#define TRB_COMPLETION_STOPPED_LENGTH_INVALID 27
//
+// USB Transfer Results Internal Definition
+// Based on XHCI spec 4.8.3, software should do the reset endpoint while USB Transaction occur.
+// Add the error code for USB Transaction error since UEFI spec don't have the related definition.
+//
+#define EDKII_USB_ERR_TRANSACTION 0x200
+
+//
// The topology string used to present usb device location
//
typedef struct _USB_DEV_TOPOLOGY {
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
new file mode 100644
index 0000000000..b183ca182c
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.c
@@ -0,0 +1,433 @@
+/** @file
+
+ SpiBus driver
+
+ Copyright (C) 2024 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/MemoryAllocationLib.h>
+#include <Protocol/SpiConfiguration.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiIo.h>
+#include "SpiBus.h"
+
+/**
+ Checks if two device paths are the same.
+
+ @param[in] DevicePath1 First device path to compare
+ @param[in] DevicePath2 Second device path to compare
+
+ @retval TRUE The device paths share the same nodes and values
+ @retval FALSE The device paths differ
+**/
+BOOLEAN
+EFIAPI
+DevicePathsAreEqual (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ UINTN Size1;
+ UINTN Size2;
+
+ Size1 = GetDevicePathSize (DevicePath1);
+ Size2 = GetDevicePathSize (DevicePath2);
+
+ if (Size1 != Size2) {
+ return FALSE;
+ }
+
+ if (CompareMem (DevicePath1, DevicePath2, Size1) != 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Calls the SpiPeripherals ChipSelect if it is not null, otherwise
+ calls the Host Controllers ChipSelect function.
+
+ @param[in] SpiChip The SpiChip to place on the bus via asserting its chip select
+ @param[in] PinValue Value to place on the chip select pin
+
+ @retval EFI_SUCCESS Chip select pin was placed at requested level
+ @retval EFI_INVALID_PARAMETER Invalid parameters passed into ChipSelect function
+**/
+EFI_STATUS
+EFIAPI
+SpiChipSelect (
+ IN CONST SPI_IO_CHIP *SpiChip,
+ IN BOOLEAN PinValue
+ )
+{
+ EFI_STATUS Status;
+
+ // Check which chip select function to use
+ if (SpiChip->Protocol.SpiPeripheral->ChipSelect != NULL) {
+ Status = SpiChip->Protocol.SpiPeripheral->ChipSelect (
+ SpiChip->BusTransaction.SpiPeripheral,
+ PinValue
+ );
+ } else {
+ Status = SpiChip->SpiHc->ChipSelect (
+ SpiChip->SpiHc,
+ SpiChip->BusTransaction.SpiPeripheral,
+ PinValue
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Checks the SpiChip's BusTransaction attributes to ensure its a valid SPI transaction.
+
+ @param[in] SpiChip The SpiChip where a bus transaction is requested
+
+ @retval EFI_SUCCESS This is a valid SPI bus transaction
+ @retval EFI_BAD_BUFFER_SIZE The WriteBytes value was invalid
+ @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid
+ @retval EFI_INVALID_PARAMETER TransactionType is not valid,
+ or BusWidth not supported by SPI peripheral or
+ SPI host controller,
+ or WriteBytes non-zero and WriteBuffer is
+ NULL,
+ or ReadBytes non-zero and ReadBuffer is NULL,
+ or ReadBuffer != WriteBuffer for full-duplex
+ type,
+ or WriteBuffer was NULL,
+ or TPL is too high
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction
+ @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI bus
+ layer or the SPI host controller
+ @retval EFI_UNSUPPORTED The SPI controller was not able to support
+**/
+EFI_STATUS
+EFIAPI
+IsValidSpiTransaction (
+ IN SPI_IO_CHIP *SpiChip
+ )
+{
+ // Error checking
+ if (SpiChip->BusTransaction.TransactionType > SPI_TRANSACTION_WRITE_THEN_READ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((SpiChip->BusTransaction.BusWidth != 1) && (SpiChip->BusTransaction.BusWidth != 2) && (SpiChip->BusTransaction.BusWidth != 4) &&
+ (SpiChip->BusTransaction.BusWidth != 8)) || (SpiChip->BusTransaction.FrameSize == 0))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((SpiChip->BusTransaction.BusWidth == 8) && (((SpiChip->Protocol.Attributes & SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH) ||
+ ((SpiChip->BusTransaction.SpiPeripheral->Attributes & SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH)))
+ {
+ return EFI_INVALID_PARAMETER;
+ } else if ((SpiChip->BusTransaction.BusWidth == 4) && (((SpiChip->Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) ||
+ ((SpiChip->BusTransaction.SpiPeripheral->Attributes & SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH)))
+ {
+ return EFI_INVALID_PARAMETER;
+ } else if ((SpiChip->BusTransaction.BusWidth == 2) && (((SpiChip->Protocol.Attributes & SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH) ||
+ ((SpiChip->BusTransaction.SpiPeripheral->Attributes & SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH)))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((SpiChip->BusTransaction.WriteBytes > 0) && (SpiChip->BusTransaction.WriteBuffer == NULL)) || ((SpiChip->BusTransaction.ReadBytes > 0) && (SpiChip->BusTransaction.ReadBuffer == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((SpiChip->BusTransaction.TransactionType == SPI_TRANSACTION_FULL_DUPLEX) && (SpiChip->BusTransaction.ReadBytes != SpiChip->BusTransaction.WriteBytes)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check frame size, passed parameter is in bits
+ if ((SpiChip->Protocol.FrameSizeSupportMask & (1<<(SpiChip->BusTransaction.FrameSize-1))) == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initiate a SPI transaction between the host and a SPI peripheral.
+
+ This routine must be called at or below TPL_NOTIFY.
+ This routine works with the SPI bus layer to pass the SPI transaction to the
+ SPI controller for execution on the SPI bus. There are four types of
+ supported transactions supported by this routine:
+ * Full Duplex: WriteBuffer and ReadBuffer are the same size.
+ * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0
+ * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0
+ * Write Then Read: WriteBuffer contains control data to write to SPI
+ peripheral before data is placed into the ReadBuffer.
+ Both WriteBytes and ReadBytes must be non-zero.
+
+ @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
+ @param[in] TransactionType Type of SPI transaction.
+ @param[in] DebugTransaction Set TRUE only when debugging is desired.
+ Debugging may be turned on for a single SPI
+ transaction. Only this transaction will display
+ debugging messages. All other transactions with
+ this value set to FALSE will not display any
+ debugging messages.
+ @param[in] ClockHz Specify the ClockHz value as zero (0) to use
+ the maximum clock frequency supported by the
+ SPI controller and part. Specify a non-zero
+ value only when a specific SPI transaction
+ requires a reduced clock rate.
+ @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4
+ @param[in] FrameSize Frame size in bits, range: 1 - 32
+ @param[in] WriteBytes The length of the WriteBuffer in bytes.
+ Specify zero for read-only operations.
+ @param[in] WriteBuffer The buffer containing data to be sent from the
+ host to the SPI chip. Specify NULL for read
+ only operations.
+ * Frame sizes 1-8 bits: UINT8 (one byte) per
+ frame
+ * Frame sizes 7-16 bits: UINT16 (two bytes) per
+ frame
+ * Frame sizes 17-32 bits: UINT32 (four bytes)
+ per frame The transmit frame is in the least
+ significant N bits.
+ @param[in] ReadBytes The length of the ReadBuffer in bytes.
+ Specify zero for write-only operations.
+ @param[out] ReadBuffer The buffer to receeive data from the SPI chip
+ during the transaction. Specify NULL for write
+ only operations.
+ * Frame sizes 1-8 bits: UINT8 (one byte) per
+ frame
+ * Frame sizes 7-16 bits: UINT16 (two bytes) per
+ frame
+ * Frame sizes 17-32 bits: UINT32 (four bytes)
+ per frame The received frame is in the least
+ significant N bits.
+
+ @retval EFI_SUCCESS The SPI transaction completed successfully
+ @retval EFI_BAD_BUFFER_SIZE The WriteBytes value was invalid
+ @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid
+ @retval EFI_INVALID_PARAMETER TransactionType is not valid,
+ or BusWidth not supported by SPI peripheral or
+ SPI host controller,
+ or WriteBytes non-zero and WriteBuffer is
+ NULL,
+ or ReadBytes non-zero and ReadBuffer is NULL,
+ or ReadBuffer != WriteBuffer for full-duplex
+ type,
+ or WriteBuffer was NULL,
+ or TPL is too high
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction
+ @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI bus
+ layer or the SPI host controller
+ @retval EFI_UNSUPPORTED The SPI controller was not able to support
+
+**/
+EFI_STATUS
+EFIAPI
+Transaction (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN EFI_SPI_TRANSACTION_TYPE TransactionType,
+ IN BOOLEAN DebugTransaction,
+ IN UINT32 ClockHz OPTIONAL,
+ IN UINT32 BusWidth,
+ IN UINT32 FrameSize,
+ IN UINT32 WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINT32 ReadBytes,
+ OUT UINT8 *ReadBuffer
+ )
+{
+ EFI_STATUS Status;
+ SPI_IO_CHIP *SpiChip;
+ UINT32 MaxClockHz;
+ UINT8 *DummyReadBuffer;
+ UINT8 *DummyWriteBuffer;
+
+ SpiChip = SPI_IO_CHIP_FROM_THIS (This);
+ SpiChip->BusTransaction.SpiPeripheral =
+ (EFI_SPI_PERIPHERAL *)SpiChip->Protocol.SpiPeripheral;
+ SpiChip->BusTransaction.TransactionType = TransactionType;
+ SpiChip->BusTransaction.DebugTransaction = DebugTransaction;
+ SpiChip->BusTransaction.BusWidth = BusWidth;
+ SpiChip->BusTransaction.FrameSize = FrameSize;
+ SpiChip->BusTransaction.WriteBytes = WriteBytes;
+ SpiChip->BusTransaction.WriteBuffer = WriteBuffer;
+ SpiChip->BusTransaction.ReadBytes = ReadBytes;
+ SpiChip->BusTransaction.ReadBuffer = ReadBuffer;
+
+ // Ensure valid spi transaction parameters
+ Status = IsValidSpiTransaction (SpiChip);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Setup the proper clock frequency
+ if (SpiChip->BusTransaction.SpiPeripheral->MaxClockHz != 0) {
+ MaxClockHz = SpiChip->BusTransaction.SpiPeripheral->MaxClockHz;
+ } else {
+ MaxClockHz = SpiChip->BusTransaction.SpiPeripheral->SpiPart->MaxClockHz;
+ }
+
+ // Call proper clock function
+ if (SpiChip->Protocol.SpiPeripheral->SpiBus->Clock != NULL) {
+ Status = SpiChip->Protocol.SpiPeripheral->SpiBus->Clock (
+ SpiChip->BusTransaction.SpiPeripheral,
+ &MaxClockHz
+ );
+ } else {
+ Status = SpiChip->SpiHc->Clock (
+ SpiChip->SpiHc,
+ SpiChip->BusTransaction.SpiPeripheral,
+ &MaxClockHz
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SpiChipSelect (SpiChip, SpiChip->BusTransaction.SpiPeripheral->SpiPart->ChipSelectPolarity);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Check transaction types and match to HC capabilities
+ if ((TransactionType == SPI_TRANSACTION_WRITE_ONLY) &&
+ ((SpiChip->SpiHc->Attributes & HC_SUPPORTS_WRITE_ONLY_OPERATIONS) != HC_SUPPORTS_WRITE_ONLY_OPERATIONS))
+ {
+ // Convert to full duplex transaction
+ SpiChip->BusTransaction.ReadBytes = SpiChip->BusTransaction.WriteBytes;
+ SpiChip->BusTransaction.ReadBuffer = AllocateZeroPool (SpiChip->BusTransaction.ReadBytes);
+
+ Status = SpiChip->SpiHc->Transaction (
+ SpiChip->SpiHc,
+ &SpiChip->BusTransaction
+ );
+
+ SpiChip->BusTransaction.ReadBytes = ReadBytes; // assign to passed parameter
+ FreePool (SpiChip->BusTransaction.ReadBuffer); // Free temporary buffer
+ } else if ((TransactionType == SPI_TRANSACTION_READ_ONLY) &&
+ ((SpiChip->SpiHc->Attributes & HC_SUPPORTS_READ_ONLY_OPERATIONS) != HC_SUPPORTS_READ_ONLY_OPERATIONS))
+ {
+ // Convert to full duplex transaction
+ SpiChip->BusTransaction.WriteBytes = SpiChip->BusTransaction.WriteBytes;
+ SpiChip->BusTransaction.WriteBuffer = AllocateZeroPool (SpiChip->BusTransaction.WriteBytes);
+
+ Status = SpiChip->SpiHc->Transaction (
+ SpiChip->SpiHc,
+ &SpiChip->BusTransaction
+ );
+
+ SpiChip->BusTransaction.WriteBytes = WriteBytes;
+ FreePool (SpiChip->BusTransaction.WriteBuffer);
+ } else if ((TransactionType == SPI_TRANSACTION_WRITE_THEN_READ) &&
+ ((SpiChip->SpiHc->Attributes & HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS) != HC_SUPPORTS_WRITE_THEN_READ_OPERATIONS))
+ {
+ // Convert to full duplex transaction
+ DummyReadBuffer = AllocateZeroPool (WriteBytes);
+ DummyWriteBuffer = AllocateZeroPool (ReadBytes);
+ SpiChip->BusTransaction.ReadBuffer = DummyReadBuffer;
+ SpiChip->BusTransaction.ReadBytes = WriteBytes;
+
+ Status = SpiChip->SpiHc->Transaction (
+ SpiChip->SpiHc,
+ &SpiChip->BusTransaction
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // Write is done, now need to read, restore passed in read buffer info
+ SpiChip->BusTransaction.ReadBuffer = ReadBuffer;
+ SpiChip->BusTransaction.ReadBytes = ReadBytes;
+
+ SpiChip->BusTransaction.WriteBuffer = DummyWriteBuffer;
+ SpiChip->BusTransaction.WriteBytes = ReadBytes;
+
+ Status = SpiChip->SpiHc->Transaction (
+ SpiChip->SpiHc,
+ &SpiChip->BusTransaction
+ );
+ // Restore write data
+ SpiChip->BusTransaction.WriteBuffer = WriteBuffer;
+ SpiChip->BusTransaction.WriteBytes = WriteBytes;
+
+ FreePool (DummyReadBuffer);
+ FreePool (DummyWriteBuffer);
+ } else {
+ // Supported transaction type, just pass info the SPI HC Protocol Transaction
+ Status = SpiChip->SpiHc->Transaction (
+ SpiChip->SpiHc,
+ &SpiChip->BusTransaction
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SpiChipSelect (SpiChip, !SpiChip->BusTransaction.SpiPeripheral->SpiPart->ChipSelectPolarity);
+
+ return Status;
+}
+
+/**
+ Update the SPI peripheral associated with this SPI 10 SpiChip.
+
+ Support socketed SPI parts by allowing the SPI peripheral driver to replace
+ the SPI peripheral after the connection is made. An example use is socketed
+ SPI NOR flash parts, where the size and parameters change depending upon
+ device is in the socket.
+
+ @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
+ @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure.
+
+ @retval EFI_SUCCESS The SPI peripheral was updated successfully
+ @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL,
+ or the SpiPeripheral->SpiBus is NULL,
+ or the SpiPeripheral->SpiBus pointing at
+ wrong bus, or the SpiPeripheral->SpiPart is NULL
+**/
+EFI_STATUS
+EFIAPI
+UpdateSpiPeripheral (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral
+ )
+{
+ EFI_STATUS Status;
+ SPI_IO_CHIP *SpiChip;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: SPI Bus - Entry\n", __func__));
+
+ SpiChip = SPI_IO_CHIP_FROM_THIS (This);
+
+ if ((SpiPeripheral == NULL) || (SpiPeripheral->SpiBus == NULL) ||
+ (SpiPeripheral->SpiPart == NULL))
+ {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // EFI_INVALID_PARAMETER if SpiPeripheral->SpiBus is pointing at wrong bus
+ if (!DevicePathsAreEqual (SpiPeripheral->SpiBus->ControllerPath, SpiChip->SpiBus->ControllerPath)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ SpiChip->Protocol.OriginalSpiPeripheral = SpiChip->Protocol.SpiPeripheral;
+ SpiChip->Protocol.SpiPeripheral = SpiPeripheral;
+
+ Status = EFI_SUCCESS;
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: SPI Bus - Exit Status=%r\n",
+ __func__,
+ Status
+ ));
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h
new file mode 100644
index 0000000000..7a43f66ac7
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.h
@@ -0,0 +1,167 @@
+/** @file
+
+ SPI bus driver
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_BUS_H_
+#define SPI_BUS_H_
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Protocol/DevicePath.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Protocol/SpiIo.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiConfiguration.h>
+
+#define SPI_IO_SIGNATURE SIGNATURE_32 ('s', 'i', 'o', 'c')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_SPI_IO_PROTOCOL Protocol;
+ EFI_SPI_BUS_TRANSACTION BusTransaction;
+ EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfig;
+ EFI_SPI_HC_PROTOCOL *SpiHc;
+ EFI_SPI_BUS *SpiBus;
+} SPI_IO_CHIP;
+
+#define SPI_IO_CHIP_FROM_THIS(a) \
+ CR (a, SPI_IO_CHIP, Protocol, \
+ SPI_IO_SIGNATURE)
+
+/**
+ Checks if two device paths are the same
+
+ @param[in] DevicePath1 First device path to compare
+ @param[in] DevicePath2 Second device path to compare
+
+ @retval TRUE The device paths share the same nodes and values
+ @retval FALSE The device paths differ
+**/
+BOOLEAN
+EFIAPI
+DevicePathsAreEqual (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ );
+
+/**
+ Initiate a SPI transaction between the host and a SPI peripheral.
+
+ This routine must be called at or below TPL_NOTIFY.
+ This routine works with the SPI bus layer to pass the SPI transaction to the
+ SPI controller for execution on the SPI bus. There are four types of
+ supported transactions supported by this routine:
+ * Full Duplex: WriteBuffer and ReadBuffer are the same size.
+ * Write Only: WriteBuffer contains data for SPI peripheral, ReadBytes = 0
+ * Read Only: ReadBuffer to receive data from SPI peripheral, WriteBytes = 0
+ * Write Then Read: WriteBuffer contains control data to write to SPI
+ peripheral before data is placed into the ReadBuffer.
+ Both WriteBytes and ReadBytes must be non-zero.
+
+ @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
+ @param[in] TransactionType Type of SPI transaction.
+ @param[in] DebugTransaction Set TRUE only when debugging is desired.
+ Debugging may be turned on for a single SPI
+ transaction. Only this transaction will display
+ debugging messages. All other transactions with
+ this value set to FALSE will not display any
+ debugging messages.
+ @param[in] ClockHz Specify the ClockHz value as zero (0) to use
+ the maximum clock frequency supported by the
+ SPI controller and part. Specify a non-zero
+ value only when a specific SPI transaction
+ requires a reduced clock rate.
+ @param[in] BusWidth Width of the SPI bus in bits: 1, 2, 4
+ @param[in] FrameSize Frame size in bits, range: 1 - 32
+ @param[in] WriteBytes The length of the WriteBuffer in bytes.
+ Specify zero for read-only operations.
+ @param[in] WriteBuffer The buffer containing data to be sent from the
+ host to the SPI chip. Specify NULL for read
+ only operations.
+ * Frame sizes 1-8 bits: UINT8 (one byte) per
+ frame
+ * Frame sizes 7-16 bits: UINT16 (two bytes) per
+ frame
+ * Frame sizes 17-32 bits: UINT32 (four bytes)
+ per frame The transmit frame is in the least
+ significant N bits.
+ @param[in] ReadBytes The length of the ReadBuffer in bytes.
+ Specify zero for write-only operations.
+ @param[out] ReadBuffer The buffer to receeive data from the SPI chip
+ during the transaction. Specify NULL for write
+ only operations.
+ * Frame sizes 1-8 bits: UINT8 (one byte) per
+ frame
+ * Frame sizes 7-16 bits: UINT16 (two bytes) per
+ frame
+ * Frame sizes 17-32 bits: UINT32 (four bytes)
+ per frame The received frame is in the least
+ significant N bits.
+
+ @retval EFI_SUCCESS The SPI transaction completed successfully
+ @retval EFI_BAD_BUFFER_SIZE The writeBytes value was invalid
+ @retval EFI_BAD_BUFFER_SIZE The ReadBytes value was invalid
+ @retval EFI_INVALID_PARAMETER TransactionType is not valid,
+ or BusWidth not supported by SPI peripheral or
+ SPI host controller,
+ or WriteBytes non-zero and WriteBuffer is
+ NULL,
+ or ReadBytes non-zero and ReadBuffer is NULL,
+ or ReadBuffer != WriteBuffer for full-duplex
+ type,
+ or WriteBuffer was NULL,
+ or TPL is too high
+ @retval EFI_OUT_OF_RESOURCES Insufficient memory for SPI transaction
+ @retval EFI_UNSUPPORTED The FrameSize is not supported by the SPI bus
+ layer or the SPI host controller
+ @retval EFI_UNSUPPORTED The SPI controller was not able to support
+
+**/
+EFI_STATUS
+EFIAPI
+Transaction (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN EFI_SPI_TRANSACTION_TYPE TransactionType,
+ IN BOOLEAN DebugTransaction,
+ IN UINT32 ClockHz OPTIONAL,
+ IN UINT32 BusWidth,
+ IN UINT32 FrameSize,
+ IN UINT32 WriteBytes,
+ IN UINT8 *WriteBuffer,
+ IN UINT32 ReadBytes,
+ OUT UINT8 *ReadBuffer
+ );
+
+/**
+ Update the SPI peripheral associated with this SPI 10 instance.
+
+ Support socketed SPI parts by allowing the SPI peripheral driver to replace
+ the SPI peripheral after the connection is made. An example use is socketed
+ SPI NOR flash parts, where the size and parameters change depending upon
+ device is in the socket.
+
+ @param[in] This Pointer to an EFI_SPI_IO_PROTOCOL structure.
+ @param[in] SpiPeripheral Pointer to an EFI_SPI_PERIPHERAL structure.
+
+ @retval EFI_SUCCESS The SPI peripheral was updated successfully
+ @retval EFI_INVALID_PARAMETER The SpiPeripheral value is NULL,
+ or the SpiPeripheral->SpiBus is NULL,
+ or the SpiPeripheral->SpiBus pointing at
+ wrong bus, or the SpiPeripheral->SpiPart is NULL
+
+**/
+EFI_STATUS
+EFIAPI
+UpdateSpiPeripheral (
+ IN CONST EFI_SPI_IO_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral
+ );
+
+#endif //SPI_BUS_H_
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni
new file mode 100644
index 0000000000..0d913bdbae
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBus.uni
@@ -0,0 +1,10 @@
+// /** @file
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US "SPI Bus driver"
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
new file mode 100644
index 0000000000..cd0a2c99a2
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.c
@@ -0,0 +1,198 @@
+/** @file
+
+ SPI bus DXE driver
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/SpiConfiguration.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiIo.h>
+#include "SpiBus.h"
+
+/**
+ Entry point of the Spi Bus layer
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Pointer to standard EFI system table.
+
+ @retval EFI_SUCCESS Succeed.
+ @retval EFI_DEVICE_ERROR SpiPeripheral is NULL.
+ @retval EFI_NOT_FOUND Fail to locate SpiHcProtocol or SpiIoConfigurationProtocol
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate SpiIoChip
+**/
+EFI_STATUS
+EFIAPI
+SpiBusEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SPI_IO_CHIP *SpiChip;
+ EFI_SPI_HC_PROTOCOL *SpiHc;
+ EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfiguration;
+ EFI_SPI_PERIPHERAL *SpiPeripheral;
+ EFI_SPI_BUS *Bus;
+ UINTN BusIndex;
+ UINTN HcIndex;
+ EFI_HANDLE *SpiHcHandles;
+ UINTN HandleCount;
+ EFI_DEVICE_PATH_PROTOCOL *SpiHcDevicePath;
+
+ DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__));
+
+ // Get all SPI HC protocols, could be multiple SPI HC's on a single platform
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSpiHcProtocolGuid,
+ NULL,
+ &HandleCount,
+ &SpiHcHandles
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n"));
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ // Locate the SPI Configuration Protocol
+ Status = gBS->LocateProtocol (
+ &gEfiSpiConfigurationProtocolGuid,
+ NULL,
+ (VOID **)&SpiConfiguration
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n"));
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ // Parse through Hc protocols, find correct device path
+ for (HcIndex = 0; HcIndex < HandleCount; HcIndex++) {
+ Status = gBS->HandleProtocol (
+ SpiHcHandles[HcIndex],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&SpiHcDevicePath
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "Error locating EFI device path for this SPI controller, status=%r \n", Status));
+ continue; // Continue searching
+ }
+
+ // Parse through SpiConfiguration's SpiBuses, find matching devicepath for SpiHc
+ for (BusIndex = 0; BusIndex < SpiConfiguration->BusCount; BusIndex++) {
+ Bus = (EFI_SPI_BUS *)SpiConfiguration->Buslist[BusIndex];
+ if (!DevicePathsAreEqual (SpiHcDevicePath, Bus->ControllerPath)) {
+ DEBUG ((DEBUG_VERBOSE, "SpiHc and SpiConfig device paths dont match, continue parsing\n"));
+ continue;
+ }
+
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Found matching device paths, Enumerating SPI BUS: %s with DevicePath: %s\n",
+ __func__,
+ Bus->FriendlyName,
+ ConvertDevicePathToText (SpiHcDevicePath, FALSE, FALSE)
+ ));
+
+ // Get SpiHc from the SpiHcHandles
+ Status = gBS->HandleProtocol (
+ SpiHcHandles[HcIndex],
+ &gEfiDevicePathProtocolGuid,
+ (VOID **)&SpiHc
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", __func__));
+ goto Exit;
+ }
+
+ SpiPeripheral = (EFI_SPI_PERIPHERAL *)Bus->Peripherallist;
+ if (SpiPeripheral != NULL) {
+ do {
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Installing SPI IO protocol for %s, by %s, PN=%s\n",
+ __func__,
+ SpiPeripheral->FriendlyName,
+ SpiPeripheral->SpiPart->Vendor,
+ SpiPeripheral->SpiPart->PartNumber
+ ));
+ // Allocate the SPI IO Device
+ SpiChip = AllocateZeroPool (sizeof (SPI_IO_CHIP));
+ ASSERT (SpiChip != NULL);
+ if (SpiChip != NULL) {
+ // Fill in the SpiChip
+ SpiChip->Signature = SPI_IO_SIGNATURE;
+ SpiChip->SpiConfig = SpiConfiguration;
+ SpiChip->SpiHc = SpiHc;
+ SpiChip->SpiBus = Bus;
+ SpiChip->Protocol.SpiPeripheral = SpiPeripheral;
+ SpiChip->Protocol.OriginalSpiPeripheral = SpiPeripheral;
+ SpiChip->Protocol.FrameSizeSupportMask = SpiHc->FrameSizeSupportMask;
+ SpiChip->Protocol.MaximumTransferBytes = SpiHc->MaximumTransferBytes;
+ if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS;
+ }
+
+ if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE;
+ }
+
+ if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH;
+ }
+
+ if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH;
+ }
+
+ if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH;
+ }
+
+ SpiChip->Protocol.Transaction = Transaction;
+ SpiChip->Protocol.UpdateSpiPeripheral = UpdateSpiPeripheral;
+ // Install the SPI IO Protocol
+ Status = gBS->InstallProtocolInterface (
+ &SpiChip->Handle,
+ (GUID *)SpiPeripheral->SpiPeripheralDriverGuid,
+ EFI_NATIVE_INTERFACE,
+ &SpiChip->Protocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n", __func__));
+ continue;
+ }
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Out of Memory resources\n",
+ __func__
+ ));
+ break;
+ }
+
+ SpiPeripheral = (EFI_SPI_PERIPHERAL *)SpiPeripheral->NextSpiPeripheral;
+ } while (SpiPeripheral != NULL);
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+ }
+ }
+
+Exit:
+ DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status));
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
new file mode 100644
index 0000000000..3e2cc2daba
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
@@ -0,0 +1,41 @@
+## @file
+# Component description for the SPI BUS DXE module
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = SpiBusDxe
+ FILE_GUID = 25CE038C-5C3A-4A9B-A111-90DF5897E058
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 0.1
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SpiBusEntry
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+
+[Sources]
+ SpiBusDxe.c
+ SpiBus.c
+ SpiBus.h
+
+[Protocols]
+ gEfiSpiConfigurationProtocolGuid ## CONSUMES
+ gEfiSpiHcProtocolGuid ## CONSUMES
+
+[Depex]
+ gEfiSpiConfigurationProtocolGuid AND
+ gEfiSpiHcProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ SpiBus.uni
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c
new file mode 100644
index 0000000000..d9189b9848
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.c
@@ -0,0 +1,162 @@
+/** @file
+
+ SPI bus SMM driver
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Protocol/SpiSmmConfiguration.h>
+#include <Protocol/SpiSmmHc.h>
+#include <Protocol/SpiIo.h>
+#include "SpiBus.h"
+
+/**
+ Entry point of the Spi Bus layer
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Pointer to standard EFI system table.
+
+ @retval EFI_SUCCESS Succeed.
+ @retval EFI_DEVICE_ERROR Fail to install EFI_SPI_HC_PROTOCOL protocol.
+ @retval EFI_NOT_FOUND fail to locate SpiHcProtocol or SpiIoConfigurationProtocol
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate SpiIoChip
+**/
+EFI_STATUS
+EFIAPI
+SpiBusEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SPI_IO_CHIP *SpiChip;
+ EFI_SPI_HC_PROTOCOL *SpiHc;
+ EFI_SPI_CONFIGURATION_PROTOCOL *SpiConfiguration;
+ EFI_SPI_PERIPHERAL *SpiPeripheral;
+ EFI_SPI_BUS *Bus;
+
+ DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__));
+
+ // Only a single Spi HC protocol in SMM
+ Status = gMmst->MmLocateProtocol (
+ &gEfiSpiSmmHcProtocolGuid,
+ NULL,
+ (VOID **)&SpiHc
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "No SpiHcProtocol is found\n"));
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ // Locate the SPI Configuration Protocol
+ Status = gMmst->MmLocateProtocol (
+ &gEfiSpiSmmConfigurationProtocolGuid,
+ NULL,
+ (VOID **)&SpiConfiguration
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "No SpiConfigurationProtocol is found\n"));
+ Status = EFI_NOT_FOUND;
+ goto Exit;
+ }
+
+ // Only one SpiBus supported in SMM
+ if (SpiConfiguration->BusCount != 1) {
+ DEBUG ((DEBUG_VERBOSE, "Only one SPI Bus supported in SMM\n"));
+ Status = EFI_UNSUPPORTED;
+ goto Exit;
+ }
+
+ Bus = (EFI_SPI_BUS *)SpiConfiguration->Buslist[0];
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "%a - Error getting SpiHc from Handle\n", __func__));
+ goto Exit;
+ }
+
+ SpiPeripheral = (EFI_SPI_PERIPHERAL *)Bus->Peripherallist;
+ if (SpiPeripheral != NULL) {
+ do {
+ DEBUG ((
+ DEBUG_VERBOSE,
+ "%a: Installing SPI IO protocol for %s, by %s, PN=%s\n",
+ __func__,
+ SpiPeripheral->FriendlyName,
+ SpiPeripheral->SpiPart->Vendor,
+ SpiPeripheral->SpiPart->PartNumber
+ ));
+ // Allocate the SPI IO Device
+ SpiChip = AllocateZeroPool (sizeof (SPI_IO_CHIP));
+ ASSERT (SpiChip != NULL);
+ if (SpiChip != NULL) {
+ // Fill in the SpiChip
+ SpiChip->Signature = SPI_IO_SIGNATURE;
+ SpiChip->SpiConfig = SpiConfiguration;
+ SpiChip->SpiHc = SpiHc;
+ SpiChip->SpiBus = Bus;
+ SpiChip->Protocol.SpiPeripheral = SpiPeripheral;
+ SpiChip->Protocol.OriginalSpiPeripheral = SpiPeripheral;
+ SpiChip->Protocol.FrameSizeSupportMask = SpiHc->FrameSizeSupportMask;
+ SpiChip->Protocol.MaximumTransferBytes = SpiHc->MaximumTransferBytes;
+ if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_ADDRESS) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_ADDRESS;
+ }
+
+ if ((SpiHc->Attributes & HC_TRANSFER_SIZE_INCLUDES_OPCODE) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_TRANSFER_SIZE_INCLUDES_OPCODE;
+ }
+
+ if ((SpiHc->Attributes & HC_SUPPORTS_8_BIT_DATA_BUS_WIDTH) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_8_BIT_DATA_BUS_WIDTH;
+ }
+
+ if ((SpiHc->Attributes & HC_SUPPORTS_4_BIT_DATA_BUS_WIDTH) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_4_BIT_DATA_BUS_WIDTH;
+ }
+
+ if ((SpiHc->Attributes & HC_SUPPORTS_2_BIT_DATA_BUS_WIDTH) != 0) {
+ SpiChip->Protocol.Attributes |= SPI_IO_SUPPORTS_2_BIT_DATA_BUS_WIDTH;
+ }
+
+ SpiChip->Protocol.Transaction = Transaction;
+ SpiChip->Protocol.UpdateSpiPeripheral = UpdateSpiPeripheral;
+ // Install the SPI IO Protocol
+ Status = gMmst->MmInstallProtocolInterface (
+ &SpiChip->Handle,
+ (GUID *)SpiPeripheral->SpiPeripheralDriverGuid,
+ EFI_NATIVE_INTERFACE,
+ &SpiChip->Protocol
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "%a - Error installing SpiIoProtocol\n", __func__));
+ continue;
+ }
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Out of Memory resources\n",
+ __func__
+ ));
+ break;
+ }
+
+ SpiPeripheral = (EFI_SPI_PERIPHERAL *)SpiPeripheral->NextSpiPeripheral;
+ } while (SpiPeripheral != NULL);
+ } else {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+Exit:
+ DEBUG ((DEBUG_VERBOSE, "%a - EXIT (Status = %r)\n", __func__, Status));
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
new file mode 100644
index 0000000000..9e3a5aae7d
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
@@ -0,0 +1,41 @@
+## @file
+# Component description for the SPI BUS SMM module
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = SpiBusSmm
+ FILE_GUID = 5DBB52E1-3D78-4C9C-A9D7-A43E79E93AC0
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 0.1
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SpiBusEntry
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ MmServicesTableLib
+ UefiDriverEntryPoint
+
+[Sources]
+ SpiBus.h
+ SpiBus.c
+ SpiBusSmm.c
+
+[Protocols]
+ gEfiSpiSmmConfigurationProtocolGuid ## CONSUMES
+ gEfiSpiSmmHcProtocolGuid ## CONSUMES
+
+[Depex]
+ gEfiSpiSmmConfigurationProtocolGuid AND
+ gEfiSpiSmmHcProtocolGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ SpiBus.uni
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.c b/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.c
new file mode 100644
index 0000000000..9d7bf9f542
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.c
@@ -0,0 +1,115 @@
+/** @file
+
+ SPI Host Controller shell implementation, as host controller code is platform
+ specfic.
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "SpiHc.h"
+
+/**
+ Assert or deassert the SPI chip select.
+
+ This routine is called at TPL_NOTIFY.
+ Update the value of the chip select line for a SPI peripheral. The SPI bus
+ layer calls this routine either in the board layer or in the SPI controller
+ to manipulate the chip select pin at the start and end of a SPI transaction.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data structure
+ describing the SPI peripheral whose chip select pin
+ is to be manipulated. The routine may access the
+ ChipSelectParameter field to gain sufficient
+ context to complete the operati on.
+ @param[in] PinValue The value to be applied to the chip select line of
+ the SPI peripheral.
+
+ @retval EFI_SUCCESS The chip select was set as requested
+ @retval EFI_NOT_READY Support for the chip select is not properly
+ initialized
+ @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents are
+ invalid
+
+**/
+EFI_STATUS
+EFIAPI
+ChipSelect (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN BOOLEAN PinValue
+ )
+{
+ return PlatformSpiHcChipSelect (This, SpiPeripheral, PinValue);
+}
+
+/**
+ Set up the clock generator to produce the correct clock frequency, phase and
+ polarity for a SPI chip.
+
+ This routine is called at TPL_NOTIFY.
+ This routine updates the clock generator to generate the correct frequency
+ and polarity for the SPI clock.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure from
+ which the routine can access the ClockParameter,
+ ClockPhase and ClockPolarity fields. The routine
+ also has access to the names for the SPI bus and
+ chip which can be used during debugging.
+ @param[in] ClockHz Pointer to the requested clock frequency. The SPI
+ host controller will choose a supported clock
+ frequency which is less then or equal to this
+ value. Specify zero to turn the clock generator
+ off. The actual clock frequency supported by the
+ SPI host controller will be returned.
+
+ @retval EFI_SUCCESS The clock was set up successfully
+ @retval EFI_UNSUPPORTED The SPI controller was not able to support the
+ frequency requested by ClockHz
+
+**/
+EFI_STATUS
+EFIAPI
+Clock (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN UINT32 *ClockHz
+ )
+{
+ return PlatformSpiHcClock (This, SpiPeripheral, ClockHz);
+}
+
+/**
+ Perform the SPI transaction on the SPI peripheral using the SPI host
+ controller.
+
+ This routine is called at TPL_NOTIFY.
+ This routine synchronously returns EFI_SUCCESS indicating that the
+ asynchronous SPI transaction was started. The routine then waits for
+ completion of the SPI transaction prior to returning the final transaction
+ status.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] BusTransaction Pointer to a EFI_SPI_BUS_ TRANSACTION containing
+ the description of the SPI transaction to perform.
+
+ @retval EFI_SUCCESS The transaction completed successfully
+ @retval EFI_BAD_BUFFER_SIZE The BusTransaction->WriteBytes value is invalid,
+ or the BusTransaction->ReadinBytes value is
+ invalid
+ @retval EFI_UNSUPPORTED The BusTransaction-> Transaction Type is
+ unsupported
+ @retval EFI_DEVICE_ERROR SPI Host Controller failed transaction
+
+**/
+EFI_STATUS
+EFIAPI
+Transaction (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN EFI_SPI_BUS_TRANSACTION *BusTransaction
+ )
+{
+ return PlatformSpiHcTransaction (This, BusTransaction);
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.h b/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.h
new file mode 100644
index 0000000000..c6e4c5893d
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.h
@@ -0,0 +1,117 @@
+/** @file
+
+ SPI Host Controller function declarations
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SPI_HC_H_
+#define SPI_HC_H_
+
+#include <PiDxe.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/SpiHc.h>
+#include <Library/SpiHcPlatformLib.h>
+
+/**
+ Assert or deassert the SPI chip select.
+
+ This routine is called at TPL_NOTIFY.
+ Update the value of the chip select line for a SPI peripheral. The SPI bus
+ layer calls this routine either in the board layer or in the SPI controller
+ to manipulate the chip select pin at the start and end of a SPI transaction.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data structure
+ describing the SPI peripheral whose chip select pin
+ is to be manipulated. The routine may access the
+ ChipSelectParameter field to gain sufficient
+ context to complete the operati on.
+ @param[in] PinValue The value to be applied to the chip select line of
+ the SPI peripheral.
+
+ @retval EFI_SUCCESS The chip select was set as requested
+ @retval EFI_NOT_READY Support for the chip select is not properly
+ initialized
+ @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents are
+ invalid
+
+**/
+EFI_STATUS
+EFIAPI
+ChipSelect (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN BOOLEAN PinValue
+ );
+
+/**
+ Set up the clock generator to produce the correct clock frequency, phase and
+ polarity for a SPI chip.
+
+ This routine is called at TPL_NOTIFY.
+ This routine updates the clock generator to generate the correct frequency
+ and polarity for the SPI clock.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure from
+ which the routine can access the ClockParameter,
+ ClockPhase and ClockPolarity fields. The routine
+ also has access to the names for the SPI bus and
+ chip which can be used during debugging.
+ @param[in] ClockHz Pointer to the requested clock frequency. The SPI
+ host controller will choose a supported clock
+ frequency which is less then or equal to this
+ value. Specify zero to turn the clock generator
+ off. The actual clock frequency supported by the
+ SPI host controller will be returned.
+
+ @retval EFI_SUCCESS The clock was set up successfully
+ @retval EFI_UNSUPPORTED The SPI controller was not able to support the
+ frequency requested by ClockHz
+
+**/
+EFI_STATUS
+EFIAPI
+Clock (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN UINT32 *ClockHz
+ );
+
+/**
+ Perform the SPI transaction on the SPI peripheral using the SPI host
+ controller.
+
+ This routine is called at TPL_NOTIFY.
+ This routine synchronously returns EFI_SUCCESS indicating that the
+ asynchronous SPI transaction was started. The routine then waits for
+ completion of the SPI transaction prior to returning the final transaction
+ status.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] BusTransaction Pointer to a EFI_SPI_BUS_ TRANSACTION containing
+ the description of the SPI transaction to perform.
+
+ @retval EFI_SUCCESS The transaction completed successfully
+ @retval EFI_BAD_BUFFER_SIZE The BusTransaction->WriteBytes value is invalid,
+ or the BusTransaction->ReadinBytes value is
+ invalid
+ @retval EFI_UNSUPPORTED The BusTransaction-> Transaction Type is
+ unsupported
+ @retval EFI_DEVICE_ERROR SPI Host Controller failed transaction
+
+**/
+EFI_STATUS
+EFIAPI
+Transaction (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN EFI_SPI_BUS_TRANSACTION *BusTransaction
+ );
+
+#endif //SPI_HC_H_
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.uni b/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.uni
new file mode 100644
index 0000000000..9fab0a7433
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHc.uni
@@ -0,0 +1,10 @@
+// /** @file
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US "SPI host controller driver"
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.c b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.c
new file mode 100644
index 0000000000..d0e9827eb6
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.c
@@ -0,0 +1,101 @@
+/** @file
+
+ SPI Host controller entry point for DXE
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SpiHcPlatformLib.h>
+#include <Protocol/SpiHc.h>
+#include <IndustryStandard/SpiNorFlashJedecSfdp.h>
+#include "SpiHc.h"
+
+EFI_HANDLE mSpiHcHandle = 0;
+
+/**
+ Entry point of the SPI Host Controller driver. Installs the EFI_SPI_HC_PROTOCOL on mSpiHcHandle.
+ Also installs the EFI_DEVICE_PATH_PROTOCOL corresponding to the SPI Host controller on the same
+ mSpiHcHandle.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Pointer to standard EFI system table.
+
+ @retval EFI_SUCCESS Succeed.
+ @retval EFI_OUT_RESOURCES If the system has run out of memory
+**/
+EFI_STATUS
+EFIAPI
+SpiHcProtocolEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SPI_HC_PROTOCOL *HcProtocol;
+ EFI_DEVICE_PATH_PROTOCOL *HcDevicePath;
+
+ DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__));
+
+ // Allocate the SPI Host Controller protocol
+ HcProtocol = AllocateZeroPool (sizeof (EFI_SPI_HC_PROTOCOL));
+ ASSERT (HcProtocol != NULL);
+ if (HcProtocol == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Fill in the SPI Host Controller Protocol
+ Status = GetPlatformSpiHcDetails (
+ &HcProtocol->Attributes,
+ &HcProtocol->FrameSizeSupportMask,
+ &HcProtocol->MaximumTransferBytes
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "Error, no Platform SPI HC details\n"));
+ return Status;
+ }
+
+ HcProtocol->ChipSelect = ChipSelect;
+ HcProtocol->Clock = Clock;
+ HcProtocol->Transaction = Transaction;
+
+ // Install Host Controller protocol
+ Status = gBS->InstallProtocolInterface (
+ &mSpiHcHandle,
+ &gEfiSpiHcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ HcProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "Error installing gEfiSpiHcProtocolGuid\n"));
+ return Status;
+ }
+
+ Status = GetSpiHcDevicePath (&HcDevicePath);
+
+ // Install HC device path here on this handle as well
+ Status = gBS->InstallProtocolInterface (
+ &mSpiHcHandle,
+ &gEfiDevicePathProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ HcDevicePath
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "Error installing gEfiDevicePathProtocolGuid\n"));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%a - EXIT Status=%r\n", __func__, Status));
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.inf b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.inf
new file mode 100644
index 0000000000..b71f1535cd
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.inf
@@ -0,0 +1,47 @@
+## @file
+# The SPI Host Controller Module DXE driver INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = SpiHcDxe
+ FILE_GUID = 95D148FF-5A23-43B9-9FC4-80AE0DD48D32
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 0.1
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SpiHcProtocolEntry
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+ SpiHcPlatformLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ UefiLib
+ UefiRuntimeServicesTableLib
+
+[Sources]
+ SpiHc.h
+ SpiHc.c
+ SpiHcDxe.c
+
+[Protocols]
+ gEfiSpiHcProtocolGuid
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ SpiHc.uni
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.c b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.c
new file mode 100644
index 0000000000..adebff9763
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.c
@@ -0,0 +1,79 @@
+/** @file
+
+ SPI Host controller entry point for SMM
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <Base.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/SpiHcPlatformLib.h>
+#include <Protocol/SpiSmmHc.h>
+#include <IndustryStandard/SpiNorFlashJedecSfdp.h>
+#include "SpiHc.h"
+
+EFI_HANDLE mSpiHcHandle = 0;
+
+/**
+ Entry point of the SPI Host Controller driver. Installs the EFI_SPI_HC_PROTOCOL on mSpiHcHandle.
+ Also installs the EFI_DEVICE_PATH_PROTOCOL corresponding to the SPI Host controller on the same
+ mSpiHcHandle.
+
+ @param[in] ImageHandle Image handle of this driver.
+ @param[in] SystemTable Pointer to standard EFI system table.
+
+ @retval EFI_SUCCESS Succeed.
+ @retval EFI_OUT_RESOURCES If the system has run out of memory
+**/
+EFI_STATUS
+EFIAPI
+SpiHcProtocolEntry (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_SPI_HC_PROTOCOL *HcProtocol;
+
+ DEBUG ((DEBUG_VERBOSE, "%a - ENTRY\n", __func__));
+
+ // Allocate the SPI Host Controller protocol
+ HcProtocol = AllocateZeroPool (sizeof (EFI_SPI_HC_PROTOCOL));
+ ASSERT (HcProtocol != NULL);
+ if (HcProtocol == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ // Fill in the SPI Host Controller Protocol
+ Status = GetPlatformSpiHcDetails (
+ &HcProtocol->Attributes,
+ &HcProtocol->FrameSizeSupportMask,
+ &HcProtocol->MaximumTransferBytes
+ );
+
+ HcProtocol->ChipSelect = ChipSelect;
+ HcProtocol->Clock = Clock;
+ HcProtocol->Transaction = Transaction;
+
+ Status = gMmst->MmInstallProtocolInterface (
+ &mSpiHcHandle,
+ &gEfiSpiSmmHcProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ HcProtocol
+ );
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_VERBOSE, "Error installing gEfiSpiSmmHcProtocolGuid\n"));
+ }
+
+ DEBUG ((DEBUG_VERBOSE, "%a - EXIT Status=%r\n", __func__, Status));
+
+ return Status;
+}
diff --git a/MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.inf b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.inf
new file mode 100644
index 0000000000..95d5466d90
--- /dev/null
+++ b/MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.inf
@@ -0,0 +1,45 @@
+## @file
+# The SPI Host Controller Module SMM driver INF file
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = SpiHcSmm
+ FILE_GUID = 0CDAE298-CB3B-480A-BDC4-A6840FFE1F5E
+ MODULE_TYPE = DXE_SMM_DRIVER
+ VERSION_STRING = 0.1
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ ENTRY_POINT = SpiHcProtocolEntry
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ MemoryAllocationLib
+ MmServicesTableLib
+ SpiHcPlatformLib
+ UefiDriverEntryPoint
+ UefiLib
+
+[Sources]
+ SpiHc.h
+ SpiHc.c
+ SpiHcSmm.c
+
+[Protocols]
+ gEfiSpiSmmHcProtocolGuid
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ SpiHc.uni
diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
index c450d1bf25..99364508cd 100644
--- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
+++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c
@@ -8,8 +8,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <Pi/PrePiDxeCis.h>
-#include <Pi/PrePiHob.h>
+#include <Pi/PiDxeCis.h>
+#include <Pi/PiHob.h>
#include "DxeMain.h"
#include "Gcd.h"
#include "Mem/HeapGuard.h"
@@ -92,6 +92,7 @@ GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = {
{ EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE },
{ EFI_RESOURCE_ATTRIBUTE_PERSISTABLE, EFI_MEMORY_NV, TRUE },
{ EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE, EFI_MEMORY_MORE_RELIABLE, TRUE },
+ { EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE, EFI_MEMORY_SP, TRUE },
{ 0, 0, FALSE }
};
@@ -105,7 +106,7 @@ GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mGcdMemoryTypeNames[] = {
"MMIO ", // EfiGcdMemoryTypeMemoryMappedIo
"PersisMem", // EfiGcdMemoryTypePersistent
"MoreRelia", // EfiGcdMemoryTypeMoreReliable
- "Unaccepte", // EFI_GCD_MEMORY_TYPE_UNACCEPTED
+ "Unaccepte", // EfiGcdMemoryTypeUnaccepted
"Unknown " // EfiGcdMemoryTypeMaximum
};
@@ -2669,8 +2670,8 @@ CoreInitializeGcdServices (
case EFI_RESOURCE_MEMORY_RESERVED:
GcdMemoryType = EfiGcdMemoryTypeReserved;
break;
- case BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED:
- GcdMemoryType = EFI_GCD_MEMORY_TYPE_UNACCEPTED;
+ case EFI_RESOURCE_MEMORY_UNACCEPTED:
+ GcdMemoryType = EfiGcdMemoryTypeUnaccepted;
break;
case EFI_RESOURCE_IO:
GcdIoType = EfiGcdIoTypeIo;
diff --git a/MdeModulePkg/Core/Dxe/Mem/Page.c b/MdeModulePkg/Core/Dxe/Mem/Page.c
index 26584648c2..5a51d9df1a 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Page.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Page.c
@@ -9,7 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "DxeMain.h"
#include "Imem.h"
#include "HeapGuard.h"
-#include <Pi/PrePiDxeCis.h>
+#include <Pi/PiDxeCis.h>
//
// Entry for tracking the memory regions for each memory type to coalesce similar memory types
@@ -70,23 +70,23 @@ EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = MAX_ALLOC_ADDRESS;
EFI_PHYSICAL_ADDRESS mDefaultBaseAddress = MAX_ALLOC_ADDRESS;
EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = {
- { EfiReservedMemoryType, 0 },
- { EfiLoaderCode, 0 },
- { EfiLoaderData, 0 },
- { EfiBootServicesCode, 0 },
- { EfiBootServicesData, 0 },
- { EfiRuntimeServicesCode, 0 },
- { EfiRuntimeServicesData, 0 },
- { EfiConventionalMemory, 0 },
- { EfiUnusableMemory, 0 },
- { EfiACPIReclaimMemory, 0 },
- { EfiACPIMemoryNVS, 0 },
- { EfiMemoryMappedIO, 0 },
- { EfiMemoryMappedIOPortSpace, 0 },
- { EfiPalCode, 0 },
- { EfiPersistentMemory, 0 },
- { EFI_GCD_MEMORY_TYPE_UNACCEPTED, 0 },
- { EfiMaxMemoryType, 0 }
+ { EfiReservedMemoryType, 0 },
+ { EfiLoaderCode, 0 },
+ { EfiLoaderData, 0 },
+ { EfiBootServicesCode, 0 },
+ { EfiBootServicesData, 0 },
+ { EfiRuntimeServicesCode, 0 },
+ { EfiRuntimeServicesData, 0 },
+ { EfiConventionalMemory, 0 },
+ { EfiUnusableMemory, 0 },
+ { EfiACPIReclaimMemory, 0 },
+ { EfiACPIMemoryNVS, 0 },
+ { EfiMemoryMappedIO, 0 },
+ { EfiMemoryMappedIOPortSpace, 0 },
+ { EfiPalCode, 0 },
+ { EfiPersistentMemory, 0 },
+ { EfiGcdMemoryTypeUnaccepted, 0 },
+ { EfiMaxMemoryType, 0 }
};
//
// Only used when load module at fixed address feature is enabled. True means the memory is alreay successfully allocated
@@ -2083,7 +2083,7 @@ CoreGetMemoryMap (
MemoryMap = MergeMemoryMapDescriptor (MemoryMapStart, MemoryMap, Size);
}
- if (MergeGcdMapEntry.GcdMemoryType == EFI_GCD_MEMORY_TYPE_UNACCEPTED) {
+ if (MergeGcdMapEntry.GcdMemoryType == EfiGcdMemoryTypeUnaccepted) {
//
// Page Align GCD range is required. When it is converted to EFI_MEMORY_DESCRIPTOR,
// it will be recorded as page PhysicalStart and NumberOfPages.
diff --git a/MdeModulePkg/Core/PiSmmCore/Smi.c b/MdeModulePkg/Core/PiSmmCore/Smi.c
index a84a1f48d3..6b56fa5f69 100644
--- a/MdeModulePkg/Core/PiSmmCore/Smi.c
+++ b/MdeModulePkg/Core/PiSmmCore/Smi.c
@@ -152,6 +152,7 @@ SmiManage (
PERF_FUNCTION_BEGIN ();
mSmiManageCallingDepth++;
+ WillReturn = FALSE;
Status = EFI_NOT_FOUND;
ReturnStatus = Status;
if (HandlerType == NULL) {
diff --git a/MdeModulePkg/Include/Library/SpiHcPlatformLib.h b/MdeModulePkg/Include/Library/SpiHcPlatformLib.h
new file mode 100644
index 0000000000..c68f745537
--- /dev/null
+++ b/MdeModulePkg/Include/Library/SpiHcPlatformLib.h
@@ -0,0 +1,148 @@
+/** @file
+
+ Function declarations for SpiHcPlatformLib
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef PLATFORM_SPI_HC_H_
+#define PLATFORM_SPI_HC_H_
+
+#include <Uefi/UefiBaseType.h>
+#include <Protocol/SpiHc.h>
+#include <Protocol/SpiConfiguration.h>
+#include <Protocol/DevicePath.h>
+#include <Library/DevicePathLib.h>
+
+/**
+ This function reports the details of the SPI Host Controller to the SpiHc driver.
+
+ @param[out] Attributes The suported attributes of the SPI host controller
+ @param[out] FrameSizeSupportMask The suported FrameSizeSupportMask of the SPI host controller
+ @param[out] MaximumTransferBytes The suported MaximumTransferBytes of the SPI host controller
+
+ @retval EFI_SUCCESS SPI_HOST_CONTROLLER_INSTANCE was allocated properly
+ @retval EFI_OUT_OF_RESOURCES The SPI_HOST_CONTROLLER_INSTANCE could not be allocated
+*/
+EFI_STATUS
+EFIAPI
+GetPlatformSpiHcDetails (
+ OUT UINT32 *Attributes,
+ OUT UINT32 *FrameSizeSupportMask,
+ OUT UINT32 *MaximumTransferBytes
+ );
+
+/**
+ This function reports the device path of SPI host controller. This is needed in order for the SpiBus
+ to match the correct SPI_BUS to the SPI host controller
+
+ @param[out] DevicePath The device path for this SPI HC is returned in this variable
+
+ @retval EFI_SUCCESS
+*/
+EFI_STATUS
+EFIAPI
+GetSpiHcDevicePath (
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+/**
+ This is the platform specific Spi Chip select function.
+ Assert or deassert the SPI chip select.
+
+ This routine is called at TPL_NOTIFY.
+ Update the value of the chip select line for a SPI peripheral. The SPI bus
+ layer calls this routine either in the board layer or in the SPI controller
+ to manipulate the chip select pin at the start and end of a SPI transaction.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data structure
+ describing the SPI peripheral whose chip select pin
+ is to be manipulated. The routine may access the
+ ChipSelectParameter field to gain sufficient
+ context to complete the operati on.
+ @param[in] PinValue The value to be applied to the chip select line of
+ the SPI peripheral.
+
+ @retval EFI_SUCCESS The chip select was set as requested
+ @retval EFI_NOT_READY Support for the chip select is not properly
+ initialized
+ @retval EFI_INVALID_PARAMETER The ChipSeLect value or its contents are
+ invalid
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSpiHcChipSelect (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN BOOLEAN PinValue
+ );
+
+/**
+ This function is the platform specific SPI clock function.
+ Set up the clock generator to produce the correct clock frequency, phase and
+ polarity for a SPI chip.
+
+ This routine is called at TPL_NOTIFY.
+ This routine updates the clock generator to generate the correct frequency
+ and polarity for the SPI clock.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure from
+ which the routine can access the ClockParameter,
+ ClockPhase and ClockPolarity fields. The routine
+ also has access to the names for the SPI bus and
+ chip which can be used during debugging.
+ @param[in] ClockHz Pointer to the requested clock frequency. The SPI
+ host controller will choose a supported clock
+ frequency which is less then or equal to this
+ value. Specify zero to turn the clock generator
+ off. The actual clock frequency supported by the
+ SPI host controller will be returned.
+
+ @retval EFI_SUCCESS The clock was set up successfully
+ @retval EFI_UNSUPPORTED The SPI controller was not able to support the
+ frequency requested by ClockHz
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSpiHcClock (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN UINT32 *ClockHz
+ );
+
+/**
+ This function is the platform specific SPI transaction function
+ Perform the SPI transaction on the SPI peripheral using the SPI host
+ controller.
+
+ This routine is called at TPL_NOTIFY.
+ This routine synchronously returns EFI_SUCCESS indicating that the
+ asynchronous SPI transaction was started. The routine then waits for
+ completion of the SPI transaction prior to returning the final transaction
+ status.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] BusTransaction Pointer to a EFI_SPI_BUS_ TRANSACTION containing
+ the description of the SPI transaction to perform.
+
+ @retval EFI_SUCCESS The transaction completed successfully
+ @retval EFI_BAD_BUFFER_SIZE The BusTransaction->WriteBytes value is invalid,
+ or the BusTransaction->ReadinBytes value is
+ invalid
+ @retval EFI_UNSUPPORTED The BusTransaction-> Transaction Type is
+ unsupported
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSpiHcTransaction (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN EFI_SPI_BUS_TRANSACTION *BusTransaction
+ );
+
+#endif // PLATFORM_SPI_HC_SMM_PROTOCOL_H_
diff --git a/MdeModulePkg/Include/Pi/PrePiDxeCis.h b/MdeModulePkg/Include/Pi/PrePiDxeCis.h
deleted file mode 100644
index 9be71d2618..0000000000
--- a/MdeModulePkg/Include/Pi/PrePiDxeCis.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/** @file
- Include file matches things in PI.
-
-Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef MDE_MODULEPKG_PRE_PI_DXE_CIS_H_
-#define MDE_MODULEPKG_PRE_PI_DXE_CIS_H_
-
-///
-/// A memory region that describes system memory that has not been accepted
-/// by a corresponding call to the underlying isolation architecture.
-///
-/// This memory region has not been defined in PI spec, so it is defined in
-/// PrePiDxeCis.h. And it is defined in the format of captial letters
-/// because only capital letters are allowed to be used for #define declarations.
-///
-/// After this memory region is defined in PI spec, it should be a value in
-/// EFI_GCD_MEMORY_TYPE in PiDxeCis.h.
-///
-#define EFI_GCD_MEMORY_TYPE_UNACCEPTED 6
-
-#endif
diff --git a/MdeModulePkg/Include/Pi/PrePiHob.h b/MdeModulePkg/Include/Pi/PrePiHob.h
deleted file mode 100644
index ac575e5972..0000000000
--- a/MdeModulePkg/Include/Pi/PrePiHob.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/** @file
- HOB related definitions which has not been officially published in PI.
-
-Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef MDE_MODULEPKG_PRE_PI_HOB_H_
-#define MDE_MODULEPKG_PRE_PI_HOB_H_
-
-//
-// BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED is defined for unaccepted memory.
-// But this defitinion has not been officially in the PI spec. Base
-// on the code-first we define BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED at
-// MdeModulePkg/Include/Pi/PrePiHob.h.
-//
-#define BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED 0x00000007
-
-#endif
diff --git a/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.c b/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.c
new file mode 100644
index 0000000000..2926e9e248
--- /dev/null
+++ b/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.c
@@ -0,0 +1,145 @@
+/** @file
+
+ Null implementation of SpiHcPlatformLib
+
+ Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include <PiDxe.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/SpiHc.h>
+#include <Library/SpiHcPlatformLib.h>
+
+/**
+ This function reports the details of the SPI Host Controller to the SpiHc driver.
+
+ @param[out] Attributes The suported attributes of the SPI host controller
+ @param[out] FrameSizeSupportMask The suported FrameSizeSupportMask of the SPI host controller
+ @param[out] MaximumTransferBytes The suported MaximumTransferBytes of the SPI host controller
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+GetPlatformSpiHcDetails (
+ OUT UINT32 *Attributes,
+ OUT UINT32 *FrameSizeSupportMask,
+ OUT UINT32 *MaximumTransferBytes
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function reports the device path of SPI host controller. This is needed in order for the SpiBus
+ to match the correct SPI_BUS to the SPI host controller
+
+ @param[out] DevicePath The device path for this SPI HC is returned in this variable
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+GetSpiHcDevicePath (
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This is the platform specific Spi Chip select function.
+ Assert or deassert the SPI chip select.
+
+ This routine is called at TPL_NOTIFY.
+ Update the value of the chip select line for a SPI peripheral. The SPI bus
+ layer calls this routine either in the board layer or in the SPI controller
+ to manipulate the chip select pin at the start and end of a SPI transaction.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral The address of an EFI_SPI_PERIPHERAL data structure
+ describing the SPI peripheral whose chip select pin
+ is to be manipulated. The routine may access the
+ ChipSelectParameter field to gain sufficient
+ context to complete the operati on.
+ @param[in] PinValue The value to be applied to the chip select line of
+ the SPI peripheral.
+
+ @retval EFI_UNSUPPORTED
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSpiHcChipSelect (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN BOOLEAN PinValue
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is the platform specific SPI clock function.
+ Set up the clock generator to produce the correct clock frequency, phase and
+ polarity for a SPI chip.
+
+ This routine is called at TPL_NOTIFY.
+ This routine updates the clock generator to generate the correct frequency
+ and polarity for the SPI clock.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] SpiPeripheral Pointer to a EFI_SPI_PERIPHERAL data structure from
+ which the routine can access the ClockParameter,
+ ClockPhase and ClockPolarity fields. The routine
+ also has access to the names for the SPI bus and
+ chip which can be used during debugging.
+ @param[in] ClockHz Pointer to the requested clock frequency. The SPI
+ host controller will choose a supported clock
+ frequency which is less then or equal to this
+ value. Specify zero to turn the clock generator
+ off. The actual clock frequency supported by the
+ SPI host controller will be returned.
+
+ @retval EFI_UNSUPPORTED
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSpiHcClock (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN CONST EFI_SPI_PERIPHERAL *SpiPeripheral,
+ IN UINT32 *ClockHz
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ This function is the platform specific SPI transaction function
+ Perform the SPI transaction on the SPI peripheral using the SPI host
+ controller.
+
+ This routine is called at TPL_NOTIFY.
+ This routine synchronously returns EFI_SUCCESS indicating that the
+ asynchronous SPI transaction was started. The routine then waits for
+ completion of the SPI transaction prior to returning the final transaction
+ status.
+
+ @param[in] This Pointer to an EFI_SPI_HC_PROTOCOL structure.
+ @param[in] BusTransaction Pointer to a EFI_SPI_BUS_ TRANSACTION containing
+ the description of the SPI transaction to perform.
+
+ @retval EFI_UNSUPPORTED
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformSpiHcTransaction (
+ IN CONST EFI_SPI_HC_PROTOCOL *This,
+ IN EFI_SPI_BUS_TRANSACTION *BusTransaction
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.inf b/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.inf
new file mode 100644
index 0000000000..805f50b895
--- /dev/null
+++ b/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.inf
@@ -0,0 +1,33 @@
+## @file
+# NULL library for platform SPI Host controller, which should be provided
+# by the OEM.
+#
+# Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = BaseSpiHcPlatformLibNull
+ FILE_GUID = 3C230948-6DF5-4802-8177-967A190579CF
+ MODULE_TYPE = BASE
+ VERSION_STRING = 0.1
+ PI_SPECIFICATION_VERSION = 0x0001000A
+ LIBRARY_CLASS = SpiHcPlatformLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ UefiLib
+
+[Sources]
+ BaseSpiHcPlatformLibNull.c
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ BaseSpiHcPlatformLibNull.uni
diff --git a/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.uni b/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.uni
new file mode 100644
index 0000000000..82fa02c31d
--- /dev/null
+++ b/MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.uni
@@ -0,0 +1,11 @@
+
+// /** @file
+//
+// Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US "Null SPI Host controller library"
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 085370eae4..f7339f0aec 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -169,6 +169,11 @@
#
ImagePropertiesRecordLib|Include/Library/ImagePropertiesRecordLib.h
+ ## @libraryclass Platform SPI Host Controller library which provides low-level
+ # control over the SPI hardware
+ #
+ SpiHcPlatformLib|Include/Library/SpiHcPlatformLib.h
+
[Guids]
## MdeModule package token space guid
# Include/Guid/MdeModulePkgTokenSpace.h
@@ -1154,6 +1159,11 @@
# @Prompt Enable large address image loading.
gEfiMdeModulePkgTokenSpaceGuid.PcdImageLargeAddressLoad|TRUE|BOOLEAN|0x30001059
+ ## Indicates time delay for XHCI registers access after it issues HCRST.
+ # Default is 2000, it represent delay is 2 ms.
+ # @Prompt Delay access XHCI register after it issues HCRST (us)
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDelayXhciHCReset|2000|UINT16|0x30001060
+
[PcdsFixedAtBuild, PcdsPatchableInModule]
## Dynamic type PCD can be registered callback function for Pcd setting action.
# PcdMaxPeiPcdCallBackNumberPerPcdEntry indicates the maximum number of callback function
diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
index 6bed9205ea..a1c8e2f905 100644
--- a/MdeModulePkg/MdeModulePkg.dsc
+++ b/MdeModulePkg/MdeModulePkg.dsc
@@ -107,6 +107,7 @@
MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
IpmiCommandLib|MdeModulePkg/Library/BaseIpmiCommandLibNull/BaseIpmiCommandLibNull.inf
+ SpiHcPlatformLib|MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.inf
[LibraryClasses.EBC.PEIM]
IoLib|MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.inf
@@ -287,6 +288,10 @@
MdeModulePkg/Bus/Pci/NonDiscoverablePciDeviceDxe/NonDiscoverablePciDeviceDxe.inf
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlashJedecSfdpDxe.inf
MdeModulePkg/Bus/Spi/SpiNorFlashJedecSfdp/SpiNorFlashJedecSfdpSmm.inf
+ MdeModulePkg/Bus/Spi/SpiBus/SpiBusDxe.inf
+ MdeModulePkg/Bus/Spi/SpiBus/SpiBusSmm.inf
+ MdeModulePkg/Bus/Spi/SpiHc/SpiHcDxe.inf
+ MdeModulePkg/Bus/Spi/SpiHc/SpiHcSmm.inf
MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
MdeModulePkg/Core/Pei/PeiMain.inf
@@ -526,6 +531,7 @@
MdeModulePkg/Library/TraceHubDebugSysTLib/BaseTraceHubDebugSysTLib.inf
MdeModulePkg/Library/TraceHubDebugSysTLib/PeiTraceHubDebugSysTLib.inf
MdeModulePkg/Library/TraceHubDebugSysTLib/DxeSmmTraceHubDebugSysTLib.inf
+ MdeModulePkg/Library/BaseSpiHcPlatformLibNull/BaseSpiHcPlatformLibNull.inf
[Components.X64]
MdeModulePkg/Universal/CapsulePei/CapsuleX64.inf
diff --git a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
index 2f2b2a80b2..2ba9215226 100644
--- a/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
+++ b/MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c
@@ -112,11 +112,15 @@ FpdtStatusCodeListenerPei (
//
S3ResumeTotal = MultU64x32 (AcpiS3ResumeRecord->AverageResume, AcpiS3ResumeRecord->ResumeCount);
AcpiS3ResumeRecord->ResumeCount++;
- AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
+ if (AcpiS3ResumeRecord->ResumeCount > 0) {
+ AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);
+ DEBUG ((DEBUG_INFO, "\nFPDT: S3 Resume Performance - AverageResume = 0x%x\n", AcpiS3ResumeRecord->AverageResume));
+ } else {
+ DEBUG ((DEBUG_ERROR, "\nFPDT: S3 ResumeCount reaches the MAX_UINT32 value. S3 ResumeCount record reset to Zero."));
+ }
- DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - ResumeCount = %d\n", AcpiS3ResumeRecord->ResumeCount));
- DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - FullResume = %ld\n", AcpiS3ResumeRecord->FullResume));
- DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - AverageResume = %ld\n", AcpiS3ResumeRecord->AverageResume));
+ DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - ResumeCount = 0x%x\n", AcpiS3ResumeRecord->ResumeCount));
+ DEBUG ((DEBUG_INFO, "FPDT: S3 Resume Performance - FullResume = 0x%x\n", AcpiS3ResumeRecord->FullResume));
//
// Update S3 Suspend Performance Record.
diff --git a/MdePkg/Include/IndustryStandard/IpmiNetFnOem.h b/MdePkg/Include/IndustryStandard/IpmiNetFnOem.h
new file mode 100644
index 0000000000..48c5dbd803
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/IpmiNetFnOem.h
@@ -0,0 +1,18 @@
+/** @file
+ IPMI 2.0 definitions from the IPMI Specification Version 2.0, Revision 1.1.
+
+ Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef IPMI_NET_FN_OEM_H_
+#define IPMI_NET_FN_OEM_H_
+
+//
+// Net function definition for OEM/Group command
+//
+#define IPMI_NETFN_OEM 0x2E
+#define IPMI_NETFN_OEM_GROUP 0x2F
+
+#endif
diff --git a/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h b/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h
index eb5ae28390..bf967880ab 100644
--- a/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h
+++ b/MdePkg/Include/IndustryStandard/SerialPortConsoleRedirectionTable.h
@@ -23,6 +23,7 @@
///
#define EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION 0x02
+#define EFI_ACPI_4_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_REVISION 0x04
///
/// Serial Port Console Redirection Table Format
///
@@ -50,6 +51,37 @@ typedef struct {
UINT32 Reserved3;
} EFI_ACPI_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE;
+///
+/// Serial Port Console Redirection Table Format Revision 4
+///
+typedef struct {
+ EFI_ACPI_DESCRIPTION_HEADER Header;
+ UINT8 InterfaceType;
+ UINT8 Reserved1[3];
+ EFI_ACPI_5_0_GENERIC_ADDRESS_STRUCTURE BaseAddress;
+ UINT8 InterruptType;
+ UINT8 Irq;
+ UINT32 GlobalSystemInterrupt;
+ UINT8 BaudRate;
+ UINT8 Parity;
+ UINT8 StopBits;
+ UINT8 FlowControl;
+ UINT8 TerminalType;
+ UINT8 Reserved2;
+ UINT16 PciDeviceId;
+ UINT16 PciVendorId;
+ UINT8 PciBusNumber;
+ UINT8 PciDeviceNumber;
+ UINT8 PciFunctionNumber;
+ UINT32 PciFlags;
+ UINT8 PciSegment;
+ UINT32 UartClockFrequency;
+ UINT32 PreciseBaudRate;
+ UINT16 NameSpaceStrLength;
+ UINT16 NameSpaceStrOffset;
+ CHAR8 NameSpaceString[0];
+} EFI_ACPI_4_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE;
+
#pragma pack()
//
diff --git a/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h b/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h
index 61bd4e4667..aaee5d6c88 100644
--- a/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h
+++ b/MdePkg/Include/IndustryStandard/UefiTcgPlatform.h
@@ -451,6 +451,7 @@ typedef struct tdTCG_PCClientTaggedEvent {
#define TCG_Sp800_155_PlatformId_Event_SIGNATURE "SP800-155 Event"
#define TCG_Sp800_155_PlatformId_Event2_SIGNATURE "SP800-155 Event2"
+#define TCG_Sp800_155_PlatformId_Event3_SIGNATURE "SP800-155 Event3"
typedef struct tdTCG_Sp800_155_PlatformId_Event2 {
UINT8 Signature[16];
@@ -478,9 +479,44 @@ typedef struct tdTCG_Sp800_155_PlatformId_Event2 {
// UINT8 FirmwareManufacturerStr[FirmwareManufacturerStrSize];
// UINT32 FirmwareManufacturerId;
// UINT8 FirmwareVersion;
- // UINT8 FirmwareVersion[FirmwareVersionSize]];
+ // UINT8 FirmwareVersion[FirmwareVersionSize];
} TCG_Sp800_155_PlatformId_Event2;
+typedef struct tdTCG_Sp800_155_PlatformId_Event3 {
+ UINT8 Signature[16];
+ //
+ // Where Vendor ID is an integer defined
+ // at http://www.iana.org/assignments/enterprisenumbers
+ //
+ UINT32 VendorId;
+ //
+ // 16-byte identifier of a given platform's static configuration of code
+ //
+ EFI_GUID ReferenceManifestGuid;
+ // UINT8 PlatformManufacturerStrSize;
+ // UINT8 PlatformManufacturerStr[PlatformManufacturerStrSize];
+ // UINT8 PlatformModelSize;
+ // UINT8 PlatformModel[PlatformModelSize];
+ // UINT8 PlatformVersionSize;
+ // UINT8 PlatformVersion[PlatformVersionSize];
+ // UINT8 PlatformModelSize;
+ // UINT8 PlatformModel[PlatformModelSize];
+ // UINT8 FirmwareManufacturerStrSize;
+ // UINT8 FirmwareManufacturerStr[FirmwareManufacturerStrSize];
+ // UINT32 FirmwareManufacturerId;
+ // UINT8 FirmwareVersion;
+ // UINT8 FirmwareVersion[FirmwareVersionSize];
+ //
+ // Below structure is newly added in TCG_Sp800_155_PlatformId_Event3
+ //
+ // UINT32 RimLocatorType;
+ // UINT32 RimLocatorLength;
+ // UINT8 RimLocator[RimLocatorLength];
+ // UINT32 PlatformCertLocatorType;
+ // UINT32 PlatformCertLocatorLength;
+ // UINT8 PlatformCertLocator[PlatformCertLocatorLength];
+} TCG_Sp800_155_PlatformId_Event3;
+
#define TCG_EfiStartupLocalityEvent_SIGNATURE "StartupLocality"
//
diff --git a/MdePkg/Include/Pi/PiDxeCis.h b/MdePkg/Include/Pi/PiDxeCis.h
index bb7fb2c38a..04410c5a1a 100644
--- a/MdePkg/Include/Pi/PiDxeCis.h
+++ b/MdePkg/Include/Pi/PiDxeCis.h
@@ -56,14 +56,11 @@ typedef enum {
/// system. If all memory has the same reliability, then this bit is not used.
///
EfiGcdMemoryTypeMoreReliable,
- // ///
- // /// A memory region that describes system memory that has not been accepted
- // /// by a corresponding call to the underlying isolation architecture.
- // ///
- // /// Please be noted:
- // /// EfiGcdMemoryTypeUnaccepted is defined in PrePiDxeCis.h because it has not been
- // /// defined in PI spec.
- // EfiGcdMemoryTypeUnaccepted,
+ ///
+ /// A memory region that describes system memory that has not been accepted
+ /// by a corresponding call to the underlying isolation architecture.
+ ///
+ EfiGcdMemoryTypeUnaccepted,
EfiGcdMemoryTypeMaximum = 7
} EFI_GCD_MEMORY_TYPE;
diff --git a/MdePkg/Include/Pi/PiHob.h b/MdePkg/Include/Pi/PiHob.h
index 4605da56e2..9e49421afa 100644
--- a/MdePkg/Include/Pi/PiHob.h
+++ b/MdePkg/Include/Pi/PiHob.h
@@ -232,16 +232,8 @@ typedef UINT32 EFI_RESOURCE_TYPE;
#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 0x00000004
#define EFI_RESOURCE_MEMORY_RESERVED 0x00000005
#define EFI_RESOURCE_IO_RESERVED 0x00000006
-//
-// BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED is defined for unaccepted memory.
-// But this defitinion has not been officially in the PI spec. Base
-// on the code-first we define BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED at
-// MdeModulePkg/Include/Pi/PrePiHob.h and update EFI_RESOURCE_MAX_MEMORY_TYPE
-// to 8. After BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED is officially published
-// in PI spec, we will re-visit here.
-//
-// #define BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED 0x00000007
-#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000008
+#define EFI_RESOURCE_MEMORY_UNACCEPTED 0x00000007
+#define EFI_RESOURCE_MAX_MEMORY_TYPE 0x00000008
///
/// A type of recount attribute type.
@@ -297,6 +289,8 @@ typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE;
#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED 0x00040000
#define EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE 0x00080000
+#define EFI_RESOURCE_ATTRIBUTE_ENCRYPTED 0x04000000
+#define EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE 0x08000000
//
// Physical memory relative reliability attribute. This
// memory provides higher reliability relative to other
diff --git a/MdePkg/Include/Ppi/DelayedDispatch.h b/MdePkg/Include/Ppi/DelayedDispatch.h
index f9b4fed30f..1c2068404c 100644
--- a/MdePkg/Include/Ppi/DelayedDispatch.h
+++ b/MdePkg/Include/Ppi/DelayedDispatch.h
@@ -49,6 +49,7 @@ This service is the single member function of the EFI_DELAYED_DISPATCH_PPI
@param This Pointer to the EFI_DELAYED_DISPATCH_PPI instance
@param Function Function to call back
@param Context Context data
+ @param UniqueId UniqueId
@param Delay Delay interval
@retval EFI_SUCCESS Function successfully loaded
@@ -62,9 +63,29 @@ EFI_STATUS
IN EFI_DELAYED_DISPATCH_PPI *This,
IN EFI_DELAYED_DISPATCH_FUNCTION Function,
IN UINT64 Context,
+ IN EFI_GUID *UniqueId OPTIONAL,
OUT UINT32 Delay
);
+/**
+Function invoked by a PEIM to wait until all specified UniqueId events have been dispatched. The other events
+will continue to dispatch while this process is being paused
+
+ @param This Pointer to the EFI_DELAYED_DISPATCH_PPI instance
+ @param UniqueId Delayed dispatch request ID the caller will wait on
+
+ @retval EFI_SUCCESS Function successfully invoked
+ @retval EFI_INVALID_PARAMETER One of the Arguments is not supported
+
+**/
+
+typedef
+EFI_STATUS
+(EFIAPI *EFI_DELAYED_DISPATCH_WAIT_ON_EVENT)(
+ IN EFI_DELAYED_DISPATCH_PPI *This,
+ IN EFI_GUID UniqueId
+ );
+
///
/// This PPI is a pointer to the Delayed Dispatch Service.
/// This service will be published by the Pei Foundation. The PEI Foundation
@@ -72,7 +93,8 @@ EFI_STATUS
/// execution.
///
struct _EFI_DELAYED_DISPATCH_PPI {
- EFI_DELAYED_DISPATCH_REGISTER Register;
+ EFI_DELAYED_DISPATCH_REGISTER Register;
+ EFI_DELAYED_DISPATCH_WAIT_ON_EVENT WaitOnEvent;
};
extern EFI_GUID gEfiPeiDelayedDispatchPpiGuid;
diff --git a/MdePkg/Include/Protocol/DevicePath.h b/MdePkg/Include/Protocol/DevicePath.h
index 9060dd782e..35008ddcdf 100644
--- a/MdePkg/Include/Protocol/DevicePath.h
+++ b/MdePkg/Include/Protocol/DevicePath.h
@@ -838,6 +838,26 @@ typedef struct {
} NVME_NAMESPACE_DEVICE_PATH;
///
+/// NVMe over Fabric (NVMe-oF) Namespace Device Path SubType.
+///
+#define MSG_NVME_OF_NAMESPACE_DP 0x22
+typedef struct {
+ EFI_DEVICE_PATH_PROTOCOL Header;
+ ///
+ /// Namespace Identifier Type (NIDT)
+ ///
+ UINT8 NamespaceIdType;
+ ///
+ /// Namespace Identifier (NID)
+ ///
+ UINT8 NamespaceId[16];
+ ///
+ /// Unique identifier of an NVM subsystem
+ ///
+ CHAR8 SubsystemNqn[];
+} NVME_OF_NAMESPACE_DEVICE_PATH;
+
+///
/// DNS Device Path SubType
///
#define MSG_DNS_DP 0x1F
@@ -1287,6 +1307,7 @@ typedef union {
SAS_DEVICE_PATH Sas;
SASEX_DEVICE_PATH SasEx;
NVME_NAMESPACE_DEVICE_PATH NvmeNamespace;
+ NVME_OF_NAMESPACE_DEVICE_PATH NvmeOfNamespace;
DNS_DEVICE_PATH Dns;
URI_DEVICE_PATH Uri;
BLUETOOTH_DEVICE_PATH Bluetooth;
@@ -1343,6 +1364,7 @@ typedef union {
SAS_DEVICE_PATH *Sas;
SASEX_DEVICE_PATH *SasEx;
NVME_NAMESPACE_DEVICE_PATH *NvmeNamespace;
+ NVME_OF_NAMESPACE_DEVICE_PATH *NvmeOfNamespace;
DNS_DEVICE_PATH *Dns;
URI_DEVICE_PATH *Uri;
BLUETOOTH_DEVICE_PATH *Bluetooth;
diff --git a/MdePkg/Include/Protocol/SpiConfiguration.h b/MdePkg/Include/Protocol/SpiConfiguration.h
index 120b54bbad..cd7c1dd71e 100644
--- a/MdePkg/Include/Protocol/SpiConfiguration.h
+++ b/MdePkg/Include/Protocol/SpiConfiguration.h
@@ -173,8 +173,8 @@ typedef struct _EFI_SPI_BUS {
/// Definitions of SPI Part Attributes.
///
#define SPI_PART_SUPPORTS_2_BIT_DATA_BUS_WIDTH BIT0
-#define SPI_PART_SUPPORTS_4_B1T_DATA_BUS_WIDTH BIT1
-#define SPI_PART_SUPPORTS_8_B1T_DATA_BUS_WIDTH BIT2
+#define SPI_PART_SUPPORTS_4_BIT_DATA_BUS_WIDTH BIT1
+#define SPI_PART_SUPPORTS_8_BIT_DATA_BUS_WIDTH BIT2
///
/// The EFI_SPI_PERIPHERAL data structure describes how a specific block of
diff --git a/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S b/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S
index 3e58119b25..505d3765c5 100644
--- a/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S
+++ b/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.S
@@ -9,6 +9,7 @@
GCC_ASM_EXPORT(SetJump)
GCC_ASM_EXPORT(InternalLongJump)
+GCC_ASM_IMPORT(InternalAssertJumpBuffer)
#define GPR_LAYOUT \
REG_PAIR (x19, x20, 0); \
diff --git a/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm b/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm
index 6ec8f35f2c..fa161e25f5 100644
--- a/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm
+++ b/MdePkg/Library/BaseLib/AArch64/SetJumpLongJump.asm
@@ -7,6 +7,7 @@
EXPORT SetJump
EXPORT InternalLongJump
+ EXTERN InternalAssertJumpBuffer
AREA BaseLib_LowLevel, CODE, READONLY
#define GPR_LAYOUT \
diff --git a/MdePkg/Library/BaseRngLib/AArch64/Rndr.c b/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
index d39db62153..3a556a2e3f 100644
--- a/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
+++ b/MdePkg/Library/BaseRngLib/AArch64/Rndr.c
@@ -50,7 +50,6 @@ BaseRngLibConstructor (
// 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);
diff --git a/MdePkg/MdeLibs.dsc.inc b/MdePkg/MdeLibs.dsc.inc
index d782dbf4ff..ddd27115f5 100644
--- a/MdePkg/MdeLibs.dsc.inc
+++ b/MdePkg/MdeLibs.dsc.inc
@@ -5,7 +5,7 @@
# by using "!include MdePkg/MdeLibs.dsc.inc" to specify the library instances
# of some EDKII basic/common library classes.
#
-# Copyright (c) 2021 - 2022, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2021 - 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -18,3 +18,4 @@
SmmCpuRendezvousLib|MdePkg/Library/SmmCpuRendezvousLibNull/SmmCpuRendezvousLibNull.inf
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+ MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf
diff --git a/MdePkg/Test/MdePkgHostTest.dsc b/MdePkg/Test/MdePkgHostTest.dsc
index e666636b7c..6a85d02236 100644
--- a/MdePkg/Test/MdePkgHostTest.dsc
+++ b/MdePkg/Test/MdePkgHostTest.dsc
@@ -43,6 +43,7 @@
MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf
MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
+ MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf
MdePkg/Test/Mock/Library/GoogleTest/MockPeiServicesLib/MockPeiServicesLib.inf
MdePkg/Test/Mock/Library/GoogleTest/MockHobLib/MockHobLib.inf
MdePkg/Test/Mock/Library/GoogleTest/MockFdtLib/MockFdtLib.inf
diff --git a/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiBootServicesTableLib.h b/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiBootServicesTableLib.h
new file mode 100644
index 0000000000..d72b941323
--- /dev/null
+++ b/MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiBootServicesTableLib.h
@@ -0,0 +1,78 @@
+/** @file
+ Google Test mocks for UefiBootServicesTableLib
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MOCK_UEFI_BOOT_SERVICES_TABLE_LIB_H_
+#define MOCK_UEFI_BOOT_SERVICES_TABLE_LIB_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/FunctionMockLib.h>
+extern "C" {
+ #include <Uefi.h>
+ #include <Library/UefiBootServicesTableLib.h>
+}
+
+//
+// Declarations to handle usage of the UefiBootServiceTableLib by creating mock
+//
+struct MockUefiBootServicesTableLib {
+ MOCK_INTERFACE_DECLARATION (MockUefiBootServicesTableLib);
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ gBS_GetMemoryMap,
+ (IN OUT UINTN *MemoryMapSize,
+ OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
+ OUT UINTN *MapKey,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *DescriptorVersion)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ gBS_CreateEvent,
+ (IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction,
+ IN VOID *NotifyContext,
+ OUT EFI_EVENT *Event)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ gBS_CloseEvent,
+ (IN EFI_EVENT Event)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ gBS_HandleProtocol,
+ (IN EFI_HANDLE Handle,
+ IN EFI_GUID *Protocol,
+ OUT VOID **Interface)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ gBS_LocateProtocol,
+ (IN EFI_GUID *Protocol,
+ IN VOID *Registration OPTIONAL,
+ OUT VOID **Interface)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ gBS_CreateEventEx,
+ (IN UINT32 Type,
+ IN EFI_TPL NotifyTpl,
+ IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL,
+ IN CONST VOID *NotifyContext OPTIONAL,
+ IN CONST EFI_GUID *EventGroup OPTIONAL,
+ OUT EFI_EVENT *Event)
+ );
+};
+
+#endif // MOCK_UEFI_BOOT_SERVICES_TABLE_LIB_H_
diff --git a/MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockHash2.h b/MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockHash2.h
new file mode 100644
index 0000000000..b44d341332
--- /dev/null
+++ b/MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockHash2.h
@@ -0,0 +1,67 @@
+/** @file
+ This file declares a mock of Hash2 Protocol.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MOCK_HASH2_H_
+#define MOCK_HASH2_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/FunctionMockLib.h>
+
+extern "C" {
+ #include <Uefi.h>
+ #include <Protocol/Hash2.h>
+}
+
+struct MockHash2 {
+ MOCK_INTERFACE_DECLARATION (MockHash2);
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ GetHashSize,
+ (IN CONST EFI_HASH2_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm,
+ OUT UINTN *HashSize)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ Hash,
+ (IN CONST EFI_HASH2_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm,
+ IN CONST UINT8 *Message,
+ IN UINTN MessageSize,
+ IN OUT EFI_HASH2_OUTPUT *Hash)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ HashInit,
+ (IN CONST EFI_HASH2_PROTOCOL *This,
+ IN CONST EFI_GUID *HashAlgorithm)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ HashUpdate,
+ (IN CONST EFI_HASH2_PROTOCOL *This,
+ IN CONST UINT8 *Message,
+ IN UINTN MessageSize)
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ HashFinal,
+ (IN CONST EFI_HASH2_PROTOCOL *This,
+ IN OUT EFI_HASH2_OUTPUT *Hash)
+ );
+};
+
+extern "C" {
+ extern EFI_HASH2_PROTOCOL *gHash2Protocol;
+}
+
+#endif // MOCK_HASH2_H_
diff --git a/MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockRng.h b/MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockRng.h
new file mode 100644
index 0000000000..b54f8a234b
--- /dev/null
+++ b/MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockRng.h
@@ -0,0 +1,48 @@
+/** @file
+ This file declares a mock of Rng Protocol.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef MOCK_RNG_H_
+#define MOCK_RNG_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/FunctionMockLib.h>
+
+extern "C" {
+ #include <Uefi.h>
+ #include <Protocol/Rng.h>
+}
+
+struct MockRng {
+ MOCK_INTERFACE_DECLARATION (MockRng);
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ GetInfo,
+ (
+ IN EFI_RNG_PROTOCOL *This,
+ IN OUT UINTN *RNGAlgorithmListSize,
+ OUT EFI_RNG_ALGORITHM *RNGAlgorithmList
+ )
+ );
+
+ MOCK_FUNCTION_DECLARATION (
+ EFI_STATUS,
+ GetRng,
+ (
+ IN EFI_RNG_PROTOCOL *This,
+ IN EFI_RNG_ALGORITHM *RNGAlgorithm,
+ IN UINTN RNGValueLength,
+ OUT UINT8 *RNGValue
+ )
+ );
+};
+
+extern "C" {
+ extern EFI_RNG_PROTOCOL *gRngProtocol;
+}
+
+#endif // MOCK_RNG_H_
diff --git a/MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.cpp b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.cpp
new file mode 100644
index 0000000000..ced6255418
--- /dev/null
+++ b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.cpp
@@ -0,0 +1,69 @@
+/** @file
+ Google Test mocks for UefiBootServicesTableLib
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+#include <GoogleTest/Library/MockUefiBootServicesTableLib.h>
+
+MOCK_INTERFACE_DEFINITION (MockUefiBootServicesTableLib);
+MOCK_FUNCTION_DEFINITION (MockUefiBootServicesTableLib, gBS_GetMemoryMap, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockUefiBootServicesTableLib, gBS_CreateEvent, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockUefiBootServicesTableLib, gBS_CloseEvent, 1, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockUefiBootServicesTableLib, gBS_HandleProtocol, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockUefiBootServicesTableLib, gBS_LocateProtocol, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockUefiBootServicesTableLib, gBS_CreateEventEx, 6, EFIAPI);
+
+static EFI_BOOT_SERVICES LocalBs = {
+ { 0, 0, 0, 0, 0 }, // EFI_TABLE_HEADER
+ NULL, // EFI_RAISE_TPL
+ NULL, // EFI_RESTORE_TPL
+ NULL, // EFI_ALLOCATE_PAGES
+ NULL, // EFI_FREE_PAGES
+ gBS_GetMemoryMap, // EFI_GET_MEMORY_MAP
+ NULL, // EFI_ALLOCATE_POOL
+ NULL, // EFI_FREE_POOL
+ gBS_CreateEvent, // EFI_CREATE_EVENT
+ NULL, // EFI_SET_TIMER
+ NULL, // EFI_WAIT_FOR_EVENT
+ NULL, // EFI_SIGNAL_EVENT
+ gBS_CloseEvent, // EFI_CLOSE_EVENT
+ NULL, // EFI_CHECK_EVENT
+ NULL, // EFI_INSTALL_PROTOCOL_INTERFACE
+ NULL, // EFI_REINSTALL_PROTOCOL_INTERFACE
+ NULL, // EFI_UNINSTALL_PROTOCOL_INTERFACE
+ gBS_HandleProtocol, // EFI_HANDLE_PROTOCOL
+ NULL, // VOID
+ NULL, // EFI_REGISTER_PROTOCOL_NOTIFY
+ NULL, // EFI_LOCATE_HANDLE
+ NULL, // EFI_LOCATE_DEVICE_PATH
+ NULL, // EFI_INSTALL_CONFIGURATION_TABLE
+ NULL, // EFI_IMAGE_LOAD
+ NULL, // EFI_IMAGE_START
+ NULL, // EFI_EXIT
+ NULL, // EFI_IMAGE_UNLOAD
+ NULL, // EFI_EXIT_BOOT_SERVICES
+ NULL, // EFI_GET_NEXT_MONOTONIC_COUNT
+ NULL, // EFI_STALL
+ NULL, // EFI_SET_WATCHDOG_TIMER
+ NULL, // EFI_CONNECT_CONTROLLER
+ NULL, // EFI_DISCONNECT_CONTROLLER
+ NULL, // EFI_OPEN_PROTOCOL
+ NULL, // EFI_CLOSE_PROTOCOL
+ NULL, // EFI_OPEN_PROTOCOL_INFORMATION
+ NULL, // EFI_PROTOCOLS_PER_HANDLE
+ NULL, // EFI_LOCATE_HANDLE_BUFFER
+ gBS_LocateProtocol, // EFI_LOCATE_PROTOCOL
+ NULL, // EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES
+ NULL, // EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES
+ NULL, // EFI_CALCULATE_CRC32
+ NULL, // EFI_COPY_MEM
+ NULL, // EFI_SET_MEM
+ gBS_CreateEventEx // EFI_CREATE_EVENT_EX
+};
+
+extern "C" {
+ EFI_BOOT_SERVICES *gBS = &LocalBs;
+ EFI_HANDLE gImageHandle = NULL;
+ EFI_SYSTEM_TABLE *gST = NULL;
+}
diff --git a/MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf
new file mode 100644
index 0000000000..8b64fd195a
--- /dev/null
+++ b/MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf
@@ -0,0 +1,32 @@
+## @file
+# Mock implementation of the UEFI Boot Services Table Library.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = MockUefiBootServicesTableLib
+ FILE_GUID = 67EA4614-E276-49EC-9AE6-B97ACCEA676E
+ MODULE_TYPE = HOST_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiBootServicesTableLib|HOST_APPLICATION
+
+#
+# VALID_ARCHITECTURES = IA32 X64 EBC
+#
+
+[Sources]
+ MockUefiBootServicesTableLib.cpp
+
+[LibraryClasses]
+ GoogleTestLib
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[BuildOptions]
+ MSFT:*_*_*_CC_FLAGS = /EHsc
diff --git a/MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockHash2.cpp b/MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockHash2.cpp
new file mode 100644
index 0000000000..5cf94c43b4
--- /dev/null
+++ b/MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockHash2.cpp
@@ -0,0 +1,27 @@
+/** @file MockHash2.cpp
+ Google Test mock for Hash2 Protocol
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <GoogleTest/Protocol/MockHash2.h>
+
+MOCK_INTERFACE_DEFINITION (MockHash2);
+MOCK_FUNCTION_DEFINITION (MockHash2, GetHashSize, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHash2, Hash, 5, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHash2, HashInit, 2, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHash2, HashUpdate, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockHash2, HashFinal, 2, EFIAPI);
+
+EFI_HASH2_PROTOCOL HASH2_PROTOCOL_INSTANCE = {
+ GetHashSize, // EFI_HASH2_GET_HASH_SIZE
+ Hash, // EFI_HASH2_HASH
+ HashInit, // EFI_HASH2_HASH_INIT
+ HashUpdate, // EFI_HASH2_HASH_UPDATE
+ HashFinal // EFI_HASH2_HASH_FINAL
+};
+
+extern "C" {
+ EFI_HASH2_PROTOCOL *gHash2Protocol = &HASH2_PROTOCOL_INSTANCE;
+}
diff --git a/MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockRng.cpp b/MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockRng.cpp
new file mode 100644
index 0000000000..7d8b69cc86
--- /dev/null
+++ b/MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockRng.cpp
@@ -0,0 +1,21 @@
+/** @file MockRng.cpp
+ Google Test mock for Rng Protocol
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <GoogleTest/Protocol/MockRng.h>
+
+MOCK_INTERFACE_DEFINITION (MockRng);
+MOCK_FUNCTION_DEFINITION (MockRng, GetInfo, 3, EFIAPI);
+MOCK_FUNCTION_DEFINITION (MockRng, GetRng, 4, EFIAPI);
+
+EFI_RNG_PROTOCOL RNG_PROTOCOL_INSTANCE = {
+ GetInfo, // EFI_RNG_GET_INFO
+ GetRng // EFI_RNG_GET_RNG
+};
+
+extern "C" {
+ EFI_RNG_PROTOCOL *gRngProtocol = &RNG_PROTOCOL_INSTANCE;
+}
diff --git a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
index 8c37e93be3..892caee368 100644
--- a/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
+++ b/NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
@@ -1,6 +1,7 @@
/** @file
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -189,6 +190,13 @@ Dhcp4CreateService (
{
DHCP_SERVICE *DhcpSb;
EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
*Service = NULL;
DhcpSb = AllocateZeroPool (sizeof (DHCP_SERVICE));
@@ -203,7 +211,7 @@ Dhcp4CreateService (
DhcpSb->Image = ImageHandle;
InitializeListHead (&DhcpSb->Children);
DhcpSb->DhcpState = Dhcp4Stopped;
- DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());
+ DhcpSb->Xid = Random;
CopyMem (
&DhcpSb->ServiceBinding,
&mDhcp4ServiceBindingTemplate,
diff --git a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
index b591a4605b..e7f2787a98 100644
--- a/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
+++ b/NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
@@ -3,7 +3,7 @@
implementation for Dhcp6 Driver.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -123,6 +123,13 @@ Dhcp6CreateService (
{
DHCP6_SERVICE *Dhcp6Srv;
EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
*Service = NULL;
Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));
@@ -147,7 +154,7 @@ Dhcp6CreateService (
Dhcp6Srv->Signature = DHCP6_SERVICE_SIGNATURE;
Dhcp6Srv->Controller = Controller;
Dhcp6Srv->Image = ImageHandle;
- Dhcp6Srv->Xid = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));
+ Dhcp6Srv->Xid = (0xffffff & Random);
CopyMem (
&Dhcp6Srv->ServiceBinding,
diff --git a/NetworkPkg/DnsDxe/DnsDhcp.c b/NetworkPkg/DnsDxe/DnsDhcp.c
index 933565a32d..9eb3c1d2d8 100644
--- a/NetworkPkg/DnsDxe/DnsDhcp.c
+++ b/NetworkPkg/DnsDxe/DnsDhcp.c
@@ -2,6 +2,7 @@
Functions implementation related with DHCPv4/v6 for DNS driver.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -277,6 +278,7 @@ GetDns4ServerFromDhcp4 (
EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token;
BOOLEAN IsDone;
UINTN Index;
+ UINT32 Random;
Image = Instance->Service->ImageHandle;
Controller = Instance->Service->ControllerHandle;
@@ -292,6 +294,12 @@ GetDns4ServerFromDhcp4 (
Data = NULL;
InterfaceInfo = NULL;
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
ZeroMem ((UINT8 *)ParaList, sizeof (ParaList));
ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA));
@@ -467,7 +475,7 @@ GetDns4ServerFromDhcp4 (
Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet);
- Token.Packet->Dhcp4.Header.Xid = HTONL (NET_RANDOM (NetRandomInitSeed ()));
+ Token.Packet->Dhcp4.Header.Xid = Random;
Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000);
diff --git a/NetworkPkg/DnsDxe/DnsImpl.c b/NetworkPkg/DnsDxe/DnsImpl.c
index d311812800..c2629bb8df 100644
--- a/NetworkPkg/DnsDxe/DnsImpl.c
+++ b/NetworkPkg/DnsDxe/DnsImpl.c
@@ -2,6 +2,7 @@
DnsDxe support functions implementation.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1963,6 +1964,14 @@ ConstructDNSQuery (
NET_FRAGMENT Frag;
DNS_HEADER *DnsHeader;
DNS_QUERY_SECTION *DnsQuery;
+ EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
//
// Messages carried by UDP are restricted to 512 bytes (not counting the IP
@@ -1977,7 +1986,7 @@ ConstructDNSQuery (
// Fill header
//
DnsHeader = (DNS_HEADER *)Frag.Bulk;
- DnsHeader->Identification = (UINT16)NET_RANDOM (NetRandomInitSeed ());
+ DnsHeader->Identification = (UINT16)Random;
DnsHeader->Flags.Uint16 = 0x0000;
DnsHeader->Flags.Bits.RD = 1;
DnsHeader->Flags.Bits.OpCode = DNS_FLAGS_OPCODE_STANDARD;
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
index b22cef4ff5..f964515b0f 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
@@ -2,6 +2,7 @@
Functions implementation related with DHCPv6 for HTTP boot driver.
Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -951,6 +952,7 @@ HttpBootDhcp6Sarr (
UINT32 OptCount;
UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];
EFI_STATUS Status;
+ UINT32 Random;
Dhcp6 = Private->Dhcp6;
ASSERT (Dhcp6 != NULL);
@@ -961,6 +963,12 @@ HttpBootDhcp6Sarr (
OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);
ASSERT (OptCount > 0);
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
if (Retransmit == NULL) {
return EFI_OUT_OF_RESOURCES;
@@ -976,7 +984,7 @@ HttpBootDhcp6Sarr (
Config.IaInfoEvent = NULL;
Config.RapidCommit = FALSE;
Config.ReconfigureAccept = FALSE;
- Config.IaDescriptor.IaId = NET_RANDOM (NetRandomInitSeed ());
+ Config.IaDescriptor.IaId = Random;
Config.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;
Config.SolicitRetransmission = Retransmit;
Retransmit->Irt = 4;
diff --git a/NetworkPkg/IScsiDxe/IScsiCHAP.c b/NetworkPkg/IScsiDxe/IScsiCHAP.c
index b507f11cd4..bebb1ac29b 100644
--- a/NetworkPkg/IScsiDxe/IScsiCHAP.c
+++ b/NetworkPkg/IScsiDxe/IScsiCHAP.c
@@ -3,6 +3,7 @@
Configuration.
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -576,16 +577,24 @@ IScsiCHAPToSendReq (
//
// CHAP_I=<I>
//
- IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
+ Status = IScsiGenRandom ((UINT8 *)&AuthData->OutIdentifier, 1);
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
//
// CHAP_C=<C>
//
- IScsiGenRandom (
- (UINT8 *)AuthData->OutChallenge,
- AuthData->Hash->DigestSize
- );
+ Status = IScsiGenRandom (
+ (UINT8 *)AuthData->OutChallenge,
+ AuthData->Hash->DigestSize
+ );
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
BinToHexStatus = IScsiBinToHex (
(UINT8 *)AuthData->OutChallenge,
AuthData->Hash->DigestSize,
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c
index 78dc5c73d3..2159b84949 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.c
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.c
@@ -2,6 +2,7 @@
Miscellaneous routines for iSCSI driver.
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -474,20 +475,17 @@ IScsiNetNtoi (
@param[in, out] Rand The buffer to contain random numbers.
@param[in] RandLength The length of the Rand buffer.
+ @retval EFI_SUCCESS on success
+ @retval others on error
+
**/
-VOID
+EFI_STATUS
IScsiGenRandom (
IN OUT UINT8 *Rand,
IN UINTN RandLength
)
{
- UINT32 Random;
-
- while (RandLength > 0) {
- Random = NET_RANDOM (NetRandomInitSeed ());
- *Rand++ = (UINT8)(Random);
- RandLength--;
- }
+ return PseudoRandom (Rand, RandLength);
}
/**
diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h
index a951eee70e..91b2cd2261 100644
--- a/NetworkPkg/IScsiDxe/IScsiMisc.h
+++ b/NetworkPkg/IScsiDxe/IScsiMisc.h
@@ -2,6 +2,7 @@
Miscellaneous definitions for iSCSI driver.
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -202,8 +203,11 @@ IScsiNetNtoi (
@param[in, out] Rand The buffer to contain random numbers.
@param[in] RandLength The length of the Rand buffer.
+ @retval EFI_SUCCESS on success
+ @retval others on error
+
**/
-VOID
+EFI_STATUS
IScsiGenRandom (
IN OUT UINT8 *Rand,
IN UINTN RandLength
diff --git a/NetworkPkg/Include/Library/NetLib.h b/NetworkPkg/Include/Library/NetLib.h
index 8c0e62b388..e8108b79db 100644
--- a/NetworkPkg/Include/Library/NetLib.h
+++ b/NetworkPkg/Include/Library/NetLib.h
@@ -3,6 +3,7 @@
It provides basic functions for the UEFI network stack.
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -539,8 +540,6 @@ extern EFI_IPv4_ADDRESS mZeroIp4Addr;
#define TICKS_PER_MS 10000U
#define TICKS_PER_SECOND 10000000U
-#define NET_RANDOM(Seed) ((UINT32) ((UINT32) (Seed) * 1103515245UL + 12345) % 4294967295UL)
-
/**
Extract a UINT32 from a byte stream.
@@ -580,19 +579,40 @@ NetPutUint32 (
);
/**
- Initialize a random seed using current time and monotonic count.
+ Generate a Random output data given a length.
- Get current time and monotonic count first. Then initialize a random seed
- based on some basic mathematics operation on the hour, day, minute, second,
- nanosecond and year of the current time and the monotonic count value.
+ @param[out] Output - The buffer to store the generated random data.
+ @param[in] OutputLength - The length of the output buffer.
- @return The random seed initialized with current time.
+ @retval EFI_SUCCESS On Success
+ @retval EFI_INVALID_PARAMETER Pointer is null or size is zero
+ @retval EFI_NOT_FOUND RNG protocol not found
+ @retval Others Error from RngProtocol->GetRNG()
+ @return Status code
**/
-UINT32
+EFI_STATUS
EFIAPI
-NetRandomInitSeed (
- VOID
+PseudoRandom (
+ OUT VOID *Output,
+ IN UINTN OutputLength
+ );
+
+/**
+ Generate a 32-bit pseudo-random number.
+
+ @param[out] Output - The buffer to store the generated random number.
+
+ @retval EFI_SUCCESS On Success
+ @retval EFI_NOT_FOUND RNG protocol not found
+ @retval Others Error from RngProtocol->GetRNG()
+
+ @return Status code
+**/
+EFI_STATUS
+EFIAPI
+PseudoRandomU32 (
+ OUT UINT32 *Output
);
#define NET_LIST_USER_STRUCT(Entry, Type, Field) \
diff --git a/NetworkPkg/Ip4Dxe/Ip4Driver.c b/NetworkPkg/Ip4Dxe/Ip4Driver.c
index ec483ff01f..683423f38d 100644
--- a/NetworkPkg/Ip4Dxe/Ip4Driver.c
+++ b/NetworkPkg/Ip4Dxe/Ip4Driver.c
@@ -2,6 +2,7 @@
The driver binding and service binding protocol for IP4 driver.
Copyright (c) 2005 - 2019, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -549,11 +550,18 @@ Ip4DriverBindingStart (
EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
UINTN Index;
IP4_CONFIG2_DATA_ITEM *DataItem;
+ UINT32 Random;
IpSb = NULL;
Ip4Cfg2 = NULL;
DataItem = NULL;
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
//
// Test for the Ip4 service binding protocol
//
@@ -653,7 +661,7 @@ Ip4DriverBindingStart (
//
// Initialize the IP4 ID
//
- mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());
+ mIp4Id = (UINT16)Random;
return Status;
diff --git a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
index 70e232ce6c..4c1354d26c 100644
--- a/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
+++ b/NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
@@ -2276,6 +2276,13 @@ Ip6ConfigInitInstance (
UINTN Index;
UINT16 IfIndex;
IP6_CONFIG_DATA_ITEM *DataItem;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
IpSb = IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance);
@@ -2381,7 +2388,7 @@ Ip6ConfigInitInstance (
// The NV variable is not set, so generate a random IAID, and write down the
// fresh new configuration as the NV variable now.
//
- Instance->IaId = NET_RANDOM (NetRandomInitSeed ());
+ Instance->IaId = Random;
for (Index = 0; Index < IpSb->SnpMode.HwAddressSize; Index++) {
Instance->IaId |= (IpSb->SnpMode.CurrentAddress.Addr[Index] << ((Index << 3) & 31));
diff --git a/NetworkPkg/Ip6Dxe/Ip6Driver.c b/NetworkPkg/Ip6Dxe/Ip6Driver.c
index b483a7d136..cbe011dad4 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Driver.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Driver.c
@@ -3,7 +3,7 @@
Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>
(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -316,7 +316,11 @@ Ip6CreateService (
IpSb->CurHopLimit = IP6_HOP_LIMIT;
IpSb->LinkMTU = IP6_MIN_LINK_MTU;
IpSb->BaseReachableTime = IP6_REACHABLE_TIME;
- Ip6UpdateReachableTime (IpSb);
+ Status = Ip6UpdateReachableTime (IpSb);
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
//
// RFC4861 RETRANS_TIMER: 1,000 milliseconds
//
@@ -516,11 +520,18 @@ Ip6DriverBindingStart (
EFI_STATUS Status;
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
IP6_CONFIG_DATA_ITEM *DataItem;
+ UINT32 Random;
IpSb = NULL;
Ip6Cfg = NULL;
DataItem = NULL;
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
//
// Test for the Ip6 service binding protocol
//
@@ -656,7 +667,7 @@ Ip6DriverBindingStart (
//
// Initialize the IP6 ID
//
- mIp6Id = NET_RANDOM (NetRandomInitSeed ());
+ mIp6Id = Random;
return EFI_SUCCESS;
diff --git a/NetworkPkg/Ip6Dxe/Ip6If.c b/NetworkPkg/Ip6Dxe/Ip6If.c
index 4629c05f25..f3d11c4d21 100644
--- a/NetworkPkg/Ip6Dxe/Ip6If.c
+++ b/NetworkPkg/Ip6Dxe/Ip6If.c
@@ -2,7 +2,7 @@
Implement IP6 pseudo interface.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -89,6 +89,14 @@ Ip6SetAddress (
IP6_PREFIX_LIST_ENTRY *PrefixEntry;
UINT64 Delay;
IP6_DELAY_JOIN_LIST *DelayNode;
+ EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
NET_CHECK_SIGNATURE (Interface, IP6_INTERFACE_SIGNATURE);
@@ -164,7 +172,7 @@ Ip6SetAddress (
// Thus queue the address to be processed in Duplicate Address Detection module
// after the delay time (in milliseconds).
//
- Delay = (UINT64)NET_RANDOM (NetRandomInitSeed ());
+ Delay = (UINT64)Random;
Delay = MultU64x32 (Delay, IP6_ONE_SECOND_IN_MS);
Delay = RShiftU64 (Delay, 32);
diff --git a/NetworkPkg/Ip6Dxe/Ip6Mld.c b/NetworkPkg/Ip6Dxe/Ip6Mld.c
index e6b2b653e2..498a118543 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Mld.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Mld.c
@@ -696,7 +696,15 @@ Ip6UpdateDelayTimer (
IN OUT IP6_MLD_GROUP *Group
)
{
- UINT32 Delay;
+ UINT32 Delay;
+ EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
//
// If the Query packet specifies a Maximum Response Delay of zero, perform timer
@@ -715,7 +723,7 @@ Ip6UpdateDelayTimer (
// is less than the remaining value of the running timer.
//
if ((Group->DelayTimer == 0) || (Delay < Group->DelayTimer)) {
- Group->DelayTimer = Delay / 4294967295UL * NET_RANDOM (NetRandomInitSeed ());
+ Group->DelayTimer = Delay / 4294967295UL * Random;
}
return EFI_SUCCESS;
diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.c b/NetworkPkg/Ip6Dxe/Ip6Nd.c
index c10c7017f8..72aa45c10f 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Nd.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.c
@@ -2,7 +2,7 @@
Implementation of Neighbor Discovery support routines.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -16,17 +16,28 @@ EFI_MAC_ADDRESS mZeroMacAddress;
@param[in, out] IpSb Points to the IP6_SERVICE.
+ @retval EFI_SUCCESS ReachableTime Updated
+ @retval others Failed to update ReachableTime
**/
-VOID
+EFI_STATUS
Ip6UpdateReachableTime (
IN OUT IP6_SERVICE *IpSb
)
{
- UINT32 Random;
+ UINT32 Random;
+ EFI_STATUS Status;
- Random = (NetRandomInitSeed () / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
+ Random = (Random / 4294967295UL) * IP6_RANDOM_FACTOR_SCALE;
Random = Random + IP6_MIN_RANDOM_FACTOR_SCALED;
IpSb->ReachableTime = (IpSb->BaseReachableTime * Random) / IP6_RANDOM_FACTOR_SCALE;
+
+ return EFI_SUCCESS;
}
/**
@@ -972,10 +983,17 @@ Ip6InitDADProcess (
IP6_SERVICE *IpSb;
EFI_STATUS Status;
UINT32 MaxDelayTick;
+ UINT32 Random;
NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);
ASSERT (AddressInfo != NULL);
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
//
// Do nothing if we have already started DAD on the address.
//
@@ -1014,7 +1032,7 @@ Ip6InitDADProcess (
Entry->Transmit = 0;
Entry->Receive = 0;
MaxDelayTick = IP6_MAX_RTR_SOLICITATION_DELAY / IP6_TIMER_INTERVAL_IN_MS;
- Entry->RetransTick = (MaxDelayTick * ((NET_RANDOM (NetRandomInitSeed ()) % 5) + 1)) / 5;
+ Entry->RetransTick = (MaxDelayTick * ((Random % 5) + 1)) / 5;
Entry->AddressInfo = AddressInfo;
Entry->Callback = Callback;
Entry->Context = Context;
@@ -2078,7 +2096,10 @@ Ip6ProcessRouterAdvertise (
// in BaseReachableTime and recompute a ReachableTime.
//
IpSb->BaseReachableTime = ReachableTime;
- Ip6UpdateReachableTime (IpSb);
+ Status = Ip6UpdateReachableTime (IpSb);
+ if (EFI_ERROR (Status)) {
+ goto Exit;
+ }
}
if (RetransTimer != 0) {
diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.h b/NetworkPkg/Ip6Dxe/Ip6Nd.h
index bf64e9114e..5795e23c7d 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Nd.h
+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.h
@@ -2,7 +2,7 @@
Definition of Neighbor Discovery support routines.
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -780,10 +780,10 @@ Ip6OnArpResolved (
/**
Update the ReachableTime in IP6 service binding instance data, in milliseconds.
- @param[in, out] IpSb Points to the IP6_SERVICE.
-
+ @retval EFI_SUCCESS ReachableTime Updated
+ @retval others Failed to update ReachableTime
**/
-VOID
+EFI_STATUS
Ip6UpdateReachableTime (
IN OUT IP6_SERVICE *IpSb
);
diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c
index fd4a9e15a8..01c13c08d2 100644
--- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.c
+++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.c
@@ -3,6 +3,7 @@
Copyright (c) 2005 - 2018, 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
**/
@@ -31,6 +32,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiLib.h>
+#include <Protocol/Rng.h>
#define NIC_ITEM_CONFIG_SIZE (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)
#define DEFAULT_ZERO_START ((UINTN) ~0)
@@ -127,6 +129,25 @@ GLOBAL_REMOVE_IF_UNREFERENCED VLAN_DEVICE_PATH mNetVlanDevicePathTemplate = {
0
};
+//
+// These represent UEFI SPEC defined algorithms that should be supported by
+// the RNG protocol and are generally considered secure.
+//
+// The order of the algorithms in this array is important. This order is the order
+// in which the algorithms will be tried by the RNG protocol.
+// If your platform needs to use a specific algorithm for the random number generator,
+// then you should place that algorithm first in the array.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID *mSecureHashAlgorithms[] = {
+ &gEfiRngAlgorithmSp80090Ctr256Guid, // SP800-90A DRBG CTR using AES-256
+ &gEfiRngAlgorithmSp80090Hmac256Guid, // SP800-90A DRBG HMAC using SHA-256
+ &gEfiRngAlgorithmSp80090Hash256Guid, // SP800-90A DRBG Hash using SHA-256
+ &gEfiRngAlgorithmArmRndr, // unspecified SP800-90A DRBG via ARM RNDR register
+ &gEfiRngAlgorithmRaw, // Raw data from NRBG (or TRNG)
+};
+
+#define SECURE_HASH_ALGORITHMS_SIZE (sizeof (mSecureHashAlgorithms) / sizeof (EFI_GUID *))
+
/**
Locate the handles that support SNP, then open one of them
to send the syslog packets. The caller isn't required to close
@@ -884,34 +905,107 @@ Ip6Swap128 (
}
/**
- Initialize a random seed using current time and monotonic count.
+ Generate a Random output data given a length.
- Get current time and monotonic count first. Then initialize a random seed
- based on some basic mathematics operation on the hour, day, minute, second,
- nanosecond and year of the current time and the monotonic count value.
+ @param[out] Output - The buffer to store the generated random data.
+ @param[in] OutputLength - The length of the output buffer.
- @return The random seed initialized with current time.
+ @retval EFI_SUCCESS On Success
+ @retval EFI_INVALID_PARAMETER Pointer is null or size is zero
+ @retval EFI_NOT_FOUND RNG protocol not found
+ @retval Others Error from RngProtocol->GetRNG()
+ @return Status code
**/
-UINT32
+EFI_STATUS
EFIAPI
-NetRandomInitSeed (
- VOID
+PseudoRandom (
+ OUT VOID *Output,
+ IN UINTN OutputLength
)
{
- EFI_TIME Time;
- UINT32 Seed;
- UINT64 MonotonicCount;
+ EFI_RNG_PROTOCOL *RngProtocol;
+ EFI_STATUS Status;
+ UINTN AlgorithmIndex;
+
+ if ((Output == NULL) || (OutputLength == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = gBS->LocateProtocol (&gEfiRngProtocolGuid, NULL, (VOID **)&RngProtocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to locate EFI_RNG_PROTOCOL: %r\n", Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ if (PcdGetBool (PcdEnforceSecureRngAlgorithms)) {
+ for (AlgorithmIndex = 0; AlgorithmIndex < SECURE_HASH_ALGORITHMS_SIZE; AlgorithmIndex++) {
+ Status = RngProtocol->GetRNG (RngProtocol, mSecureHashAlgorithms[AlgorithmIndex], OutputLength, (UINT8 *)Output);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Secure Algorithm was supported on this platform
+ //
+ return EFI_SUCCESS;
+ } else if (Status == EFI_UNSUPPORTED) {
+ //
+ // Secure Algorithm was not supported on this platform
+ //
+ DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", AlgorithmIndex, Status));
+
+ //
+ // Try the next secure algorithm
+ //
+ continue;
+ } else {
+ //
+ // Some other error occurred
+ //
+ DEBUG ((DEBUG_ERROR, "Failed to generate random data using secure algorithm %d: %r\n", AlgorithmIndex, Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+ }
+
+ //
+ // If we get here, we failed to generate random data using any secure algorithm
+ // Platform owner should ensure that at least one secure algorithm is supported
+ //
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Lets try using the default algorithm (which may not be secure)
+ //
+ Status = RngProtocol->GetRNG (RngProtocol, NULL, OutputLength, (UINT8 *)Output);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random data: %r\n", __func__, Status));
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
- gRT->GetTime (&Time, NULL);
- Seed = (Time.Hour << 24 | Time.Day << 16 | Time.Minute << 8 | Time.Second);
- Seed ^= Time.Nanosecond;
- Seed ^= Time.Year << 7;
+ return EFI_SUCCESS;
+}
+
+/**
+ Generate a 32-bit pseudo-random number.
- gBS->GetNextMonotonicCount (&MonotonicCount);
- Seed += (UINT32)MonotonicCount;
+ @param[out] Output - The buffer to store the generated random number.
- return Seed;
+ @retval EFI_SUCCESS On Success
+ @retval EFI_NOT_FOUND RNG protocol not found
+ @retval Others Error from RngProtocol->GetRNG()
+
+ @return Status code
+**/
+EFI_STATUS
+EFIAPI
+PseudoRandomU32 (
+ OUT UINT32 *Output
+ )
+{
+ return PseudoRandom (Output, sizeof (*Output));
}
/**
diff --git a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
index 8145d256ec..a8f534a293 100644
--- a/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+++ b/NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
@@ -3,6 +3,7 @@
#
# Copyright (c) 2006 - 2018, 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
#
##
@@ -49,7 +50,11 @@
gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable
gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable
gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES
-
+ gEfiRngAlgorithmRaw ## CONSUMES
+ gEfiRngAlgorithmSp80090Ctr256Guid ## CONSUMES
+ gEfiRngAlgorithmSp80090Hmac256Guid ## CONSUMES
+ gEfiRngAlgorithmSp80090Hash256Guid ## CONSUMES
+ gEfiRngAlgorithmArmRndr ## CONSUMES
[Protocols]
gEfiSimpleNetworkProtocolGuid ## SOMETIMES_CONSUMES
@@ -59,3 +64,10 @@
gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMES
gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES
gEfiAdapterInformationProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiRngProtocolGuid ## CONSUMES
+
+[FixedPcd]
+ gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms ## CONSUMES
+
+[Depex]
+ gEfiRngProtocolGuid
diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
index e06f35e774..7c4289b77b 100644
--- a/NetworkPkg/NetworkPkg.dec
+++ b/NetworkPkg/NetworkPkg.dec
@@ -5,6 +5,7 @@
#
# Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
# (C) Copyright 2015-2020 Hewlett Packard Enterprise Development LP<BR>
+# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -130,6 +131,12 @@
# @Prompt Indicates whether SnpDxe creates event for ExitBootServices() call.
gEfiNetworkPkgTokenSpaceGuid.PcdSnpCreateExitBootServicesEvent|TRUE|BOOLEAN|0x1000000C
+ ## Enforces the use of Secure UEFI spec defined RNG algorithms for all network connections.
+ # TRUE - Enforce the use of Secure UEFI spec defined RNG algorithms.
+ # FALSE - Do not enforce and depend on the default implementation of RNG algorithm from the provider.
+ # @Prompt Enforce the use of Secure UEFI spec defined RNG algorithms.
+ gEfiNetworkPkgTokenSpaceGuid.PcdEnforceSecureRngAlgorithms|TRUE|BOOLEAN|0x1000000D
+
[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
## IPv6 DHCP Unique Identifier (DUID) Type configuration (From RFCs 3315 and 6355).
# 01 = DUID Based on Link-layer Address Plus Time [DUID-LLT]
diff --git a/NetworkPkg/SecurityFixes.yaml b/NetworkPkg/SecurityFixes.yaml
index fa42025e0d..4305328425 100644
--- a/NetworkPkg/SecurityFixes.yaml
+++ b/NetworkPkg/SecurityFixes.yaml
@@ -122,3 +122,64 @@ CVE_2023_45235:
- http://www.openwall.com/lists/oss-security/2024/01/16/2
- http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
- https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+CVE_2023_45236:
+ commit_titles:
+ - "NetworkPkg: TcpDxe: SECURITY PATCH CVE-2023-45236 Patch"
+ cve: CVE-2023-45236
+ date_reported: 2023-08-28 13:56 UTC
+ description: "Bug 08 - edk2/NetworkPkg: Predictable TCP Initial Sequence Numbers"
+ note:
+ files_impacted:
+ - NetworkPkg/Include/Library/NetLib.h
+ - NetworkPkg/TcpDxe/TcpDriver.c
+ - NetworkPkg/TcpDxe/TcpDxe.inf
+ - NetworkPkg/TcpDxe/TcpFunc.h
+ - NetworkPkg/TcpDxe/TcpInput.c
+ - NetworkPkg/TcpDxe/TcpMain.h
+ - NetworkPkg/TcpDxe/TcpMisc.c
+ - NetworkPkg/TcpDxe/TcpTimer.c
+ links:
+ - https://bugzilla.tianocore.org/show_bug.cgi?id=4541
+ - https://nvd.nist.gov/vuln/detail/CVE-2023-45236
+ - http://www.openwall.com/lists/oss-security/2024/01/16/2
+ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
+ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
+CVE_2023_45237:
+ commit_titles:
+ - "NetworkPkg:: SECURITY PATCH CVE 2023-45237"
+ cve: CVE-2023-45237
+ date_reported: 2023-08-28 13:56 UTC
+ description: "Bug 09 - Use of a Weak PseudoRandom Number Generator"
+ note:
+ files_impacted:
+ - NetworkPkg/Dhcp4Dxe/Dhcp4Driver.c
+ - NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
+ - NetworkPkg/DnsDxe/DnsDhcp.c
+ - NetworkPkg/DnsDxe/DnsImpl.c
+ - NetworkPkg/HttpBootDxe/HttpBootDhcp6.c
+ - NetworkPkg/IScsiDxe/IScsiCHAP.c
+ - NetworkPkg/IScsiDxe/IScsiMisc.c
+ - NetworkPkg/IScsiDxe/IScsiMisc.h
+ - NetworkPkg/Include/Library/NetLib.h
+ - NetworkPkg/Ip4Dxe/Ip4Driver.c
+ - NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
+ - NetworkPkg/Ip6Dxe/Ip6Driver.c
+ - NetworkPkg/Ip6Dxe/Ip6If.c
+ - NetworkPkg/Ip6Dxe/Ip6Mld.c
+ - NetworkPkg/Ip6Dxe/Ip6Nd.c
+ - NetworkPkg/Ip6Dxe/Ip6Nd.h
+ - NetworkPkg/Library/DxeNetLib/DxeNetLib.c
+ - NetworkPkg/Library/DxeNetLib/DxeNetLib.inf
+ - NetworkPkg/NetworkPkg.dec
+ - NetworkPkg/TcpDxe/TcpDriver.c
+ - NetworkPkg/Udp4Dxe/Udp4Driver.c
+ - NetworkPkg/Udp6Dxe/Udp6Driver.c
+ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
+ - NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+ - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
+ links:
+ - https://bugzilla.tianocore.org/show_bug.cgi?id=4542
+ - https://nvd.nist.gov/vuln/detail/CVE-2023-45237
+ - http://www.openwall.com/lists/oss-security/2024/01/16/2
+ - http://packetstormsecurity.com/files/176574/PixieFail-Proof-Of-Concepts.html
+ - https://blog.quarkslab.com/pixiefail-nine-vulnerabilities-in-tianocores-edk-ii-ipv6-network-stack.html
diff --git a/NetworkPkg/TcpDxe/TcpDriver.c b/NetworkPkg/TcpDxe/TcpDriver.c
index 98a90e0210..c6e7c0df54 100644
--- a/NetworkPkg/TcpDxe/TcpDriver.c
+++ b/NetworkPkg/TcpDxe/TcpDriver.c
@@ -2,7 +2,7 @@
The driver binding and service binding protocol for the TCP driver.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -83,6 +83,12 @@ EFI_SERVICE_BINDING_PROTOCOL gTcpServiceBinding = {
TcpServiceBindingDestroyChild
};
+//
+// This is the handle for the Hash2ServiceBinding Protocol instance this driver produces
+// if the platform does not provide one.
+//
+EFI_HANDLE mHash2ServiceHandle = NULL;
+
/**
Create and start the heartbeat timer for the TCP driver.
@@ -163,7 +169,30 @@ TcpDriverEntryPoint (
)
{
EFI_STATUS Status;
- UINT32 Seed;
+ UINT32 Random;
+
+ //
+ // Initialize the Secret used for hashing TCP sequence numbers
+ //
+ // Normally this should be regenerated periodically, but since
+ // this is only used for UEFI networking and not a general purpose
+ // operating system, it is not necessary to regenerate it.
+ //
+ Status = PseudoRandomU32 (&mTcpGlobalSecret);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
+ //
+ // Get a random number used to generate a random port number
+ // Intentionally not linking this to mTcpGlobalSecret to avoid leaking information about the secret
+ //
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a Failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
//
// Install the TCP Driver Binding Protocol
@@ -201,11 +230,9 @@ TcpDriverEntryPoint (
}
//
- // Initialize ISS and random port.
+ // Initialize the random port.
//
- Seed = NetRandomInitSeed ();
- mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
- mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN));
+ mTcp4RandomPort = (UINT16)(TCP_PORT_KNOWN + (Random % TCP_PORT_KNOWN));
mTcp6RandomPort = mTcp4RandomPort;
return EFI_SUCCESS;
@@ -219,6 +246,8 @@ TcpDriverEntryPoint (
@param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
@retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
+ @retval EFI_UNSUPPORTED Service Binding Protocols are unavailable.
+ @retval EFI_ALREADY_STARTED The TCP driver is already started on the controller.
@retval EFI_SUCCESS A new IP6 service binding private was created.
**/
@@ -229,11 +258,13 @@ TcpCreateService (
IN UINT8 IpVersion
)
{
- EFI_STATUS Status;
- EFI_GUID *IpServiceBindingGuid;
- EFI_GUID *TcpServiceBindingGuid;
- TCP_SERVICE_DATA *TcpServiceData;
- IP_IO_OPEN_DATA OpenData;
+ EFI_STATUS Status;
+ EFI_GUID *IpServiceBindingGuid;
+ EFI_GUID *TcpServiceBindingGuid;
+ TCP_SERVICE_DATA *TcpServiceData;
+ IP_IO_OPEN_DATA OpenData;
+ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
+ EFI_HASH2_PROTOCOL *Hash2Protocol;
if (IpVersion == IP_VERSION_4) {
IpServiceBindingGuid = &gEfiIp4ServiceBindingProtocolGuid;
@@ -267,6 +298,33 @@ TcpCreateService (
return EFI_UNSUPPORTED;
}
+ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
+ if (EFI_ERROR (Status)) {
+ //
+ // If we can't find the Hashing protocol, then we need to create one.
+ //
+
+ //
+ // Platform is expected to publish the hash service binding protocol to support TCP.
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHash2ServiceBindingProtocolGuid,
+ NULL,
+ (VOID **)&Hash2ServiceBinding
+ );
+ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->CreateChild == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Create an instance of the hash protocol for this controller.
+ //
+ Status = Hash2ServiceBinding->CreateChild (Hash2ServiceBinding, &mHash2ServiceHandle);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
//
// Create the TCP service data.
//
@@ -418,6 +476,7 @@ TcpDestroyService (
EFI_STATUS Status;
LIST_ENTRY *List;
TCP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
+ EFI_SERVICE_BINDING_PROTOCOL *Hash2ServiceBinding;
ASSERT ((IpVersion == IP_VERSION_4) || (IpVersion == IP_VERSION_6));
@@ -434,6 +493,30 @@ TcpDestroyService (
return EFI_SUCCESS;
}
+ //
+ // Destroy the Hash2ServiceBinding instance if it is created by Tcp driver.
+ //
+ if (mHash2ServiceHandle != NULL) {
+ Status = gBS->LocateProtocol (
+ &gEfiHash2ServiceBindingProtocolGuid,
+ NULL,
+ (VOID **)&Hash2ServiceBinding
+ );
+ if (EFI_ERROR (Status) || (Hash2ServiceBinding == NULL) || (Hash2ServiceBinding->DestroyChild == NULL)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Destroy the instance of the hashing protocol for this controller.
+ //
+ Status = Hash2ServiceBinding->DestroyChild (Hash2ServiceBinding, mHash2ServiceHandle);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ mHash2ServiceHandle = NULL;
+ }
+
Status = gBS->OpenProtocol (
NicHandle,
ServiceBindingGuid,
diff --git a/NetworkPkg/TcpDxe/TcpDxe.inf b/NetworkPkg/TcpDxe/TcpDxe.inf
index c0acbdca57..76de4cf9ec 100644
--- a/NetworkPkg/TcpDxe/TcpDxe.inf
+++ b/NetworkPkg/TcpDxe/TcpDxe.inf
@@ -6,6 +6,7 @@
# stack has been loaded in system. This driver supports both IPv4 and IPv6 network stack.
#
# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) Microsoft Corporation
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -68,7 +69,6 @@
NetLib
IpIoLib
-
[Protocols]
## SOMETIMES_CONSUMES
## SOMETIMES_PRODUCES
@@ -81,6 +81,15 @@
gEfiIp6ServiceBindingProtocolGuid ## TO_START
gEfiTcp6ProtocolGuid ## BY_START
gEfiTcp6ServiceBindingProtocolGuid ## BY_START
+ gEfiHash2ProtocolGuid ## BY_START
+ gEfiHash2ServiceBindingProtocolGuid ## BY_START
+
+[Guids]
+ gEfiHashAlgorithmMD5Guid ## CONSUMES
+ gEfiHashAlgorithmSha256Guid ## CONSUMES
+
+[Depex]
+ gEfiHash2ServiceBindingProtocolGuid
[UserExtensions.TianoCore."ExtraFiles"]
TcpDxeExtra.uni
diff --git a/NetworkPkg/TcpDxe/TcpFunc.h b/NetworkPkg/TcpDxe/TcpFunc.h
index a7af01fff2..c707bee3e5 100644
--- a/NetworkPkg/TcpDxe/TcpFunc.h
+++ b/NetworkPkg/TcpDxe/TcpFunc.h
@@ -2,7 +2,7 @@
Declaration of external functions shared in TCP driver.
Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -36,8 +36,11 @@ VOID
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpInitTcbLocal (
IN OUT TCP_CB *Tcb
);
@@ -129,17 +132,6 @@ TcpCloneTcb (
);
/**
- Compute an ISS to be used by a new connection.
-
- @return The result ISS.
-
-**/
-TCP_SEQNO
-TcpGetIss (
- VOID
- );
-
-/**
Get the local mss.
@param[in] Sock Pointer to the socket to get mss.
@@ -202,8 +194,11 @@ TcpFormatNetbuf (
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
connection.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpOnAppConnect (
IN OUT TCP_CB *Tcb
);
diff --git a/NetworkPkg/TcpDxe/TcpInput.c b/NetworkPkg/TcpDxe/TcpInput.c
index 97633a3908..a5d575ccaf 100644
--- a/NetworkPkg/TcpDxe/TcpInput.c
+++ b/NetworkPkg/TcpDxe/TcpInput.c
@@ -724,6 +724,7 @@ TcpInput (
TCP_SEQNO Urg;
UINT16 Checksum;
INT32 Usable;
+ EFI_STATUS Status;
ASSERT ((Version == IP_VERSION_4) || (Version == IP_VERSION_6));
@@ -872,7 +873,17 @@ TcpInput (
Tcb->LocalEnd.Port = Head->DstPort;
Tcb->RemoteEnd.Port = Head->SrcPort;
- TcpInitTcbLocal (Tcb);
+ Status = TcpInitTcbLocal (Tcb);
+ if (EFI_ERROR (Status)) {
+ DEBUG (
+ (DEBUG_ERROR,
+ "TcpInput: discard a segment because failed to init local end for TCB %p\n",
+ Tcb)
+ );
+
+ goto DISCARD;
+ }
+
TcpInitTcbPeer (Tcb, Seg, &Option);
TcpSetState (Tcb, TCP_SYN_RCVD);
diff --git a/NetworkPkg/TcpDxe/TcpMain.h b/NetworkPkg/TcpDxe/TcpMain.h
index c0c9b7f46e..4d5566ab93 100644
--- a/NetworkPkg/TcpDxe/TcpMain.h
+++ b/NetworkPkg/TcpDxe/TcpMain.h
@@ -3,7 +3,7 @@
It is the common head file for all Tcp*.c in TCP driver.
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -13,6 +13,7 @@
#include <Protocol/ServiceBinding.h>
#include <Protocol/DriverBinding.h>
+#include <Protocol/Hash2.h>
#include <Library/IpIoLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
@@ -31,7 +32,7 @@ extern EFI_UNICODE_STRING_TABLE *gTcpControllerNameTable;
extern LIST_ENTRY mTcpRunQue;
extern LIST_ENTRY mTcpListenQue;
-extern TCP_SEQNO mTcpGlobalIss;
+extern TCP_SEQNO mTcpGlobalSecret;
extern UINT32 mTcpTick;
///
@@ -45,14 +46,6 @@ extern UINT32 mTcpTick;
#define TCP_EXPIRE_TIME 65535
-///
-/// The implementation selects the initial send sequence number and the unit to
-/// be added when it is increased.
-///
-#define TCP_BASE_ISS 0x4d7e980b
-#define TCP_ISS_INCREMENT_1 2048
-#define TCP_ISS_INCREMENT_2 100
-
typedef union {
EFI_TCP4_CONFIG_DATA Tcp4CfgData;
EFI_TCP6_CONFIG_DATA Tcp6CfgData;
@@ -774,4 +767,50 @@ Tcp6Poll (
IN EFI_TCP6_PROTOCOL *This
);
+/**
+ Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
+ and remote IP addresses and ports.
+
+ This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
+ Where the ISN is computed as follows:
+ ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
+
+ Otherwise:
+ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
+
+ "Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
+ connection's identifying parameters ("localip, localport, remoteip, remoteport")
+ and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
+ outside (MUST-9), or an attacker could still guess at sequence numbers from the
+ ISN used for some other connection. The PRF could be implemented as a
+ cryptographic hash of the concatenation of the TCP connection parameters and some
+ secret data. For discussion of the selection of a specific hash algorithm and
+ management of the secret key data."
+
+ @param[in] LocalIp A pointer to the local IP address of the TCP connection.
+ @param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
+ @param[in] LocalPort The local port number of the TCP connection.
+ @param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
+ @param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
+ @param[in] RemotePort The remote port number of the TCP connection.
+ @param[out] Isn A pointer to the variable that will receive the Initial
+ Sequence Number (ISN).
+
+ @retval EFI_SUCCESS The operation completed successfully, and the ISN was
+ retrieved.
+ @retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+TcpGetIsn (
+ IN UINT8 *LocalIp,
+ IN UINTN LocalIpSize,
+ IN UINT16 LocalPort,
+ IN UINT8 *RemoteIp,
+ IN UINTN RemoteIpSize,
+ IN UINT16 RemotePort,
+ OUT TCP_SEQNO *Isn
+ );
+
#endif
diff --git a/NetworkPkg/TcpDxe/TcpMisc.c b/NetworkPkg/TcpDxe/TcpMisc.c
index c93212d47d..3310306f63 100644
--- a/NetworkPkg/TcpDxe/TcpMisc.c
+++ b/NetworkPkg/TcpDxe/TcpMisc.c
@@ -3,7 +3,7 @@
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -20,7 +20,34 @@ LIST_ENTRY mTcpListenQue = {
&mTcpListenQue
};
-TCP_SEQNO mTcpGlobalIss = TCP_BASE_ISS;
+//
+// The Session secret
+// This must be initialized to a random value at boot time
+//
+TCP_SEQNO mTcpGlobalSecret;
+
+//
+// Union to hold either an IPv4 or IPv6 address
+// This is used to simplify the ISN hash computation
+//
+typedef union {
+ UINT8 IPv4[4];
+ UINT8 IPv6[16];
+} NETWORK_ADDRESS;
+
+//
+// The ISN is computed by hashing this structure
+// It is initialized with the local and remote IP addresses and ports
+// and the secret
+//
+//
+typedef struct {
+ UINT16 LocalPort;
+ UINT16 RemotePort;
+ NETWORK_ADDRESS LocalAddress;
+ NETWORK_ADDRESS RemoteAddress;
+ TCP_SEQNO Secret;
+} ISN_HASH_CTX;
CHAR16 *mTcpStateName[] = {
L"TCP_CLOSED",
@@ -41,12 +68,18 @@ CHAR16 *mTcpStateName[] = {
@param[in, out] Tcb Pointer to the TCP_CB of this TCP instance.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpInitTcbLocal (
IN OUT TCP_CB *Tcb
)
{
+ TCP_SEQNO Isn;
+ EFI_STATUS Status;
+
//
// Compute the checksum of the fixed parts of pseudo header
//
@@ -57,6 +90,16 @@ TcpInitTcbLocal (
0x06,
0
);
+
+ Status = TcpGetIsn (
+ Tcb->LocalEnd.Ip.v4.Addr,
+ sizeof (IPv4_ADDRESS),
+ Tcb->LocalEnd.Port,
+ Tcb->RemoteEnd.Ip.v4.Addr,
+ sizeof (IPv4_ADDRESS),
+ Tcb->RemoteEnd.Port,
+ &Isn
+ );
} else {
Tcb->HeadSum = NetIp6PseudoHeadChecksum (
&Tcb->LocalEnd.Ip.v6,
@@ -64,9 +107,25 @@ TcpInitTcbLocal (
0x06,
0
);
+
+ Status = TcpGetIsn (
+ Tcb->LocalEnd.Ip.v6.Addr,
+ sizeof (IPv6_ADDRESS),
+ Tcb->LocalEnd.Port,
+ Tcb->RemoteEnd.Ip.v6.Addr,
+ sizeof (IPv6_ADDRESS),
+ Tcb->RemoteEnd.Port,
+ &Isn
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "TcpInitTcbLocal: failed to get isn\n"));
+ ASSERT (FALSE);
+ return Status;
}
- Tcb->Iss = TcpGetIss ();
+ Tcb->Iss = Isn;
Tcb->SndUna = Tcb->Iss;
Tcb->SndNxt = Tcb->Iss;
@@ -82,6 +141,8 @@ TcpInitTcbLocal (
Tcb->RetxmitSeqMax = 0;
Tcb->ProbeTimerOn = FALSE;
+
+ return EFI_SUCCESS;
}
/**
@@ -506,18 +567,162 @@ TcpCloneTcb (
}
/**
- Compute an ISS to be used by a new connection.
-
- @return The resulting ISS.
+ Retrieves the Initial Sequence Number (ISN) for a TCP connection identified by local
+ and remote IP addresses and ports.
+
+ This method is based on https://datatracker.ietf.org/doc/html/rfc9293#section-3.4.1
+ Where the ISN is computed as follows:
+ ISN = TimeStamp + MD5(LocalIP, LocalPort, RemoteIP, RemotePort, Secret)
+
+ Otherwise:
+ ISN = M + F(localip, localport, remoteip, remoteport, secretkey)
+
+ "Here M is the 4 microsecond timer, and F() is a pseudorandom function (PRF) of the
+ connection's identifying parameters ("localip, localport, remoteip, remoteport")
+ and a secret key ("secretkey") (SHLD-1). F() MUST NOT be computable from the
+ outside (MUST-9), or an attacker could still guess at sequence numbers from the
+ ISN used for some other connection. The PRF could be implemented as a
+ cryptographic hash of the concatenation of the TCP connection parameters and some
+ secret data. For discussion of the selection of a specific hash algorithm and
+ management of the secret key data."
+
+ @param[in] LocalIp A pointer to the local IP address of the TCP connection.
+ @param[in] LocalIpSize The size, in bytes, of the LocalIp buffer.
+ @param[in] LocalPort The local port number of the TCP connection.
+ @param[in] RemoteIp A pointer to the remote IP address of the TCP connection.
+ @param[in] RemoteIpSize The size, in bytes, of the RemoteIp buffer.
+ @param[in] RemotePort The remote port number of the TCP connection.
+ @param[out] Isn A pointer to the variable that will receive the Initial
+ Sequence Number (ISN).
+
+ @retval EFI_SUCCESS The operation completed successfully, and the ISN was
+ retrieved.
+ @retval EFI_INVALID_PARAMETER One or more of the input parameters are invalid.
+ @retval EFI_UNSUPPORTED The operation is not supported.
**/
-TCP_SEQNO
-TcpGetIss (
- VOID
+EFI_STATUS
+TcpGetIsn (
+ IN UINT8 *LocalIp,
+ IN UINTN LocalIpSize,
+ IN UINT16 LocalPort,
+ IN UINT8 *RemoteIp,
+ IN UINTN RemoteIpSize,
+ IN UINT16 RemotePort,
+ OUT TCP_SEQNO *Isn
)
{
- mTcpGlobalIss += TCP_ISS_INCREMENT_1;
- return mTcpGlobalIss;
+ EFI_STATUS Status;
+ EFI_HASH2_PROTOCOL *Hash2Protocol;
+ EFI_HASH2_OUTPUT HashResult;
+ ISN_HASH_CTX IsnHashCtx;
+ EFI_TIME TimeStamp;
+
+ //
+ // Check that the ISN pointer is valid
+ //
+ if (Isn == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The local ip may be a v4 or v6 address and may not be NULL
+ //
+ if ((LocalIp == NULL) || (LocalIpSize == 0) || (RemoteIp == NULL) || (RemoteIpSize == 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // the local ip may be a v4 or v6 address
+ //
+ if ((LocalIpSize != sizeof (EFI_IPv4_ADDRESS)) && (LocalIpSize != sizeof (EFI_IPv6_ADDRESS))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Locate the Hash Protocol
+ //
+ Status = gBS->LocateProtocol (&gEfiHash2ProtocolGuid, NULL, (VOID **)&Hash2Protocol);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to locate Hash Protocol: %r\n", Status));
+
+ //
+ // TcpCreateService(..) is expected to be called prior to this function
+ //
+ ASSERT_EFI_ERROR (Status);
+ return Status;
+ }
+
+ //
+ // Initialize the hash algorithm
+ //
+ Status = Hash2Protocol->HashInit (Hash2Protocol, &gEfiHashAlgorithmSha256Guid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to initialize sha256 hash algorithm: %r\n", Status));
+ return Status;
+ }
+
+ IsnHashCtx.LocalPort = LocalPort;
+ IsnHashCtx.RemotePort = RemotePort;
+ IsnHashCtx.Secret = mTcpGlobalSecret;
+
+ //
+ // Check the IP address family and copy accordingly
+ //
+ if (LocalIpSize == sizeof (EFI_IPv4_ADDRESS)) {
+ CopyMem (&IsnHashCtx.LocalAddress.IPv4, LocalIp, LocalIpSize);
+ } else if (LocalIpSize == sizeof (EFI_IPv6_ADDRESS)) {
+ CopyMem (&IsnHashCtx.LocalAddress.IPv6, LocalIp, LocalIpSize);
+ } else {
+ return EFI_INVALID_PARAMETER; // Unsupported address size
+ }
+
+ //
+ // Repeat the process for the remote IP address
+ //
+ if (RemoteIpSize == sizeof (EFI_IPv4_ADDRESS)) {
+ CopyMem (&IsnHashCtx.RemoteAddress.IPv4, RemoteIp, RemoteIpSize);
+ } else if (RemoteIpSize == sizeof (EFI_IPv6_ADDRESS)) {
+ CopyMem (&IsnHashCtx.RemoteAddress.IPv6, RemoteIp, RemoteIpSize);
+ } else {
+ return EFI_INVALID_PARAMETER; // Unsupported address size
+ }
+
+ //
+ // Compute the hash
+ // Update the hash with the data
+ //
+ Status = Hash2Protocol->HashUpdate (Hash2Protocol, (UINT8 *)&IsnHashCtx, sizeof (IsnHashCtx));
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to update hash: %r\n", Status));
+ return Status;
+ }
+
+ //
+ // Finalize the hash and retrieve the result
+ //
+ Status = Hash2Protocol->HashFinal (Hash2Protocol, &HashResult);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_NET, "Failed to finalize hash: %r\n", Status));
+ return Status;
+ }
+
+ Status = gRT->GetTime (&TimeStamp, NULL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // copy the first 4 bytes of the hash result into the ISN
+ //
+ CopyMem (Isn, HashResult.Md5Hash, sizeof (*Isn));
+
+ //
+ // now add the timestamp to the ISN as 4 microseconds units (1000 / 4 = 250)
+ //
+ *Isn += (TCP_SEQNO)TimeStamp.Nanosecond * 250;
+
+ return Status;
}
/**
@@ -721,17 +926,28 @@ TcpFormatNetbuf (
@param[in, out] Tcb Pointer to the TCP_CB that wants to initiate a
connection.
+ @retval EFI_SUCCESS The operation completed successfully
+ @retval others The underlying functions failed and could not complete the operation
+
**/
-VOID
+EFI_STATUS
TcpOnAppConnect (
IN OUT TCP_CB *Tcb
)
{
- TcpInitTcbLocal (Tcb);
+ EFI_STATUS Status;
+
+ Status = TcpInitTcbLocal (Tcb);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
TcpSetState (Tcb, TCP_SYN_SENT);
TcpSetTimer (Tcb, TCP_TIMER_CONNECT, Tcb->ConnectTimeout);
TcpToSendData (Tcb, 1);
+
+ return EFI_SUCCESS;
}
/**
diff --git a/NetworkPkg/TcpDxe/TcpTimer.c b/NetworkPkg/TcpDxe/TcpTimer.c
index 5d2e124977..065b1bdf5f 100644
--- a/NetworkPkg/TcpDxe/TcpTimer.c
+++ b/NetworkPkg/TcpDxe/TcpTimer.c
@@ -2,7 +2,7 @@
TCP timer related functions.
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -483,7 +483,6 @@ TcpTickingDpc (
INT16 Index;
mTcpTick++;
- mTcpGlobalIss += TCP_ISS_INCREMENT_2;
//
// Don't use LIST_FOR_EACH, which isn't delete safe.
diff --git a/NetworkPkg/Test/NetworkPkgHostTest.dsc b/NetworkPkg/Test/NetworkPkgHostTest.dsc
index fa301a7a52..1772afb058 100644
--- a/NetworkPkg/Test/NetworkPkgHostTest.dsc
+++ b/NetworkPkg/Test/NetworkPkgHostTest.dsc
@@ -30,6 +30,7 @@
NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf {
<LibraryClasses>
UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
+ UefiBootServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiBootServicesTableLib/MockUefiBootServicesTableLib.inf
}
# Despite these library classes being listed in [LibraryClasses] below, they are not needed for the host-based unit tests.
diff --git a/NetworkPkg/Udp4Dxe/Udp4Driver.c b/NetworkPkg/Udp4Dxe/Udp4Driver.c
index cb917fcfc9..c7ea16f4cd 100644
--- a/NetworkPkg/Udp4Dxe/Udp4Driver.c
+++ b/NetworkPkg/Udp4Dxe/Udp4Driver.c
@@ -1,6 +1,7 @@
/** @file
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -555,6 +556,13 @@ Udp4DriverEntryPoint (
)
{
EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
//
// Install the Udp4DriverBinding and Udp4ComponentName protocols.
@@ -571,7 +579,7 @@ Udp4DriverEntryPoint (
//
// Initialize the UDP random port.
//
- mUdp4RandomPort = (UINT16)(((UINT16)NetRandomInitSeed ()) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
+ mUdp4RandomPort = (UINT16)(((UINT16)Random) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
}
return Status;
diff --git a/NetworkPkg/Udp6Dxe/Udp6Driver.c b/NetworkPkg/Udp6Dxe/Udp6Driver.c
index ae96fb9966..edb758d57c 100644
--- a/NetworkPkg/Udp6Dxe/Udp6Driver.c
+++ b/NetworkPkg/Udp6Dxe/Udp6Driver.c
@@ -2,7 +2,7 @@
Driver Binding functions and Service Binding functions for the Network driver module.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -596,6 +596,13 @@ Udp6DriverEntryPoint (
)
{
EFI_STATUS Status;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
//
// Install the Udp6DriverBinding and Udp6ComponentName protocols.
@@ -614,7 +621,7 @@ Udp6DriverEntryPoint (
// Initialize the UDP random port.
//
mUdp6RandomPort = (UINT16)(
- ((UINT16)NetRandomInitSeed ()) %
+ ((UINT16)Random) %
UDP6_PORT_KNOWN +
UDP6_PORT_KNOWN
);
diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
index bd423ebadf..61736ff79e 100644
--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
+++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/PxeBcDhcp6GoogleTest.cpp
@@ -7,6 +7,8 @@
#include <Library/GoogleTestLib.h>
#include <GoogleTest/Library/MockUefiLib.h>
#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
+#include <GoogleTest/Library/MockUefiBootServicesTableLib.h>
+#include <GoogleTest/Protocol/MockRng.h>
extern "C" {
#include <Uefi.h>
@@ -165,7 +167,7 @@ protected:
// Note:
// Testing PxeBcHandleDhcp6Offer() is difficult because it depends on a
// properly setup Private structure. Attempting to properly test this function
-// without a signficant refactor is a fools errand. Instead, we will test
+// without a significant refactor is a fools errand. Instead, we will test
// that we can prevent an overflow in the function.
TEST_F (PxeBcHandleDhcp6OfferTest, BasicUsageTest) {
PXEBC_DHCP6_PACKET_CACHE *Cache6 = NULL;
@@ -238,6 +240,7 @@ TEST_F (PxeBcCacheDnsServerAddressesTest, BasicUsageTest) {
FreePool (Option);
}
}
+
// Test Description
// Test that we can prevent an overflow in the function
TEST_F (PxeBcCacheDnsServerAddressesTest, AttemptOverflowTest) {
@@ -470,10 +473,15 @@ TEST_F (PxeBcRequestBootServiceTest, AttemptRequestOverFlowExpectFailure) {
class PxeBcDhcp6DiscoverTest : public ::testing::Test {
public:
PXEBC_PRIVATE_DATA Private = { 0 };
+ // create a mock md5 hash
+ UINT8 Md5Hash[16] = { 0 };
+
EFI_UDP6_PROTOCOL Udp6Read;
protected:
MockUefiRuntimeServicesTableLib RtServicesMock;
+ MockUefiBootServicesTableLib BsMock;
+ MockRng RngMock;
// Add any setup code if needed
virtual void
@@ -527,8 +535,21 @@ TEST_F (PxeBcDhcp6DiscoverTest, BasicOverflowTest) {
Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
- EXPECT_CALL (RtServicesMock, gRT_GetTime)
- .WillOnce (::testing::Return (0));
+ EXPECT_CALL (BsMock, gBS_LocateProtocol)
+ .WillOnce (
+ ::testing::DoAll (
+ ::testing::SetArgPointee<2> (::testing::ByRef (gRngProtocol)),
+ ::testing::Return (EFI_SUCCESS)
+ )
+ );
+
+ EXPECT_CALL (RngMock, GetRng)
+ .WillOnce (
+ ::testing::DoAll (
+ ::testing::SetArgPointee<3> (::testing::ByRef (Md5Hash[0])),
+ ::testing::Return (EFI_SUCCESS)
+ )
+ );
ASSERT_EQ (
PxeBcDhcp6Discover (
@@ -558,8 +579,21 @@ TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) {
Private.Dhcp6Request->Length = (UINT16)(Cursor - (UINT8 *)Private.Dhcp6Request);
- EXPECT_CALL (RtServicesMock, gRT_GetTime)
- .WillOnce (::testing::Return (0));
+ EXPECT_CALL (BsMock, gBS_LocateProtocol)
+ .WillOnce (
+ ::testing::DoAll (
+ ::testing::SetArgPointee<2> (::testing::ByRef (gRngProtocol)),
+ ::testing::Return (EFI_SUCCESS)
+ )
+ );
+
+ EXPECT_CALL (RngMock, GetRng)
+ .WillOnce (
+ ::testing::DoAll (
+ ::testing::SetArgPointee<3> (::testing::ByRef (Md5Hash[0])),
+ ::testing::Return (EFI_SUCCESS)
+ )
+ );
ASSERT_EQ (
PxeBcDhcp6Discover (
@@ -572,3 +606,61 @@ TEST_F (PxeBcDhcp6DiscoverTest, BasicUsageTest) {
EFI_SUCCESS
);
}
+
+TEST_F (PxeBcDhcp6DiscoverTest, MultipleRequestsAttemptOverflow) {
+ EFI_IPv6_ADDRESS DestIp = { 0 };
+ EFI_DHCP6_PACKET_OPTION RequestOpt = { 0 }; // the data section doesn't really matter
+
+ RequestOpt.OpCode = HTONS (0x1337);
+ RequestOpt.OpLen = HTONS (REQUEST_OPTION_LENGTH); // this length would overflow without a check
+ UINT8 RequestOptBuffer[REQUEST_OPTION_LENGTH] = { 0 };
+
+ // make sure we have enough space for 10 of these options
+ ASSERT_TRUE (REQUEST_OPTION_LENGTH * 10 <= PACKET_SIZE);
+
+ UINT8 Index = 0;
+ EFI_DHCP6_PACKET *Packet = (EFI_DHCP6_PACKET *)&Private.Dhcp6Request[Index];
+ UINT8 *Cursor = (UINT8 *)(Packet->Dhcp6.Option);
+
+ // let's add 10 of these options - this should overflow
+ for (UINT8 i = 0; i < 10; i++) {
+ CopyMem (Cursor, &RequestOpt, sizeof (RequestOpt));
+ Cursor += sizeof (RequestOpt) - 1;
+ CopyMem (Cursor, RequestOptBuffer, REQUEST_OPTION_LENGTH);
+ Cursor += REQUEST_OPTION_LENGTH;
+ }
+
+ // Update the packet length
+ Packet->Length = (UINT16)(Cursor - (UINT8 *)Packet);
+ Packet->Size = PACKET_SIZE;
+
+ // Make sure we're larger than the buffer we're trying to write into
+ ASSERT_TRUE (Packet->Length > sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
+
+ EXPECT_CALL (BsMock, gBS_LocateProtocol)
+ .WillOnce (
+ ::testing::DoAll (
+ ::testing::SetArgPointee<2> (::testing::ByRef (gRngProtocol)),
+ ::testing::Return (EFI_SUCCESS)
+ )
+ );
+
+ EXPECT_CALL (RngMock, GetRng)
+ .WillOnce (
+ ::testing::DoAll (
+ ::testing::SetArgPointee<3> (::testing::ByRef (Md5Hash[0])),
+ ::testing::Return (EFI_SUCCESS)
+ )
+ );
+
+ ASSERT_EQ (
+ PxeBcDhcp6Discover (
+ &(PxeBcDhcp6DiscoverTest::Private),
+ 0,
+ NULL,
+ FALSE,
+ (EFI_IP_ADDRESS *)&DestIp
+ ),
+ EFI_OUT_OF_RESOURCES
+ );
+}
diff --git a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
index 301dcdf611..8b092d9291 100644
--- a/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
+++ b/NetworkPkg/UefiPxeBcDxe/GoogleTest/UefiPxeBcDxeGoogleTest.inf
@@ -14,7 +14,7 @@ VERSION_STRING = 1.0
#
# The following information is for reference only and not required by the build tools.
#
-# VALID_ARCHITECTURES = IA32 X64
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
#
[Sources]
@@ -23,6 +23,7 @@ VERSION_STRING = 1.0
PxeBcDhcp6GoogleTest.h
../PxeBcDhcp6.c
../PxeBcSupport.c
+ ../../../MdePkg/Test/Mock/Library/GoogleTest/Protocol/MockRng.cpp
[Packages]
MdePkg/MdePkg.dec
diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
index 91146b78cb..452038c219 100644
--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
+++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp4.c
@@ -2,7 +2,7 @@
Functions implementation related with DHCPv4 for UefiPxeBc Driver.
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
-
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -1381,6 +1381,12 @@ PxeBcDhcp4Discover (
UINT8 VendorOptLen;
UINT32 Xid;
+ Status = PseudoRandomU32 (&Xid);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
Mode = Private->PxeBc.Mode;
Dhcp4 = Private->Dhcp4;
Status = EFI_SUCCESS;
@@ -1471,7 +1477,6 @@ PxeBcDhcp4Discover (
//
// Set fields of the token for the request packet.
//
- Xid = NET_RANDOM (NetRandomInitSeed ());
Token.Packet->Dhcp4.Header.Xid = HTONL (Xid);
Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)((IsBCast) ? 0x8000 : 0x0));
CopyMem (&Token.Packet->Dhcp4.Header.ClientAddr, &Private->StationIp, sizeof (EFI_IPv4_ADDRESS));
diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
index 7fd1281c11..bcabbd2219 100644
--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
+++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDhcp6.c
@@ -2180,7 +2180,7 @@ PxeBcDhcp6Discover (
UINTN ReadSize;
UINT16 OpCode;
UINT16 OpLen;
- UINT32 Xid;
+ UINT32 Random;
EFI_STATUS Status;
UINTN DiscoverLenNeeded;
@@ -2198,6 +2198,12 @@ PxeBcDhcp6Discover (
return EFI_DEVICE_ERROR;
}
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
+ return Status;
+ }
+
DiscoverLenNeeded = sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET);
Discover = AllocateZeroPool (DiscoverLenNeeded);
if (Discover == NULL) {
@@ -2207,8 +2213,7 @@ PxeBcDhcp6Discover (
//
// Build the discover packet by the cached request packet before.
//
- Xid = NET_RANDOM (NetRandomInitSeed ());
- Discover->TransactionId = HTONL (Xid);
+ Discover->TransactionId = HTONL (Random);
Discover->MessageType = Request->Dhcp6.Header.MessageType;
RequestOpt = Request->Dhcp6.Option;
DiscoverOpt = Discover->DhcpOptions;
diff --git a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
index d84aca7e85..4cd915b411 100644
--- a/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
+++ b/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
@@ -3,6 +3,7 @@
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -892,6 +893,13 @@ PxeBcCreateIp6Children (
PXEBC_PRIVATE_PROTOCOL *Id;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
UINTN Index;
+ UINT32 Random;
+
+ Status = PseudoRandomU32 (&Random);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to generate random number using EFI_RNG_PROTOCOL: %r\n", Status));
+ return Status;
+ }
if (Private->Ip6Nic != NULL) {
//
@@ -935,9 +943,9 @@ PxeBcCreateIp6Children (
}
//
- // Generate a random IAID for the Dhcp6 assigned address.
+ // Set a random IAID for the Dhcp6 assigned address.
//
- Private->IaId = NET_RANDOM (NetRandomInitSeed ());
+ Private->IaId = Random;
if (Private->Snp != NULL) {
for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
diff --git a/OvmfPkg/AmdSev/AmdSevX64.dsc b/OvmfPkg/AmdSev/AmdSevX64.dsc
index a7540bb636..8eb6f4f24f 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.dsc
+++ b/OvmfPkg/AmdSev/AmdSevX64.dsc
@@ -110,6 +110,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses]
+ SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index db3675ae86..d497a343d3 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -20,7 +20,7 @@
#include <Library/UefiBootServicesTableLib.h>
#include <Guid/ConfidentialComputingSevSnpBlob.h>
#include <Library/PcdLib.h>
-#include <Pi/PrePiDxeCis.h>
+#include <Pi/PiDxeCis.h>
#include <Protocol/SevMemoryAcceptance.h>
#include <Protocol/MemoryAccept.h>
#include <Uefi/UefiSpec.h>
@@ -119,7 +119,7 @@ AcceptAllMemory (
CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;
Desc = &AllDescMap[Index];
- if (Desc->GcdMemoryType != EFI_GCD_MEMORY_TYPE_UNACCEPTED) {
+ if (Desc->GcdMemoryType != EfiGcdMemoryTypeUnaccepted) {
continue;
}
diff --git a/OvmfPkg/CloudHv/CloudHvX64.dsc b/OvmfPkg/CloudHv/CloudHvX64.dsc
index b1911d6ab4..4996885301 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.dsc
+++ b/OvmfPkg/CloudHv/CloudHvX64.dsc
@@ -126,6 +126,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses]
+ SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
diff --git a/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c b/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c
index 3372cee2f7..19e9b1bf54 100644
--- a/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c
+++ b/OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c
@@ -19,7 +19,7 @@
#include <Library/TdxLib.h>
#include <Library/TdxMailboxLib.h>
#include <Library/SynchronizationLib.h>
-#include <Pi/PrePiHob.h>
+#include <Pi/PiHob.h>
#include <WorkArea.h>
#include <ConfidentialComputingGuestAttr.h>
#include <Library/TdxHelperLib.h>
@@ -351,7 +351,7 @@ AcceptMemoryForAPsStack (
if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
DEBUG ((DEBUG_INFO, "\nResourceType: 0x%x\n", Hob.ResourceDescriptor->ResourceType));
- if (Hob.ResourceDescriptor->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED) {
ResourceLength = Hob.ResourceDescriptor->ResourceLength;
PhysicalStart = Hob.ResourceDescriptor->PhysicalStart;
PhysicalEnd = PhysicalStart + ResourceLength;
@@ -427,7 +427,7 @@ AcceptMemory (
//
while (!END_OF_HOB_LIST (Hob)) {
if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- if (Hob.ResourceDescriptor->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED) {
PhysicalStart = Hob.ResourceDescriptor->PhysicalStart;
PhysicalEnd = PhysicalStart + Hob.ResourceDescriptor->ResourceLength;
@@ -563,7 +563,7 @@ ValidateHobList (
EFI_RESOURCE_MEMORY_MAPPED_IO_PORT,
EFI_RESOURCE_MEMORY_RESERVED,
EFI_RESOURCE_IO_RESERVED,
- BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED
+ EFI_RESOURCE_MEMORY_UNACCEPTED
};
if (VmmHobList == NULL) {
@@ -643,6 +643,8 @@ ValidateHobList (
EFI_RESOURCE_ATTRIBUTE_PERSISTABLE |
EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED |
EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTABLE |
+ EFI_RESOURCE_ATTRIBUTE_ENCRYPTED|
+ EFI_RESOURCE_ATTRIBUTE_SPECIAL_PURPOSE |
EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE))) != 0)
{
DEBUG ((DEBUG_ERROR, "HOB: Unknow ResourceDescriptor ResourceAttribute type. Type: 0x%08x\n", Hob.ResourceDescriptor->ResourceAttribute));
diff --git a/OvmfPkg/Library/PeilessStartupLib/Hob.c b/OvmfPkg/Library/PeilessStartupLib/Hob.c
index 318b74c95d..725927da73 100644
--- a/OvmfPkg/Library/PeilessStartupLib/Hob.c
+++ b/OvmfPkg/Library/PeilessStartupLib/Hob.c
@@ -20,7 +20,7 @@
#include <IndustryStandard/UefiTcgPlatform.h>
#include <Library/PlatformInitLib.h>
#include <OvmfPlatforms.h>
-#include <Pi/PrePiHob.h>
+#include <Pi/PiHob.h>
#include "PeilessStartupInternal.h"
/**
@@ -92,7 +92,7 @@ ConstructFwHobList (
//
while (!END_OF_HOB_LIST (Hob)) {
if (Hob.Header->HobType == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
- if (Hob.ResourceDescriptor->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {
+ if (Hob.ResourceDescriptor->ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED) {
PhysicalEnd = Hob.ResourceDescriptor->PhysicalStart + Hob.ResourceDescriptor->ResourceLength;
ResourceLength = Hob.ResourceDescriptor->ResourceLength;
diff --git a/OvmfPkg/Library/PlatformInitLib/IntelTdx.c b/OvmfPkg/Library/PlatformInitLib/IntelTdx.c
index ada8592ddd..e561cee30b 100644
--- a/OvmfPkg/Library/PlatformInitLib/IntelTdx.c
+++ b/OvmfPkg/Library/PlatformInitLib/IntelTdx.c
@@ -17,7 +17,7 @@
#include <IndustryStandard/Tdx.h>
#include <IndustryStandard/IntelTdx.h>
#include <Library/PeiServicesLib.h>
-#include <Pi/PrePiHob.h>
+#include <Pi/PiHob.h>
#include <WorkArea.h>
#include <ConfidentialComputingGuestAttr.h>
@@ -40,9 +40,9 @@ BuildResourceDescriptorHobForUnacceptedMemory (
EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute;
UINT64 MaxAcceptedMemoryAddress;
- ASSERT (Hob->ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED);
+ ASSERT (Hob->ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED);
- ResourceType = BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED;
+ ResourceType = EFI_RESOURCE_MEMORY_UNACCEPTED;
ResourceAttribute = Hob->ResourceAttribute;
PhysicalStart = Hob->PhysicalStart;
ResourceLength = Hob->ResourceLength;
@@ -104,7 +104,7 @@ TransferTdxHobList (
ResourceType = Hob.ResourceDescriptor->ResourceType;
ResourceAttribute = Hob.ResourceDescriptor->ResourceAttribute;
- if (ResourceType == BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED) {
+ if (ResourceType == EFI_RESOURCE_MEMORY_UNACCEPTED) {
BuildResourceDescriptorHobForUnacceptedMemory (Hob.ResourceDescriptor);
} else {
BuildResourceDescriptorHob (
diff --git a/OvmfPkg/Library/PlatformInitLib/MemDetect.c b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
index 7b6e5102ad..e64c0ee324 100644
--- a/OvmfPkg/Library/PlatformInitLib/MemDetect.c
+++ b/OvmfPkg/Library/PlatformInitLib/MemDetect.c
@@ -1,7 +1,7 @@
/**@file
Memory Detection for Virtual Machines.
- Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
Module Name:
@@ -43,6 +43,9 @@ Module Name:
#include <Library/PlatformInitLib.h>
+#include <Guid/AcpiS3Context.h>
+#include <Guid/SmramMemoryReserve.h>
+
#define MEGABYTE_SHIFT 20
VOID
@@ -982,6 +985,65 @@ PlatformAddressWidthInitialization (
PlatformInfoHob->PhysMemAddressWidth = PhysMemAddressWidth;
}
+/**
+ Create gEfiSmmSmramMemoryGuid HOB defined in the PI specification Vol. 3,
+ section 5, which is used to describe the SMRAM memory regions supported
+ by the platform.
+
+ @param[in] StartAddress StartAddress of smram.
+ @param[in] Size Size of smram.
+
+**/
+STATIC
+VOID
+CreateSmmSmramMemoryHob (
+ IN EFI_PHYSICAL_ADDRESS StartAddress,
+ IN UINT32 Size
+ )
+{
+ UINTN BufferSize;
+ UINT8 SmramRanges;
+ EFI_PEI_HOB_POINTERS Hob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *SmramHobDescriptorBlock;
+ VOID *GuidHob;
+
+ SmramRanges = 2;
+ BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + (SmramRanges - 1) * sizeof (EFI_SMRAM_DESCRIPTOR);
+
+ Hob.Raw = BuildGuidHob (
+ &gEfiSmmSmramMemoryGuid,
+ BufferSize
+ );
+ ASSERT (Hob.Raw);
+
+ SmramHobDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)(Hob.Raw);
+ SmramHobDescriptorBlock->NumberOfSmmReservedRegions = SmramRanges;
+
+ //
+ // 1. Create first SMRAM descriptor, which contains data structures used in S3 resume.
+ // One page is enough for the data structure
+ //
+ SmramHobDescriptorBlock->Descriptor[0].PhysicalStart = StartAddress;
+ SmramHobDescriptorBlock->Descriptor[0].CpuStart = StartAddress;
+ SmramHobDescriptorBlock->Descriptor[0].PhysicalSize = EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[0].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE | EFI_ALLOCATED;
+
+ //
+ // 1.1 Create gEfiAcpiVariableGuid according SmramHobDescriptorBlock->Descriptor[0] since it's used in S3 resume.
+ //
+ GuidHob = BuildGuidHob (&gEfiAcpiVariableGuid, sizeof (EFI_SMRAM_DESCRIPTOR));
+ ASSERT (GuidHob != NULL);
+ CopyMem (GuidHob, &SmramHobDescriptorBlock->Descriptor[0], sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ //
+ // 2. Create second SMRAM descriptor, which is free and will be used by SMM foundation.
+ //
+ SmramHobDescriptorBlock->Descriptor[1].PhysicalStart = SmramHobDescriptorBlock->Descriptor[0].PhysicalStart + EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[1].CpuStart = SmramHobDescriptorBlock->Descriptor[0].CpuStart + EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[1].PhysicalSize = Size - EFI_PAGE_SIZE;
+ SmramHobDescriptorBlock->Descriptor[1].RegionState = EFI_SMRAM_CLOSED | EFI_CACHEABLE;
+}
+
STATIC
VOID
QemuInitializeRamBelow1gb (
@@ -1029,48 +1091,43 @@ PlatformQemuInitializeRam (
//
PlatformGetSystemMemorySizeBelow4gb (PlatformInfoHob);
- if (PlatformInfoHob->BootMode == 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.
+ //
+ // 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.
+ //
+ QemuInitializeRamBelow1gb (PlatformInfoHob);
+
+ if (PlatformInfoHob->SmmSmramRequire) {
+ UINT32 TsegSize;
+ EFI_PHYSICAL_ADDRESS TsegBase;
+
+ TsegSize = PlatformInfoHob->Q35TsegMbytes * SIZE_1MB;
+ TsegBase = PlatformInfoHob->LowMemory - TsegSize;
+ PlatformAddMemoryRangeHob (BASE_1MB, TsegBase);
+ PlatformAddReservedMemoryBaseSizeHob (
+ TsegBase,
+ TsegSize,
+ TRUE
+ );
+
//
- // 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.
+ // Create gEfiSmmSmramMemoryGuid HOB
//
- QemuInitializeRamBelow1gb (PlatformInfoHob);
+ CreateSmmSmramMemoryHob (TsegBase, TsegSize);
} else {
- //
- // Create memory HOBs
- //
- QemuInitializeRamBelow1gb (PlatformInfoHob);
-
- if (PlatformInfoHob->SmmSmramRequire) {
- UINT32 TsegSize;
-
- TsegSize = PlatformInfoHob->Q35TsegMbytes * SIZE_1MB;
- PlatformAddMemoryRangeHob (BASE_1MB, PlatformInfoHob->LowMemory - TsegSize);
- PlatformAddReservedMemoryBaseSizeHob (
- PlatformInfoHob->LowMemory - TsegSize,
- TsegSize,
- TRUE
- );
- } else {
- PlatformAddMemoryRangeHob (BASE_1MB, PlatformInfoHob->LowMemory);
- }
+ PlatformAddMemoryRangeHob (BASE_1MB, PlatformInfoHob->LowMemory);
+ }
+ if (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME) {
//
// If QEMU presents an E820 map, then create memory HOBs for the >=4GB RAM
// entries. Otherwise, create a single memory HOB with the flat >=4GB
diff --git a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
index 5a79d95b68..21e6efa5e0 100644
--- a/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
+++ b/OvmfPkg/Library/PlatformInitLib/PlatformInitLib.inf
@@ -2,7 +2,7 @@
# Platform Initialization Lib
#
# This module provides platform specific function to detect boot mode.
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -56,6 +56,10 @@
[LibraryClasses.X64]
TdxLib
+[Guids]
+ gEfiSmmSmramMemoryGuid
+ gEfiAcpiVariableGuid
+
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable
diff --git a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
index 63822b126e..0a6f33c2b1 100644
--- a/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
+++ b/OvmfPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.c
@@ -28,6 +28,12 @@
//
#define LMA BIT10
+//
+// Indicate SmBase for each Processors has been relocated or not. If TRUE,
+// means no need to do the relocation in SmmCpuFeaturesInitializeProcessor().
+//
+BOOLEAN mSmmCpuFeaturesSmmRelocated;
+
/**
The constructor function
@@ -46,9 +52,9 @@ SmmCpuFeaturesLibConstructor (
{
//
// If gSmmBaseHobGuid found, means SmBase info has been relocated and recorded
- // in the SmBase array. ASSERT it's not supported in OVMF.
+ // in the SmBase array.
//
- ASSERT (GetFirstGuidHob (&gSmmBaseHobGuid) == NULL);
+ mSmmCpuFeaturesSmmRelocated = (BOOLEAN)(GetFirstGuidHob (&gSmmBaseHobGuid) != NULL);
//
// No need to program SMRRs on our virtual platform.
@@ -92,16 +98,21 @@ SmmCpuFeaturesInitializeProcessor (
AMD_SMRAM_SAVE_STATE_MAP *CpuState;
//
- // Configure SMBASE.
+ // No need to configure SMBASE if SmBase relocation has been done.
//
- CpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(
- SMM_DEFAULT_SMBASE +
- SMRAM_SAVE_STATE_MAP_OFFSET
- );
- if ((CpuState->x86.SMMRevId & 0xFFFF) == 0) {
- CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
- } else {
- CpuState->x64.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+ if (!mSmmCpuFeaturesSmmRelocated) {
+ //
+ // Configure SMBASE.
+ //
+ CpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(
+ SMM_DEFAULT_SMBASE +
+ SMRAM_SAVE_STATE_MAP_OFFSET
+ );
+ if ((CpuState->x86.SMMRevId & 0xFFFF) == 0) {
+ CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+ } else {
+ CpuState->x64.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+ }
}
//
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c b/OvmfPkg/Library/SmmRelocationLib/Ia32/Semaphore.c
index a9fcc89dda..5d9eea3de9 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/Semaphore.c
+++ b/OvmfPkg/Library/SmmRelocationLib/Ia32/Semaphore.c
@@ -1,13 +1,13 @@
/** @file
-Semaphore mechanism to indicate to the BSP that an AP has exited SMM
-after SMBASE relocation.
+ Semaphore mechanism to indicate to the BSP that an AP has exited SMM
+ after SMBASE relocation.
-Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "PiSmmCpuDxeSmm.h"
+#include "InternalSmmRelocationLib.h"
UINTN mSmmRelocationOriginalAddress;
volatile BOOLEAN *mRebasedFlag;
@@ -17,14 +17,12 @@ volatile BOOLEAN *mRebasedFlag;
can be executed immediately after AP exits SMM to indicate to
the BSP that an AP has exited SMM after SMBASE relocation.
- @param[in] CpuIndex The processor index.
@param[in] RebasedFlag A pointer to a flag that is set to TRUE
immediately after AP exits SMM.
**/
VOID
SemaphoreHook (
- IN UINTN CpuIndex,
IN volatile BOOLEAN *RebasedFlag
)
{
@@ -34,7 +32,6 @@ SemaphoreHook (
CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
mSmmRelocationOriginalAddress = (UINTN)HookReturnFromSmm (
- CpuIndex,
CpuState,
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete,
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete
diff --git a/OvmfPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm b/OvmfPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm
new file mode 100644
index 0000000000..8916cb7d06
--- /dev/null
+++ b/OvmfPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm
@@ -0,0 +1,151 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; SmmInit.nasm
+;
+; Abstract:
+;
+; Functions for relocating SMBASE's for all processors
+;
+;-------------------------------------------------------------------------------
+
+%include "StuffRsbNasm.inc"
+
+extern ASM_PFX(SmmInitHandler)
+extern ASM_PFX(mRebasedFlag)
+extern ASM_PFX(mSmmRelocationOriginalAddress)
+
+global ASM_PFX(gPatchSmmInitCr3)
+global ASM_PFX(gPatchSmmInitCr4)
+global ASM_PFX(gPatchSmmInitCr0)
+global ASM_PFX(gPatchSmmInitStack)
+global ASM_PFX(gcSmmInitGdtr)
+global ASM_PFX(gcSmmInitSize)
+global ASM_PFX(gcSmmInitTemplate)
+
+%define PROTECT_MODE_CS 0x8
+%define PROTECT_MODE_DS 0x20
+
+ SECTION .data
+
+NullSeg: DQ 0 ; reserved by architecture
+CodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeCodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeSsSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+DataSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+CodeSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x9b
+ DB 0x8f
+ DB 0
+DataSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x93
+ DB 0x8f
+ DB 0
+CodeSeg64:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xaf ; LimitHigh
+ DB 0 ; BaseHigh
+GDT_SIZE equ $ - NullSeg
+
+ASM_PFX(gcSmmInitGdtr):
+ DW GDT_SIZE - 1
+ DD NullSeg
+
+
+ SECTION .text
+
+global ASM_PFX(SmmStartup)
+
+BITS 16
+ASM_PFX(SmmStartup):
+ mov eax, 0x80000001 ; read capability
+ cpuid
+ mov ebx, edx ; rdmsr will change edx. keep it in ebx.
+ and ebx, BIT20 ; extract NX capability bit
+ shr ebx, 9 ; shift bit to IA32_EFER.NXE[BIT11] position
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr3):
+ mov cr3, eax
+o32 lgdt [cs:ebp + (ASM_PFX(gcSmmInitGdtr) - ASM_PFX(SmmStartup))]
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr4):
+ mov cr4, eax
+ mov ecx, 0xc0000080 ; IA32_EFER MSR
+ rdmsr
+ or eax, ebx ; set NXE bit if NX is available
+ wrmsr
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr0):
+ mov di, PROTECT_MODE_DS
+ mov cr0, eax
+ jmp PROTECT_MODE_CS : dword @32bit
+
+BITS 32
+@32bit:
+ mov ds, edi
+ mov es, edi
+ mov fs, edi
+ mov gs, edi
+ mov ss, edi
+ mov esp, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitStack):
+ call ASM_PFX(SmmInitHandler)
+ StuffRsb32
+ rsm
+
+BITS 16
+ASM_PFX(gcSmmInitTemplate):
+ mov ebp, ASM_PFX(SmmStartup)
+ sub ebp, 0x30000
+ jmp ebp
+
+ASM_PFX(gcSmmInitSize): DW $ - ASM_PFX(gcSmmInitTemplate)
+
+BITS 32
+global ASM_PFX(SmmRelocationSemaphoreComplete)
+ASM_PFX(SmmRelocationSemaphoreComplete):
+ push eax
+ mov eax, [ASM_PFX(mRebasedFlag)]
+ mov byte [eax], 1
+ pop eax
+ jmp [ASM_PFX(mSmmRelocationOriginalAddress)]
+
+global ASM_PFX(SmmInitFixupAddress)
+ASM_PFX(SmmInitFixupAddress):
+ ret
diff --git a/OvmfPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h b/OvmfPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h
new file mode 100644
index 0000000000..d1387f2dfb
--- /dev/null
+++ b/OvmfPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h
@@ -0,0 +1,127 @@
+/** @file
+ SMM Relocation Lib for each processor.
+
+ This Lib produces the SMM_BASE_HOB in HOB database which tells
+ the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+ SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+ SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+ Index.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef INTERNAL_SMM_RELOCATION_LIB_H_
+#define INTERNAL_SMM_RELOCATION_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SmmRelocationLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Guid/SmmBaseHob.h>
+#include <Register/Intel/Cpuid.h>
+#include <Register/Intel/SmramSaveStateMap.h>
+#include <Protocol/MmCpu.h>
+
+extern IA32_DESCRIPTOR gcSmmInitGdtr;
+extern CONST UINT16 gcSmmInitSize;
+extern CONST UINT8 gcSmmInitTemplate[];
+
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr0;
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr3;
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr4;
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitStack;
+
+//
+// The size 0x20 must be bigger than
+// the size of template code of SmmInit. Currently,
+// the size of SmmInit requires the 0x16 Bytes buffer
+// at least.
+//
+#define BACK_BUF_SIZE 0x20
+
+#define CR4_CET_ENABLE BIT23
+
+//
+// EFER register LMA bit
+//
+#define LMA BIT10
+
+/**
+ This function configures the SmBase on the currently executing CPU.
+
+ @param[in] SmBase The SmBase on the currently executing CPU.
+
+**/
+VOID
+EFIAPI
+ConfigureSmBase (
+ IN UINT64 SmBase
+ );
+
+/**
+ Semaphore operation for all processor relocate SMMBase.
+**/
+VOID
+EFIAPI
+SmmRelocationSemaphoreComplete (
+ VOID
+ );
+
+/**
+ Hook the code executed immediately after an RSM instruction on the currently
+ executing CPU. The mode of code executed immediately after RSM must be
+ detected, and the appropriate hook must be selected. Always clear the auto
+ HALT restart flag if it is set.
+
+ @param[in,out] CpuState Pointer to SMRAM Save State Map for the
+ currently executing CPU.
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
+ 32-bit mode from 64-bit SMM.
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to
+ same mode as SMM.
+
+ @retval The value of the original instruction pointer before it was hooked.
+
+**/
+UINT64
+EFIAPI
+HookReturnFromSmm (
+ IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
+ IN UINT64 NewInstructionPointer32,
+ IN UINT64 NewInstructionPointer
+ );
+
+/**
+ Hook return address of SMM Save State so that semaphore code
+ can be executed immediately after AP exits SMM to indicate to
+ the BSP that an AP has exited SMM after SMBASE relocation.
+
+ @param[in] RebasedFlag A pointer to a flag that is set to TRUE
+ immediately after AP exits SMM.
+
+**/
+VOID
+SemaphoreHook (
+ IN volatile BOOLEAN *RebasedFlag
+ );
+
+/**
+ This function fixes up the address of the global variable or function
+ referred in SmmInit assembly files to be the absolute address.
+**/
+VOID
+EFIAPI
+SmmInitFixupAddress (
+ );
+
+#endif
diff --git a/OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.c b/OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.c
new file mode 100644
index 0000000000..7e65bbf929
--- /dev/null
+++ b/OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.c
@@ -0,0 +1,549 @@
+/** @file
+ SMM Relocation Lib for each processor.
+
+ This Lib produces the SMM_BASE_HOB in HOB database which tells
+ the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+ SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+ SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+ Index.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "InternalSmmRelocationLib.h"
+
+UINTN mMaxNumberOfCpus = 1;
+UINTN mNumberOfCpus = 1;
+
+//
+// IDT used during SMM Init
+//
+IA32_DESCRIPTOR gcSmmInitIdtr;
+
+//
+// Smbase for current CPU
+//
+UINT64 mSmBase;
+
+//
+// SmBase Rebased flag for current CPU
+//
+volatile BOOLEAN mRebased;
+
+/**
+ This function will get the SmBase for CpuIndex.
+
+ @param[in] CpuIndex The processor index.
+ @param[in] SmmRelocationStart The start address of Smm relocated memory in SMRAM.
+ @param[in] TileSize The total size required for a CPU save state, any
+ additional CPU-specific context and the size of code
+ for the SMI entry point.
+
+ @retval The value of SmBase for CpuIndex.
+
+**/
+UINTN
+GetSmBase (
+ IN UINTN CpuIndex,
+ IN EFI_PHYSICAL_ADDRESS SmmRelocationStart,
+ IN UINTN TileSize
+ )
+{
+ return (UINTN)(SmmRelocationStart) + CpuIndex * TileSize - SMM_HANDLER_OFFSET;
+}
+
+/**
+ This function will create SmBase for all CPUs.
+
+ @param[in] SmmRelocationStart The start address of Smm relocated memory in SMRAM.
+ @param[in] TileSize The total size required for a CPU save state, any
+ additional CPU-specific context and the size of code
+ for the SMI entry point.
+
+ @retval EFI_SUCCESS Create SmBase for all CPUs successfully.
+ @retval Others Failed to create SmBase for all CPUs.
+
+**/
+EFI_STATUS
+CreateSmmBaseHob (
+ IN EFI_PHYSICAL_ADDRESS SmmRelocationStart,
+ IN UINTN TileSize
+ )
+{
+ UINTN Index;
+ SMM_BASE_HOB_DATA *SmmBaseHobData;
+ UINT32 CpuCount;
+ UINT32 NumberOfProcessorsInHob;
+ UINT32 MaxCapOfProcessorsInHob;
+ UINT32 HobCount;
+
+ SmmBaseHobData = NULL;
+ CpuCount = 0;
+ NumberOfProcessorsInHob = 0;
+ MaxCapOfProcessorsInHob = 0;
+ HobCount = 0;
+
+ //
+ // Count the HOB instance maximum capacity of CPU (MaxCapOfProcessorsInHob) since the max HobLength is 0xFFF8.
+ //
+ MaxCapOfProcessorsInHob = (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE) - sizeof (SMM_BASE_HOB_DATA)) / sizeof (UINT64) + 1;
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - MaxCapOfProcessorsInHob: %d\n", MaxCapOfProcessorsInHob));
+
+ //
+ // Create Guided SMM Base HOB Instances.
+ //
+ while (CpuCount != mMaxNumberOfCpus) {
+ NumberOfProcessorsInHob = MIN ((UINT32)mMaxNumberOfCpus - CpuCount, MaxCapOfProcessorsInHob);
+
+ SmmBaseHobData = BuildGuidHob (
+ &gSmmBaseHobGuid,
+ sizeof (SMM_BASE_HOB_DATA) + sizeof (UINT64) * NumberOfProcessorsInHob
+ );
+ if (SmmBaseHobData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SmmBaseHobData->ProcessorIndex = CpuCount;
+ SmmBaseHobData->NumberOfProcessors = NumberOfProcessorsInHob;
+
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - SmmBaseHobData[%d]->ProcessorIndex: %d\n", HobCount, SmmBaseHobData->ProcessorIndex));
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - SmmBaseHobData[%d]->NumberOfProcessors: %d\n", HobCount, SmmBaseHobData->NumberOfProcessors));
+ for (Index = 0; Index < SmmBaseHobData->NumberOfProcessors; Index++) {
+ //
+ // Calculate the new SMBASE address
+ //
+ SmmBaseHobData->SmBase[Index] = GetSmBase (Index + CpuCount, SmmRelocationStart, TileSize);
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - SmmBaseHobData[%d]->SmBase[%d]: 0x%08x\n", HobCount, Index, SmmBaseHobData->SmBase[Index]));
+ }
+
+ CpuCount += NumberOfProcessorsInHob;
+ HobCount++;
+ SmmBaseHobData = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ C function for SMI handler. To change all processor's SMMBase Register.
+
+**/
+VOID
+EFIAPI
+SmmInitHandler (
+ VOID
+ )
+{
+ //
+ // Update SMM IDT entries' code segment and load IDT
+ //
+ AsmWriteIdtr (&gcSmmInitIdtr);
+
+ //
+ // Configure SmBase.
+ //
+ ConfigureSmBase (mSmBase);
+
+ //
+ // Hook return after RSM to set SMM re-based flag
+ // SMM re-based flag can't be set before RSM, because SMM save state context might be override
+ // by next AP flow before it take effect.
+ //
+ SemaphoreHook (&mRebased);
+}
+
+/**
+ Relocate SmmBases for each processor.
+ Execute on first boot and all S3 resumes
+
+ @param[in] MpServices2 Pointer to this instance of the MpServices.
+ @param[in] SmmRelocationStart The start address of Smm relocated memory in SMRAM.
+ @param[in] TileSize The total size required for a CPU save state, any
+ additional CPU-specific context and the size of code
+ for the SMI entry point.
+
+**/
+VOID
+SmmRelocateBases (
+ IN EDKII_PEI_MP_SERVICES2_PPI *MpServices2,
+ IN EFI_PHYSICAL_ADDRESS SmmRelocationStart,
+ IN UINTN TileSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 BakBuf[BACK_BUF_SIZE];
+ SMRAM_SAVE_STATE_MAP BakBuf2;
+ SMRAM_SAVE_STATE_MAP *CpuStatePtr;
+ UINT8 *U8Ptr;
+ UINTN Index;
+ UINTN BspIndex;
+ UINT32 BspApicId;
+ EFI_PROCESSOR_INFORMATION ProcessorInfo;
+
+ //
+ // Make sure the reserved size is large enough for procedure SmmInitTemplate.
+ //
+ ASSERT (sizeof (BakBuf) >= gcSmmInitSize);
+
+ //
+ // Patch ASM code template with current CR0, CR3, and CR4 values
+ //
+ PatchInstructionX86 (gPatchSmmInitCr0, AsmReadCr0 (), 4);
+ PatchInstructionX86 (gPatchSmmInitCr3, AsmReadCr3 (), 4);
+ PatchInstructionX86 (gPatchSmmInitCr4, AsmReadCr4 () & (~CR4_CET_ENABLE), 4);
+
+ U8Ptr = (UINT8 *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET);
+ CpuStatePtr = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+
+ //
+ // Backup original contents at address 0x38000
+ //
+ CopyMem (BakBuf, U8Ptr, sizeof (BakBuf));
+ CopyMem (&BakBuf2, CpuStatePtr, sizeof (BakBuf2));
+
+ //
+ // Load image for relocation
+ //
+ CopyMem (U8Ptr, gcSmmInitTemplate, gcSmmInitSize);
+
+ //
+ // Retrieve the local APIC ID of current processor
+ //
+ BspApicId = GetApicId ();
+
+ //
+ // Relocate SM bases for all APs
+ // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate
+ //
+ BspIndex = (UINTN)-1;
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ Status = MpServices2->GetProcessorInfo (MpServices2, Index | CPU_V2_EXTENDED_TOPOLOGY, &ProcessorInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BspApicId != (UINT32)ProcessorInfo.ProcessorId) {
+ mRebased = FALSE;
+ mSmBase = GetSmBase (Index, SmmRelocationStart, TileSize);
+ SendSmiIpi ((UINT32)ProcessorInfo.ProcessorId);
+ //
+ // Wait for this AP to finish its 1st SMI
+ //
+ while (!mRebased) {
+ }
+ } else {
+ //
+ // BSP will be Relocated later
+ //
+ BspIndex = Index;
+ }
+ }
+
+ //
+ // Relocate BSP's SMM base
+ //
+ ASSERT (BspIndex != (UINTN)-1);
+ mRebased = FALSE;
+ mSmBase = GetSmBase (BspIndex, SmmRelocationStart, TileSize);
+ SendSmiIpi (BspApicId);
+
+ //
+ // Wait for the BSP to finish its 1st SMI
+ //
+ while (!mRebased) {
+ }
+
+ //
+ // Restore contents at address 0x38000
+ //
+ CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2));
+ CopyMem (U8Ptr, BakBuf, sizeof (BakBuf));
+}
+
+/**
+ Initialize IDT to setup exception handlers in SMM.
+
+**/
+VOID
+InitSmmIdt (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN InterruptState;
+ IA32_DESCRIPTOR PeiIdtr;
+ CONST EFI_PEI_SERVICES **PeiServices;
+
+ //
+ // There are 32 (not 255) entries in it since only processor
+ // generated exceptions will be handled.
+ //
+ gcSmmInitIdtr.Limit = (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;
+
+ //
+ // Allocate for IDT.
+ // sizeof (UINTN) is for the PEI Services Table pointer.
+ //
+ gcSmmInitIdtr.Base = (UINTN)AllocateZeroPool (gcSmmInitIdtr.Limit + 1 + sizeof (UINTN));
+ ASSERT (gcSmmInitIdtr.Base != 0);
+ gcSmmInitIdtr.Base += sizeof (UINTN);
+
+ //
+ // Disable Interrupt, save InterruptState and save PEI IDT table
+ //
+ InterruptState = SaveAndDisableInterrupts ();
+ AsmReadIdtr (&PeiIdtr);
+
+ //
+ // Save the PEI Services Table pointer
+ // The PEI Services Table pointer will be stored in the sizeof (UINTN) bytes
+ // immediately preceding the IDT in memory.
+ //
+ PeiServices = (CONST EFI_PEI_SERVICES **)(*(UINTN *)(PeiIdtr.Base - sizeof (UINTN)));
+ (*(UINTN *)(gcSmmInitIdtr.Base - sizeof (UINTN))) = (UINTN)PeiServices;
+
+ //
+ // Load SMM temporary IDT table
+ //
+ AsmWriteIdtr (&gcSmmInitIdtr);
+
+ //
+ // Setup SMM default exception handlers, SMM IDT table
+ // will be updated and saved in gcSmmInitIdtr
+ //
+ Status = InitializeCpuExceptionHandlers (NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Restore PEI IDT table and CPU InterruptState
+ //
+ AsmWriteIdtr ((IA32_DESCRIPTOR *)&PeiIdtr);
+ SetInterruptState (InterruptState);
+}
+
+/**
+ This routine will split SmramReserve HOB to reserve SmmRelocationSize for Smm relocated memory.
+
+ @param[in] SmmRelocationSize SmmRelocationSize for all processors.
+ @param[in,out] SmmRelocationStart Return the start address of Smm relocated memory in SMRAM.
+
+ @retval EFI_SUCCESS The gEfiSmmSmramMemoryGuid is split successfully.
+ @retval EFI_DEVICE_ERROR Failed to build new HOB for gEfiSmmSmramMemoryGuid.
+ @retval EFI_NOT_FOUND The gEfiSmmSmramMemoryGuid is not found.
+
+**/
+EFI_STATUS
+SplitSmramHobForSmmRelocation (
+ IN UINT64 SmmRelocationSize,
+ IN OUT EFI_PHYSICAL_ADDRESS *SmmRelocationStart
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *Block;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *NewBlock;
+ UINTN NewBlockSize;
+
+ ASSERT (SmmRelocationStart != NULL);
+
+ //
+ // Retrieve the GUID HOB data that contains the set of SMRAM descriptors
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
+ if (GuidHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Block = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)GET_GUID_HOB_DATA (GuidHob);
+
+ //
+ // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe smram carved out for all SMBASE
+ //
+ NewBlockSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + (Block->NumberOfSmmReservedRegions * sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ NewBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)BuildGuidHob (
+ &gEfiSmmSmramMemoryGuid,
+ NewBlockSize
+ );
+ ASSERT (NewBlock != NULL);
+ if (NewBlock == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Copy old EFI_SMRAM_HOB_DESCRIPTOR_BLOCK to new allocated region
+ //
+ CopyMem ((VOID *)NewBlock, Block, NewBlockSize - sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ //
+ // Increase the number of SMRAM descriptors by 1 to make room for the ALLOCATED descriptor of size EFI_PAGE_SIZE
+ //
+ NewBlock->NumberOfSmmReservedRegions = (UINT32)(Block->NumberOfSmmReservedRegions + 1);
+
+ ASSERT (Block->NumberOfSmmReservedRegions >= 1);
+ //
+ // Copy last entry to the end - we assume TSEG is last entry.
+ //
+ CopyMem (&NewBlock->Descriptor[Block->NumberOfSmmReservedRegions], &NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1], sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ //
+ // Update the entry in the array with a size of SmmRelocationSize and put into the ALLOCATED state
+ //
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1].PhysicalSize = SmmRelocationSize;
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1].RegionState |= EFI_ALLOCATED;
+
+ //
+ // Return the start address of Smm relocated memory in SMRAM.
+ //
+ *SmmRelocationStart = NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1].CpuStart;
+
+ //
+ // Reduce the size of the last SMRAM descriptor by SmmRelocationSize
+ //
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions].PhysicalStart += SmmRelocationSize;
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions].CpuStart += SmmRelocationSize;
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions].PhysicalSize -= SmmRelocationSize;
+
+ //
+ // Last step, we can scrub old one
+ //
+ ZeroMem (&GuidHob->Name, sizeof (GuidHob->Name));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ CPU SmmBase Relocation Init.
+
+ This function is to relocate CPU SmmBase.
+
+ @param[in] MpServices2 Pointer to this instance of the MpServices.
+
+ @retval EFI_SUCCESS CPU SmmBase Relocated successfully.
+ @retval Others CPU SmmBase Relocation failed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmRelocationInit (
+ IN EDKII_PEI_MP_SERVICES2_PPI *MpServices2
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfEnabledCpus;
+ UINTN TileSize;
+ UINT64 SmmRelocationSize;
+ EFI_PHYSICAL_ADDRESS SmmRelocationStart;
+ UINTN SmmStackSize;
+ UINT8 *SmmStacks;
+
+ SmmRelocationStart = 0;
+ SmmStacks = NULL;
+
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit Start \n"));
+ if (MpServices2 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the number of processors
+ //
+ Status = MpServices2->GetNumberOfProcessors (
+ MpServices2,
+ &mNumberOfCpus,
+ &NumberOfEnabledCpus
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ mMaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ } else {
+ mMaxNumberOfCpus = mNumberOfCpus;
+ }
+
+ ASSERT (mNumberOfCpus <= mMaxNumberOfCpus);
+
+ //
+ // Calculate SmmRelocationSize for all of the tiles.
+ //
+ // The CPU save state and code for the SMI entry point are tiled within an SMRAM
+ // allocated buffer. The minimum size of this buffer for a uniprocessor system
+ // is 32 KB, because the entry point is SMBASE + 32KB, and CPU save state area
+ // just below SMBASE + 64KB. If more than one CPU is present in the platform,
+ // then the SMI entry point and the CPU save state areas can be tiles to minimize
+ // the total amount SMRAM required for all the CPUs. The tile size can be computed
+ // by adding the CPU save state size, any extra CPU specific context, and
+ // the size of code that must be placed at the SMI entry point to transfer
+ // control to a C function in the native SMM execution mode. This size is
+ // rounded up to the nearest power of 2 to give the tile size for a each CPU.
+ // The total amount of memory required is the maximum number of CPUs that
+ // platform supports times the tile size.
+ //
+ TileSize = SIZE_8KB;
+ SmmRelocationSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)));
+
+ //
+ // Split SmramReserve HOB to reserve SmmRelocationSize for Smm relocated memory
+ //
+ Status = SplitSmramHobForSmmRelocation (
+ SmmRelocationSize,
+ &SmmRelocationStart
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ ASSERT (SmmRelocationStart != 0);
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmRelocationSize: 0x%08x\n", SmmRelocationSize));
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmRelocationStart: 0x%08x\n", SmmRelocationStart));
+
+ //
+ // Fix up the address of the global variable or function referred in
+ // SmmInit assembly files to be the absolute address
+ //
+ SmmInitFixupAddress ();
+
+ //
+ // Patch SMI stack for SMM base relocation
+ // Note: No need allocate stack for all CPUs since the relocation
+ // occurs serially for each CPU
+ //
+ SmmStackSize = EFI_PAGE_SIZE;
+ SmmStacks = (UINT8 *)AllocatePages (EFI_SIZE_TO_PAGES (SmmStackSize));
+ if (SmmStacks == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmStackSize: 0x%08x\n", SmmStackSize));
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmStacks: 0x%08x\n", SmmStacks));
+
+ PatchInstructionX86 (
+ gPatchSmmInitStack,
+ (UINTN)(SmmStacks + SmmStackSize - sizeof (UINTN)),
+ sizeof (UINTN)
+ );
+
+ //
+ // Initialize the SMM IDT for SMM base relocation
+ //
+ InitSmmIdt ();
+
+ //
+ // Relocate SmmBases for each processor.
+ //
+ SmmRelocateBases (MpServices2, SmmRelocationStart, TileSize);
+
+ //
+ // Create the SmBase HOB for all CPUs
+ //
+ Status = CreateSmmBaseHob (SmmRelocationStart, TileSize);
+
+ON_EXIT:
+ if (SmmStacks != NULL) {
+ FreePages (SmmStacks, EFI_SIZE_TO_PAGES (SmmStackSize));
+ }
+
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit Done\n"));
+ return Status;
+}
diff --git a/OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf b/OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
new file mode 100644
index 0000000000..3ea6a1a0bc
--- /dev/null
+++ b/OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
@@ -0,0 +1,60 @@
+## @file
+# SMM Relocation Lib for each processor.
+#
+# This Lib produces the SMM_BASE_HOB in HOB database which tells
+# the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+# SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+# SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+# Index.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmRelocationLib
+ FILE_GUID = 51834F51-CCE0-4743-B553-935D0C8A53FF
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmmRelocationLib
+
+[Sources]
+ InternalSmmRelocationLib.h
+ SmramSaveStateConfig.c
+ SmmRelocationLib.c
+
+[Sources.Ia32]
+ Ia32/Semaphore.c
+ Ia32/SmmInit.nasm
+
+[Sources.X64]
+ X64/Semaphore.c
+ X64/SmmInit.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CpuExceptionHandlerLib
+ DebugLib
+ HobLib
+ LocalApicLib
+ MemoryAllocationLib
+ PcdLib
+ PeiServicesLib
+
+[Guids]
+ gSmmBaseHobGuid ## HOB ALWAYS_PRODUCED
+ gEfiSmmSmramMemoryGuid ## CONSUMES
+
+[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport ## CONSUMES
diff --git a/OvmfPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c b/OvmfPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c
new file mode 100644
index 0000000000..146e6d54d9
--- /dev/null
+++ b/OvmfPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c
@@ -0,0 +1,100 @@
+/** @file
+ Config SMRAM Save State for SmmBases Relocation.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "InternalSmmRelocationLib.h"
+#include <Register/Amd/SmramSaveStateMap.h>
+
+/**
+ This function configures the SmBase on the currently executing CPU.
+
+ @param[in] SmBase The SmBase on the currently executing CPU.
+
+**/
+VOID
+EFIAPI
+ConfigureSmBase (
+ IN UINT64 SmBase
+ )
+{
+ AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;
+
+ CpuSaveState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+
+ if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
+ CpuSaveState->x86.SMBASE = (UINT32)SmBase;
+ } else {
+ CpuSaveState->x64.SMBASE = (UINT32)SmBase;
+ }
+}
+
+/**
+ 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,out] CpuState Pointer to SMRAM Save State Map for the
+ currently executing CPU.
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
+ 32-bit mode from 64-bit SMM.
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to
+ same mode as SMM.
+
+ @retval The value of the original instruction pointer before it was hooked.
+
+**/
+UINT64
+EFIAPI
+HookReturnFromSmm (
+ IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
+ IN UINT64 NewInstructionPointer32,
+ IN UINT64 NewInstructionPointer
+ )
+{
+ UINT64 OriginalInstructionPointer;
+ AMD_SMRAM_SAVE_STATE_MAP *CpuSaveState;
+
+ CpuSaveState = (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
+ if ((CpuSaveState->x86.SMMRevId & 0xFFFF) == 0) {
+ OriginalInstructionPointer = (UINT64)CpuSaveState->x86._EIP;
+ CpuSaveState->x86._EIP = (UINT32)NewInstructionPointer;
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction.
+ //
+ if ((CpuSaveState->x86.AutoHALTRestart & BIT0) != 0) {
+ CpuSaveState->x86.AutoHALTRestart &= ~BIT0;
+ }
+ } else {
+ OriginalInstructionPointer = CpuSaveState->x64._RIP;
+ if ((CpuSaveState->x64.EFER & LMA) == 0) {
+ CpuSaveState->x64._RIP = (UINT32)NewInstructionPointer32;
+ } else {
+ CpuSaveState->x64._RIP = (UINT32)NewInstructionPointer;
+ }
+
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction.
+ //
+ if ((CpuSaveState->x64.AutoHALTRestart & BIT0) != 0) {
+ CpuSaveState->x64.AutoHALTRestart &= ~BIT0;
+ }
+ }
+
+ return OriginalInstructionPointer;
+}
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/Semaphore.c b/OvmfPkg/Library/SmmRelocationLib/X64/Semaphore.c
index dafbc3390e..cd6778e3fc 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/Semaphore.c
+++ b/OvmfPkg/Library/SmmRelocationLib/X64/Semaphore.c
@@ -1,13 +1,13 @@
/** @file
-Semaphore mechanism to indicate to the BSP that an AP has exited SMM
-after SMBASE relocation.
+ Semaphore mechanism to indicate to the BSP that an AP has exited SMM
+ after SMBASE relocation.
-Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include "PiSmmCpuDxeSmm.h"
+#include "InternalSmmRelocationLib.h"
X86_ASSEMBLY_PATCH_LABEL gPatchSmmRelocationOriginalAddressPtr32;
X86_ASSEMBLY_PATCH_LABEL gPatchRebasedFlagAddr32;
@@ -28,14 +28,12 @@ SmmRelocationSemaphoreComplete32 (
can be executed immediately after AP exits SMM to indicate to
the BSP that an AP has exited SMM after SMBASE relocation.
- @param[in] CpuIndex The processor index.
@param[in] RebasedFlag A pointer to a flag that is set to TRUE
immediately after AP exits SMM.
**/
VOID
SemaphoreHook (
- IN UINTN CpuIndex,
IN volatile BOOLEAN *RebasedFlag
)
{
@@ -51,7 +49,6 @@ SemaphoreHook (
CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
mSmmRelocationOriginalAddress = HookReturnFromSmm (
- CpuIndex,
CpuState,
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete32,
(UINT64)(UINTN)&SmmRelocationSemaphoreComplete
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmInit.nasm b/OvmfPkg/Library/SmmRelocationLib/X64/SmmInit.nasm
index 9cf3a6dcf9..8288b723c4 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmInit.nasm
+++ b/OvmfPkg/Library/SmmRelocationLib/X64/SmmInit.nasm
@@ -1,5 +1,5 @@
;------------------------------------------------------------------------------ ;
-; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -18,11 +18,11 @@ extern ASM_PFX(SmmInitHandler)
extern ASM_PFX(mRebasedFlag)
extern ASM_PFX(mSmmRelocationOriginalAddress)
-global ASM_PFX(gPatchSmmCr3)
-global ASM_PFX(gPatchSmmCr4)
-global ASM_PFX(gPatchSmmCr0)
+global ASM_PFX(gPatchSmmInitCr3)
+global ASM_PFX(gPatchSmmInitCr4)
+global ASM_PFX(gPatchSmmInitCr0)
global ASM_PFX(gPatchSmmInitStack)
-global ASM_PFX(gcSmiInitGdtr)
+global ASM_PFX(gcSmmInitGdtr)
global ASM_PFX(gcSmmInitSize)
global ASM_PFX(gcSmmInitTemplate)
global ASM_PFX(gPatchRebasedFlagAddr32)
@@ -30,13 +30,68 @@ global ASM_PFX(gPatchSmmRelocationOriginalAddressPtr32)
%define LONG_MODE_CS 0x38
+ SECTION .data
+
+NullSeg: DQ 0 ; reserved by architecture
+CodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeCodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeSsSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+DataSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+CodeSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x9b
+ DB 0x8f
+ DB 0
+DataSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x93
+ DB 0x8f
+ DB 0
+CodeSeg64:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xaf ; LimitHigh
+ DB 0 ; BaseHigh
+GDT_SIZE equ $ - NullSeg
+
+ASM_PFX(gcSmmInitGdtr):
+ DW GDT_SIZE - 1
+ DQ NullSeg
+
+
DEFAULT REL
SECTION .text
-ASM_PFX(gcSmiInitGdtr):
- DW 0
- DQ 0
-
global ASM_PFX(SmmStartup)
BITS 16
@@ -45,11 +100,11 @@ ASM_PFX(SmmStartup):
cpuid
mov ebx, edx ; rdmsr will change edx. keep it in ebx.
mov eax, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmCr3):
+ASM_PFX(gPatchSmmInitCr3):
mov cr3, eax
-o32 lgdt [cs:ebp + (ASM_PFX(gcSmiInitGdtr) - ASM_PFX(SmmStartup))]
+o32 lgdt [cs:ebp + (ASM_PFX(gcSmmInitGdtr) - ASM_PFX(SmmStartup))]
mov eax, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmCr4):
+ASM_PFX(gPatchSmmInitCr4):
or ah, 2 ; enable XMM registers access
mov cr4, eax
mov ecx, 0xc0000080 ; IA32_EFER MSR
@@ -61,7 +116,7 @@ ASM_PFX(gPatchSmmCr4):
.1:
wrmsr
mov eax, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmCr0):
+ASM_PFX(gPatchSmmInitCr0):
mov cr0, eax ; enable protected mode & paging
jmp LONG_MODE_CS : dword 0 ; offset will be patched to @LongMode
@PatchLongModeOffset:
@@ -134,8 +189,8 @@ ASM_PFX(gPatchRebasedFlagAddr32):
ASM_PFX(gPatchSmmRelocationOriginalAddressPtr32):
BITS 64
-global ASM_PFX(PiSmmCpuSmmInitFixupAddress)
-ASM_PFX(PiSmmCpuSmmInitFixupAddress):
+global ASM_PFX(SmmInitFixupAddress)
+ASM_PFX(SmmInitFixupAddress):
lea rax, [@LongMode]
lea rcx, [@PatchLongModeOffset - 6]
mov dword [rcx], eax
diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc
index 1f2f8b5bb6..69de4dd3f1 100644
--- a/OvmfPkg/Microvm/MicrovmX64.dsc
+++ b/OvmfPkg/Microvm/MicrovmX64.dsc
@@ -129,6 +129,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses]
+ SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|MdePkg/Library/SecPeiDxeTimerLibCpu/SecPeiDxeTimerLibCpu.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLibMicrovm.inf
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 9db3ebd0e7..2ca005d768 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -129,6 +129,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses]
+ SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
@@ -228,7 +229,6 @@
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
-
#
# Network libraries
#
@@ -858,6 +858,11 @@
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
#
+ # Hash2 Protocol producer
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# Network Support
#
!include NetworkPkg/NetworkComponents.dsc.inc
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 6eb26f7d46..0d4abb50a8 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -296,6 +296,11 @@ INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
INF MdeModulePkg/Logo/LogoDxe.inf
#
+# Hash2 Protocol producer
+#
+INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+#
# Network modules
#
!include NetworkPkg/Network.fdf.inc
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 4337812292..a39070a626 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -134,6 +134,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses]
+ SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
@@ -233,7 +234,6 @@
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
-
#
# Network libraries
#
@@ -872,6 +872,11 @@
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
#
+ # Hash2 Protocol producer
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# Network Support
#
!include NetworkPkg/NetworkComponents.dsc.inc
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 080784f722..23a825a012 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -297,6 +297,11 @@ INF OvmfPkg/VirtioFsDxe/VirtioFsDxe.inf
INF MdeModulePkg/Logo/LogoDxe.inf
#
+# Hash2 Protocol producer
+#
+INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+#
# Network modules
#
!if $(E1000_ENABLE)
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 157ae6c0e4..1b90aa8f57 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -147,6 +147,7 @@
!include MdePkg/MdeLibs.dsc.inc
[LibraryClasses]
+ SmmRelocationLib|OvmfPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
TimerLib|OvmfPkg/Library/AcpiTimerLib/BaseAcpiTimerLib.inf
ResetSystemLib|OvmfPkg/Library/ResetSystemLib/BaseResetSystemLib.inf
@@ -249,7 +250,6 @@
VariablePolicyHelperLib|MdeModulePkg/Library/VariablePolicyHelperLib/VariablePolicyHelperLib.inf
VariableFlashInfoLib|MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
-
#
# Network libraries
#
@@ -940,6 +940,11 @@
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
#
+ # Hash2 Protocol producer
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# Network Support
#
!include NetworkPkg/NetworkComponents.dsc.inc
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index b6e8f43566..4dcd6a033c 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -330,6 +330,11 @@ INF MdeModulePkg/Logo/LogoDxe.inf
INF OvmfPkg/TdxDxe/TdxDxe.inf
#
+# Hash2 Protocol producer
+#
+INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+#
# Network modules
#
!if $(E1000_ENABLE)
diff --git a/OvmfPkg/OvmfXen.dsc b/OvmfPkg/OvmfXen.dsc
index fa1a570e74..7fc340d1c1 100644
--- a/OvmfPkg/OvmfXen.dsc
+++ b/OvmfPkg/OvmfXen.dsc
@@ -668,6 +668,11 @@
MdeModulePkg/Universal/Acpi/BootGraphicsResourceTableDxe/BootGraphicsResourceTableDxe.inf
#
+ # Hash2 Protocol producer
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# Network Support
#
!include NetworkPkg/NetworkComponents.dsc.inc
diff --git a/OvmfPkg/OvmfXen.fdf b/OvmfPkg/OvmfXen.fdf
index 5770b17316..41368f37e2 100644
--- a/OvmfPkg/OvmfXen.fdf
+++ b/OvmfPkg/OvmfXen.fdf
@@ -315,6 +315,11 @@ INF ShellPkg/Application/Shell/Shell.inf
INF MdeModulePkg/Logo/LogoDxe.inf
#
+# Hash2 Protocol producer
+#
+INF SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+#
# Network modules
#
!if $(E1000_ENABLE)
diff --git a/OvmfPkg/PlatformCI/PlatformBuildLib.py b/OvmfPkg/PlatformCI/PlatformBuildLib.py
index 00d454954b..3fe80f5c1c 100644
--- a/OvmfPkg/PlatformCI/PlatformBuildLib.py
+++ b/OvmfPkg/PlatformCI/PlatformBuildLib.py
@@ -208,6 +208,8 @@ class PlatformBuilder( UefiBuilder, BuildSettingsManager):
args += " -net none" # turn off network
args += " -smp 4"
args += f" -drive file=fat:rw:{VirtualDrive},format=raw,media=disk" # Mount disk with startup.nsh
+ # Provides Rng services to the Guest VM
+ args += " -device virtio-rng-pci"
if (self.env.GetValue("QEMU_HEADLESS").upper() == "TRUE"):
args += " -display none" # no graphics
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index e6724cf493..88ca14507f 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -17,7 +17,7 @@
#include <Library/MemEncryptSevLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
-#include <Pi/PrePiHob.h>
+#include <Pi/PiHob.h>
#include <PiPei.h>
#include <Register/Amd/Msr.h>
#include <Register/Intel/SmramSaveStateMap.h>
@@ -149,7 +149,7 @@ AmdSevSnpInitialize (
if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {
if (ResourceHob->PhysicalStart >= SIZE_4GB) {
- ResourceHob->ResourceType = BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED;
+ ResourceHob->ResourceType = EFI_RESOURCE_MEMORY_UNACCEPTED;
continue;
}
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
index f5dc41c3a8..df35726ff6 100644
--- a/OvmfPkg/PlatformPei/Platform.c
+++ b/OvmfPkg/PlatformPei/Platform.c
@@ -367,6 +367,9 @@ InitializePlatform (
IntelTdxInitialize ();
InstallFeatureControlCallback (PlatformInfoHob);
+ if (PlatformInfoHob->SmmSmramRequire) {
+ RelocateSmBase ();
+ }
return EFI_SUCCESS;
}
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
index 1cf44844a7..0a59547cfc 100644
--- a/OvmfPkg/PlatformPei/Platform.h
+++ b/OvmfPkg/PlatformPei/Platform.h
@@ -79,6 +79,11 @@ InstallClearCacheCallback (
);
VOID
+RelocateSmBase (
+ VOID
+ );
+
+VOID
AmdSevInitialize (
IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob
);
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index 20b1b98292..e036018eab 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -2,7 +2,7 @@
# Platform PEI driver
#
# This module provides platform specific function to detect boot mode.
-# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -32,6 +32,7 @@
Platform.c
Platform.h
IntelTdx.c
+ SmmRelocation.c
[Packages]
EmbeddedPkg/EmbeddedPkg.dec
@@ -66,6 +67,7 @@
PcdLib
CcExitLib
PlatformInitLib
+ SmmRelocationLib
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
@@ -142,6 +144,7 @@
gEfiPeiMasterBootModePpiGuid
gEfiPeiMpServicesPpiGuid
gEfiPeiReadOnlyVariable2PpiGuid
+ gEdkiiPeiMpServices2PpiGuid
[Depex]
TRUE
diff --git a/OvmfPkg/PlatformPei/SmmRelocation.c b/OvmfPkg/PlatformPei/SmmRelocation.c
new file mode 100644
index 0000000000..1151fc9220
--- /dev/null
+++ b/OvmfPkg/PlatformPei/SmmRelocation.c
@@ -0,0 +1,80 @@
+/**@file
+ Install a callback to do smm relocation.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SmmRelocationLib.h>
+#include <Ppi/MpServices2.h>
+#include "Platform.h"
+
+/**
+ Notification function called when EDKII_PEI_MP_SERVICES2_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
+OnMpServices2Available (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EDKII_PEI_MP_SERVICES2_PPI *MpServices2;
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "%a: %a\n", gEfiCallerBaseName, __func__));
+
+ MpServices2 = Ppi;
+
+ //
+ // Smm Relocation Initialize.
+ //
+ Status = SmmRelocationInit (MpServices2);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_WARN, "OnMpServices2Available: Not able to execute Smm Relocation Init. Status: %r\n", Status));
+ }
+
+ return EFI_SUCCESS;
+}
+
+//
+// Notification object for registering the callback, for when
+// EDKII_PEI_MP_SERVICES2_PPI becomes available.
+//
+STATIC CONST EFI_PEI_NOTIFY_DESCRIPTOR mMpServices2Notify = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | // Flags
+ EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEdkiiPeiMpServices2PpiGuid, // Guid
+ OnMpServices2Available // Notify
+};
+
+VOID
+RelocateSmBase (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesNotifyPpi (&mMpServices2Notify);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: failed to set up MP Services2 callback: %r\n",
+ __func__,
+ Status
+ ));
+ }
+}
diff --git a/OvmfPkg/SmmAccess/SmmAccess2Dxe.c b/OvmfPkg/SmmAccess/SmmAccess2Dxe.c
index 4b9e6df37f..3371592de7 100644
--- a/OvmfPkg/SmmAccess/SmmAccess2Dxe.c
+++ b/OvmfPkg/SmmAccess/SmmAccess2Dxe.c
@@ -6,7 +6,7 @@
driver.
Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
- Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2009 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -115,8 +115,6 @@ SmmAccess2DxeGetCapabilities (
)
{
return SmramAccessGetCapabilities (
- This->LockState,
- This->OpenState,
SmramMapSize,
SmramMap
);
diff --git a/OvmfPkg/SmmAccess/SmmAccess2Dxe.inf b/OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
index d86381d0fb..d9f01a13c4 100644
--- a/OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
+++ b/OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
@@ -5,6 +5,7 @@
# driver.
#
# Copyright (C) 2013, 2015, Red Hat, Inc.
+# Copyright (c) 2024 Intel Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -41,6 +42,7 @@
PciLib
UefiBootServicesTableLib
UefiDriverEntryPoint
+ HobLib
[Protocols]
gEfiSmmAccess2ProtocolGuid ## PRODUCES
@@ -48,6 +50,9 @@
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
+[Guids]
+ gEfiSmmSmramMemoryGuid # ALWAYS_CONSUMED
+
[Pcd]
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase
gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes
diff --git a/OvmfPkg/SmmAccess/SmmAccessPei.c b/OvmfPkg/SmmAccess/SmmAccessPei.c
index 0e57b7804c..ded22f035d 100644
--- a/OvmfPkg/SmmAccess/SmmAccessPei.c
+++ b/OvmfPkg/SmmAccess/SmmAccessPei.c
@@ -3,25 +3,21 @@
A PEIM with the following responsibilities:
- verify & configure the Q35 TSEG in the entry point,
- - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,
- - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose
- it via the gEfiAcpiVariableGuid GUID HOB.
+ - provide SMRAM access by producing PEI_SMM_ACCESS_PPI
This PEIM runs from RAM, so we can write to variables with static storage
duration.
Copyright (C) 2013, 2015, Red Hat, Inc.<BR>
- Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2010 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <Guid/AcpiS3Context.h>
#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>
@@ -64,7 +60,17 @@ SmmAccessPeiOpen (
IN UINTN DescriptorIndex
)
{
- if (DescriptorIndex >= DescIdxCount) {
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+
+ //
+ // Get the number of regions in the system that can be usable for SMRAM
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+ if (DescriptorIndex >= DescriptorBlock->NumberOfSmmReservedRegions) {
return EFI_INVALID_PARAMETER;
}
@@ -102,7 +108,17 @@ SmmAccessPeiClose (
IN UINTN DescriptorIndex
)
{
- if (DescriptorIndex >= DescIdxCount) {
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+
+ //
+ // Get the number of regions in the system that can be usable for SMRAM
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+ if (DescriptorIndex >= DescriptorBlock->NumberOfSmmReservedRegions) {
return EFI_INVALID_PARAMETER;
}
@@ -139,7 +155,17 @@ SmmAccessPeiLock (
IN UINTN DescriptorIndex
)
{
- if (DescriptorIndex >= DescIdxCount) {
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+
+ //
+ // Get the number of regions in the system that can be usable for SMRAM
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
+
+ if (DescriptorIndex >= DescriptorBlock->NumberOfSmmReservedRegions) {
return EFI_INVALID_PARAMETER;
}
@@ -178,8 +204,6 @@ SmmAccessPeiGetCapabilities (
)
{
return SmramAccessGetCapabilities (
- This->LockState,
- This->OpenState,
SmramMapSize,
SmramMap
);
@@ -240,14 +264,10 @@ SmmAccessPeiEntryPoint (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
- UINT16 HostBridgeDevId;
- UINT8 EsmramcVal;
- UINT8 RegMask8;
- UINT32 TopOfLowRam, TopOfLowRamMb;
- EFI_STATUS Status;
- UINTN SmramMapSize;
- EFI_SMRAM_DESCRIPTOR SmramMap[DescIdxCount];
- VOID *GuidHob;
+ UINT16 HostBridgeDevId;
+ UINT8 EsmramcVal;
+ UINT8 RegMask8;
+ UINT32 TopOfLowRam, TopOfLowRamMb;
//
// This module should only be included if SMRAM support is required.
@@ -356,65 +376,7 @@ SmmAccessPeiEntryPoint (
MCH_SMRAM_G_SMRAME
);
- //
- // Create the GUID HOB and point it to the first SMRAM range.
- //
GetStates (&mAccess.LockState, &mAccess.OpenState);
- SmramMapSize = sizeof SmramMap;
- Status = SmramAccessGetCapabilities (
- mAccess.LockState,
- mAccess.OpenState,
- &SmramMapSize,
- SmramMap
- );
- ASSERT_EFI_ERROR (Status);
-
- DEBUG_CODE_BEGIN ();
- {
- UINTN Count;
- UINTN Idx;
-
- Count = SmramMapSize / sizeof SmramMap[0];
- DEBUG ((
- DEBUG_VERBOSE,
- "%a: SMRAM map follows, %d entries\n",
- __func__,
- (INT32)Count
- ));
- DEBUG ((
- DEBUG_VERBOSE,
- "% 20a % 20a % 20a % 20a\n",
- "PhysicalStart(0x)",
- "PhysicalSize(0x)",
- "CpuStart(0x)",
- "RegionState(0x)"
- ));
- for (Idx = 0; Idx < Count; ++Idx) {
- DEBUG ((
- DEBUG_VERBOSE,
- "% 20Lx % 20Lx % 20Lx % 20Lx\n",
- SmramMap[Idx].PhysicalStart,
- SmramMap[Idx].PhysicalSize,
- SmramMap[Idx].CpuStart,
- SmramMap[Idx].RegionState
- ));
- }
- }
- DEBUG_CODE_END ();
-
- GuidHob = BuildGuidHob (
- &gEfiAcpiVariableGuid,
- sizeof SmramMap[DescIdxSmmS3ResumeState]
- );
- if (GuidHob == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CopyMem (
- GuidHob,
- &SmramMap[DescIdxSmmS3ResumeState],
- sizeof SmramMap[DescIdxSmmS3ResumeState]
- );
//
// SmramAccessLock() depends on "mQ35SmramAtDefaultSmbase"; init the latter
diff --git a/OvmfPkg/SmmAccess/SmmAccessPei.inf b/OvmfPkg/SmmAccess/SmmAccessPei.inf
index 1698c4ce6c..1e7cedf290 100644
--- a/OvmfPkg/SmmAccess/SmmAccessPei.inf
+++ b/OvmfPkg/SmmAccess/SmmAccessPei.inf
@@ -2,11 +2,10 @@
# A PEIM with the following responsibilities:
#
# - provide SMRAM access by producing PEI_SMM_ACCESS_PPI,
-# - verify & configure the Q35 TSEG in the entry point,
-# - set aside the SMM_S3_RESUME_STATE object at the bottom of TSEG, and expose
-# it via the gEfiAcpiVariableGuid GUIDed HOB.
+# - verify & configure the Q35 TSEG in the entry point.
#
# Copyright (C) 2013, 2015, Red Hat, Inc.
+# Copyright (c) 2024 Intel Corporation.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -36,9 +35,6 @@
MdePkg/MdePkg.dec
OvmfPkg/OvmfPkg.dec
-[Guids]
- gEfiAcpiVariableGuid
-
[LibraryClasses]
BaseLib
BaseMemoryLib
@@ -57,6 +53,9 @@
gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase
gUefiOvmfPkgTokenSpaceGuid.PcdQ35TsegMbytes
+[Guids]
+ gEfiSmmSmramMemoryGuid # ALWAYS_CONSUMED
+
[Ppis]
gPeiSmmAccessPpiGuid ## PRODUCES
diff --git a/OvmfPkg/SmmAccess/SmramInternal.c b/OvmfPkg/SmmAccess/SmramInternal.c
index d391ddc9ae..ff67d302a2 100644
--- a/OvmfPkg/SmmAccess/SmramInternal.c
+++ b/OvmfPkg/SmmAccess/SmramInternal.c
@@ -3,12 +3,11 @@
Functions and types shared by the SMM accessor PEI and DXE modules.
Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2024 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-
-#include <Guid/AcpiS3Context.h>
#include <IndustryStandard/Q35MchIch9.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
@@ -166,68 +165,43 @@ SmramAccessLock (
EFI_STATUS
SmramAccessGetCapabilities (
- IN BOOLEAN LockState,
- IN BOOLEAN OpenState,
IN OUT UINTN *SmramMapSize,
IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
)
{
- UINTN OriginalSize;
- UINT32 TsegMemoryBaseMb, TsegMemoryBase;
- UINT64 CommonRegionState;
- UINT8 TsegSizeBits;
-
- OriginalSize = *SmramMapSize;
- *SmramMapSize = DescIdxCount * sizeof *SmramMap;
- if (OriginalSize < *SmramMapSize) {
- return EFI_BUFFER_TOO_SMALL;
- }
+ UINTN BufferSize;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;
+ UINTN Index;
//
- // Read the TSEG Memory Base register.
+ // Get Hob list
//
- TsegMemoryBaseMb = PciRead32 (DRAMC_REGISTER_Q35 (MCH_TSEGMB));
- TsegMemoryBase = (TsegMemoryBaseMb >> MCH_TSEGMB_MB_SHIFT) << 20;
+ GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
+ DescriptorBlock = GET_GUID_HOB_DATA (GuidHob);
+ ASSERT (DescriptorBlock);
- //
- // Precompute the region state bits that will be set for all regions.
- //
- CommonRegionState = (OpenState ? EFI_SMRAM_OPEN : EFI_SMRAM_CLOSED) |
- (LockState ? EFI_SMRAM_LOCKED : 0) |
- EFI_CACHEABLE;
+ BufferSize = DescriptorBlock->NumberOfSmmReservedRegions * sizeof (EFI_SMRAM_DESCRIPTOR);
- //
- // The first region hosts an SMM_S3_RESUME_STATE object. It is located at the
- // start of TSEG. We round up the size to whole pages, and we report it as
- // EFI_ALLOCATED, so that the SMM_CORE stays away from it.
- //
- SmramMap[DescIdxSmmS3ResumeState].PhysicalStart = TsegMemoryBase;
- SmramMap[DescIdxSmmS3ResumeState].CpuStart = TsegMemoryBase;
- SmramMap[DescIdxSmmS3ResumeState].PhysicalSize =
- EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (sizeof (SMM_S3_RESUME_STATE)));
- SmramMap[DescIdxSmmS3ResumeState].RegionState =
- CommonRegionState | EFI_ALLOCATED;
+ if (*SmramMapSize < BufferSize) {
+ *SmramMapSize = BufferSize;
+ return EFI_BUFFER_TOO_SMALL;
+ }
//
- // Get the TSEG size bits from the ESMRAMC register.
+ // Update SmramMapSize to real return SMRAM map size
//
- TsegSizeBits = PciRead8 (DRAMC_REGISTER_Q35 (MCH_ESMRAMC)) &
- MCH_ESMRAMC_TSEG_MASK;
+ *SmramMapSize = BufferSize;
//
- // The second region is the main one, following the first.
+ // Use the hob to publish SMRAM capabilities
//
- SmramMap[DescIdxMain].PhysicalStart =
- SmramMap[DescIdxSmmS3ResumeState].PhysicalStart +
- SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
- SmramMap[DescIdxMain].CpuStart = SmramMap[DescIdxMain].PhysicalStart;
- SmramMap[DescIdxMain].PhysicalSize =
- (TsegSizeBits == MCH_ESMRAMC_TSEG_8MB ? SIZE_8MB :
- TsegSizeBits == MCH_ESMRAMC_TSEG_2MB ? SIZE_2MB :
- TsegSizeBits == MCH_ESMRAMC_TSEG_1MB ? SIZE_1MB :
- mQ35TsegMbytes * SIZE_1MB) -
- SmramMap[DescIdxSmmS3ResumeState].PhysicalSize;
- SmramMap[DescIdxMain].RegionState = CommonRegionState;
+ for (Index = 0; Index < DescriptorBlock->NumberOfSmmReservedRegions; Index++) {
+ SmramMap[Index].PhysicalStart = DescriptorBlock->Descriptor[Index].PhysicalStart;
+ SmramMap[Index].CpuStart = DescriptorBlock->Descriptor[Index].CpuStart;
+ SmramMap[Index].PhysicalSize = DescriptorBlock->Descriptor[Index].PhysicalSize;
+ SmramMap[Index].RegionState = DescriptorBlock->Descriptor[Index].RegionState;
+ }
return EFI_SUCCESS;
}
diff --git a/OvmfPkg/SmmAccess/SmramInternal.h b/OvmfPkg/SmmAccess/SmramInternal.h
index da5b7bbca1..aa23c6dff8 100644
--- a/OvmfPkg/SmmAccess/SmramInternal.h
+++ b/OvmfPkg/SmmAccess/SmramInternal.h
@@ -3,6 +3,7 @@
Functions and types shared by the SMM accessor PEI and DXE modules.
Copyright (C) 2015, Red Hat, Inc.
+ Copyright (c) 2024 Intel Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -10,20 +11,8 @@
#include <Pi/PiMultiPhase.h>
-//
-// We'll have two SMRAM ranges.
-//
-// The first is a tiny one that hosts an SMM_S3_RESUME_STATE object, to be
-// filled in by the CPU SMM driver during normal boot, for the PEI instance of
-// the LockBox library (which will rely on the object during S3 resume).
-//
-// The other SMRAM range is the main one, for the SMM core and the SMM drivers.
-//
-typedef enum {
- DescIdxSmmS3ResumeState = 0,
- DescIdxMain = 1,
- DescIdxCount = 2
-} DESCRIPTOR_INDEX;
+#include <Guid/SmramMemoryReserve.h>
+#include <Library/HobLib.h>
//
// The value of PcdQ35TsegMbytes is saved into this variable at module startup.
@@ -97,8 +86,6 @@ SmramAccessLock (
EFI_STATUS
SmramAccessGetCapabilities (
- IN BOOLEAN LockState,
- IN BOOLEAN OpenState,
IN OUT UINTN *SmramMapSize,
IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap
);
diff --git a/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.c b/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.c
index 6ca29f5de0..5241f60891 100644
--- a/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.c
+++ b/OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.c
@@ -821,11 +821,16 @@ Is800155Event (
{
if ((((TCG_PCR_EVENT2_HDR *)NewEventHdr)->EventType == EV_NO_ACTION) &&
(NewEventSize >= sizeof (TCG_Sp800_155_PlatformId_Event2)) &&
- (CompareMem (
- NewEventData,
- TCG_Sp800_155_PlatformId_Event2_SIGNATURE,
- sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1
- ) == 0))
+ ((CompareMem (
+ NewEventData,
+ TCG_Sp800_155_PlatformId_Event2_SIGNATURE,
+ sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1
+ ) == 0) ||
+ (CompareMem (
+ NewEventData,
+ TCG_Sp800_155_PlatformId_Event3_SIGNATURE,
+ sizeof (TCG_Sp800_155_PlatformId_Event3_SIGNATURE) - 1
+ ) == 0)))
{
return TRUE;
}
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.c b/OvmfPkg/VirtioRngDxe/VirtioRng.c
index 069aed148a..8959e51faf 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.c
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.c
@@ -156,6 +156,11 @@ VirtioRngGetRNG (
}
Dev = VIRTIO_ENTROPY_SOURCE_FROM_RNG (This);
+ if (!Dev->Ready) {
+ DEBUG ((DEBUG_INFO, "%a: not ready\n", __func__));
+ return EFI_DEVICE_ERROR;
+ }
+
//
// Map Buffer's system physical address to device address
//
@@ -382,6 +387,7 @@ VirtioRngInit (
//
Dev->Rng.GetInfo = VirtioRngGetInfo;
Dev->Rng.GetRNG = VirtioRngGetRNG;
+ Dev->Ready = TRUE;
return EFI_SUCCESS;
@@ -414,8 +420,8 @@ VirtioRngUninit (
// VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
// the old comms area.
//
+ Dev->Ready = FALSE;
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
-
Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
@@ -435,7 +441,7 @@ VirtioRngExitBoot (
{
VIRTIO_RNG_DEV *Dev;
- DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __func__, Context));
+ DEBUG ((DEBUG_INFO, "%a: Context=0x%p\n", __func__, Context));
//
// Reset the device. This causes the hypervisor to forget about the virtio
// ring.
@@ -443,7 +449,8 @@ VirtioRngExitBoot (
// We allocated said ring in EfiBootServicesData type memory, and code
// executing after ExitBootServices() is permitted to overwrite it.
//
- Dev = Context;
+ Dev = Context;
+ Dev->Ready = FALSE;
Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
}
diff --git a/OvmfPkg/VirtioRngDxe/VirtioRng.h b/OvmfPkg/VirtioRngDxe/VirtioRng.h
index 2da99540a2..3519521d6a 100644
--- a/OvmfPkg/VirtioRngDxe/VirtioRng.h
+++ b/OvmfPkg/VirtioRngDxe/VirtioRng.h
@@ -33,6 +33,7 @@ typedef struct {
VRING Ring; // VirtioRingInit 2
EFI_RNG_PROTOCOL Rng; // VirtioRngInit 1
VOID *RingMap; // VirtioRingMap 2
+ BOOLEAN Ready;
} VIRTIO_RNG_DEV;
#define VIRTIO_ENTROPY_SOURCE_FROM_RNG(RngPointer) \
diff --git a/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h b/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
index 51a1861639..b6e60635ea 100644
--- a/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
+++ b/RedfishPkg/Include/Library/RedfishPlatformConfigLib.h
@@ -2,7 +2,7 @@
Definitions of RedfishPlatformConfigLib
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -82,7 +82,7 @@ RedfishPlatformConfigGetConfigureLang (
Get the list of supported Redfish schema from platform configuration.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
index d20b2c980e..a1d5592c7e 100644
--- a/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
+++ b/RedfishPkg/Include/Protocol/EdkIIRedfishPlatformConfig.h
@@ -2,7 +2,7 @@
This file defines the EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL interface.
(C) Copyright 2021-2022 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -227,7 +227,7 @@ EFI_STATUS
@param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
index 3500b6aa8f..decb1fd012 100644
--- a/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
+++ b/RedfishPkg/Library/RedfishPlatformConfigLib/RedfishPlatformConfigLib.c
@@ -2,7 +2,7 @@
Wrapper function to support Redfish Platform Config protocol.
(C) Copyright 2021 Hewlett Packard Enterprise Development LP<BR>
- Copyright (c) 2022-2023, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+ Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -191,7 +191,7 @@ RedfishPlatformConfigGetConfigureLang (
Get the list of supported Redfish schema from platform configuration.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/RedfishPkg.dec b/RedfishPkg/RedfishPkg.dec
index c048e43f53..54318527fe 100644
--- a/RedfishPkg/RedfishPkg.dec
+++ b/RedfishPkg/RedfishPkg.dec
@@ -195,10 +195,10 @@
gEfiRedfishPkgTokenSpaceGuid.PcdRedfishDebugCategory|0|UINT64|0x00001012
#
# Redfish RedfishPlatformConfigDxe Debug Properties
- # 0x00000001 x-uefi-redfish string database message enabled
+ # 0x00000001 x-UEFI-redfish string database message enabled
# 0x00000002 Debug Message for dumping formset
- # 0x00000004 Debug Message for x-uefi-redfish searching result
- # 0x00000008 Debug Message for x-uefi-redfish Regular Expression searching result
+ # 0x00000004 Debug Message for x-UEFI-redfish searching result
+ # 0x00000008 Debug Message for x-UEFI-redfish Regular Expression searching result
#
gEfiRedfishPkgTokenSpaceGuid.PcdRedfishPlatformConfigDebugProperty|0|UINT32|0x00001013
#
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
index 8bcee5a16a..46d01fca60 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.c
@@ -1419,7 +1419,7 @@ HiiValueToRedfishValue (
RedfishValue->Value.Buffer = HiiGetRedfishAsciiString (HiiHandle, FullSchema, HiiStatement->ExtraData.TextTwo);
if (RedfishValue->Value.Buffer == NULL) {
//
- // No x-uefi-redfish string defined. Try to get string in English.
+ // No x-UEFI-redfish string defined. Try to get string in English.
//
RedfishValue->Value.Buffer = HiiGetEnglishAsciiString (HiiHandle, HiiStatement->ExtraData.TextTwo);
}
@@ -2112,7 +2112,7 @@ RELEASE_RESOURCE:
@param[in] This Pointer to EDKII_REDFISH_PLATFORM_CONFIG_PROTOCOL instance.
@param[out] SupportedSchema The supported schema list which is separated by ';'.
- For example: "x-uefi-redfish-Memory.v1_7_1;x-uefi-redfish-Boot.v1_0_1"
+ For example: "x-UEFI-redfish-Memory.v1_7_1;x-UEFI-redfish-Boot.v1_0_1"
The SupportedSchema is allocated by the callee. It's caller's
responsibility to free this buffer using FreePool().
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
index 8eb7b0dc2a..e3e185a03b 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigDxe.h
@@ -111,7 +111,7 @@ typedef struct {
#define REDFISH_PLATFORM_CONFIG_PRIVATE_FROM_THIS(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_PRIVATE, Protocol)
#define REGULAR_EXPRESSION_INCLUDE_ALL L".*"
-#define CONFIGURE_LANGUAGE_PREFIX "x-uefi-redfish-"
+#define CONFIGURE_LANGUAGE_PREFIX "x-UEFI-redfish-"
#define REDFISH_PLATFORM_CONFIG_VERSION 0x00010000
#define REDFISH_MENU_PATH_SIZE 8
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
index 5fcaf42610..6a90e31f6a 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.c
@@ -657,7 +657,7 @@ GetStatementPrivateByConfigureLangRegex (
}
} else {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
- DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-uefi-string has something wrong.\n", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-UEFI-string has something wrong.\n", __func__));
ASSERT (FALSE);
}
}
@@ -758,7 +758,7 @@ GetStatementPrivateByConfigureLang (
}
} else {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
- DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-uefi-string has something wrong.\n", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: HiiStatementPrivate->XuefiRedfishStr is NULL, x-UEFI-string has something wrong.\n", __func__));
ASSERT (FALSE);
}
}
@@ -819,7 +819,7 @@ GetFormsetPrivateByHiiHandle (
}
/**
- Release x-uefi-string related information.
+ Release x-UEFI-string related information.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@@ -842,7 +842,7 @@ ReleaseXuefiStringDatabase (
FreePool (FormsetPrivate->HiiPackageListHeader);
}
- // Walk through x-uefi-redfish string database.
+ // Walk through x-UEFI-redfish string database.
if (!IsListEmpty (&FormsetPrivate->XuefiRedfishStringDatabase)) {
EndDatabase = FALSE;
ThisDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)GetFirstNode (&FormsetPrivate->XuefiRedfishStringDatabase);
@@ -989,9 +989,9 @@ NewFormsetPrivate (
}
/**
- Create new x-uefi-redfish string array.
+ Create new x-UEFI-redfish string array.
- @param[in] XuefiRedfishStringDatabase The x-uefi-redfish string database.
+ @param[in] XuefiRedfishStringDatabase The x-UEFI-redfish string database.
@retval EFI_OUT_OF_RESOURCES Not enough memory for creating a new array.
EFI_SUCCESS New array is created successfully.
@@ -1028,13 +1028,13 @@ NewRedfishXuefiStringArray (
}
/**
- Get the pointer of x-uefi-redfish database or create a new database.
+ Get the pointer of x-UEFI-redfish database or create a new database.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] HiiStringPackageHeader HII string package header.
@retval Pointer to REDFISH_X_UEFI_STRING_DATABASE.
- If NULL, it fails to obtain x-uefi-redfish database.
+ If NULL, it fails to obtain x-UEFI-redfish database.
**/
REDFISH_X_UEFI_STRING_DATABASE *
@@ -1068,7 +1068,7 @@ GetExistOrCreateXuefiStringDatabase (
}
if (CreateNewOne) {
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Creating x-uefi-redfish (%a) string database...\n", HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Creating x-UEFI-redfish (%a) string database...\n", HiiStringPackageHeader->Language));
XuefiRedfishStringDatabase = (REDFISH_X_UEFI_STRING_DATABASE *)AllocateZeroPool (sizeof (REDFISH_X_UEFI_STRING_DATABASE));
if (XuefiRedfishStringDatabase == NULL) {
DEBUG ((DEBUG_ERROR, " Failed to allocate REDFISH_X_UEFI_STRING_DATABASE.\n"));
@@ -1088,7 +1088,7 @@ GetExistOrCreateXuefiStringDatabase (
DEBUG ((
DEBUG_REDFISH_PLATFORM_CONFIG,
- " x-uefi-redfish (%a):\n String array is added to XuefiRedfishStringDatabase, total %d arrays now.\n",
+ " x-UEFI-redfish (%a):\n String array is added to XuefiRedfishStringDatabase, total %d arrays now.\n",
XuefiRedfishStringDatabase->XuefiRedfishLanguage,
XuefiRedfishStringDatabase->StringsArrayBlocks
));
@@ -1101,14 +1101,14 @@ GetExistOrCreateXuefiStringDatabase (
}
/**
- Check and allocate a new x-uefi-redfish array if it is insufficient for the
- newly added x-uefi-redfish string.
+ Check and allocate a new x-UEFI-redfish array if it is insufficient for the
+ newly added x-UEFI-redfish string.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
- @param[in] XuefiRedfishStringDatabase Pointer to the x-uefi-redfish database.
+ @param[in] XuefiRedfishStringDatabase Pointer to the x-UEFI-redfish database.
@param[in] StringId String ID added to database.
- @retval EFI_SUCCESS The size of x-uefi-string array is adjusted or
+ @retval EFI_SUCCESS The size of x-UEFI-string array is adjusted or
is not required to be adjusted.
Otherwise, refer to the error code returned from NewRedfishXuefiStringArray().
@@ -1125,7 +1125,7 @@ RedfishXuefiStringAdjustArrays (
while (((StringId + X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) / X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) > (UINT16)XuefiRedfishStringDatabase->StringsArrayBlocks) {
Status = NewRedfishXuefiStringArray (XuefiRedfishStringDatabase);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-uefi-string array", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-UEFI-string array", __func__));
return Status;
}
}
@@ -1134,7 +1134,7 @@ RedfishXuefiStringAdjustArrays (
}
/**
- Insert a x-uefi-redfish string to database.
+ Insert a x-UEFI-redfish string to database.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] HiiStringPackageHeader Pointer to HII string package.
@@ -1161,19 +1161,19 @@ RedfishXuefiStringInsertDatabase (
XuefiRedfishStringDatabase = GetExistOrCreateXuefiStringDatabase (FormsetPrivate, HiiStringPackageHeader);
if (XuefiRedfishStringDatabase == NULL) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to get REDFISH_X_UEFI_STRING_DATABASE of x-uefi-redfish language %a.\n", __func__, HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to get REDFISH_X_UEFI_STRING_DATABASE of x-UEFI-redfish language %a.\n", __func__, HiiStringPackageHeader->Language));
ReleaseXuefiStringDatabase (FormsetPrivate);
return EFI_LOAD_ERROR;
}
Status = RedfishXuefiStringAdjustArrays (FormsetPrivate, XuefiRedfishStringDatabase, StringId);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-uefi-redfish string array.\n", __func__));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to adjust x-UEFI-redfish string array.\n", __func__));
ReleaseXuefiStringDatabase (FormsetPrivate);
return EFI_LOAD_ERROR;
}
- // Insert string to x-uefi-redfish string array.
+ // Insert string to x-UEFI-redfish string array.
StringIdOffset = (UINTN)StringId;
ThisArray = (REDFISH_X_UEFI_STRINGS_ARRAY *)GetFirstNode (&XuefiRedfishStringDatabase->XuefiRedfishStringArrays);
while (StringIdOffset >= X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER) {
@@ -1187,7 +1187,7 @@ RedfishXuefiStringInsertDatabase (
DEBUG_REDFISH_THIS_MODULE (
REDFISH_PLATFORM_CONFIG_DEBUG_STRING_DATABASE,
- " Insert string ID: (%d) to database\n x-uefi-string: \"%s\"\n Language: %a.\n",
+ " Insert string ID: (%d) to database\n x-UEFI-string: \"%s\"\n Language: %a.\n",
StringId,
StringTextPtr,
HiiStringPackageHeader->Language
@@ -1196,14 +1196,14 @@ RedfishXuefiStringInsertDatabase (
}
/**
- Get x-uefi-redfish string and language by string ID.
+ Get x-UEFI-redfish string and language by string ID.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] HiiStringPackageHeader HII string package header.
@param[out] TotalStringAdded Return the total strings added to database.
- @retval TRUE x-uefi-redfish string and ID map is inserted to database.
- FALSE Something is wrong when insert x-uefi-redfish string and ID map.
+ @retval TRUE x-UEFI-redfish string and ID map is inserted to database.
+ FALSE Something is wrong when insert x-UEFI-redfish string and ID map.
**/
BOOLEAN
@@ -1288,7 +1288,7 @@ CreateXuefiLanguageStringIdMap (
Offset = sizeof (EFI_HII_STRING_BLOCK);
StringTextPtr = BlockHdr + Offset;
- // x-uefi-redfish string is always encoded as UCS and started with '/'.
+ // x-UEFI-redfish string is always encoded as UCS and started with '/'.
if (*StringTextPtr == (UINT16)'/') {
Status = RedfishXuefiStringInsertDatabase (
FormsetPrivate,
@@ -1297,7 +1297,7 @@ CreateXuefiLanguageStringIdMap (
(CHAR16 *)StringTextPtr
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "%a: Failed to insert x-uefi-redfish string %s.\n", __func__, StringTextPtr));
+ DEBUG ((DEBUG_ERROR, "%a: Failed to insert x-UEFI-redfish string %s.\n", __func__, StringTextPtr));
return FALSE;
}
@@ -1398,13 +1398,13 @@ CreateXuefiLanguageStringIdMap (
}
/**
- Get x-uefi-redfish string and language by string ID.
+ Get x-UEFI-redfish string and language by string ID.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@param[in] StringId The HII string ID.
@param[out] String Optionally return USC string.
- @param[out] Language Optionally return x-uefi-redfish language.
- @param[out] XuefiStringDatabase Optionally return x-uefi-redfish database.
+ @param[out] Language Optionally return x-UEFI-redfish language.
+ @param[out] XuefiStringDatabase Optionally return x-UEFI-redfish database.
@retval EFI_SUCCESS String information is returned.
EFI_INVALID_PARAMETER One of the given parameters to this function is
@@ -1456,7 +1456,7 @@ GetXuefiStringAndLangByStringId (
//
// NOTE: The string ID in the formset is a unique number.
// If the string in the array is NULL, then the matched string ID
- // should be in another x-uefi-redfish database.
+ // should be in another x-UEFI-redfish database.
//
if ((StringArray->ArrayEntryAddress + StringIndex)->UcsString != NULL) {
//
@@ -1489,7 +1489,7 @@ ErrorExit:;
}
/**
- Build a x-uefi-redfish database for the newly added x-uefi-redfish language.
+ Build a x-UEFI-redfish database for the newly added x-UEFI-redfish language.
@param[in] FormsetPrivate Pointer to HII form-set private instance.
@@ -1510,7 +1510,7 @@ BuildXUefiRedfishStringDatabase (
UINTN TotalStringsAdded;
UINTN NumberPackageStrings;
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Building x-uefi-redfish string database, HII Formset GUID - %g.\n", __func__, FormsetPrivate->Guid));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: Building x-UEFI-redfish string database, HII Formset GUID - %g.\n", __func__, FormsetPrivate->Guid));
BufferSize = 0;
Status = mRedfishPlatformConfigPrivate->HiiDatabase->ExportPackageLists (
@@ -1555,7 +1555,7 @@ BuildXUefiRedfishStringDatabase (
StringIdMapIsBuilt = FALSE;
HiiStringPackageHeader = (EFI_HII_STRING_PACKAGE_HDR *)PackageHeader;
- // Check if this is the string package for x-uefi-redfish
+ // Check if this is the string package for x-UEFI-redfish
for (SupportedSchemaLangCount = 0;
SupportedSchemaLangCount < FormsetPrivate->SupportedSchema.Count;
SupportedSchemaLangCount++
@@ -1578,9 +1578,9 @@ BuildXUefiRedfishStringDatabase (
if (StringIdMapIsBuilt == FALSE) {
if (AsciiStrStr (HiiStringPackageHeader->Language, X_UEFI_SCHEMA_PREFIX) == NULL) {
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " No need to build x-uefi-redfish string ID map for HII language %a\n", HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " No need to build x-UEFI-redfish string ID map for HII language %a\n", HiiStringPackageHeader->Language));
} else {
- DEBUG ((DEBUG_ERROR, " Failed to build x-uefi-redfish string ID map of HII language %a\n", HiiStringPackageHeader->Language));
+ DEBUG ((DEBUG_ERROR, " Failed to build x-UEFI-redfish string ID map of HII language %a\n", HiiStringPackageHeader->Language));
}
}
@@ -1589,7 +1589,7 @@ BuildXUefiRedfishStringDatabase (
}
}
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Total %d x-uefi-redfish config language are added.\n", TotalStringsAdded));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, " Total %d x-UEFI-redfish config language are added.\n", TotalStringsAdded));
}
/**
@@ -1599,7 +1599,7 @@ BuildXUefiRedfishStringDatabase (
@param[out] FormsetPrivate The formset private data.
@retval EFI_STATUS The formset is loaded successfully.
- @retval EFI_UNSUPPORTED This formset doesn't have any x-uefi-redfish configuration.
+ @retval EFI_UNSUPPORTED This formset doesn't have any x-UEFI-redfish configuration.
**/
EFI_STATUS
@@ -1656,15 +1656,15 @@ LoadFormset (
Status = GetSupportedSchema (FormsetPrivate->HiiHandle, &FormsetPrivate->SupportedSchema);
if (EFI_ERROR (Status)) {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
- DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: No x-uefi-redfish configuration found on the formset - %g\n", __func__, FormsetPrivate->Guid));
+ DEBUG ((DEBUG_REDFISH_PLATFORM_CONFIG, "%a: No x-UEFI-redfish configuration found on the formset - %g\n", __func__, FormsetPrivate->Guid));
//
- // If there is no x-uefi-redfish language in this form-set, we don't add formset
+ // If there is no x-UEFI-redfish language in this form-set, we don't add formset
// since we don't need to build menu path for attribute registry.
//
return EFI_UNSUPPORTED;
}
} else {
- // Building x-uefi-redfish string database
+ // Building x-UEFI-redfish string database
BuildXUefiRedfishStringDatabase (FormsetPrivate);
}
@@ -1739,7 +1739,7 @@ LoadFormset (
}
}
- // Get x-uefi-redfish string using String ID.
+ // Get x-UEFI-redfish string using String ID.
Status = GetXuefiStringAndLangByStringId (FormsetPrivate, HiiStatementPrivate->Description, &String, NULL, NULL);
if (!EFI_ERROR (Status)) {
HiiStatementPrivate->XuefiRedfishStr = String;
@@ -1750,13 +1750,13 @@ LoadFormset (
} else {
if (!RedfishPlatformConfigFeatureProp (REDFISH_PLATFORM_CONFIG_BUILD_MENU_PATH)) {
//
- // If there is no x-uefi-redfish language for this statement, we don't add this statement
+ // If there is no x-UEFI-redfish language for this statement, we don't add this statement
// since we don't need to build menu path for attribute registry.
//
FreePool (HiiStatementPrivate);
} else {
//
- // This is not x-uefi-redfish string and we don't cache its string for searching Redfish configure language.
+ // This is not x-UEFI-redfish string and we don't cache its string for searching Redfish configure language.
// When caller wants the string, we will read English string by calling HiiGetString().
//
HiiStatementPrivate->XuefiRedfishStr = NULL;
@@ -2111,7 +2111,7 @@ ProcessPendingList (
Status = LoadFormsetList (Target->HiiHandle, FormsetList);
if (EFI_ERROR (Status)) {
if (Status == EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_ERROR, " The formset has no x-uefi-redfish configurations.\n"));
+ DEBUG ((DEBUG_ERROR, " The formset has no x-UEFI-redfish configurations.\n"));
} else {
DEBUG ((DEBUG_ERROR, " load formset from HII handle: 0x%x failed: %r\n", Target->HiiHandle, Status));
}
diff --git a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
index 24a7dae517..525ca43fa9 100644
--- a/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
+++ b/RedfishPkg/RedfishPlatformConfigDxe/RedfishPlatformConfigImpl.h
@@ -29,7 +29,7 @@
#define IS_EMPTY_STRING(a) (a == NULL || a[0] == L'\0')
#define ENGLISH_LANGUAGE_CODE "en-US"
-#define X_UEFI_SCHEMA_PREFIX "x-uefi-redfish-"
+#define X_UEFI_SCHEMA_PREFIX "x-UEFI-redfish-"
#define MAX_X_UEFI_REDFISH_STRING_SIZE (128 * 2)// 128 character in UCS.
@@ -55,7 +55,7 @@ typedef struct {
#define X_UEFI_REDFISH_STRING_ARRAY_ENTRY_NUMBER 1024
//
-// Definition of x-uefi-redfish string element.
+// Definition of x-UEFI-redfish string element.
//
typedef struct {
EFI_STRING_ID StringId;
@@ -71,14 +71,14 @@ typedef struct {
} REDFISH_X_UEFI_STRINGS_ARRAY;
//
-// x-uefi-redfish string database, x-uefi-redfish language based.
+// x-UEFI-redfish string database, x-UEFI-redfish language based.
//
typedef struct {
- LIST_ENTRY NextXuefiRedfishLanguage; // Link to the next suppoted x-uefi-Redfish language.
- CHAR8 *XuefiRedfishLanguage; // x-uefi-redfish language.
+ LIST_ENTRY NextXuefiRedfishLanguage; // Link to the next suppoted x-UEFI-Redfish language.
+ CHAR8 *XuefiRedfishLanguage; // x-UEFI-redfish language.
UINTN StringsArrayBlocks; // Number of the array blocks that accommodate X_UEFI_REDFISH_STRING_ARRAY_NUMBER
// elements in each.
- LIST_ENTRY XuefiRedfishStringArrays; // Link entry of x-uefi-redfish string array.
+ LIST_ENTRY XuefiRedfishStringArrays; // Link entry of x-UEFI-redfish string array.
} REDFISH_X_UEFI_STRING_DATABASE;
//
@@ -93,7 +93,7 @@ typedef struct {
LIST_ENTRY HiiFormList; // Form list that keep form data under this formset.
CHAR16 *DevicePathStr; // Device path of this formset.
REDFISH_PLATFORM_CONFIG_SCHEMA SupportedSchema; // Schema that is supported in this formset.
- LIST_ENTRY XuefiRedfishStringDatabase; // x-uefi-redfish string/Id data base;
+ LIST_ENTRY XuefiRedfishStringDatabase; // x-UEFI-redfish string/Id data base;
} REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE;
#define REDFISH_PLATFORM_CONFIG_FORMSET_FROM_LINK(a) BASE_CR (a, REDFISH_PLATFORM_CONFIG_FORM_SET_PRIVATE, Link)
@@ -133,7 +133,7 @@ struct _REDFISH_PLATFORM_CONFIG_STATEMENT_PRIVATE {
HII_STATEMENT *HiiStatement; // Pointer to HII statement data.
EFI_QUESTION_ID QuestionId; // Question ID of this statement.
EFI_STRING_ID Description; // String token of this question.
- CHAR16 *XuefiRedfishStr; // x-uefi-redfish string of this question.
+ CHAR16 *XuefiRedfishStr; // x-UEFI-redfish string of this question.
EFI_STRING_ID Help; // String token of help message.
UINT8 Flags; // The statement flag.
REDFISH_PLATFORM_CONFIG_STATEMENT_DATA StatementData; // The max/min for statement value.
diff --git a/SecurityPkg/DeviceSecurity/SpdmLib/libspdm b/SecurityPkg/DeviceSecurity/SpdmLib/libspdm
-Subproject 828ef62524bcaeca4e90d0c021221e714872e2b
+Subproject 50924a4c8145fc721e17208f55814d2b38766fe
diff --git a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
index 7e06e16e4b..5723ed6957 100644
--- a/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
+++ b/SecurityPkg/RandomNumberGenerator/RngDxe/Rand/RngDxe.c
@@ -116,14 +116,6 @@ RngGetRNG (
// 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 = GenerateEntropy (RNGValueLength, RNGValue);
return Status;
}
diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
index b8f50e25df..b55b6c12d2 100644
--- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
+++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c
@@ -812,11 +812,16 @@ Is800155Event (
{
if ((((TCG_PCR_EVENT2_HDR *)NewEventHdr)->EventType == EV_NO_ACTION) &&
(NewEventSize >= sizeof (TCG_Sp800_155_PlatformId_Event2)) &&
- (CompareMem (
- NewEventData,
- TCG_Sp800_155_PlatformId_Event2_SIGNATURE,
- sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1
- ) == 0))
+ ((CompareMem (
+ NewEventData,
+ TCG_Sp800_155_PlatformId_Event2_SIGNATURE,
+ sizeof (TCG_Sp800_155_PlatformId_Event2_SIGNATURE) - 1
+ ) == 0) ||
+ (CompareMem (
+ NewEventData,
+ TCG_Sp800_155_PlatformId_Event3_SIGNATURE,
+ sizeof (TCG_Sp800_155_PlatformId_Event3_SIGNATURE) - 1
+ ) == 0)))
{
return TRUE;
}
diff --git a/StandaloneMmPkg/Core/Mmi.c b/StandaloneMmPkg/Core/Mmi.c
index e035245c87..fb205df490 100644
--- a/StandaloneMmPkg/Core/Mmi.c
+++ b/StandaloneMmPkg/Core/Mmi.c
@@ -174,6 +174,7 @@ MmiManage (
EFI_STATUS Status;
mMmiManageCallingDepth++;
+ WillReturn = FALSE;
Status = EFI_NOT_FOUND;
ReturnStatus = Status;
if (HandlerType == NULL) {
diff --git a/UefiCpuPkg/Include/Library/SmmRelocationLib.h b/UefiCpuPkg/Include/Library/SmmRelocationLib.h
new file mode 100644
index 0000000000..999a5b46d1
--- /dev/null
+++ b/UefiCpuPkg/Include/Library/SmmRelocationLib.h
@@ -0,0 +1,42 @@
+/** @file
+ Header file for SMM Relocation Library.
+
+ The SmmRelocationLib class provides the SmmRelocationInit()
+ interface for platform to do the smbase relocation, which
+ shall provide below 2 functionalities:
+ 1. Relocate SmBases for each processor.
+ 2. Create the SmBase HOB (gSmmBaseHobGuid).
+
+ With SmmRelocationLib, PiSmmCpuDxeSmm driver (which runs at a later phase)
+ shall:
+ 1. Consume the gSmmBaseHobGuid for the relocated smbase for each Processor.
+ 2. Execute early SMM init.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef SMM_RELOCATION_LIB_H_
+#define SMM_RELOCATION_LIB_H_
+
+#include <Ppi/MpServices2.h>
+
+/**
+ CPU SmmBase Relocation Init.
+
+ This function is to relocate CPU SmmBase.
+
+ @param[in] MpServices2 Pointer to this instance of the MpServices.
+
+ @retval EFI_SUCCESS CPU SmmBase Relocated successfully.
+ @retval Others CPU SmmBase Relocation failed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmRelocationInit (
+ IN EDKII_PEI_MP_SERVICES2_PPI *MpServices2
+ );
+
+#endif
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index d724456502..4bf3dc5fca 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c
@@ -1,7 +1,7 @@
/** @file
CPU MP Initialize Library common functions.
- Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2020 - 2024, AMD Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -114,6 +114,10 @@ FutureBSPProc (
SaveVolatileRegisters (&DataInHob->APInfo.VolatileRegisters);
AsmExchangeRole (&DataInHob->APInfo, &DataInHob->BSPInfo);
RestoreVolatileRegisters (&DataInHob->APInfo.VolatileRegisters, FALSE);
+ //
+ // Update VolatileRegisters saved in CpuMpData->CpuData
+ //
+ CopyMem (&DataInHob->CpuData[DataInHob->BspNumber].VolatileRegisters, &DataInHob->APInfo.VolatileRegisters, sizeof (CPU_VOLATILE_REGISTERS));
}
/**
@@ -761,11 +765,11 @@ ApWakeupFunction (
BistData = (UINT32)ApStackData->Bist;
//
- // CpuMpData->CpuData[0].VolatileRegisters is initialized based on BSP environment,
+ // CpuMpData->CpuData[BspNumber].VolatileRegisters is initialized based on BSP environment,
// to initialize AP in InitConfig path.
- // NOTE: IDTR.BASE stored in CpuMpData->CpuData[0].VolatileRegisters points to a different IDT shared by all APs.
+ // NOTE: IDTR.BASE stored in CpuMpData->CpuData[BspNumber].VolatileRegisters points to a different IDT shared by all APs.
//
- RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
+ RestoreVolatileRegisters (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, FALSE);
InitializeApData (CpuMpData, ProcessorNumber, BistData, ApTopOfStack);
ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal;
} else {
@@ -798,10 +802,10 @@ ApWakeupFunction (
// 1. AP is re-enabled after it's disabled, in either PEI or DXE phase.
// 2. AP is initialized in DXE phase.
// In either case, use the volatile registers value derived from BSP.
- // NOTE: IDTR.BASE stored in CpuMpData->CpuData[0].VolatileRegisters points to a
+ // NOTE: IDTR.BASE stored in CpuMpData->CpuData[BspNumber].VolatileRegisters points to a
// different IDT shared by all APs.
//
- RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
+ RestoreVolatileRegisters (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, FALSE);
} else {
if (CpuMpData->ApLoopMode == ApInHltLoop) {
//
@@ -927,7 +931,7 @@ DxeApEntryPoint (
AsmWriteMsr64 (MSR_IA32_EFER, EferMsr.Uint64);
}
- RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE);
+ RestoreVolatileRegisters (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, FALSE);
InterlockedIncrement ((UINT32 *)&CpuMpData->FinishedCount);
PlaceAPInMwaitLoopOrRunLoop (
CpuMpData->ApLoopMode,
@@ -2151,11 +2155,16 @@ MpInitLibInitialize (
CpuMpData->BackupBufferSize = ApResetVectorSizeBelow1Mb;
CpuMpData->WakeupBuffer = (UINTN)-1;
CpuMpData->CpuCount = 1;
- CpuMpData->BspNumber = 0;
- CpuMpData->WaitEvent = NULL;
- CpuMpData->SwitchBspFlag = FALSE;
- CpuMpData->CpuData = (CPU_AP_DATA *)(CpuMpData + 1);
- CpuMpData->CpuInfoInHob = (UINT64)(UINTN)(CpuMpData->CpuData + MaxLogicalProcessorNumber);
+ if (FirstMpHandOff == NULL) {
+ CpuMpData->BspNumber = 0;
+ } else {
+ CpuMpData->BspNumber = GetBspNumber (FirstMpHandOff);
+ }
+
+ CpuMpData->WaitEvent = NULL;
+ CpuMpData->SwitchBspFlag = FALSE;
+ CpuMpData->CpuData = (CPU_AP_DATA *)(CpuMpData + 1);
+ CpuMpData->CpuInfoInHob = (UINT64)(UINTN)(CpuMpData->CpuData + MaxLogicalProcessorNumber);
InitializeSpinLock (&CpuMpData->MpLock);
CpuMpData->SevEsIsEnabled = ConfidentialComputingGuestHas (CCAttrAmdSevEs);
CpuMpData->SevSnpIsEnabled = ConfidentialComputingGuestHas (CCAttrAmdSevSnp);
@@ -2186,11 +2195,11 @@ MpInitLibInitialize (
// Don't pass BSP's TR to APs to avoid AP init failure.
//
VolatileRegisters.Tr = 0;
- CopyMem (&CpuMpData->CpuData[0].VolatileRegisters, &VolatileRegisters, sizeof (VolatileRegisters));
+ CopyMem (&CpuMpData->CpuData[CpuMpData->BspNumber].VolatileRegisters, &VolatileRegisters, sizeof (VolatileRegisters));
//
// Set BSP basic information
//
- InitializeApData (CpuMpData, 0, 0, CpuMpData->Buffer + ApStackSize);
+ InitializeApData (CpuMpData, CpuMpData->BspNumber, 0, CpuMpData->Buffer + ApStackSize * (CpuMpData->BspNumber + 1));
//
// Save assembly code information
//
@@ -2245,9 +2254,8 @@ MpInitLibInitialize (
AmdSevUpdateCpuMpData (CpuMpData);
}
- CpuMpData->CpuCount = MaxLogicalProcessorNumber;
- CpuMpData->BspNumber = GetBspNumber (FirstMpHandOff);
- CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
+ CpuMpData->CpuCount = MaxLogicalProcessorNumber;
+ CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;
for (MpHandOff = FirstMpHandOff;
MpHandOff != NULL;
MpHandOff = GetNextMpHandOffHob (MpHandOff))
@@ -2615,7 +2623,12 @@ SwitchBSPWorker (
SaveVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters);
AsmExchangeRole (&CpuMpData->BSPInfo, &CpuMpData->APInfo);
RestoreVolatileRegisters (&CpuMpData->BSPInfo.VolatileRegisters, FALSE);
-
+ //
+ // Update VolatileRegisters saved in CpuMpData->CpuData
+ // Don't pass BSP's TR to APs to avoid AP init failure.
+ //
+ CopyMem (&CpuMpData->CpuData[CpuMpData->NewBspNumber].VolatileRegisters, &CpuMpData->BSPInfo.VolatileRegisters, sizeof (CPU_VOLATILE_REGISTERS));
+ CpuMpData->CpuData[CpuMpData->NewBspNumber].VolatileRegisters.Tr = 0;
//
// Set the BSP bit of MSR_IA32_APIC_BASE on new BSP
//
diff --git a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c
index e635cade5d..d799b7f5d1 100644
--- a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c
+++ b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.c
@@ -1,7 +1,7 @@
/** @file
CPU Register Table Library functions.
- Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2017 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -101,7 +101,7 @@ GetProcessorInformation (
Status = MpServices->GetProcessorInfo (
MpServices,
- ProcessorNumber,
+ ProcessorNumber | CPU_V2_EXTENDED_TOPOLOGY,
ProcessorInfoBuffer
);
return Status;
diff --git a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
index d4c528b3e9..1db6adc280 100644
--- a/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
+++ b/UefiCpuPkg/Library/RegisterCpuFeaturesLib/PeiRegisterCpuFeaturesLib.c
@@ -1,7 +1,7 @@
/** @file
CPU Register Table Library functions.
- Copyright (c) 2016 - 2020, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -139,7 +139,7 @@ GetProcessorInformation (
Status = CpuMp2Ppi->GetProcessorInfo (
CpuMp2Ppi,
- ProcessorNumber,
+ ProcessorNumber | CPU_V2_EXTENDED_TOPOLOGY,
ProcessorInfoBuffer
);
return Status;
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/AmdSmmRelocationLib.inf b/UefiCpuPkg/Library/SmmRelocationLib/AmdSmmRelocationLib.inf
new file mode 100644
index 0000000000..e69079fa02
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/AmdSmmRelocationLib.inf
@@ -0,0 +1,60 @@
+## @file
+# SMM Relocation Lib for each processor.
+#
+# This Lib produces the SMM_BASE_HOB in HOB database which tells
+# the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+# SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+# SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+# Index.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmRelocationLib
+ FILE_GUID = 65C74DCD-0D09-494A-8BFF-A64226EB8054
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmmRelocationLib
+
+[Sources]
+ InternalSmmRelocationLib.h
+ AmdSmramSaveStateConfig.c
+ SmmRelocationLib.c
+
+[Sources.Ia32]
+ Ia32/Semaphore.c
+ Ia32/SmmInit.nasm
+
+[Sources.X64]
+ X64/Semaphore.c
+ X64/SmmInit.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CpuExceptionHandlerLib
+ DebugLib
+ HobLib
+ LocalApicLib
+ MemoryAllocationLib
+ PcdLib
+ PeiServicesLib
+
+[Guids]
+ gSmmBaseHobGuid ## HOB ALWAYS_PRODUCED
+ gEfiSmmSmramMemoryGuid ## CONSUMES
+
+[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport ## CONSUMES
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/AmdSmramSaveStateConfig.c b/UefiCpuPkg/Library/SmmRelocationLib/AmdSmramSaveStateConfig.c
new file mode 100644
index 0000000000..068ae60887
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/AmdSmramSaveStateConfig.c
@@ -0,0 +1,125 @@
+/** @file
+ Config SMRAM Save State for SmmBases Relocation.
+
+ Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "InternalSmmRelocationLib.h"
+#include <Register/Amd/SmramSaveStateMap.h>
+
+#define EFER_ADDRESS 0XC0000080ul
+
+/**
+ Get the mode of the CPU at the time an SMI occurs
+
+ @retval EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT 32 bit.
+ @retval EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT 64 bit.
+
+**/
+UINT8
+GetMmSaveStateRegisterLma (
+ VOID
+ )
+{
+ UINT8 SmmSaveStateRegisterLma;
+ UINT32 LMAValue;
+
+ SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT;
+
+ LMAValue = (UINT32)AsmReadMsr64 (EFER_ADDRESS) & LMA;
+ if (LMAValue) {
+ SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
+ }
+
+ return SmmSaveStateRegisterLma;
+}
+
+/**
+ This function configures the SmBase on the currently executing CPU.
+
+ @param[in] SmBase The SmBase on the currently executing CPU.
+
+**/
+VOID
+EFIAPI
+ConfigureSmBase (
+ IN UINT64 SmBase
+ )
+{
+ AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
+
+ AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+
+ AmdCpuState->x64.SMBASE = (UINT32)SmBase;
+}
+
+/**
+ 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,out] CpuState Pointer to SMRAM Save State Map for the
+ currently executing CPU.
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
+ 32-bit mode from 64-bit SMM.
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to
+ same mode as SMM.
+
+ @retval The value of the original instruction pointer before it was hooked.
+
+**/
+UINT64
+EFIAPI
+HookReturnFromSmm (
+ IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
+ IN UINT64 NewInstructionPointer32,
+ IN UINT64 NewInstructionPointer
+ )
+{
+ UINT64 OriginalInstructionPointer;
+ AMD_SMRAM_SAVE_STATE_MAP *AmdCpuState;
+
+ AmdCpuState = (AMD_SMRAM_SAVE_STATE_MAP *)CpuState;
+
+ if (GetMmSaveStateRegisterLma () == EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT) {
+ OriginalInstructionPointer = (UINT64)AmdCpuState->x86._EIP;
+ AmdCpuState->x86._EIP = (UINT32)NewInstructionPointer;
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction.
+ //
+ if ((AmdCpuState->x86.AutoHALTRestart & BIT0) != 0) {
+ AmdCpuState->x86.AutoHALTRestart &= ~BIT0;
+ }
+ } else {
+ OriginalInstructionPointer = AmdCpuState->x64._RIP;
+ if ((AmdCpuState->x64.EFER & LMA) == 0) {
+ AmdCpuState->x64._RIP = (UINT32)NewInstructionPointer32;
+ } else {
+ AmdCpuState->x64._RIP = (UINT32)NewInstructionPointer;
+ }
+
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction.
+ //
+ if ((AmdCpuState->x64.AutoHALTRestart & BIT0) != 0) {
+ AmdCpuState->x64.AutoHALTRestart &= ~BIT0;
+ }
+ }
+
+ return OriginalInstructionPointer;
+}
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/Ia32/Semaphore.c b/UefiCpuPkg/Library/SmmRelocationLib/Ia32/Semaphore.c
new file mode 100644
index 0000000000..5d9eea3de9
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/Ia32/Semaphore.c
@@ -0,0 +1,39 @@
+/** @file
+ Semaphore mechanism to indicate to the BSP that an AP has exited SMM
+ after SMBASE relocation.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalSmmRelocationLib.h"
+
+UINTN mSmmRelocationOriginalAddress;
+volatile BOOLEAN *mRebasedFlag;
+
+/**
+ Hook return address of SMM Save State so that semaphore code
+ can be executed immediately after AP exits SMM to indicate to
+ the BSP that an AP has exited SMM after SMBASE relocation.
+
+ @param[in] RebasedFlag A pointer to a flag that is set to TRUE
+ immediately after AP exits SMM.
+
+**/
+VOID
+SemaphoreHook (
+ IN volatile BOOLEAN *RebasedFlag
+ )
+{
+ SMRAM_SAVE_STATE_MAP *CpuState;
+
+ mRebasedFlag = RebasedFlag;
+
+ CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+ mSmmRelocationOriginalAddress = (UINTN)HookReturnFromSmm (
+ CpuState,
+ (UINT64)(UINTN)&SmmRelocationSemaphoreComplete,
+ (UINT64)(UINTN)&SmmRelocationSemaphoreComplete
+ );
+}
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm b/UefiCpuPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm
new file mode 100644
index 0000000000..8916cb7d06
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/Ia32/SmmInit.nasm
@@ -0,0 +1,151 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; SmmInit.nasm
+;
+; Abstract:
+;
+; Functions for relocating SMBASE's for all processors
+;
+;-------------------------------------------------------------------------------
+
+%include "StuffRsbNasm.inc"
+
+extern ASM_PFX(SmmInitHandler)
+extern ASM_PFX(mRebasedFlag)
+extern ASM_PFX(mSmmRelocationOriginalAddress)
+
+global ASM_PFX(gPatchSmmInitCr3)
+global ASM_PFX(gPatchSmmInitCr4)
+global ASM_PFX(gPatchSmmInitCr0)
+global ASM_PFX(gPatchSmmInitStack)
+global ASM_PFX(gcSmmInitGdtr)
+global ASM_PFX(gcSmmInitSize)
+global ASM_PFX(gcSmmInitTemplate)
+
+%define PROTECT_MODE_CS 0x8
+%define PROTECT_MODE_DS 0x20
+
+ SECTION .data
+
+NullSeg: DQ 0 ; reserved by architecture
+CodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeCodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeSsSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+DataSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+CodeSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x9b
+ DB 0x8f
+ DB 0
+DataSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x93
+ DB 0x8f
+ DB 0
+CodeSeg64:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xaf ; LimitHigh
+ DB 0 ; BaseHigh
+GDT_SIZE equ $ - NullSeg
+
+ASM_PFX(gcSmmInitGdtr):
+ DW GDT_SIZE - 1
+ DD NullSeg
+
+
+ SECTION .text
+
+global ASM_PFX(SmmStartup)
+
+BITS 16
+ASM_PFX(SmmStartup):
+ mov eax, 0x80000001 ; read capability
+ cpuid
+ mov ebx, edx ; rdmsr will change edx. keep it in ebx.
+ and ebx, BIT20 ; extract NX capability bit
+ shr ebx, 9 ; shift bit to IA32_EFER.NXE[BIT11] position
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr3):
+ mov cr3, eax
+o32 lgdt [cs:ebp + (ASM_PFX(gcSmmInitGdtr) - ASM_PFX(SmmStartup))]
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr4):
+ mov cr4, eax
+ mov ecx, 0xc0000080 ; IA32_EFER MSR
+ rdmsr
+ or eax, ebx ; set NXE bit if NX is available
+ wrmsr
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr0):
+ mov di, PROTECT_MODE_DS
+ mov cr0, eax
+ jmp PROTECT_MODE_CS : dword @32bit
+
+BITS 32
+@32bit:
+ mov ds, edi
+ mov es, edi
+ mov fs, edi
+ mov gs, edi
+ mov ss, edi
+ mov esp, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitStack):
+ call ASM_PFX(SmmInitHandler)
+ StuffRsb32
+ rsm
+
+BITS 16
+ASM_PFX(gcSmmInitTemplate):
+ mov ebp, ASM_PFX(SmmStartup)
+ sub ebp, 0x30000
+ jmp ebp
+
+ASM_PFX(gcSmmInitSize): DW $ - ASM_PFX(gcSmmInitTemplate)
+
+BITS 32
+global ASM_PFX(SmmRelocationSemaphoreComplete)
+ASM_PFX(SmmRelocationSemaphoreComplete):
+ push eax
+ mov eax, [ASM_PFX(mRebasedFlag)]
+ mov byte [eax], 1
+ pop eax
+ jmp [ASM_PFX(mSmmRelocationOriginalAddress)]
+
+global ASM_PFX(SmmInitFixupAddress)
+ASM_PFX(SmmInitFixupAddress):
+ ret
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h b/UefiCpuPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h
new file mode 100644
index 0000000000..d1387f2dfb
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/InternalSmmRelocationLib.h
@@ -0,0 +1,127 @@
+/** @file
+ SMM Relocation Lib for each processor.
+
+ This Lib produces the SMM_BASE_HOB in HOB database which tells
+ the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+ SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+ SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+ Index.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef INTERNAL_SMM_RELOCATION_LIB_H_
+#define INTERNAL_SMM_RELOCATION_LIB_H_
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/CpuExceptionHandlerLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/LocalApicLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/SmmRelocationLib.h>
+#include <Guid/SmramMemoryReserve.h>
+#include <Guid/SmmBaseHob.h>
+#include <Register/Intel/Cpuid.h>
+#include <Register/Intel/SmramSaveStateMap.h>
+#include <Protocol/MmCpu.h>
+
+extern IA32_DESCRIPTOR gcSmmInitGdtr;
+extern CONST UINT16 gcSmmInitSize;
+extern CONST UINT8 gcSmmInitTemplate[];
+
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr0;
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr3;
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitCr4;
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitStack;
+
+//
+// The size 0x20 must be bigger than
+// the size of template code of SmmInit. Currently,
+// the size of SmmInit requires the 0x16 Bytes buffer
+// at least.
+//
+#define BACK_BUF_SIZE 0x20
+
+#define CR4_CET_ENABLE BIT23
+
+//
+// EFER register LMA bit
+//
+#define LMA BIT10
+
+/**
+ This function configures the SmBase on the currently executing CPU.
+
+ @param[in] SmBase The SmBase on the currently executing CPU.
+
+**/
+VOID
+EFIAPI
+ConfigureSmBase (
+ IN UINT64 SmBase
+ );
+
+/**
+ Semaphore operation for all processor relocate SMMBase.
+**/
+VOID
+EFIAPI
+SmmRelocationSemaphoreComplete (
+ VOID
+ );
+
+/**
+ Hook the code executed immediately after an RSM instruction on the currently
+ executing CPU. The mode of code executed immediately after RSM must be
+ detected, and the appropriate hook must be selected. Always clear the auto
+ HALT restart flag if it is set.
+
+ @param[in,out] CpuState Pointer to SMRAM Save State Map for the
+ currently executing CPU.
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
+ 32-bit mode from 64-bit SMM.
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to
+ same mode as SMM.
+
+ @retval The value of the original instruction pointer before it was hooked.
+
+**/
+UINT64
+EFIAPI
+HookReturnFromSmm (
+ IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
+ IN UINT64 NewInstructionPointer32,
+ IN UINT64 NewInstructionPointer
+ );
+
+/**
+ Hook return address of SMM Save State so that semaphore code
+ can be executed immediately after AP exits SMM to indicate to
+ the BSP that an AP has exited SMM after SMBASE relocation.
+
+ @param[in] RebasedFlag A pointer to a flag that is set to TRUE
+ immediately after AP exits SMM.
+
+**/
+VOID
+SemaphoreHook (
+ IN volatile BOOLEAN *RebasedFlag
+ );
+
+/**
+ This function fixes up the address of the global variable or function
+ referred in SmmInit assembly files to be the absolute address.
+**/
+VOID
+EFIAPI
+SmmInitFixupAddress (
+ );
+
+#endif
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.c b/UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.c
new file mode 100644
index 0000000000..7e65bbf929
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.c
@@ -0,0 +1,549 @@
+/** @file
+ SMM Relocation Lib for each processor.
+
+ This Lib produces the SMM_BASE_HOB in HOB database which tells
+ the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+ SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+ SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+ Index.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "InternalSmmRelocationLib.h"
+
+UINTN mMaxNumberOfCpus = 1;
+UINTN mNumberOfCpus = 1;
+
+//
+// IDT used during SMM Init
+//
+IA32_DESCRIPTOR gcSmmInitIdtr;
+
+//
+// Smbase for current CPU
+//
+UINT64 mSmBase;
+
+//
+// SmBase Rebased flag for current CPU
+//
+volatile BOOLEAN mRebased;
+
+/**
+ This function will get the SmBase for CpuIndex.
+
+ @param[in] CpuIndex The processor index.
+ @param[in] SmmRelocationStart The start address of Smm relocated memory in SMRAM.
+ @param[in] TileSize The total size required for a CPU save state, any
+ additional CPU-specific context and the size of code
+ for the SMI entry point.
+
+ @retval The value of SmBase for CpuIndex.
+
+**/
+UINTN
+GetSmBase (
+ IN UINTN CpuIndex,
+ IN EFI_PHYSICAL_ADDRESS SmmRelocationStart,
+ IN UINTN TileSize
+ )
+{
+ return (UINTN)(SmmRelocationStart) + CpuIndex * TileSize - SMM_HANDLER_OFFSET;
+}
+
+/**
+ This function will create SmBase for all CPUs.
+
+ @param[in] SmmRelocationStart The start address of Smm relocated memory in SMRAM.
+ @param[in] TileSize The total size required for a CPU save state, any
+ additional CPU-specific context and the size of code
+ for the SMI entry point.
+
+ @retval EFI_SUCCESS Create SmBase for all CPUs successfully.
+ @retval Others Failed to create SmBase for all CPUs.
+
+**/
+EFI_STATUS
+CreateSmmBaseHob (
+ IN EFI_PHYSICAL_ADDRESS SmmRelocationStart,
+ IN UINTN TileSize
+ )
+{
+ UINTN Index;
+ SMM_BASE_HOB_DATA *SmmBaseHobData;
+ UINT32 CpuCount;
+ UINT32 NumberOfProcessorsInHob;
+ UINT32 MaxCapOfProcessorsInHob;
+ UINT32 HobCount;
+
+ SmmBaseHobData = NULL;
+ CpuCount = 0;
+ NumberOfProcessorsInHob = 0;
+ MaxCapOfProcessorsInHob = 0;
+ HobCount = 0;
+
+ //
+ // Count the HOB instance maximum capacity of CPU (MaxCapOfProcessorsInHob) since the max HobLength is 0xFFF8.
+ //
+ MaxCapOfProcessorsInHob = (0xFFF8 - sizeof (EFI_HOB_GUID_TYPE) - sizeof (SMM_BASE_HOB_DATA)) / sizeof (UINT64) + 1;
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - MaxCapOfProcessorsInHob: %d\n", MaxCapOfProcessorsInHob));
+
+ //
+ // Create Guided SMM Base HOB Instances.
+ //
+ while (CpuCount != mMaxNumberOfCpus) {
+ NumberOfProcessorsInHob = MIN ((UINT32)mMaxNumberOfCpus - CpuCount, MaxCapOfProcessorsInHob);
+
+ SmmBaseHobData = BuildGuidHob (
+ &gSmmBaseHobGuid,
+ sizeof (SMM_BASE_HOB_DATA) + sizeof (UINT64) * NumberOfProcessorsInHob
+ );
+ if (SmmBaseHobData == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SmmBaseHobData->ProcessorIndex = CpuCount;
+ SmmBaseHobData->NumberOfProcessors = NumberOfProcessorsInHob;
+
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - SmmBaseHobData[%d]->ProcessorIndex: %d\n", HobCount, SmmBaseHobData->ProcessorIndex));
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - SmmBaseHobData[%d]->NumberOfProcessors: %d\n", HobCount, SmmBaseHobData->NumberOfProcessors));
+ for (Index = 0; Index < SmmBaseHobData->NumberOfProcessors; Index++) {
+ //
+ // Calculate the new SMBASE address
+ //
+ SmmBaseHobData->SmBase[Index] = GetSmBase (Index + CpuCount, SmmRelocationStart, TileSize);
+ DEBUG ((DEBUG_INFO, "CreateSmmBaseHob - SmmBaseHobData[%d]->SmBase[%d]: 0x%08x\n", HobCount, Index, SmmBaseHobData->SmBase[Index]));
+ }
+
+ CpuCount += NumberOfProcessorsInHob;
+ HobCount++;
+ SmmBaseHobData = NULL;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ C function for SMI handler. To change all processor's SMMBase Register.
+
+**/
+VOID
+EFIAPI
+SmmInitHandler (
+ VOID
+ )
+{
+ //
+ // Update SMM IDT entries' code segment and load IDT
+ //
+ AsmWriteIdtr (&gcSmmInitIdtr);
+
+ //
+ // Configure SmBase.
+ //
+ ConfigureSmBase (mSmBase);
+
+ //
+ // Hook return after RSM to set SMM re-based flag
+ // SMM re-based flag can't be set before RSM, because SMM save state context might be override
+ // by next AP flow before it take effect.
+ //
+ SemaphoreHook (&mRebased);
+}
+
+/**
+ Relocate SmmBases for each processor.
+ Execute on first boot and all S3 resumes
+
+ @param[in] MpServices2 Pointer to this instance of the MpServices.
+ @param[in] SmmRelocationStart The start address of Smm relocated memory in SMRAM.
+ @param[in] TileSize The total size required for a CPU save state, any
+ additional CPU-specific context and the size of code
+ for the SMI entry point.
+
+**/
+VOID
+SmmRelocateBases (
+ IN EDKII_PEI_MP_SERVICES2_PPI *MpServices2,
+ IN EFI_PHYSICAL_ADDRESS SmmRelocationStart,
+ IN UINTN TileSize
+ )
+{
+ EFI_STATUS Status;
+ UINT8 BakBuf[BACK_BUF_SIZE];
+ SMRAM_SAVE_STATE_MAP BakBuf2;
+ SMRAM_SAVE_STATE_MAP *CpuStatePtr;
+ UINT8 *U8Ptr;
+ UINTN Index;
+ UINTN BspIndex;
+ UINT32 BspApicId;
+ EFI_PROCESSOR_INFORMATION ProcessorInfo;
+
+ //
+ // Make sure the reserved size is large enough for procedure SmmInitTemplate.
+ //
+ ASSERT (sizeof (BakBuf) >= gcSmmInitSize);
+
+ //
+ // Patch ASM code template with current CR0, CR3, and CR4 values
+ //
+ PatchInstructionX86 (gPatchSmmInitCr0, AsmReadCr0 (), 4);
+ PatchInstructionX86 (gPatchSmmInitCr3, AsmReadCr3 (), 4);
+ PatchInstructionX86 (gPatchSmmInitCr4, AsmReadCr4 () & (~CR4_CET_ENABLE), 4);
+
+ U8Ptr = (UINT8 *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET);
+ CpuStatePtr = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+
+ //
+ // Backup original contents at address 0x38000
+ //
+ CopyMem (BakBuf, U8Ptr, sizeof (BakBuf));
+ CopyMem (&BakBuf2, CpuStatePtr, sizeof (BakBuf2));
+
+ //
+ // Load image for relocation
+ //
+ CopyMem (U8Ptr, gcSmmInitTemplate, gcSmmInitSize);
+
+ //
+ // Retrieve the local APIC ID of current processor
+ //
+ BspApicId = GetApicId ();
+
+ //
+ // Relocate SM bases for all APs
+ // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate
+ //
+ BspIndex = (UINTN)-1;
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ Status = MpServices2->GetProcessorInfo (MpServices2, Index | CPU_V2_EXTENDED_TOPOLOGY, &ProcessorInfo);
+ ASSERT_EFI_ERROR (Status);
+
+ if (BspApicId != (UINT32)ProcessorInfo.ProcessorId) {
+ mRebased = FALSE;
+ mSmBase = GetSmBase (Index, SmmRelocationStart, TileSize);
+ SendSmiIpi ((UINT32)ProcessorInfo.ProcessorId);
+ //
+ // Wait for this AP to finish its 1st SMI
+ //
+ while (!mRebased) {
+ }
+ } else {
+ //
+ // BSP will be Relocated later
+ //
+ BspIndex = Index;
+ }
+ }
+
+ //
+ // Relocate BSP's SMM base
+ //
+ ASSERT (BspIndex != (UINTN)-1);
+ mRebased = FALSE;
+ mSmBase = GetSmBase (BspIndex, SmmRelocationStart, TileSize);
+ SendSmiIpi (BspApicId);
+
+ //
+ // Wait for the BSP to finish its 1st SMI
+ //
+ while (!mRebased) {
+ }
+
+ //
+ // Restore contents at address 0x38000
+ //
+ CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2));
+ CopyMem (U8Ptr, BakBuf, sizeof (BakBuf));
+}
+
+/**
+ Initialize IDT to setup exception handlers in SMM.
+
+**/
+VOID
+InitSmmIdt (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN InterruptState;
+ IA32_DESCRIPTOR PeiIdtr;
+ CONST EFI_PEI_SERVICES **PeiServices;
+
+ //
+ // There are 32 (not 255) entries in it since only processor
+ // generated exceptions will be handled.
+ //
+ gcSmmInitIdtr.Limit = (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;
+
+ //
+ // Allocate for IDT.
+ // sizeof (UINTN) is for the PEI Services Table pointer.
+ //
+ gcSmmInitIdtr.Base = (UINTN)AllocateZeroPool (gcSmmInitIdtr.Limit + 1 + sizeof (UINTN));
+ ASSERT (gcSmmInitIdtr.Base != 0);
+ gcSmmInitIdtr.Base += sizeof (UINTN);
+
+ //
+ // Disable Interrupt, save InterruptState and save PEI IDT table
+ //
+ InterruptState = SaveAndDisableInterrupts ();
+ AsmReadIdtr (&PeiIdtr);
+
+ //
+ // Save the PEI Services Table pointer
+ // The PEI Services Table pointer will be stored in the sizeof (UINTN) bytes
+ // immediately preceding the IDT in memory.
+ //
+ PeiServices = (CONST EFI_PEI_SERVICES **)(*(UINTN *)(PeiIdtr.Base - sizeof (UINTN)));
+ (*(UINTN *)(gcSmmInitIdtr.Base - sizeof (UINTN))) = (UINTN)PeiServices;
+
+ //
+ // Load SMM temporary IDT table
+ //
+ AsmWriteIdtr (&gcSmmInitIdtr);
+
+ //
+ // Setup SMM default exception handlers, SMM IDT table
+ // will be updated and saved in gcSmmInitIdtr
+ //
+ Status = InitializeCpuExceptionHandlers (NULL);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Restore PEI IDT table and CPU InterruptState
+ //
+ AsmWriteIdtr ((IA32_DESCRIPTOR *)&PeiIdtr);
+ SetInterruptState (InterruptState);
+}
+
+/**
+ This routine will split SmramReserve HOB to reserve SmmRelocationSize for Smm relocated memory.
+
+ @param[in] SmmRelocationSize SmmRelocationSize for all processors.
+ @param[in,out] SmmRelocationStart Return the start address of Smm relocated memory in SMRAM.
+
+ @retval EFI_SUCCESS The gEfiSmmSmramMemoryGuid is split successfully.
+ @retval EFI_DEVICE_ERROR Failed to build new HOB for gEfiSmmSmramMemoryGuid.
+ @retval EFI_NOT_FOUND The gEfiSmmSmramMemoryGuid is not found.
+
+**/
+EFI_STATUS
+SplitSmramHobForSmmRelocation (
+ IN UINT64 SmmRelocationSize,
+ IN OUT EFI_PHYSICAL_ADDRESS *SmmRelocationStart
+ )
+{
+ EFI_HOB_GUID_TYPE *GuidHob;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *Block;
+ EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *NewBlock;
+ UINTN NewBlockSize;
+
+ ASSERT (SmmRelocationStart != NULL);
+
+ //
+ // Retrieve the GUID HOB data that contains the set of SMRAM descriptors
+ //
+ GuidHob = GetFirstGuidHob (&gEfiSmmSmramMemoryGuid);
+ if (GuidHob == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ Block = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)GET_GUID_HOB_DATA (GuidHob);
+
+ //
+ // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe smram carved out for all SMBASE
+ //
+ NewBlockSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + (Block->NumberOfSmmReservedRegions * sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ NewBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)BuildGuidHob (
+ &gEfiSmmSmramMemoryGuid,
+ NewBlockSize
+ );
+ ASSERT (NewBlock != NULL);
+ if (NewBlock == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ //
+ // Copy old EFI_SMRAM_HOB_DESCRIPTOR_BLOCK to new allocated region
+ //
+ CopyMem ((VOID *)NewBlock, Block, NewBlockSize - sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ //
+ // Increase the number of SMRAM descriptors by 1 to make room for the ALLOCATED descriptor of size EFI_PAGE_SIZE
+ //
+ NewBlock->NumberOfSmmReservedRegions = (UINT32)(Block->NumberOfSmmReservedRegions + 1);
+
+ ASSERT (Block->NumberOfSmmReservedRegions >= 1);
+ //
+ // Copy last entry to the end - we assume TSEG is last entry.
+ //
+ CopyMem (&NewBlock->Descriptor[Block->NumberOfSmmReservedRegions], &NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1], sizeof (EFI_SMRAM_DESCRIPTOR));
+
+ //
+ // Update the entry in the array with a size of SmmRelocationSize and put into the ALLOCATED state
+ //
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1].PhysicalSize = SmmRelocationSize;
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1].RegionState |= EFI_ALLOCATED;
+
+ //
+ // Return the start address of Smm relocated memory in SMRAM.
+ //
+ *SmmRelocationStart = NewBlock->Descriptor[Block->NumberOfSmmReservedRegions - 1].CpuStart;
+
+ //
+ // Reduce the size of the last SMRAM descriptor by SmmRelocationSize
+ //
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions].PhysicalStart += SmmRelocationSize;
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions].CpuStart += SmmRelocationSize;
+ NewBlock->Descriptor[Block->NumberOfSmmReservedRegions].PhysicalSize -= SmmRelocationSize;
+
+ //
+ // Last step, we can scrub old one
+ //
+ ZeroMem (&GuidHob->Name, sizeof (GuidHob->Name));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ CPU SmmBase Relocation Init.
+
+ This function is to relocate CPU SmmBase.
+
+ @param[in] MpServices2 Pointer to this instance of the MpServices.
+
+ @retval EFI_SUCCESS CPU SmmBase Relocated successfully.
+ @retval Others CPU SmmBase Relocation failed.
+
+**/
+EFI_STATUS
+EFIAPI
+SmmRelocationInit (
+ IN EDKII_PEI_MP_SERVICES2_PPI *MpServices2
+ )
+{
+ EFI_STATUS Status;
+ UINTN NumberOfEnabledCpus;
+ UINTN TileSize;
+ UINT64 SmmRelocationSize;
+ EFI_PHYSICAL_ADDRESS SmmRelocationStart;
+ UINTN SmmStackSize;
+ UINT8 *SmmStacks;
+
+ SmmRelocationStart = 0;
+ SmmStacks = NULL;
+
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit Start \n"));
+ if (MpServices2 == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Get the number of processors
+ //
+ Status = MpServices2->GetNumberOfProcessors (
+ MpServices2,
+ &mNumberOfCpus,
+ &NumberOfEnabledCpus
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ mMaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ } else {
+ mMaxNumberOfCpus = mNumberOfCpus;
+ }
+
+ ASSERT (mNumberOfCpus <= mMaxNumberOfCpus);
+
+ //
+ // Calculate SmmRelocationSize for all of the tiles.
+ //
+ // The CPU save state and code for the SMI entry point are tiled within an SMRAM
+ // allocated buffer. The minimum size of this buffer for a uniprocessor system
+ // is 32 KB, because the entry point is SMBASE + 32KB, and CPU save state area
+ // just below SMBASE + 64KB. If more than one CPU is present in the platform,
+ // then the SMI entry point and the CPU save state areas can be tiles to minimize
+ // the total amount SMRAM required for all the CPUs. The tile size can be computed
+ // by adding the CPU save state size, any extra CPU specific context, and
+ // the size of code that must be placed at the SMI entry point to transfer
+ // control to a C function in the native SMM execution mode. This size is
+ // rounded up to the nearest power of 2 to give the tile size for a each CPU.
+ // The total amount of memory required is the maximum number of CPUs that
+ // platform supports times the tile size.
+ //
+ TileSize = SIZE_8KB;
+ SmmRelocationSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)));
+
+ //
+ // Split SmramReserve HOB to reserve SmmRelocationSize for Smm relocated memory
+ //
+ Status = SplitSmramHobForSmmRelocation (
+ SmmRelocationSize,
+ &SmmRelocationStart
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ ASSERT (SmmRelocationStart != 0);
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmRelocationSize: 0x%08x\n", SmmRelocationSize));
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmRelocationStart: 0x%08x\n", SmmRelocationStart));
+
+ //
+ // Fix up the address of the global variable or function referred in
+ // SmmInit assembly files to be the absolute address
+ //
+ SmmInitFixupAddress ();
+
+ //
+ // Patch SMI stack for SMM base relocation
+ // Note: No need allocate stack for all CPUs since the relocation
+ // occurs serially for each CPU
+ //
+ SmmStackSize = EFI_PAGE_SIZE;
+ SmmStacks = (UINT8 *)AllocatePages (EFI_SIZE_TO_PAGES (SmmStackSize));
+ if (SmmStacks == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmStackSize: 0x%08x\n", SmmStackSize));
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit - SmmStacks: 0x%08x\n", SmmStacks));
+
+ PatchInstructionX86 (
+ gPatchSmmInitStack,
+ (UINTN)(SmmStacks + SmmStackSize - sizeof (UINTN)),
+ sizeof (UINTN)
+ );
+
+ //
+ // Initialize the SMM IDT for SMM base relocation
+ //
+ InitSmmIdt ();
+
+ //
+ // Relocate SmmBases for each processor.
+ //
+ SmmRelocateBases (MpServices2, SmmRelocationStart, TileSize);
+
+ //
+ // Create the SmBase HOB for all CPUs
+ //
+ Status = CreateSmmBaseHob (SmmRelocationStart, TileSize);
+
+ON_EXIT:
+ if (SmmStacks != NULL) {
+ FreePages (SmmStacks, EFI_SIZE_TO_PAGES (SmmStackSize));
+ }
+
+ DEBUG ((DEBUG_INFO, "SmmRelocationInit Done\n"));
+ return Status;
+}
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf b/UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
new file mode 100644
index 0000000000..45fdaf35bc
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
@@ -0,0 +1,61 @@
+## @file
+# SMM Relocation Lib for each processor.
+#
+# This Lib produces the SMM_BASE_HOB in HOB database which tells
+# the PiSmmCpuDxeSmm driver (runs at a later phase) about the new
+# SMBASE for each processor. PiSmmCpuDxeSmm driver installs the
+# SMI handler at the SMM_BASE_HOB.SmBase[Index]+0x8000 for processor
+# Index.
+#
+# Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SmmRelocationLib
+ FILE_GUID = 853E97B3-790C-4EA3-945C-8F622FC47FE8
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SmmRelocationLib
+
+[Sources]
+ InternalSmmRelocationLib.h
+ SmramSaveStateConfig.c
+ SmmRelocationLib.c
+
+[Sources.Ia32]
+ Ia32/Semaphore.c
+ Ia32/SmmInit.nasm
+
+[Sources.X64]
+ X64/Semaphore.c
+ X64/SmmInit.nasm
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ CpuExceptionHandlerLib
+ CpuLib
+ DebugLib
+ HobLib
+ LocalApicLib
+ MemoryAllocationLib
+ PcdLib
+ PeiServicesLib
+
+[Guids]
+ gSmmBaseHobGuid ## HOB ALWAYS_PRODUCED
+ gEfiSmmSmramMemoryGuid ## CONSUMES
+
+[Pcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+
+[FeaturePcd]
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugSupport ## CONSUMES
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c b/UefiCpuPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c
new file mode 100644
index 0000000000..76d798aba5
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/SmramSaveStateConfig.c
@@ -0,0 +1,136 @@
+/** @file
+ Config SMRAM Save State for SmmBases Relocation.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "InternalSmmRelocationLib.h"
+#include <Library/CpuLib.h>
+
+/**
+ Get the mode of the CPU at the time an SMI occurs
+
+ @retval EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT 32 bit.
+ @retval EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT 64 bit.
+
+**/
+UINT8
+GetMmSaveStateRegisterLma (
+ VOID
+ )
+{
+ CPUID_VERSION_INFO_EAX RegEax;
+ CPUID_EXTENDED_CPU_SIG_EDX RegEdx;
+ UINTN FamilyId;
+ UINTN ModelId;
+ UINT32 Eax;
+ UINT8 SmmSaveStateRegisterLma;
+
+ //
+ // Determine the mode of the CPU at the time an SMI occurs
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 34.4.1.1
+ //
+ RegEax.Uint32 = GetCpuFamilyModel ();
+ FamilyId = RegEax.Bits.FamilyId;
+ ModelId = RegEax.Bits.Model;
+ if ((FamilyId == 0x06) || (FamilyId == 0x0f)) {
+ ModelId = ModelId | RegEax.Bits.ExtendedModelId << 4;
+ }
+
+ RegEdx.Uint32 = 0;
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &Eax, NULL, NULL, NULL);
+ if (Eax >= CPUID_EXTENDED_CPU_SIG) {
+ AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &(RegEdx.Uint32));
+ }
+
+ SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT;
+ if (RegEdx.Bits.LM) {
+ SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
+ }
+
+ if (FamilyId == 0x06) {
+ if ((ModelId == 0x17) || (ModelId == 0x0f) || (ModelId == 0x1c)) {
+ SmmSaveStateRegisterLma = (UINT8)EFI_MM_SAVE_STATE_REGISTER_LMA_64BIT;
+ }
+ }
+
+ return SmmSaveStateRegisterLma;
+}
+
+/**
+ This function configures the SmBase on the currently executing CPU.
+
+ @param[in] SmBase The SmBase on the currently executing CPU.
+
+**/
+VOID
+EFIAPI
+ConfigureSmBase (
+ IN UINT64 SmBase
+ )
+{
+ SMRAM_SAVE_STATE_MAP *CpuState;
+
+ CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+
+ CpuState->x86.SMBASE = (UINT32)SmBase;
+}
+
+/**
+ Hook the code executed immediately after an RSM instruction on the currently
+ executing CPU. The mode of code executed immediately after RSM must be
+ detected, and the appropriate hook must be selected. Always clear the auto
+ HALT restart flag if it is set.
+
+ @param[in,out] CpuState Pointer to SMRAM Save State Map for the
+ currently executing CPU.
+ @param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
+ 32-bit mode from 64-bit SMM.
+ @param[in] NewInstructionPointer Instruction pointer to use if resuming to
+ same mode as SMM.
+
+ @retval The value of the original instruction pointer before it was hooked.
+
+**/
+UINT64
+EFIAPI
+HookReturnFromSmm (
+ IN OUT SMRAM_SAVE_STATE_MAP *CpuState,
+ IN UINT64 NewInstructionPointer32,
+ IN UINT64 NewInstructionPointer
+ )
+{
+ UINT64 OriginalInstructionPointer;
+
+ if (GetMmSaveStateRegisterLma () == EFI_MM_SAVE_STATE_REGISTER_LMA_32BIT) {
+ OriginalInstructionPointer = (UINT64)CpuState->x86._EIP;
+ CpuState->x86._EIP = (UINT32)NewInstructionPointer;
+
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction.
+ //
+ if ((CpuState->x86.AutoHALTRestart & BIT0) != 0) {
+ CpuState->x86.AutoHALTRestart &= ~BIT0;
+ }
+ } else {
+ OriginalInstructionPointer = CpuState->x64._RIP;
+ if ((CpuState->x64.IA32_EFER & LMA) == 0) {
+ CpuState->x64._RIP = (UINT32)NewInstructionPointer32;
+ } else {
+ CpuState->x64._RIP = (UINT32)NewInstructionPointer;
+ }
+
+ //
+ // Clear the auto HALT restart flag so the RSM instruction returns
+ // program control to the instruction following the HLT instruction.
+ //
+ if ((CpuState->x64.AutoHALTRestart & BIT0) != 0) {
+ CpuState->x64.AutoHALTRestart &= ~BIT0;
+ }
+ }
+
+ return OriginalInstructionPointer;
+}
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/X64/Semaphore.c b/UefiCpuPkg/Library/SmmRelocationLib/X64/Semaphore.c
new file mode 100644
index 0000000000..cd6778e3fc
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/X64/Semaphore.c
@@ -0,0 +1,66 @@
+/** @file
+ Semaphore mechanism to indicate to the BSP that an AP has exited SMM
+ after SMBASE relocation.
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalSmmRelocationLib.h"
+
+X86_ASSEMBLY_PATCH_LABEL gPatchSmmRelocationOriginalAddressPtr32;
+X86_ASSEMBLY_PATCH_LABEL gPatchRebasedFlagAddr32;
+
+UINTN mSmmRelocationOriginalAddress;
+volatile BOOLEAN *mRebasedFlag;
+
+/**
+AP Semaphore operation in 32-bit mode while BSP runs in 64-bit mode.
+**/
+VOID
+SmmRelocationSemaphoreComplete32 (
+ VOID
+ );
+
+/**
+ Hook return address of SMM Save State so that semaphore code
+ can be executed immediately after AP exits SMM to indicate to
+ the BSP that an AP has exited SMM after SMBASE relocation.
+
+ @param[in] RebasedFlag A pointer to a flag that is set to TRUE
+ immediately after AP exits SMM.
+
+**/
+VOID
+SemaphoreHook (
+ IN volatile BOOLEAN *RebasedFlag
+ )
+{
+ SMRAM_SAVE_STATE_MAP *CpuState;
+ UINTN TempValue;
+
+ mRebasedFlag = RebasedFlag;
+ PatchInstructionX86 (
+ gPatchRebasedFlagAddr32,
+ (UINT32)(UINTN)mRebasedFlag,
+ 4
+ );
+
+ CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+ mSmmRelocationOriginalAddress = HookReturnFromSmm (
+ CpuState,
+ (UINT64)(UINTN)&SmmRelocationSemaphoreComplete32,
+ (UINT64)(UINTN)&SmmRelocationSemaphoreComplete
+ );
+
+ //
+ // Use temp value to fix ICC compiler warning
+ //
+ TempValue = (UINTN)&mSmmRelocationOriginalAddress;
+ PatchInstructionX86 (
+ gPatchSmmRelocationOriginalAddressPtr32,
+ (UINT32)TempValue,
+ 4
+ );
+}
diff --git a/UefiCpuPkg/Library/SmmRelocationLib/X64/SmmInit.nasm b/UefiCpuPkg/Library/SmmRelocationLib/X64/SmmInit.nasm
new file mode 100644
index 0000000000..8288b723c4
--- /dev/null
+++ b/UefiCpuPkg/Library/SmmRelocationLib/X64/SmmInit.nasm
@@ -0,0 +1,201 @@
+;------------------------------------------------------------------------------ ;
+; Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; SmmInit.nasm
+;
+; Abstract:
+;
+; Functions for relocating SMBASE's for all processors
+;
+;-------------------------------------------------------------------------------
+
+%include "StuffRsbNasm.inc"
+
+extern ASM_PFX(SmmInitHandler)
+extern ASM_PFX(mRebasedFlag)
+extern ASM_PFX(mSmmRelocationOriginalAddress)
+
+global ASM_PFX(gPatchSmmInitCr3)
+global ASM_PFX(gPatchSmmInitCr4)
+global ASM_PFX(gPatchSmmInitCr0)
+global ASM_PFX(gPatchSmmInitStack)
+global ASM_PFX(gcSmmInitGdtr)
+global ASM_PFX(gcSmmInitSize)
+global ASM_PFX(gcSmmInitTemplate)
+global ASM_PFX(gPatchRebasedFlagAddr32)
+global ASM_PFX(gPatchSmmRelocationOriginalAddressPtr32)
+
+%define LONG_MODE_CS 0x38
+
+ SECTION .data
+
+NullSeg: DQ 0 ; reserved by architecture
+CodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeCodeSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+ProtModeSsSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+DataSeg32:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x93
+ DB 0xcf ; LimitHigh
+ DB 0 ; BaseHigh
+CodeSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x9b
+ DB 0x8f
+ DB 0
+DataSeg16:
+ DW -1
+ DW 0
+ DB 0
+ DB 0x93
+ DB 0x8f
+ DB 0
+CodeSeg64:
+ DW -1 ; LimitLow
+ DW 0 ; BaseLow
+ DB 0 ; BaseMid
+ DB 0x9b
+ DB 0xaf ; LimitHigh
+ DB 0 ; BaseHigh
+GDT_SIZE equ $ - NullSeg
+
+ASM_PFX(gcSmmInitGdtr):
+ DW GDT_SIZE - 1
+ DQ NullSeg
+
+
+ DEFAULT REL
+ SECTION .text
+
+global ASM_PFX(SmmStartup)
+
+BITS 16
+ASM_PFX(SmmStartup):
+ mov eax, 0x80000001 ; read capability
+ cpuid
+ mov ebx, edx ; rdmsr will change edx. keep it in ebx.
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr3):
+ mov cr3, eax
+o32 lgdt [cs:ebp + (ASM_PFX(gcSmmInitGdtr) - ASM_PFX(SmmStartup))]
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr4):
+ or ah, 2 ; enable XMM registers access
+ mov cr4, eax
+ mov ecx, 0xc0000080 ; IA32_EFER MSR
+ rdmsr
+ or ah, BIT0 ; set LME bit
+ test ebx, BIT20 ; check NXE capability
+ jz .1
+ or ah, BIT3 ; set NXE bit
+.1:
+ wrmsr
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitCr0):
+ mov cr0, eax ; enable protected mode & paging
+ jmp LONG_MODE_CS : dword 0 ; offset will be patched to @LongMode
+@PatchLongModeOffset:
+
+BITS 64
+@LongMode: ; long-mode starts here
+ mov rsp, strict qword 0 ; source operand will be patched
+ASM_PFX(gPatchSmmInitStack):
+ and sp, 0xfff0 ; make sure RSP is 16-byte aligned
+ ;
+ ; According to X64 calling convention, XMM0~5 are volatile, we need to save
+ ; them before calling C-function.
+ ;
+ sub rsp, 0x60
+ movdqa [rsp], xmm0
+ movdqa [rsp + 0x10], xmm1
+ movdqa [rsp + 0x20], xmm2
+ movdqa [rsp + 0x30], xmm3
+ movdqa [rsp + 0x40], xmm4
+ movdqa [rsp + 0x50], xmm5
+
+ add rsp, -0x20
+ call ASM_PFX(SmmInitHandler)
+ add rsp, 0x20
+
+ ;
+ ; Restore XMM0~5 after calling C-function.
+ ;
+ movdqa xmm0, [rsp]
+ movdqa xmm1, [rsp + 0x10]
+ movdqa xmm2, [rsp + 0x20]
+ movdqa xmm3, [rsp + 0x30]
+ movdqa xmm4, [rsp + 0x40]
+ movdqa xmm5, [rsp + 0x50]
+
+ StuffRsb64
+ rsm
+
+BITS 16
+ASM_PFX(gcSmmInitTemplate):
+ mov ebp, [cs:@L1 - ASM_PFX(gcSmmInitTemplate) + 0x8000]
+ sub ebp, 0x30000
+ jmp ebp
+@L1:
+ DQ 0; ASM_PFX(SmmStartup)
+
+ASM_PFX(gcSmmInitSize): DW $ - ASM_PFX(gcSmmInitTemplate)
+
+BITS 64
+global ASM_PFX(SmmRelocationSemaphoreComplete)
+ASM_PFX(SmmRelocationSemaphoreComplete):
+ push rax
+ mov rax, [ASM_PFX(mRebasedFlag)]
+ mov byte [rax], 1
+ pop rax
+ jmp [ASM_PFX(mSmmRelocationOriginalAddress)]
+
+;
+; Semaphore code running in 32-bit mode
+;
+BITS 32
+global ASM_PFX(SmmRelocationSemaphoreComplete32)
+ASM_PFX(SmmRelocationSemaphoreComplete32):
+ push eax
+ mov eax, strict dword 0 ; source operand will be patched
+ASM_PFX(gPatchRebasedFlagAddr32):
+ mov byte [eax], 1
+ pop eax
+ jmp dword [dword 0] ; destination will be patched
+ASM_PFX(gPatchSmmRelocationOriginalAddressPtr32):
+
+BITS 64
+global ASM_PFX(SmmInitFixupAddress)
+ASM_PFX(SmmInitFixupAddress):
+ lea rax, [@LongMode]
+ lea rcx, [@PatchLongModeOffset - 6]
+ mov dword [rcx], eax
+
+ lea rax, [ASM_PFX(SmmStartup)]
+ lea rcx, [@L1]
+ mov qword [rcx], rax
+ ret
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
index b14c289a27..d67fb49890 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -641,23 +641,10 @@ InitializeCpuProcedure (
}
if (IsBsp) {
- DEBUG ((DEBUG_INFO, "SmmRestoreCpu: mSmmRelocated is %d\n", mSmmRelocated));
-
//
- // Check whether Smm Relocation is done or not.
- // If not, will do the SmmBases Relocation here!!!
+ // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
//
- if (!mSmmRelocated) {
- //
- // Restore SMBASE for BSP and all APs
- //
- SmmRelocateBases ();
- } else {
- //
- // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
- //
- ExecuteFirstSmiInit ();
- }
+ ExecuteFirstSmiInit ();
}
//
@@ -980,9 +967,9 @@ InitSmmS3ResumeState (
SmmS3ResumeState->SmmS3StackSize = 0;
}
- SmmS3ResumeState->SmmS3Cr0 = mSmmCr0;
+ SmmS3ResumeState->SmmS3Cr0 = (UINT32)AsmReadCr0 ();
SmmS3ResumeState->SmmS3Cr3 = Cr3;
- SmmS3ResumeState->SmmS3Cr4 = mSmmCr4;
+ SmmS3ResumeState->SmmS3Cr4 = (UINT32)AsmReadCr4 ();
if (sizeof (UINTN) == sizeof (UINT64)) {
SmmS3ResumeState->Signature = SMM_S3_RESUME_SMM_64;
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm
deleted file mode 100644
index b5e77a1a5b..0000000000
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm
+++ /dev/null
@@ -1,96 +0,0 @@
-;------------------------------------------------------------------------------ ;
-; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Module Name:
-;
-; SmmInit.nasm
-;
-; Abstract:
-;
-; Functions for relocating SMBASE's for all processors
-;
-;-------------------------------------------------------------------------------
-
-%include "StuffRsbNasm.inc"
-
-extern ASM_PFX(SmmInitHandler)
-extern ASM_PFX(mRebasedFlag)
-extern ASM_PFX(mSmmRelocationOriginalAddress)
-
-global ASM_PFX(gPatchSmmCr3)
-global ASM_PFX(gPatchSmmCr4)
-global ASM_PFX(gPatchSmmCr0)
-global ASM_PFX(gPatchSmmInitStack)
-global ASM_PFX(gcSmiInitGdtr)
-global ASM_PFX(gcSmmInitSize)
-global ASM_PFX(gcSmmInitTemplate)
-
-%define PROTECT_MODE_CS 0x8
-%define PROTECT_MODE_DS 0x20
-
- SECTION .text
-
-ASM_PFX(gcSmiInitGdtr):
- DW 0
- DQ 0
-
-global ASM_PFX(SmmStartup)
-
-BITS 16
-ASM_PFX(SmmStartup):
- mov eax, 0x80000001 ; read capability
- cpuid
- mov ebx, edx ; rdmsr will change edx. keep it in ebx.
- and ebx, BIT20 ; extract NX capability bit
- shr ebx, 9 ; shift bit to IA32_EFER.NXE[BIT11] position
- mov eax, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmCr3):
- mov cr3, eax
-o32 lgdt [cs:ebp + (ASM_PFX(gcSmiInitGdtr) - ASM_PFX(SmmStartup))]
- mov eax, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmCr4):
- mov cr4, eax
- mov ecx, 0xc0000080 ; IA32_EFER MSR
- rdmsr
- or eax, ebx ; set NXE bit if NX is available
- wrmsr
- mov eax, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmCr0):
- mov di, PROTECT_MODE_DS
- mov cr0, eax
- jmp PROTECT_MODE_CS : dword @32bit
-
-BITS 32
-@32bit:
- mov ds, edi
- mov es, edi
- mov fs, edi
- mov gs, edi
- mov ss, edi
- mov esp, strict dword 0 ; source operand will be patched
-ASM_PFX(gPatchSmmInitStack):
- call ASM_PFX(SmmInitHandler)
- StuffRsb32
- rsm
-
-BITS 16
-ASM_PFX(gcSmmInitTemplate):
- mov ebp, ASM_PFX(SmmStartup)
- sub ebp, 0x30000
- jmp ebp
-
-ASM_PFX(gcSmmInitSize): DW $ - ASM_PFX(gcSmmInitTemplate)
-
-BITS 32
-global ASM_PFX(SmmRelocationSemaphoreComplete)
-ASM_PFX(SmmRelocationSemaphoreComplete):
- push eax
- mov eax, [ASM_PFX(mRebasedFlag)]
- mov byte [eax], 1
- pop eax
- jmp [ASM_PFX(mSmmRelocationOriginalAddress)]
-
-global ASM_PFX(PiSmmCpuSmmInitFixupAddress)
-ASM_PFX(PiSmmCpuSmmInitFixupAddress):
- ret
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
index 081f0c1501..10baf3ceb9 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
@@ -1513,9 +1513,7 @@ SmiRendezvous (
ASSERT (CpuIndex < mMaxNumberOfCpus);
- if (mSmmRelocated) {
- ASSERT (mSmmInitialized != NULL);
- }
+ ASSERT (mSmmInitialized != NULL);
//
// Save Cr2 because Page Fault exception in SMM may override its value,
@@ -1524,11 +1522,11 @@ SmiRendezvous (
Cr2 = 0;
SaveCr2 (&Cr2);
- if (mSmmRelocated && !mSmmInitialized[CpuIndex]) {
+ if (!mSmmInitialized[CpuIndex]) {
//
- // Perform SmmInitHandler for CpuIndex
+ // Perform InitializeSmm for CpuIndex
//
- SmmInitHandler ();
+ InitializeSmm ();
//
// Restore Cr2
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
index 499f979d34..e400bee8d5 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -3,7 +3,7 @@ Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.
Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -56,11 +56,6 @@ CPU_HOT_PLUG_DATA mCpuHotPlugData = {
//
SMM_CPU_PRIVATE_DATA *gSmmCpuPrivate = &mSmmCpuPrivateData;
-//
-// SMM Relocation variables
-//
-volatile BOOLEAN *mRebased;
-
///
/// Handle for the SMM CPU Protocol
///
@@ -85,7 +80,6 @@ EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute = {
EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];
-BOOLEAN mSmmRelocated = FALSE;
volatile BOOLEAN *mSmmInitialized = NULL;
UINT32 mBspApicId = 0;
@@ -135,12 +129,6 @@ UINTN mSmmCpuSmramRangeCount;
UINT8 mPhysicalAddressBits;
-//
-// Control register contents saved for SMM S3 resume state initialization.
-//
-UINT32 mSmmCr0;
-UINT32 mSmmCr4;
-
/**
Initialize IDT to setup exception handlers for SMM.
@@ -337,12 +325,11 @@ SmmWriteSaveState (
}
/**
- C function for SMI handler. To change all processor's SMMBase Register.
+ Initialize SMM environment.
**/
VOID
-EFIAPI
-SmmInitHandler (
+InitializeSmm (
VOID
)
{
@@ -350,10 +337,6 @@ SmmInitHandler (
UINTN Index;
BOOLEAN IsBsp;
- //
- // Update SMM IDT entries' code segment and load IDT
- //
- AsmWriteIdtr (&gcSmiIdtr);
ApicId = GetApicId ();
IsBsp = (BOOLEAN)(mBspApicId == ApicId);
@@ -363,7 +346,7 @@ SmmInitHandler (
for (Index = 0; Index < mNumberOfCpus; Index++) {
if (ApicId == (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
PERF_CODE (
- MpPerfBegin (Index, SMM_MP_PERF_PROCEDURE_ID (SmmInitHandler));
+ MpPerfBegin (Index, SMM_MP_PERF_PROCEDURE_ID (InitializeSmm));
);
//
// Initialize SMM specific features on the currently executing CPU
@@ -388,15 +371,8 @@ SmmInitHandler (
InitializeMpSyncData ();
}
- if (!mSmmRelocated) {
- //
- // Hook return after RSM to set SMM re-based flag
- //
- SemaphoreHook (Index, &mRebased[Index]);
- }
-
PERF_CODE (
- MpPerfEnd (Index, SMM_MP_PERF_PROCEDURE_ID (SmmInitHandler));
+ MpPerfEnd (Index, SMM_MP_PERF_PROCEDURE_ID (InitializeSmm));
);
return;
@@ -457,107 +433,6 @@ ExecuteFirstSmiInit (
}
/**
- Relocate SmmBases for each processor.
-
- Execute on first boot and all S3 resumes
-
-**/
-VOID
-EFIAPI
-SmmRelocateBases (
- VOID
- )
-{
- UINT8 BakBuf[BACK_BUF_SIZE];
- SMRAM_SAVE_STATE_MAP BakBuf2;
- SMRAM_SAVE_STATE_MAP *CpuStatePtr;
- UINT8 *U8Ptr;
- UINTN Index;
- UINTN BspIndex;
-
- PERF_FUNCTION_BEGIN ();
-
- //
- // Make sure the reserved size is large enough for procedure SmmInitTemplate.
- //
- ASSERT (sizeof (BakBuf) >= gcSmmInitSize);
-
- //
- // Patch ASM code template with current CR0, CR3, and CR4 values
- //
- mSmmCr0 = (UINT32)AsmReadCr0 ();
- PatchInstructionX86 (gPatchSmmCr0, mSmmCr0, 4);
- PatchInstructionX86 (gPatchSmmCr3, AsmReadCr3 (), 4);
- mSmmCr4 = (UINT32)AsmReadCr4 ();
- PatchInstructionX86 (gPatchSmmCr4, mSmmCr4 & (~CR4_CET_ENABLE), 4);
-
- //
- // Patch GDTR for SMM base relocation
- //
- gcSmiInitGdtr.Base = gcSmiGdtr.Base;
- gcSmiInitGdtr.Limit = gcSmiGdtr.Limit;
-
- U8Ptr = (UINT8 *)(UINTN)(SMM_DEFAULT_SMBASE + SMM_HANDLER_OFFSET);
- CpuStatePtr = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
-
- //
- // Backup original contents at address 0x38000
- //
- CopyMem (BakBuf, U8Ptr, sizeof (BakBuf));
- CopyMem (&BakBuf2, CpuStatePtr, sizeof (BakBuf2));
-
- //
- // Load image for relocation
- //
- CopyMem (U8Ptr, gcSmmInitTemplate, gcSmmInitSize);
-
- //
- // Retrieve the local APIC ID of current processor
- //
- mBspApicId = GetApicId ();
-
- //
- // Relocate SM bases for all APs
- // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate
- //
- BspIndex = (UINTN)-1;
- for (Index = 0; Index < mNumberOfCpus; Index++) {
- mRebased[Index] = FALSE;
- if (mBspApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {
- SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId);
- //
- // Wait for this AP to finish its 1st SMI
- //
- while (!mRebased[Index]) {
- }
- } else {
- //
- // BSP will be Relocated later
- //
- BspIndex = Index;
- }
- }
-
- //
- // Relocate BSP's SMM base
- //
- ASSERT (BspIndex != (UINTN)-1);
- SendSmiIpi (mBspApicId);
- //
- // Wait for the BSP to finish its 1st SMI
- //
- while (!mRebased[BspIndex]) {
- }
-
- //
- // Restore contents at address 0x38000
- //
- CopyMem (CpuStatePtr, &BakBuf2, sizeof (BakBuf2));
- CopyMem (U8Ptr, BakBuf, sizeof (BakBuf));
- PERF_FUNCTION_END ();
-}
-
-/**
SMM Ready To Lock event notification handler.
The CPU S3 data is copied to SMRAM for security and mSmmReadyToLock is set to
@@ -751,6 +626,85 @@ MpInformation2HobCompare (
}
/**
+ Extract NumberOfCpus, MaxNumberOfCpus and EFI_PROCESSOR_INFORMATION for all CPU from gEfiMpServiceProtocolGuid.
+
+ @param[out] NumberOfCpus Pointer to NumberOfCpus.
+ @param[out] MaxNumberOfCpus Pointer to MaxNumberOfCpus.
+
+ @retval ProcessorInfo Pointer to EFI_PROCESSOR_INFORMATION buffer.
+**/
+EFI_PROCESSOR_INFORMATION *
+GetMpInformationFromMpServices (
+ OUT UINTN *NumberOfCpus,
+ OUT UINTN *MaxNumberOfCpus
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN NumberOfEnabledProcessors;
+ UINTN NumberOfProcessors;
+ EFI_MP_SERVICES_PROTOCOL *MpService;
+ EFI_PROCESSOR_INFORMATION *ProcessorInfo;
+
+ if ((NumberOfCpus == NULL) || (MaxNumberOfCpus == NULL)) {
+ ASSERT_EFI_ERROR (EFI_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ ProcessorInfo = NULL;
+ *NumberOfCpus = 0;
+ *MaxNumberOfCpus = 0;
+
+ /// Get the MP Services Protocol
+ Status = gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&MpService);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return NULL;
+ }
+
+ /// Get the number of processors
+ Status = MpService->GetNumberOfProcessors (MpService, &NumberOfProcessors, &NumberOfEnabledProcessors);
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return NULL;
+ }
+
+ ASSERT (NumberOfProcessors <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
+
+ /// Allocate buffer for processor information
+ ProcessorInfo = AllocateZeroPool (sizeof (EFI_PROCESSOR_INFORMATION) * NumberOfProcessors);
+ if (ProcessorInfo == NULL) {
+ ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);
+ return NULL;
+ }
+
+ /// Get processor information
+ for (Index = 0; Index < NumberOfProcessors; Index++) {
+ Status = MpService->GetProcessorInfo (MpService, Index | CPU_V2_EXTENDED_TOPOLOGY, &ProcessorInfo[Index]);
+ if (EFI_ERROR (Status)) {
+ FreePool (ProcessorInfo);
+ DEBUG ((DEBUG_ERROR, "%a: Failed to get processor information for processor %d\n", __func__, Index));
+ ASSERT_EFI_ERROR (Status);
+ return NULL;
+ }
+ }
+
+ *NumberOfCpus = NumberOfEnabledProcessors;
+
+ ASSERT (*NumberOfCpus <= PcdGet32 (PcdCpuMaxLogicalProcessorNumber));
+ //
+ // If support CPU hot plug, we need to allocate resources for possibly hot-added processors
+ //
+ if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
+ *MaxNumberOfCpus = PcdGet32 (PcdCpuMaxLogicalProcessorNumber);
+ } else {
+ *MaxNumberOfCpus = *NumberOfCpus;
+ }
+
+ return ProcessorInfo;
+}
+
+/**
Extract NumberOfCpus, MaxNumberOfCpus and EFI_PROCESSOR_INFORMATION for all CPU from MpInformation2 HOB.
@param[out] NumberOfCpus Pointer to NumberOfCpus.
@@ -784,7 +738,11 @@ GetMpInformation (
HobCount = 0;
FirstMpInfo2Hob = GetFirstGuidHob (&gMpInformation2HobGuid);
- ASSERT (FirstMpInfo2Hob != NULL);
+ if (FirstMpInfo2Hob == NULL) {
+ DEBUG ((DEBUG_INFO, "%a: [INFO] gMpInformation2HobGuid HOB not found.\n", __func__));
+ return GetMpInformationFromMpServices (NumberOfCpus, MaxNumberOfCpus);
+ }
+
GuidHob = FirstMpInfo2Hob;
while (GuidHob != NULL) {
MpInformation2HobData = GET_GUID_HOB_DATA (GuidHob);
@@ -883,8 +841,6 @@ PiCpuSmmEntry (
{
EFI_STATUS Status;
UINTN Index;
- VOID *Buffer;
- UINTN BufferPages;
UINTN TileCodeSize;
UINTN TileDataSize;
UINTN TileSize;
@@ -903,7 +859,6 @@ PiCpuSmmEntry (
//
// Initialize address fixup
//
- PiSmmCpuSmmInitFixupAddress ();
PiSmmCpuSmiEntryFixupAddress ();
//
@@ -1115,62 +1070,30 @@ PiCpuSmmEntry (
ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET));
//
- // Retrive the allocated SmmBase from gSmmBaseHobGuid. If found,
+ // Check whether the Required TileSize is enough.
+ //
+ if (TileSize > SIZE_8KB) {
+ DEBUG ((DEBUG_ERROR, "The Range of Smbase in SMRAM is not enough -- Required TileSize = 0x%08x, Actual TileSize = 0x%08x\n", TileSize, SIZE_8KB));
+ FreePool (gSmmCpuPrivate->ProcessorInfo);
+ CpuDeadLoop ();
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ //
+ // Retrieve the allocated SmmBase from gSmmBaseHobGuid. If found,
// means the SmBase relocation has been done.
//
mCpuHotPlugData.SmBase = NULL;
Status = GetSmBase (mMaxNumberOfCpus, &mCpuHotPlugData.SmBase);
- if (Status == EFI_OUT_OF_RESOURCES) {
- ASSERT (Status != EFI_OUT_OF_RESOURCES);
+ ASSERT (!EFI_ERROR (Status));
+ if (EFI_ERROR (Status)) {
CpuDeadLoop ();
}
- if (!EFI_ERROR (Status)) {
- ASSERT (mCpuHotPlugData.SmBase != NULL);
- //
- // Check whether the Required TileSize is enough.
- //
- if (TileSize > SIZE_8KB) {
- DEBUG ((DEBUG_ERROR, "The Range of Smbase in SMRAM is not enough -- Required TileSize = 0x%08x, Actual TileSize = 0x%08x\n", TileSize, SIZE_8KB));
- FreePool (mCpuHotPlugData.SmBase);
- FreePool (gSmmCpuPrivate->ProcessorInfo);
- CpuDeadLoop ();
- return RETURN_BUFFER_TOO_SMALL;
- }
-
- mSmmRelocated = TRUE;
- } else {
- ASSERT (Status == EFI_NOT_FOUND);
- ASSERT (mCpuHotPlugData.SmBase == NULL);
- //
- // When the HOB doesn't exist, allocate new SMBASE itself.
- //
- DEBUG ((DEBUG_INFO, "PiCpuSmmEntry: gSmmBaseHobGuid not found!\n"));
-
- mCpuHotPlugData.SmBase = (UINTN *)AllocatePool (sizeof (UINTN) * mMaxNumberOfCpus);
- if (mCpuHotPlugData.SmBase == NULL) {
- ASSERT (mCpuHotPlugData.SmBase != NULL);
- CpuDeadLoop ();
- }
-
- //
- // very old processors (i486 + pentium) need 32k not 4k alignment, exclude them.
- //
- ASSERT (FamilyId >= 6);
- //
- // Allocate buffer for all of the tiles.
- //
- BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));
- Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);
- if (Buffer == NULL) {
- DEBUG ((DEBUG_ERROR, "Failed to allocate %Lu pages.\n", (UINT64)BufferPages));
- CpuDeadLoop ();
- return EFI_OUT_OF_RESOURCES;
- }
-
- ASSERT (Buffer != NULL);
- DEBUG ((DEBUG_INFO, "New Allcoated SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages)));
- }
+ //
+ // ASSERT SmBase has been relocated.
+ //
+ ASSERT (mCpuHotPlugData.SmBase != NULL);
//
// Allocate buffer for pointers to array in SMM_CPU_PRIVATE_DATA.
@@ -1200,10 +1123,6 @@ PiCpuSmmEntry (
// size for each CPU in the platform
//
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
- if (!mSmmRelocated) {
- mCpuHotPlugData.SmBase[Index] = (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET;
- }
-
gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof (SMRAM_SAVE_STATE_MAP);
gSmmCpuPrivate->CpuSaveState[Index] = (VOID *)(mCpuHotPlugData.SmBase[Index] + SMRAM_SAVE_STATE_MAP_OFFSET);
gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
@@ -1300,41 +1219,11 @@ PiCpuSmmEntry (
}
//
- // Set SMI stack for SMM base relocation
- //
- PatchInstructionX86 (
- gPatchSmmInitStack,
- (UINTN)(Stacks + mSmmStackSize - sizeof (UINTN)),
- sizeof (UINTN)
- );
-
- //
// Initialize IDT
//
InitializeSmmIdt ();
//
- // Check whether Smm Relocation is done or not.
- // If not, will do the SmmBases Relocation here!!!
- //
- if (!mSmmRelocated) {
- //
- // Relocate SMM Base addresses to the ones allocated from SMRAM
- //
- mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus);
- ASSERT (mRebased != NULL);
- SmmRelocateBases ();
-
- //
- // Call hook for BSP to perform extra actions in normal mode after all
- // SMM base addresses have been relocated on all CPUs
- //
- SmmCpuFeaturesSmmRelocationComplete ();
- }
-
- DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));
-
- //
// SMM Time initialization
//
InitializeSmmTimer ();
@@ -1370,15 +1259,15 @@ PiCpuSmmEntry (
// Those MSRs & CSRs must be configured before normal SMI sources happen.
// So, here is to issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
//
- if (mSmmRelocated) {
- ExecuteFirstSmiInit ();
+ ExecuteFirstSmiInit ();
- //
- // Call hook for BSP to perform extra actions in normal mode after all
- // SMM base addresses have been relocated on all CPUs
- //
- SmmCpuFeaturesSmmRelocationComplete ();
- }
+ //
+ // Call hook for BSP to perform extra actions in normal mode after all
+ // SMM base addresses have been relocated on all CPUs
+ //
+ SmmCpuFeaturesSmmRelocationComplete ();
+
+ DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));
//
// Fill in SMM Reserved Regions
@@ -1770,88 +1659,6 @@ AllocateCodePages (
}
/**
- Allocate aligned pages for code.
-
- @param[in] Pages Number of pages to be allocated.
- @param[in] Alignment The requested alignment of the allocation.
- Must be a power of two.
- If Alignment is zero, then byte alignment is used.
-
- @return Allocated memory.
-**/
-VOID *
-AllocateAlignedCodePages (
- IN UINTN Pages,
- IN UINTN Alignment
- )
-{
- EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS Memory;
- UINTN AlignedMemory;
- UINTN AlignmentMask;
- UINTN UnalignedPages;
- UINTN RealPages;
-
- //
- // Alignment must be a power of two or zero.
- //
- ASSERT ((Alignment & (Alignment - 1)) == 0);
-
- if (Pages == 0) {
- return NULL;
- }
-
- if (Alignment > EFI_PAGE_SIZE) {
- //
- // Calculate the total number of pages since alignment is larger than page size.
- //
- AlignmentMask = Alignment - 1;
- RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment);
- //
- // Make sure that Pages plus EFI_SIZE_TO_PAGES (Alignment) does not overflow.
- //
- ASSERT (RealPages > Pages);
-
- Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, RealPages, &Memory);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- AlignedMemory = ((UINTN)Memory + AlignmentMask) & ~AlignmentMask;
- UnalignedPages = EFI_SIZE_TO_PAGES (AlignedMemory - (UINTN)Memory);
- if (UnalignedPages > 0) {
- //
- // Free first unaligned page(s).
- //
- Status = gSmst->SmmFreePages (Memory, UnalignedPages);
- ASSERT_EFI_ERROR (Status);
- }
-
- Memory = AlignedMemory + EFI_PAGES_TO_SIZE (Pages);
- UnalignedPages = RealPages - Pages - UnalignedPages;
- if (UnalignedPages > 0) {
- //
- // Free last unaligned page(s).
- //
- Status = gSmst->SmmFreePages (Memory, UnalignedPages);
- ASSERT_EFI_ERROR (Status);
- }
- } else {
- //
- // Do not over-allocate pages in this case.
- //
- Status = gSmst->SmmAllocatePages (AllocateAnyPages, EfiRuntimeServicesCode, Pages, &Memory);
- if (EFI_ERROR (Status)) {
- return NULL;
- }
-
- AlignedMemory = (UINTN)Memory;
- }
-
- return (VOID *)AlignedMemory;
-}
-
-/**
Perform the remaining tasks.
**/
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 7f244ea803..f42910ddf1 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -188,14 +188,6 @@ typedef struct {
#define PROTECT_MODE_CODE_SEGMENT 0x08
#define LONG_MODE_CODE_SEGMENT 0x38
-//
-// The size 0x20 must be bigger than
-// the size of template code of SmmInit. Currently,
-// the size of SmmInit requires the 0x16 Bytes buffer
-// at least.
-//
-#define BACK_BUF_SIZE 0x20
-
#define EXCEPTION_VECTOR_NUMBER 0x20
#define INVALID_APIC_ID 0xFFFFFFFFFFFFFFFFULL
@@ -357,12 +349,11 @@ SmmWriteSaveState (
);
/**
- C function for SMI handler. To change all processor's SMMBase Register.
+ Initialize SMM environment.
**/
VOID
-EFIAPI
-SmmInitHandler (
+InitializeSmm (
VOID
);
@@ -375,18 +366,9 @@ ExecuteFirstSmiInit (
VOID
);
-extern BOOLEAN mSmmRelocated;
extern volatile BOOLEAN *mSmmInitialized;
extern UINT32 mBspApicId;
-extern CONST UINT8 gcSmmInitTemplate[];
-extern CONST UINT16 gcSmmInitSize;
-X86_ASSEMBLY_PATCH_LABEL gPatchSmmCr0;
-extern UINT32 mSmmCr0;
-X86_ASSEMBLY_PATCH_LABEL gPatchSmmCr3;
-extern UINT32 mSmmCr4;
-X86_ASSEMBLY_PATCH_LABEL gPatchSmmCr4;
-X86_ASSEMBLY_PATCH_LABEL gPatchSmmInitStack;
X86_ASSEMBLY_PATCH_LABEL mPatchCetSupported;
extern BOOLEAN mCetSupported;
@@ -475,7 +457,6 @@ extern UINTN mSmmStackArrayBase;
extern UINTN mSmmStackArrayEnd;
extern UINTN mSmmStackSize;
extern EFI_SMM_CPU_SERVICE_PROTOCOL mSmmCpuService;
-extern IA32_DESCRIPTOR gcSmiInitGdtr;
extern SMM_CPU_SEMAPHORES mSmmCpuSemaphores;
extern UINTN mSemaphoreSize;
extern SPIN_LOCK *mPFLock;
@@ -794,18 +775,6 @@ FindSmramInfo (
);
/**
- Relocate SmmBases for each processor.
-
- Execute on first boot and all S3 resumes
-
-**/
-VOID
-EFIAPI
-SmmRelocateBases (
- VOID
- );
-
-/**
Page Fault handler for SMM use.
@param InterruptType Defines the type of interrupt or exception that
@@ -850,22 +819,6 @@ InitMsrSpinLockByIndex (
);
/**
- Hook return address of SMM Save State so that semaphore code
- can be executed immediately after AP exits SMM to indicate to
- the BSP that an AP has exited SMM after SMBASE relocation.
-
- @param[in] CpuIndex The processor index.
- @param[in] RebasedFlag A pointer to a flag that is set to TRUE
- immediately after AP exits SMM.
-
-**/
-VOID
-SemaphoreHook (
- IN UINTN CpuIndex,
- IN volatile BOOLEAN *RebasedFlag
- );
-
-/**
Configure SMM Code Access Check feature for all processors.
SMM Feature Control MSR will be locked after configuration.
**/
@@ -875,33 +828,6 @@ ConfigSmmCodeAccessCheck (
);
/**
- Hook the code executed immediately after an RSM instruction on the currently
- executing CPU. The mode of code executed immediately after RSM must be
- detected, and the appropriate hook must be selected. Always clear the auto
- HALT restart flag if it is set.
-
- @param[in] CpuIndex The processor index for the currently
- executing CPU.
- @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 mode from 64-bit SMM.
- @param[in] NewInstructionPointer Instruction pointer to use if resuming to
- same mode as SMM.
-
- @retval The value of the original instruction pointer before it was hooked.
-
-**/
-UINT64
-EFIAPI
-HookReturnFromSmm (
- IN UINTN CpuIndex,
- SMRAM_SAVE_STATE_MAP *CpuState,
- UINT64 NewInstructionPointer32,
- UINT64 NewInstructionPointer
- );
-
-/**
Get the size of the SMI Handler in bytes.
@retval The size, in bytes, of the SMI Handler.
@@ -1105,22 +1031,6 @@ AllocateCodePages (
IN UINTN Pages
);
-/**
- Allocate aligned pages for code.
-
- @param[in] Pages Number of pages to be allocated.
- @param[in] Alignment The requested alignment of the allocation.
- Must be a power of two.
- If Alignment is zero, then byte alignment is used.
-
- @return Allocated memory.
-**/
-VOID *
-AllocateAlignedCodePages (
- IN UINTN Pages,
- IN UINTN Alignment
- );
-
//
// S3 related global variable and function prototype.
//
@@ -1304,15 +1214,6 @@ EdkiiSmmGetMemoryAttributes (
/**
This function fixes up the address of the global variable or function
- referred in SmmInit assembly files to be the absolute address.
-**/
-VOID
-EFIAPI
-PiSmmCpuSmmInitFixupAddress (
- );
-
-/**
- This function fixes up the address of the global variable or function
referred in SmiEntry assembly files to be the absolute address.
**/
VOID
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index a018954ed7..3354f94a64 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -6,7 +6,7 @@
#
# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
-# Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.<BR>
+# Copyright (C) 2023 - 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -47,24 +47,20 @@
SmmMpPerf.c
[Sources.Ia32]
- Ia32/Semaphore.c
Ia32/PageTbl.c
Ia32/SmmFuncsArch.c
Ia32/SmmProfileArch.c
Ia32/SmmProfileArch.h
- Ia32/SmmInit.nasm
Ia32/SmiEntry.nasm
Ia32/SmiException.nasm
Ia32/MpFuncs.nasm
Ia32/Cet.nasm
[Sources.X64]
- X64/Semaphore.c
X64/PageTbl.c
X64/SmmFuncsArch.c
X64/SmmProfileArch.c
X64/SmmProfileArch.h
- X64/SmmInit.nasm
X64/SmiEntry.nasm
X64/SmiException.nasm
X64/MpFuncs.nasm
@@ -114,6 +110,7 @@
gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES
gEfiMmMpProtocolGuid ## PRODUCES
gEdkiiSmmCpuRendezvousProtocolGuid ## PRODUCES
+ gEfiMpServiceProtocolGuid ## CONSUMES
[Guids]
gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot.
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmMpPerf.h b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmMpPerf.h
index 591b212c06..2e2ea3c76e 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmMpPerf.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmMpPerf.h
@@ -14,7 +14,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
// The list of all MP procedures that need to be perf-logged.
//
#define SMM_MP_PERF_PROCEDURE_LIST(_) \
- _(SmmInitHandler), \
+ _(InitializeSmm), \
_(SmmRendezvousEntry), \
_(PlatformValidSmi), \
_(SmmRendezvousExit), \
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
index 1e316ee0ac..b9a62aeeb0 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c
@@ -70,75 +70,6 @@ IA32_DESCRIPTOR gSmiHandlerIdtr;
UINT8 mSmmSaveStateRegisterLma;
/**
- Hook the code executed immediately after an RSM instruction on the currently
- executing CPU. The mode of code executed immediately after RSM must be
- detected, and the appropriate hook must be selected. Always clear the auto
- HALT restart flag if it is set.
-
- @param[in] CpuIndex The processor index for the currently
- executing CPU.
- @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 mode from 64-bit SMM.
- @param[in] NewInstructionPointer Instruction pointer to use if resuming to
- same mode as SMM.
-
- @retval The value of the original instruction pointer before it was hooked.
-
-**/
-UINT64
-EFIAPI
-HookReturnFromSmm (
- IN UINTN CpuIndex,
- SMRAM_SAVE_STATE_MAP *CpuState,
- UINT64 NewInstructionPointer32,
- UINT64 NewInstructionPointer
- )
-{
- UINT64 OriginalInstructionPointer;
-
- OriginalInstructionPointer = SmmCpuFeaturesHookReturnFromSmm (
- CpuIndex,
- CpuState,
- NewInstructionPointer32,
- NewInstructionPointer
- );
- if (OriginalInstructionPointer != 0) {
- return OriginalInstructionPointer;
- }
-
- if (mSmmSaveStateRegisterLma == EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT) {
- OriginalInstructionPointer = (UINT64)CpuState->x86._EIP;
- CpuState->x86._EIP = (UINT32)NewInstructionPointer;
- //
- // Clear the auto HALT restart flag so the RSM instruction returns
- // program control to the instruction following the HLT instruction.
- //
- if ((CpuState->x86.AutoHALTRestart & BIT0) != 0) {
- CpuState->x86.AutoHALTRestart &= ~BIT0;
- }
- } else {
- OriginalInstructionPointer = CpuState->x64._RIP;
- if ((CpuState->x64.IA32_EFER & LMA) == 0) {
- CpuState->x64._RIP = (UINT32)NewInstructionPointer32;
- } else {
- CpuState->x64._RIP = (UINT32)NewInstructionPointer;
- }
-
- //
- // Clear the auto HALT restart flag so the RSM instruction returns
- // program control to the instruction following the HLT instruction.
- //
- if ((CpuState->x64.AutoHALTRestart & BIT0) != 0) {
- CpuState->x64.AutoHALTRestart &= ~BIT0;
- }
- }
-
- return OriginalInstructionPointer;
-}
-
-/**
Get the size of the SMI Handler in bytes.
@retval The size, in bytes, of the SMI Handler.
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index f412ac0ce2..f86a6d2bcb 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -71,6 +71,9 @@
## @libraryclass Provides functions for SMM CPU Sync Operation.
SmmCpuSyncLib|Include/Library/SmmCpuSyncLib.h
+ ## @libraryclass Provides functions for SMM Relocation Operation.
+ SmmRelocationLib|Include/Library/SmmRelocationLib.h
+
[LibraryClasses.RISCV64]
## @libraryclass Provides functions to manage MMU features on RISCV64 CPUs.
##
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 9426641eb2..3d49f72588 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -201,6 +201,8 @@
UefiCpuPkg/Library/MmSaveStateLib/AmdMmSaveStateLib.inf
UefiCpuPkg/Library/MmSaveStateLib/IntelMmSaveStateLib.inf
UefiCpuPkg/Library/SmmCpuFeaturesLib/AmdSmmCpuFeaturesLib.inf
+ UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
+ UefiCpuPkg/Library/SmmRelocationLib/AmdSmmRelocationLib.inf
[Components.X64]
UefiCpuPkg/Library/CpuExceptionHandlerLib/UnitTest/DxeCpuExceptionHandlerLibUnitTest.inf
diff --git a/UefiPayloadPkg/Readme.md b/UefiPayloadPkg/Readme.md
index cb7f39b3f7..4149eab90d 100644
--- a/UefiPayloadPkg/Readme.md
+++ b/UefiPayloadPkg/Readme.md
@@ -55,11 +55,13 @@ FIT Format URL: https://universalpayload.github.io/spec/chapter2-payload-image-f
```
- FIT
- Windows
+ ```
+ Download and install swig by https://swig.org/ and also set install path into environment variable
+ ```
```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
choco install dtc-msys2
pip3 install pefile
- pip3 install swig
pip3 install pylibfdt
```
- Ubuntu
diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc
index e1b9d5ecf1..2860a659f6 100644
--- a/UefiPayloadPkg/UefiPayloadPkg.dsc
+++ b/UefiPayloadPkg/UefiPayloadPkg.dsc
@@ -316,6 +316,8 @@
AmdSvsmLib|UefiCpuPkg/Library/AmdSvsmLibNull/AmdSvsmLibNull.inf
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
FdtLib|MdePkg/Library/BaseFdtLib/BaseFdtLib.inf
+ SmmRelocationLib|UefiCpuPkg/Library/SmmRelocationLib/SmmRelocationLib.inf
+
[LibraryClasses.common]
!if $(BOOTSPLASH_IMAGE)
SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf
diff --git a/pip-requirements.txt b/pip-requirements.txt
index 2f4cd33cc6..92d46e865f 100644
--- a/pip-requirements.txt
+++ b/pip-requirements.txt
@@ -12,9 +12,9 @@
# https://www.python.org/dev/peps/pep-0440/#version-specifiers
##
-edk2-pytool-library==0.20.0
-edk2-pytool-extensions==0.26.4
+edk2-pytool-library==0.21.5
+edk2-pytool-extensions==0.27.5
edk2-basetools==0.1.51
antlr4-python3-runtime==4.7.1
lcov-cobertura==2.0.2
-regex==2023.12.25
+regex==2024.5.15