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/Library/ArmMonitorLib/ArmMonitorLib.c2
-rw-r--r--ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf1
-rw-r--r--ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c2
-rw-r--r--ArmVirtPkg/ArmVirt.dsc.inc7
-rw-r--r--ArmVirtPkg/ArmVirtKvmTool.dsc2
-rw-r--r--ArmVirtPkg/ArmVirtQemu.dsc33
-rw-r--r--ArmVirtPkg/ArmVirtQemuFvMain.fdf.inc6
-rw-r--r--ArmVirtPkg/ArmVirtQemuKernel.dsc32
-rw-r--r--ArmVirtPkg/ArmVirtXen.dsc4
-rw-r--r--ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c95
-rw-r--r--ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf39
-rw-r--r--ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf42
-rw-r--r--ArmVirtPkg/PlatformCI/PlatformBuildLib.py2
-rw-r--r--ArmVirtPkg/PrePi/AArch64/ArchPrePi.c5
-rw-r--r--ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S41
-rw-r--r--ArmVirtPkg/VarStore.fdf.inc5
-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.py4
-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/BaseCryptLib/SmmCryptLib.inf6
-rw-r--r--CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c41
-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/Include/CrtLibSupport.h37
-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--Maintainers.txt4
-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/Guid/AcpiS3Context.h3
-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/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c13
-rw-r--r--MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c4
-rw-r--r--MdeModulePkg/MdeModulePkg.dec15
-rw-r--r--MdeModulePkg/MdeModulePkg.dsc6
-rw-r--r--MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c8
-rw-r--r--MdeModulePkg/Universal/Acpi/FirmwarePerformanceDataTablePei/FirmwarePerformancePei.c12
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c5
-rw-r--r--MdeModulePkg/Universal/HiiDatabaseDxe/Image.c9
-rw-r--r--MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c2
-rw-r--r--MdePkg/Include/IndustryStandard/IpmiNetFnOem.h18
-rw-r--r--MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h46
-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/Include/Register/Amd/Cpuid.h4
-rw-r--r--MdePkg/Include/Register/Intel/ArchitecturalMsr.h8
-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/AmdSev/AmdSevX64.fdf5
-rw-r--r--OvmfPkg/AmdSevDxe/AmdSevDxe.c4
-rw-r--r--OvmfPkg/Bhyve/BhyveX64.dsc1
-rw-r--r--OvmfPkg/CloudHv/CloudHvX64.dsc1
-rw-r--r--OvmfPkg/CloudHv/CloudHvX64.fdf5
-rw-r--r--OvmfPkg/CpuS3DataDxe/CpuS3Data.c13
-rw-r--r--OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf4
-rw-r--r--OvmfPkg/Include/Dsc/MorLock.dsc.inc10
-rw-r--r--OvmfPkg/Include/Fdf/MorLock.fdf.inc10
-rw-r--r--OvmfPkg/IntelTdx/TdxHelperLib/SecTdxHelper.c10
-rw-r--r--OvmfPkg/Library/CcExitLib/CcExitVcHandler.c12
-rw-r--r--OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c (renamed from ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c)47
-rw-r--r--OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf46
-rw-r--r--OvmfPkg/Library/PeilessStartupLib/Hob.c4
-rw-r--r--OvmfPkg/Library/PlatformInitLib/IntelTdx.c8
-rw-r--r--OvmfPkg/Library/PlatformInitLib/MemDetect.c162
-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/Microvm/MicrovmX64.fdf3
-rw-r--r--OvmfPkg/OvmfPkg.dec5
-rw-r--r--OvmfPkg/OvmfPkgIa32.dsc8
-rw-r--r--OvmfPkg/OvmfPkgIa32.fdf6
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.dsc8
-rw-r--r--OvmfPkg/OvmfPkgIa32X64.fdf6
-rw-r--r--OvmfPkg/OvmfPkgX64.dsc8
-rw-r--r--OvmfPkg/OvmfPkgX64.fdf11
-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/QemuVideoDxe/Driver.c9
-rw-r--r--OvmfPkg/QemuVideoDxe/Qemu.h6
-rw-r--r--OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf4
-rw-r--r--OvmfPkg/QemuVideoDxe/VbeShim.asm281
-rw-r--r--OvmfPkg/QemuVideoDxe/VbeShim.c328
-rw-r--r--OvmfPkg/QemuVideoDxe/VbeShim.h701
-rwxr-xr-xOvmfPkg/QemuVideoDxe/VbeShim.sh82
-rw-r--r--OvmfPkg/ResetVector/Ia32/AmdSev.asm5
-rw-r--r--OvmfPkg/ResetVector/Ia32/PageTables64.asm20
-rw-r--r--OvmfPkg/Sec/AmdSev.c58
-rw-r--r--OvmfPkg/Sec/AmdSev.h14
-rw-r--r--OvmfPkg/Sec/SecMain.c1
-rw-r--r--OvmfPkg/Sec/SecMain.inf3
-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--ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c6
-rw-r--r--StandaloneMmPkg/Core/Mmi.c1
-rw-r--r--UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c13
-rw-r--r--UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf4
-rw-r--r--UefiCpuPkg/Include/Library/SmmRelocationLib.h42
-rw-r--r--UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c9
-rw-r--r--UefiCpuPkg/Library/MpInitLib/DxeMpLib.c183
-rw-r--r--UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm6
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.c191
-rw-r--r--UefiCpuPkg/Library/MpInitLib/MpLib.h56
-rw-r--r--UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf6
-rw-r--r--UefiCpuPkg/Library/MpInitLib/PeiMpLib.c154
-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.c1010
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.nasm153
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c29
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmInit.nasm96
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c10
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c429
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h129
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf12
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmmMpPerf.h2
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/SmramSaveState.c69
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.nasm189
-rw-r--r--UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c30
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dec7
-rw-r--r--UefiCpuPkg/UefiCpuPkg.dsc5
-rw-r--r--UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c78
-rw-r--r--UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf4
-rw-r--r--UefiPayloadPkg/Readme.md4
-rw-r--r--UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c5
-rw-r--r--UefiPayloadPkg/UefiPayloadPkg.dsc2
-rw-r--r--UefiPayloadPkg/UniversalPayloadBuild.py4
-rw-r--r--pip-requirements.txt6
285 files changed, 15992 insertions, 4476 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/Library/ArmMonitorLib/ArmMonitorLib.c b/ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.c
index 741f5c6157..617e88f367 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 (FeaturePcdGet (PcdMonitorConduitHvc)) {
ArmCallHvc ((ARM_HVC_ARGS *)Args);
} else {
ArmCallSmc ((ARM_SMC_ARGS *)Args);
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
index 60d8fe31c2..e8f1011fa1 100644
--- a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
@@ -78,7 +78,6 @@
gArmTokenSpaceGuid.PcdBaseBoardManufacturer
gArmTokenSpaceGuid.PcdBaseBoardProductName
gArmTokenSpaceGuid.PcdBaseBoardVersion
- gArmTokenSpaceGuid.PcdFdBaseAddress
[Guids]
gEfiGenericVariableGuid
diff --git a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
index 03f9f07cfa..b1b0d8eb5e 100644
--- a/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
+++ b/ArmPkg/Universal/Smbios/SmbiosMiscDxe/Type00/MiscBiosVendorFunction.c
@@ -253,7 +253,7 @@ SMBIOS_MISC_TABLE_FUNCTION (MiscBiosVendor) {
(VOID)CopyMem (SmbiosRecord, InputData, sizeof (SMBIOS_TABLE_TYPE0));
SmbiosRecord->Hdr.Length = sizeof (SMBIOS_TABLE_TYPE0);
- SmbiosRecord->BiosSegment = (UINT16)(FixedPcdGet32 (PcdFdBaseAddress) / SIZE_64KB);
+ SmbiosRecord->BiosSegment = 0;
if (BiosPhysicalSize < SIZE_16MB) {
SmbiosRecord->BiosSize = Base2ToByteWith64KUnit (BiosPhysicalSize) - 1;
} else {
diff --git a/ArmVirtPkg/ArmVirt.dsc.inc b/ArmVirtPkg/ArmVirt.dsc.inc
index 2bc6a29eb1..038931562c 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
@@ -286,6 +289,8 @@
gEmbeddedTokenSpaceGuid.PcdPrePiProduceMemoryTypeInformationHob|TRUE
+ gArmTokenSpaceGuid.PcdMonitorConduitHvc|TRUE
+
[PcdsFeatureFlag.AARCH64]
#
# Activate AcpiSdtProtocol
diff --git a/ArmVirtPkg/ArmVirtKvmTool.dsc b/ArmVirtPkg/ArmVirtKvmTool.dsc
index 20da331966..da6737d9d7 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
diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc
index 7e2ff33ad1..d90c60b28a 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
@@ -66,7 +66,7 @@
QemuLoadImageLib|OvmfPkg/Library/GenericQemuLoadImageLib/GenericQemuLoadImageLib.inf
TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
- VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
+ VirtNorFlashPlatformLib|OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
@@ -92,6 +92,8 @@
TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf
!endif
+ ArmMonitorLib|ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf
+
[LibraryClasses.AARCH64]
ArmPlatformLib|ArmVirtPkg/Library/ArmPlatformLibQemu/ArmPlatformLibQemu.inf
@@ -152,6 +154,9 @@
gArmTokenSpaceGuid.PcdVFPEnabled|1
!endif
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress|0x00000000
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|$(FD_SIZE)
+
gArmPlatformTokenSpaceGuid.PcdCPUCoresStackBase|0x4007c000
gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
@@ -231,6 +236,10 @@
# System Memory Size -- 128 MB initially, actual size will be fetched from DT
gArmTokenSpaceGuid.PcdSystemMemorySize|0x8000000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize | 0x40000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize | 0x40000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize | 0x40000
+
[PcdsFixedAtBuild.AARCH64]
# Clearing BIT0 in this PCD prevents installing a 32-bit SMBIOS entry point,
# if the entry point version is >= 3.0. AARCH64 OSes cannot assume the
@@ -243,6 +252,13 @@
[PcdsDynamicDefault.common]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 | 0
+
## If TRUE, OvmfPkg/AcpiPlatformDxe will not wait for PCI
# enumeration to complete before installing ACPI tables.
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE
@@ -404,7 +420,10 @@
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
!endif
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
- MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {
+ <LibraryClasses>
+ NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf
+ }
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf {
@@ -432,6 +451,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
}
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
#
# Status Code Routing
@@ -555,6 +575,11 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
#
+ # Hash2 Protocol Support
+ #
+ SecurityPkg/Hash2DxeCrypto/Hash2DxeCrypto.inf
+
+ #
# TPM2 support
#
!if $(TPM2_ENABLE) == TRUE
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..7d41f280cb 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
@@ -65,7 +65,7 @@
ArmVirtMemInfoLib|ArmVirtPkg/Library/QemuVirtMemInfoLib/QemuVirtMemInfoLib.inf
TimerLib|ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
- VirtNorFlashPlatformLib|ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
+ VirtNorFlashPlatformLib|OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
@@ -82,6 +82,8 @@
TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
TpmPlatformHierarchyLib|SecurityPkg/Library/PeiDxeTpmPlatformHierarchyLibNull/PeiDxeTpmPlatformHierarchyLib.inf
+ ArmMonitorLib|ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf
+
[LibraryClasses.common.DXE_DRIVER]
AcpiPlatformLib|OvmfPkg/Library/AcpiPlatformLib/DxeAcpiPlatformLib.inf
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
@@ -120,6 +122,8 @@
gArmTokenSpaceGuid.PcdVFPEnabled|1
!endif
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress|0x00000000
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize|$(FD_SIZE)
gArmPlatformTokenSpaceGuid.PcdCPUCorePrimaryStackSize|0x4000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
gEfiMdeModulePkgTokenSpaceGuid.PcdMaxAuthVariableSize|0x2800
@@ -181,6 +185,10 @@
gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|3
gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x20000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize | 0x40000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize | 0x40000
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize | 0x40000
+
[PcdsPatchableInModule.common]
# we need to provide a resolution for this PCD that supports PcdSet64()
# being called from ArmVirtPkg/Library/PlatformPeiLib/PlatformPeiLib.c,
@@ -206,6 +214,13 @@
[PcdsDynamicDefault.common]
gEfiMdePkgTokenSpaceGuid.PcdPlatformBootTimeOut|3
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase64 | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase64 | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase | 0
+ gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase64 | 0
+
## If TRUE, OvmfPkg/AcpiPlatformDxe will not wait for PCI
# enumeration to complete before installing ACPI tables.
gEfiMdeModulePkgTokenSpaceGuid.PcdPciDisableBusEnumeration|TRUE
@@ -311,7 +326,10 @@
MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf
!endif
MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf
- MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf
+ MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf {
+ <LibraryClasses>
+ NULL|EmbeddedPkg/Library/NvVarStoreFormattedLib/NvVarStoreFormattedLib.inf
+ }
MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntimeDxe.inf
MdeModulePkg/Universal/ResetSystemRuntimeDxe/ResetSystemRuntimeDxe.inf
EmbeddedPkg/RealTimeClockRuntimeDxe/RealTimeClockRuntimeDxe.inf {
@@ -339,6 +357,7 @@
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
}
MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf
+ SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf
#
# Status Code Routing
@@ -462,6 +481,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..3689106857 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
diff --git a/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c
new file mode 100644
index 0000000000..1c8b18d5e5
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.c
@@ -0,0 +1,95 @@
+/** @file
+ Arm Monitor Library that chooses the conduit based on the PSCI node in the
+ device tree provided by QEMU
+
+ Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+ Copyright (c) 2024, Google LLC. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ArmHvcLib.h>
+#include <Library/ArmMonitorLib.h>
+#include <Library/ArmSmcLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+#include <Protocol/FdtClient.h>
+
+STATIC UINT32 mArmSmcccMethod;
+
+/** Library constructor.
+
+ Assign the global variable mArmSmcccMethod based on the PSCI node in the
+ device tree.
+**/
+RETURN_STATUS
+EFIAPI
+ArmVirtQemuMonitorLibConstructor (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ FDT_CLIENT_PROTOCOL *FdtClient;
+ CONST VOID *Prop;
+
+ Status = gBS->LocateProtocol (
+ &gFdtClientProtocolGuid,
+ NULL,
+ (VOID **)&FdtClient
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ Status = FdtClient->FindCompatibleNodeProperty (
+ FdtClient,
+ "arm,psci-0.2",
+ "method",
+ &Prop,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (AsciiStrnCmp (Prop, "hvc", 3) == 0) {
+ mArmSmcccMethod = 1;
+ } else if (AsciiStrnCmp (Prop, "smc", 3) == 0) {
+ mArmSmcccMethod = 2;
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Unknown SMCCC method \"%a\"\n",
+ __func__,
+ Prop
+ ));
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/** Monitor call.
+
+ An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued
+ depending on the default conduit.
+
+ @param [in,out] Args Arguments for the HVC/SMC.
+**/
+VOID
+EFIAPI
+ArmMonitorCall (
+ IN OUT ARM_MONITOR_ARGS *Args
+ )
+{
+ if (mArmSmcccMethod == 1) {
+ ArmCallHvc ((ARM_HVC_ARGS *)Args);
+ } else if (mArmSmcccMethod == 2) {
+ ArmCallSmc ((ARM_SMC_ARGS *)Args);
+ } else {
+ ASSERT ((mArmSmcccMethod == 1) || (mArmSmcccMethod == 2));
+ }
+}
diff --git a/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf
new file mode 100644
index 0000000000..e43ba215c2
--- /dev/null
+++ b/ArmVirtPkg/Library/ArmVirtQemuMonitorLib/ArmVirtQemuMonitorLib.inf
@@ -0,0 +1,39 @@
+## @file
+# Arm Monitor Library that chooses the conduit based on the PSCI node in the
+# device tree provided by QEMU
+#
+# Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
+# Copyright (c) 2024, Google LLC. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = ArmVirtQemuMonitorLib
+ FILE_GUID = 09f50ee5-2aa2-42b9-a2a0-090faeefed2b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ArmMonitorLib|DXE_DRIVER DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = ArmVirtQemuMonitorLibConstructor
+
+[Sources]
+ ArmVirtQemuMonitorLib.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ ArmHvcLib
+ ArmSmcLib
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gFdtClientProtocolGuid ## CONSUMES
+
+[Depex]
+ gFdtClientProtocolGuid
diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf b/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
deleted file mode 100644
index a6b5865be9..0000000000
--- a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.inf
+++ /dev/null
@@ -1,42 +0,0 @@
-#/** @file
-#
-# Component description file for NorFlashQemuLib module
-#
-# Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-#**/
-
-[Defines]
- INF_VERSION = 0x00010005
- BASE_NAME = NorFlashQemuLib
- FILE_GUID = 339B7829-4C5F-4EFC-B2DD-5050E530DECE
- MODULE_TYPE = DXE_DRIVER
- VERSION_STRING = 1.0
- LIBRARY_CLASS = VirtNorFlashPlatformLib
-
-[Sources.common]
- NorFlashQemuLib.c
-
-[Packages]
- MdePkg/MdePkg.dec
- ArmPkg/ArmPkg.dec
- ArmVirtPkg/ArmVirtPkg.dec
- EmbeddedPkg/EmbeddedPkg.dec
- OvmfPkg/OvmfPkg.dec
-
-[LibraryClasses]
- BaseLib
- DebugLib
- UefiBootServicesTableLib
-
-[Protocols]
- gFdtClientProtocolGuid ## CONSUMES
-
-[Depex]
- gFdtClientProtocolGuid
-
-[Pcd]
- gArmTokenSpaceGuid.PcdFvBaseAddress
- gArmTokenSpaceGuid.PcdFvSize
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/ArmVirtPkg/PrePi/AArch64/ArchPrePi.c b/ArmVirtPkg/PrePi/AArch64/ArchPrePi.c
index 9cab88ca08..a02c2ad560 100644
--- a/ArmVirtPkg/PrePi/AArch64/ArchPrePi.c
+++ b/ArmVirtPkg/PrePi/AArch64/ArchPrePi.c
@@ -15,11 +15,6 @@ ArchInitialize (
VOID
)
{
- // Enable Floating Point
- if (FixedPcdGet32 (PcdVFPEnabled)) {
- ArmEnableVFP ();
- }
-
if (ArmReadCurrentEL () == AARCH64_EL2) {
// Trap General Exceptions. All exceptions that would be routed to EL1 are routed to EL2
ArmWriteHcr (ARM_HCR_TGE);
diff --git a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
index 01623b6b35..fc06c28daa 100644
--- a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
+++ b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
@@ -9,6 +9,23 @@
#include <AsmMacroIoLibV8.h>
ASM_FUNC(_ModuleEntryPoint)
+ //
+ // If we are booting from RAM using the Linux kernel boot protocol, x0 will
+ // point to the DTB image in memory. Otherwise, use the default value defined
+ // by the platform.
+ //
+ cbnz x0, 0f
+ ldr x0, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
+
+0:mov x28, x0 // preserve DTB pointer
+ mov x27, x1 // preserve base of image pointer
+
+#if (FixedPcdGet32 (PcdVFPEnabled))
+ // Enable Floating Point. This needs to be done before entering C code, which
+ // may use FP/SIMD registers.
+ bl ArmEnableVFP
+#endif
+
bl ASM_PFX(DiscoverDramFromDt)
// Get ID of this CPU in Multicore system
@@ -95,28 +112,18 @@ _NeverReturn:
// VOID
// DiscoverDramFromDt (
-// VOID *DeviceTreeBaseAddress, // passed by loader in x0
-// VOID *ImageBase // passed by FDF trampoline in x1
+// VOID *DeviceTreeBaseAddress, // passed by loader in x0, preserved in x28
+// VOID *ImageBase // passed by FDF trampoline in x1, preserved in x27
// );
ASM_PFX(DiscoverDramFromDt):
- //
- // If we are booting from RAM using the Linux kernel boot protocol, x0 will
- // point to the DTB image in memory. Otherwise, use the default value defined
- // by the platform.
- //
- cbnz x0, 0f
- ldr x0, PcdGet64 (PcdDeviceTreeInitialBaseAddress)
-
-0:mov x29, x30 // preserve LR
- mov x28, x0 // preserve DTB pointer
- mov x27, x1 // preserve base of image pointer
+ mov x29, x30 // preserve LR
//
- // The base of the runtime image has been preserved in x1. Check whether
+ // The base of the runtime image has been preserved in x27. Check whether
// the expected magic number can be found in the header.
//
ldr w8, .LArm64LinuxMagic
- ldr w9, [x1, #0x38]
+ ldr w9, [x27, #0x38]
cmp w8, w9
bne .Lout
@@ -132,8 +139,8 @@ ASM_PFX(DiscoverDramFromDt):
ldr x6, [x8]
ldr x7, [x9]
sub x7, x7, x6
- add x7, x7, x1
- str x1, [x8]
+ add x7, x7, x27
+ str x27, [x8]
str x7, [x9]
//
diff --git a/ArmVirtPkg/VarStore.fdf.inc b/ArmVirtPkg/VarStore.fdf.inc
index b4afaf12b6..1f035a132e 100644
--- a/ArmVirtPkg/VarStore.fdf.inc
+++ b/ArmVirtPkg/VarStore.fdf.inc
@@ -10,7 +10,7 @@
##
[FD.QEMU_VARS]
-BaseAddress = 0x04000000
+BaseAddress = 0x00000000
Size = 0xc0000
ErasePolarity = 1
BlockSize = 0x40000
@@ -18,7 +18,6 @@ NumBlocks = 3
0x00000000|0x00040000
-gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
#NV_VARIABLE_STORE
DATA = {
## This is the EFI_FIRMWARE_VOLUME_HEADER
@@ -57,7 +56,6 @@ DATA = {
0x00040000|0x00040000
-gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
#NV_FTW_WORKING
DATA = {
# EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER->Signature = gEdkiiWorkingBlockSignatureGuid =
@@ -71,5 +69,4 @@ DATA = {
}
0x00080000|0x00040000
-gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase|gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
#NV_FTW_SPARE
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..d797ac80c1 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]')
@@ -686,8 +684,6 @@ class CheckGitCommits:
def __init__(self, rev_spec, max_count):
dec_files = self.read_dec_files_from_git()
commits = self.read_commit_list_from_git(rev_spec, max_count)
- if len(commits) == 1 and Verbose.level > Verbose.ONELINE:
- commits = [ rev_spec ]
self.ok = True
blank_line = False
for commit in commits:
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..021cc328f8 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/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index 109e08377a..984a5b293a 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -48,10 +48,10 @@
Cipher/CryptAes.c
Cipher/CryptAeadAesGcmNull.c
Pk/CryptRsaBasic.c
- Pk/CryptRsaExtNull.c
+ Pk/CryptRsaExt.c
Pk/CryptPkcs1Oaep.c
Pk/CryptPkcs5Pbkdf2.c
- Pk/CryptPkcs7SignNull.c
+ Pk/CryptPkcs7Sign.c
Pk/CryptPkcs7VerifyCommon.c
Pk/CryptPkcs7VerifyBase.c
Pk/CryptPkcs7VerifyEku.c
@@ -63,7 +63,7 @@
Pk/CryptRsaPssSignNull.c
Pk/CryptEcNull.c
Pem/CryptPem.c
- Bn/CryptBnNull.c
+ Bn/CryptBn.c
SysCall/CrtWrapper.c
SysCall/ConstantTimeClock.c
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
index 37cdecc9bd..b114cc069a 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
@@ -271,7 +271,46 @@ strcpy (
const char *strSource
)
{
- AsciiStrCpyS (strDest, MAX_STRING_SIZE, strSource);
+ AsciiStrCpyS (strDest, AsciiStrnSizeS (strSource, MAX_STRING_SIZE - 1), strSource);
+ return strDest;
+}
+
+char *
+strncpy (
+ char *strDest,
+ const char *strSource,
+ size_t count
+ )
+{
+ UINTN DestMax = MAX_STRING_SIZE;
+
+ if (count < MAX_STRING_SIZE) {
+ DestMax = count + 1;
+ } else {
+ count = MAX_STRING_SIZE-1;
+ }
+
+ AsciiStrnCpyS (strDest, DestMax, strSource, (UINTN)count);
+
+ return strDest;
+}
+
+char *
+strcat (
+ char *strDest,
+ const char *strSource
+ )
+{
+ UINTN DestMax;
+
+ DestMax = AsciiStrnLenS (strDest, MAX_STRING_SIZE) + AsciiStrnSizeS (strSource, MAX_STRING_SIZE);
+
+ if (DestMax > MAX_STRING_SIZE) {
+ DestMax = MAX_STRING_SIZE;
+ }
+
+ AsciiStrCatS (strDest, DestMax, strSource);
+
return strDest;
}
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/Include/CrtLibSupport.h b/CryptoPkg/Library/Include/CrtLibSupport.h
index f36fe08f0c..afc00956ab 100644
--- a/CryptoPkg/Library/Include/CrtLibSupport.h
+++ b/CryptoPkg/Library/Include/CrtLibSupport.h
@@ -403,22 +403,33 @@ strcpy (
const char *strSource
);
+char *
+strncpy (
+ char *strDest,
+ const char *strSource,
+ size_t count
+ );
+
+char *
+strcat (
+ char *strDest,
+ const char *strSource
+ );
+
//
// Macros that directly map functions to BaseLib, BaseMemoryLib, and DebugLib functions
//
-#define memcpy(dest, source, count) CopyMem(dest,source,(UINTN)(count))
-#define memset(dest, ch, count) SetMem(dest,(UINTN)(count),(UINT8)(ch))
-#define memchr(buf, ch, count) ScanMem8(buf,(UINTN)(count),(UINT8)ch)
-#define memcmp(buf1, buf2, count) (int)(CompareMem(buf1,buf2,(UINTN)(count)))
-#define memmove(dest, source, count) CopyMem(dest,source,(UINTN)(count))
-#define strlen(str) (size_t)(AsciiStrnLenS(str,MAX_STRING_SIZE))
-#define strncpy(strDest, strSource, count) AsciiStrnCpyS(strDest,MAX_STRING_SIZE,strSource,(UINTN)count)
-#define strcat(strDest, strSource) AsciiStrCatS(strDest,MAX_STRING_SIZE,strSource)
-#define strncmp(string1, string2, count) (int)(AsciiStrnCmp(string1,string2,(UINTN)(count)))
-#define strcasecmp(str1, str2) (int)AsciiStriCmp(str1,str2)
-#define strstr(s1, s2) AsciiStrStr(s1,s2)
-#define sprintf(buf, ...) AsciiSPrint(buf,MAX_STRING_SIZE,__VA_ARGS__)
-#define localtime(timer) NULL
+#define memcpy(dest, source, count) CopyMem(dest,source,(UINTN)(count))
+#define memset(dest, ch, count) SetMem(dest,(UINTN)(count),(UINT8)(ch))
+#define memchr(buf, ch, count) ScanMem8(buf,(UINTN)(count),(UINT8)ch)
+#define memcmp(buf1, buf2, count) (int)(CompareMem(buf1,buf2,(UINTN)(count)))
+#define memmove(dest, source, count) CopyMem(dest,source,(UINTN)(count))
+#define strlen(str) (size_t)(AsciiStrnLenS(str,MAX_STRING_SIZE))
+#define strncmp(string1, string2, count) (int)(AsciiStrnCmp(string1,string2,(UINTN)(count)))
+#define strcasecmp(str1, str2) (int)AsciiStriCmp(str1,str2)
+#define strstr(s1, s2) AsciiStrStr(s1,s2)
+#define sprintf(buf, ...) AsciiSPrint(buf,MAX_STRING_SIZE,__VA_ARGS__)
+#define localtime(timer) NULL
#define assert(expression)
#define offsetof(type, member) OFFSET_OF(type,member)
#define atoi(nptr) AsciiStrDecimalToUintn(nptr)
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/Maintainers.txt b/Maintainers.txt
index 7d9cdca611..274554a2c5 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -567,7 +567,7 @@ F: OvmfPkg/XenIoPvhDxe/
F: OvmfPkg/XenPlatformPei/
F: OvmfPkg/XenPvBlkDxe/
F: OvmfPkg/XenResetVector/
-R: Anthony Perard <anthony.perard@citrix.com> [tperard]
+R: Anthony Perard <anthony@xenproject.org> [tperard]
OvmfPkg: RISC-V Qemu Virt Platform
F: OvmfPkg/RiscVVirt
@@ -626,6 +626,7 @@ F: StandaloneMmPkg/
M: Ard Biesheuvel <ardb+tianocore@kernel.org> [ardbiesheuvel]
M: Sami Mujawar <sami.mujawar@arm.com> [samimujawar]
M: Ray Ni <ray.ni@intel.com> [niruiyu]
+R: Jiaxin Wu <jiaxin.wu@intel.com> [jiaxinwu]
UefiCpuPkg
F: UefiCpuPkg/
@@ -633,6 +634,7 @@ W: https://github.com/tianocore/tianocore.github.io/wiki/UefiCpuPkg
M: Ray Ni <ray.ni@intel.com> [niruiyu]
R: Rahul Kumar <rahul1.kumar@intel.com> [rahul1-kumar]
R: Gerd Hoffmann <kraxel@redhat.com> [kraxel]
+R: Jiaxin Wu <jiaxin.wu@intel.com> [jiaxinwu]
UefiCpuPkg: Sec related modules
F: UefiCpuPkg/SecCore/
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/Guid/AcpiS3Context.h b/MdeModulePkg/Include/Guid/AcpiS3Context.h
index 72d173c4fd..6c7237727e 100644
--- a/MdeModulePkg/Include/Guid/AcpiS3Context.h
+++ b/MdeModulePkg/Include/Guid/AcpiS3Context.h
@@ -1,7 +1,7 @@
/** @file
Definitions for data structures used in S3 resume.
-Copyright (c) 2011 - 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2011 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -30,7 +30,6 @@ typedef struct {
EFI_PHYSICAL_ADDRESS ReturnContext1;
EFI_PHYSICAL_ADDRESS ReturnContext2;
EFI_PHYSICAL_ADDRESS ReturnStackPointer;
- EFI_PHYSICAL_ADDRESS MpService2Ppi;
EFI_PHYSICAL_ADDRESS Smst;
} SMM_S3_RESUME_STATE;
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/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
index 2433c76a8c..36efd64c4c 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c
@@ -11,6 +11,7 @@
performs basic validation.
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -48,6 +49,8 @@ EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;
EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress = NULL;
+extern BOOLEAN mDxeCapsuleLibReadyToBootEvent;
+
/**
Initialize capsule related variables.
**/
@@ -1402,6 +1405,16 @@ IsNestedFmpCapsule (
}
}
} else {
+ if (mDxeCapsuleLibReadyToBootEvent) {
+ //
+ // The ESRT table (mEsrtTable) in the Configuration Table would be located
+ // at the ReadyToBoot event if it exists. Hence, it should return here to
+ // avoid a crash due to calling gBS->LocateProtocol () at runtime in case
+ // there is no ERST table installed.
+ //
+ return FALSE;
+ }
+
//
// Check ESRT protocol
//
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
index 44f30c16c2..efff714d01 100644
--- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
+++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleRuntime.c
@@ -2,6 +2,7 @@
Capsule library runtime support.
Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2024, Ampere Computing LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -23,6 +24,7 @@
extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
EFI_EVENT mDxeRuntimeCapsuleLibVirtualAddressChangeEvent = NULL;
EFI_EVENT mDxeRuntimeCapsuleLibReadyToBootEvent = NULL;
+BOOLEAN mDxeCapsuleLibReadyToBootEvent = FALSE;
/**
Convert EsrtTable physical address to virtual address.
@@ -93,6 +95,8 @@ DxeCapsuleLibReadyToBootEventNotify (
//
mEsrtTable->FwResourceCountMax = mEsrtTable->FwResourceCount;
}
+
+ mDxeCapsuleLibReadyToBootEvent = TRUE;
}
/**
diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 085370eae4..02f330a453 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -4,7 +4,7 @@
# and libraries instances, which are used for those modules.
#
# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.
-# Copyright (c) 2007 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
# (C) Copyright 2016 - 2019 Hewlett Packard Enterprise Development LP<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
@@ -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
@@ -460,6 +465,9 @@
gEdk2JedecSfdpSpiDxeDriverGuid = { 0xBE71701E, 0xB63C, 0x4574, { 0x9C, 0x5C, 0x36, 0x29, 0xE8, 0xEA, 0xC4, 0x14 }}
gEdk2JedecSfdpSpiSmmDriverGuid = { 0x95A1E915, 0x195C, 0x477C, { 0x92, 0x6F, 0x7E, 0x24, 0x67, 0xC1, 0xB3, 0x1F }}
+ ## This GUID will be used to save MTRR_SETTINGS at EndOfDxe by LockBox and restore at S3 boot PEI phase for s3 usage.
+ gEdkiiS3MtrrSettingGuid = { 0xd77baa84, 0xb332, 0x4463, { 0x9f, 0x1d, 0xce, 0x81, 0x00, 0xfe, 0x7f, 0x35 }}
+
[Ppis]
## Include/Ppi/FirmwareVolumeShadowPpi.h
gEdkiiPeiFirmwareVolumeShadowPpiGuid = { 0x7dfe756c, 0xed8d, 0x4d77, {0x9e, 0xc4, 0x39, 0x9a, 0x8a, 0x81, 0x51, 0x16 } }
@@ -1154,6 +1162,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/AcpiTableDxe/AcpiTableProtocol.c b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
index 5f8d20a7e9..45c0ae6c80 100644
--- a/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
+++ b/MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableProtocol.c
@@ -1279,16 +1279,16 @@ RemoveTableFromRsdt (
{
//
// Found entry, so copy all following entries and shrink table
- // We actually copy all + 1 to copy the initialized value of memory over
- // the last entry.
//
if (Rsdt != NULL) {
- CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index) * sizeof (UINT32));
+ CopyMem (CurrentRsdtEntry, CurrentRsdtEntry + 1, (*NumberOfTableEntries - Index - 1) * sizeof (UINT32));
+ ZeroMem ((UINT8 *)Rsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + ((*NumberOfTableEntries - 1) * sizeof (UINT32)), sizeof (UINT32));
Rsdt->Length = Rsdt->Length - sizeof (UINT32);
}
if (Xsdt != NULL) {
- CopyMem (CurrentXsdtEntry, ((UINT64 *)CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index) * sizeof (UINT64));
+ CopyMem (CurrentXsdtEntry, ((UINT64 *)CurrentXsdtEntry) + 1, (*NumberOfTableEntries - Index - 1) * sizeof (UINT64));
+ ZeroMem ((UINT8 *)Xsdt + sizeof (EFI_ACPI_DESCRIPTION_HEADER) + ((*NumberOfTableEntries - 1) * sizeof (UINT64)), sizeof (UINT64));
Xsdt->Length = Xsdt->Length - sizeof (UINT64);
}
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/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
index 6e791783a6..426dead981 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/ConfigKeywordHandler.c
@@ -2101,8 +2101,9 @@ ExtractConfigRequest (
//
// Header->VarStoreId == 0 means no storage for this question.
//
- ASSERT (Header->VarStoreId != 0);
- DEBUG ((DEBUG_INFO, "Varstore Id: 0x%x\n", Header->VarStoreId));
+ if (Header->VarStoreId == 0) {
+ continue;
+ }
Storage = FindStorageFromVarId (FormPackage, Header->VarStoreId);
ASSERT (Storage != NULL);
diff --git a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
index b5b9625969..ab8f056914 100644
--- a/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
+++ b/MdeModulePkg/Universal/HiiDatabaseDxe/Image.c
@@ -1288,7 +1288,6 @@ HiiDrawImage (
UINTN BufferLen;
UINT16 Width;
UINT16 Height;
- UINTN Xpos;
UINTN Ypos;
UINTN OffsetY1;
UINTN OffsetY2;
@@ -1390,9 +1389,11 @@ HiiDrawImage (
for (Ypos = 0; Ypos < Height; Ypos++) {
OffsetY1 = Image->Width * Ypos;
OffsetY2 = Width * Ypos;
- for (Xpos = 0; Xpos < Width; Xpos++) {
- BltBuffer[OffsetY2 + Xpos] = Image->Bitmap[OffsetY1 + Xpos];
- }
+ CopyMem (
+ &BltBuffer[OffsetY2],
+ &Image->Bitmap[OffsetY1],
+ Width * sizeof (*BltBuffer)
+ );
}
}
diff --git a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
index d394d237a5..1c7659031d 100644
--- a/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
+++ b/MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c
@@ -2364,6 +2364,8 @@ Done:
);
ASSERT_EFI_ERROR (Status);
}
+ } else if (Status == EFI_OUT_OF_RESOURCES) {
+ DEBUG ((DEBUG_WARN, "UpdateVariable failed: Out of flash space\n"));
}
return Status;
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/IpmiNetFnSensorEvent.h b/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h
index b92958454f..93f625a32b 100644
--- a/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h
+++ b/MdePkg/Include/IndustryStandard/IpmiNetFnSensorEvent.h
@@ -10,6 +10,7 @@
and Appendix H, Sub-function Assignments.
Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -42,5 +43,50 @@ typedef struct {
UINT8 OEMEvData3;
} IPMI_PLATFORM_EVENT_MESSAGE_DATA_REQUEST;
+//
+// Definitions for Set Sensor Thresholds command
+//
+#define IPMI_SENSOR_SET_SENSOR_THRESHOLDS 0x26
+
+typedef union {
+ struct _SENSOR_BITS {
+ UINT8 LowerNonCriticalThreshold : 1;
+ UINT8 LowerCriticalThreshold : 1;
+ UINT8 LowerNonRecoverableThreshold : 1;
+ UINT8 UpperNonCriticalThreshold : 1;
+ UINT8 UpperCriticalThreshold : 1;
+ UINT8 UpperNonRecoverableThreshold : 1;
+ UINT8 Reserved : 2;
+ } Bits;
+ UINT8 Uint8;
+} SENSOR_BITS;
+
+typedef struct _IPMI_SENSOR_SET_SENSOR_THRESHOLD_REQUEST_DATA {
+ UINT8 SensorNumber;
+ SENSOR_BITS SetBitEnable;
+ UINT8 LowerNonCriticalThreshold;
+ UINT8 LowerCriticalThreshold;
+ UINT8 LowerNonRecoverableThreshold;
+ UINT8 UpperNonCriticalThreshold;
+ UINT8 UpperCriticalThreshold;
+ UINT8 UpperNonRecoverableThreshold;
+} IPMI_SENSOR_SET_SENSOR_THRESHOLD_REQUEST_DATA;
+
+//
+// Definitions for Get Sensor Thresholds command
+//
+#define IPMI_SENSOR_GET_SENSOR_THRESHOLDS 0x27
+
+typedef struct _IPMI_SENSOR_GET_SENSOR_THRESHOLD_RESPONSE_DATA {
+ UINT8 CompletionCode;
+ SENSOR_BITS GetBitEnable;
+ UINT8 LowerNonCriticalThreshold;
+ UINT8 LowerCriticalThreshold;
+ UINT8 LowerNonRecoverableThreshold;
+ UINT8 UpperNonCriticalThreshold;
+ UINT8 UpperCriticalThreshold;
+ UINT8 UpperNonRecoverableThreshold;
+} IPMI_SENSOR_GET_SENSOR_THRESHOLD_RESPONSE_DATA;
+
#pragma pack()
#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/Include/Register/Amd/Cpuid.h b/MdePkg/Include/Register/Amd/Cpuid.h
index add43c40aa..51fa9f235c 100644
--- a/MdePkg/Include/Register/Amd/Cpuid.h
+++ b/MdePkg/Include/Register/Amd/Cpuid.h
@@ -46,9 +46,9 @@ CPUID Signature Information
CPUID Extended Topology Enumeration
@note
- Reference: AMD64 Architecture Programmer’s Manual Volume 3: General-Purpose and System Instructions,
+ Reference: AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions,
Revision 3.35 Appendix E,
- E.4.24 Function 8000_0026—Extended CPU Topology:
+ E.4.24 Function 8000_0026-Extended CPU Topology:
CPUID Fn8000_0026 reports extended topology information for logical processors, including
asymmetric and heterogenous topology descriptions. Individual logical processors may report
different values in systems with asynchronous and heterogeneous topologies.
diff --git a/MdePkg/Include/Register/Intel/ArchitecturalMsr.h b/MdePkg/Include/Register/Intel/ArchitecturalMsr.h
index 756e7c86ec..4715c59dc4 100644
--- a/MdePkg/Include/Register/Intel/ArchitecturalMsr.h
+++ b/MdePkg/Include/Register/Intel/ArchitecturalMsr.h
@@ -5733,9 +5733,9 @@ typedef union {
/// [Bit 7:4] TME Policy/Encryption Algorithm: Only algorithms enumerated in
/// IA32_TME_CAPABILITY are allowed.
/// For example:
- /// 0000 – AES-XTS-128.
- /// 0001 – AES-XTS-128 with integrity.
- /// 0010 – AES-XTS-256.
+ /// 0000 - AES-XTS-128.
+ /// 0001 - AES-XTS-128 with integrity.
+ /// 0010 - AES-XTS-256.
/// Other values are invalid.
///
UINT32 TmePolicy : 4;
@@ -5756,7 +5756,7 @@ typedef union {
/// Similar to enumeration, this is an encoded value.
/// Writing a value greater than MK_TME_MAX_KEYID_BITS will result in #GP.
/// Writing a non-zero value to this field will #GP if bit 1 of EAX (Hardware
- /// Encryption Enable) is not also set to ‘1, as encryption hardware must be
+ /// Encryption Enable) is not also set to 1, as encryption hardware must be
/// enabled to use MKTME.
/// Example: To support 255 keys, this field would be set to a value of 8.
///
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/AmdSev/AmdSevX64.fdf b/OvmfPkg/AmdSev/AmdSevX64.fdf
index d49555c6c8..595945181c 100644
--- a/OvmfPkg/AmdSev/AmdSevX64.fdf
+++ b/OvmfPkg/AmdSev/AmdSevX64.fdf
@@ -77,7 +77,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdSevLaunchSecretBase|gUefiOvmfPkgTokenSpaceGuid.Pcd
0x010C00|0x000400
gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdQemuHashTableSize
-0x011000|0x00F000
+0x011000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x012000|0x00E000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
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/Bhyve/BhyveX64.dsc b/OvmfPkg/Bhyve/BhyveX64.dsc
index 6f305d690d..78050959f8 100644
--- a/OvmfPkg/Bhyve/BhyveX64.dsc
+++ b/OvmfPkg/Bhyve/BhyveX64.dsc
@@ -174,6 +174,7 @@
PeiHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/PeiHardwareInfoLib.inf
DxeHardwareInfoLib|OvmfPkg/Library/HardwareInfoLib/DxeHardwareInfoLib.inf
ImagePropertiesRecordLib|MdeModulePkg/Library/ImagePropertiesRecordLib/ImagePropertiesRecordLib.inf
+ CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
CustomizedDisplayLib|MdeModulePkg/Library/CustomizedDisplayLib/CustomizedDisplayLib.inf
FrameBufferBltLib|MdeModulePkg/Library/FrameBufferBltLib/FrameBufferBltLib.inf
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/CloudHv/CloudHvX64.fdf b/OvmfPkg/CloudHv/CloudHvX64.fdf
index eae3ada191..3e6688b103 100644
--- a/OvmfPkg/CloudHv/CloudHvX64.fdf
+++ b/OvmfPkg/CloudHv/CloudHvX64.fdf
@@ -76,7 +76,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtr|gUefiOvmfPkgTokenSpaceGuid.PcdXenPvhStartOfDayStructPtrSize
-0x010000|0x010000
+0x010000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
diff --git a/OvmfPkg/CpuS3DataDxe/CpuS3Data.c b/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
index 289048b75d..eacdfa12c3 100644
--- a/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
+++ b/OvmfPkg/CpuS3DataDxe/CpuS3Data.c
@@ -9,7 +9,7 @@ number of CPUs reported by the MP Services Protocol, so this module does not
support hot plug CPUs. This module can be copied into a CPU specific package
and customized if these additional features are required.
-Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2013 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2015 - 2020, Red Hat, Inc.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -26,6 +26,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/MemoryAllocationLib.h>
#include <Library/MtrrLib.h>
#include <Library/UefiBootServicesTableLib.h>
+#include <Library/LockBoxLib.h>
#include <Protocol/MpService.h>
#include <Guid/EventGroup.h>
@@ -131,6 +132,16 @@ CpuS3DataOnEndOfDxe (
MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);
//
+ // Save MTRR in lockbox
+ //
+ Status = SaveLockBox (
+ &gEdkiiS3MtrrSettingGuid,
+ &AcpiCpuDataEx->MtrrTable,
+ sizeof (MTRR_SETTINGS)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
// Close event, so it will not be invoked again.
//
gBS->CloseEvent (Event);
diff --git a/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf b/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf
index 228d5ae1b2..5369613f5d 100644
--- a/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+++ b/OvmfPkg/CpuS3DataDxe/CpuS3DataDxe.inf
@@ -9,7 +9,7 @@
# support hot plug CPUs. This module can be copied into a CPU specific package
# and customized if these additional features are required.
#
-# Copyright (c) 2013-2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2013-2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2015-2020, Red Hat, Inc.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -46,9 +46,11 @@
MtrrLib
UefiBootServicesTableLib
UefiDriverEntryPoint
+ LockBoxLib
[Guids]
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+ gEdkiiS3MtrrSettingGuid
[Protocols]
gEfiMpServiceProtocolGuid ## CONSUMES
diff --git a/OvmfPkg/Include/Dsc/MorLock.dsc.inc b/OvmfPkg/Include/Dsc/MorLock.dsc.inc
new file mode 100644
index 0000000000..a8c5fb24b8
--- /dev/null
+++ b/OvmfPkg/Include/Dsc/MorLock.dsc.inc
@@ -0,0 +1,10 @@
+##
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# MorLock support
+##
+
+ SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf
+!if $(SMM_REQUIRE) == TRUE
+ SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf
+!endif
diff --git a/OvmfPkg/Include/Fdf/MorLock.fdf.inc b/OvmfPkg/Include/Fdf/MorLock.fdf.inc
new file mode 100644
index 0000000000..20b7d6619a
--- /dev/null
+++ b/OvmfPkg/Include/Fdf/MorLock.fdf.inc
@@ -0,0 +1,10 @@
+##
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# MorLock support
+##
+
+INF SecurityPkg/Tcg/MemoryOverwriteControl/TcgMor.inf
+!if $(SMM_REQUIRE) == TRUE
+INF SecurityPkg/Tcg/MemoryOverwriteRequestControlLock/TcgMorLockSmm.inf
+!endif
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/CcExitLib/CcExitVcHandler.c b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
index 549375dfed..da8f1e5db9 100644
--- a/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
+++ b/OvmfPkg/Library/CcExitLib/CcExitVcHandler.c
@@ -98,7 +98,7 @@ UnsupportedExit (
Validate that the MMIO memory access is not to encrypted memory.
Examine the pagetable entry for the memory specified. MMIO should not be
- performed against encrypted memory. MMIO to the APIC page is always allowed.
+ performed against encrypted memory.
@param[in] Ghcb Pointer to the Guest-Hypervisor Communication Block
@param[in] MemoryAddress Memory address to validate
@@ -118,16 +118,6 @@ ValidateMmioMemory (
{
MEM_ENCRYPT_SEV_ADDRESS_RANGE_STATE State;
GHCB_EVENT_INJECTION GpEvent;
- UINTN Address;
-
- //
- // Allow APIC accesses (which will have the encryption bit set during
- // SEC and PEI phases).
- //
- Address = MemoryAddress & ~(SIZE_4KB - 1);
- if (Address == GetLocalApicBaseAddress ()) {
- return 0;
- }
State = MemEncryptSevGetAddressRangeState (
0,
diff --git a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c
index d0fa7e5046..e5c7d4cdfa 100644
--- a/ArmVirtPkg/Library/NorFlashQemuLib/NorFlashQemuLib.c
+++ b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.c
@@ -1,10 +1,11 @@
/** @file
- Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
+ Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
+ Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
+ SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
+**/
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
@@ -12,10 +13,12 @@
#include <Library/VirtNorFlashPlatformLib.h>
#include <Protocol/FdtClient.h>
+#include <stdbool.h>
#define QEMU_NOR_BLOCK_SIZE SIZE_256KB
+#define MAX_FLASH_BANKS 4
-#define MAX_FLASH_BANKS 4
+STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
EFI_STATUS
VirtNorFlashPlatformInitialization (
@@ -25,8 +28,6 @@ VirtNorFlashPlatformInitialization (
return EFI_SUCCESS;
}
-STATIC VIRT_NOR_FLASH_DESCRIPTION mNorFlashDevices[MAX_FLASH_BANKS];
-
EFI_STATUS
VirtNorFlashPlatformGetDevices (
OUT VIRT_NOR_FLASH_DESCRIPTION **NorFlashDescriptions,
@@ -42,6 +43,7 @@ VirtNorFlashPlatformGetDevices (
UINT32 Num;
UINT64 Base;
UINT64 Size;
+ BOOLEAN Found;
Status = gBS->LocateProtocol (
&gFdtClientProtocolGuid,
@@ -50,7 +52,8 @@ VirtNorFlashPlatformGetDevices (
);
ASSERT_EFI_ERROR (Status);
- Num = 0;
+ Num = 0;
+ Found = FALSE;
for (FindNodeStatus = FdtClient->FindCompatibleNode (
FdtClient,
"cfi-flash",
@@ -94,8 +97,8 @@ VirtNorFlashPlatformGetDevices (
// Disregard any flash devices that overlap with the primary FV.
// The firmware is not updatable from inside the guest anyway.
//
- if ((PcdGet64 (PcdFvBaseAddress) + PcdGet32 (PcdFvSize) > Base) &&
- ((Base + Size) > PcdGet64 (PcdFvBaseAddress)))
+ if ((PcdGet32 (PcdOvmfFdBaseAddress) + PcdGet32 (PcdOvmfFirmwareFdSize) > Base) &&
+ ((Base + Size) > PcdGet32 (PcdOvmfFdBaseAddress)))
{
continue;
}
@@ -105,6 +108,32 @@ VirtNorFlashPlatformGetDevices (
mNorFlashDevices[Num].Size = (UINTN)Size;
mNorFlashDevices[Num].BlockSize = QEMU_NOR_BLOCK_SIZE;
Num++;
+ if (!Found) {
+ //
+ // By default, the second available flash is stored as a non-volatile variable.
+ //
+ Status = PcdSet32S (PcdFlashNvStorageVariableBase, Base);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // The Base is the value of PcdFlashNvStorageVariableBase,
+ // PcdFlashNvStorageFtwWorkingBase can be got by
+ // PcdFlashNvStorageVariableBase + PcdFlashNvStorageVariableSize
+ //
+ Base += PcdGet32 (PcdFlashNvStorageVariableSize);
+ Status = PcdSet32S (PcdFlashNvStorageFtwWorkingBase, Base);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Now, the Base is the value of PcdFlashNvStorageFtwWorkingBase,
+ // PcdFlashNvStorageFtwSpareBase can be got by
+ // PcdFlashNvStorageFtwWorkingBase + PcdFlashNvStorageFtwWorkingSize.
+ //
+ Base += PcdGet32 (PcdFlashNvStorageFtwWorkingSize);
+ Status = PcdSet32S (PcdFlashNvStorageFtwSpareBase, Base);
+ ASSERT_EFI_ERROR (Status);
+ Found = TRUE;
+ }
}
//
diff --git a/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
new file mode 100644
index 0000000000..14ddb4c11e
--- /dev/null
+++ b/OvmfPkg/Library/FdtNorFlashQemuLib/FdtNorFlashQemuLib.inf
@@ -0,0 +1,46 @@
+## @file
+#
+# Copyright (c) 2014-2018, Linaro Ltd. All rights reserved.<BR>
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = NorFlashQemuLib
+ FILE_GUID = E225C90F-6CB9-8AF3-095B-2668FC633A57
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NorFlashQemuLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER UEFI_APPLICATION
+
+[Sources]
+ FdtNorFlashQemuLib.c
+
+[Packages]
+ EmbeddedPkg/EmbeddedPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ UefiBootServicesTableLib
+
+[Protocols]
+ gFdtClientProtocolGuid ## CONSUMES
+
+[Depex]
+ gFdtClientProtocolGuid
+
+[Pcd]
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFirmwareFdSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingSize
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageVariableBase
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwWorkingBase
+gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareBase
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..2b6404cc51 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
@@ -630,6 +633,7 @@ PlatformAddressWidthFromCpuid (
{
UINT32 RegEax, RegEbx, RegEcx, RegEdx, Max;
UINT8 PhysBits;
+ UINT8 GuestPhysBits;
CHAR8 Signature[13];
IA32_CR4 Cr4;
BOOLEAN Valid = FALSE;
@@ -652,13 +656,17 @@ PlatformAddressWidthFromCpuid (
if (Max >= 0x80000008) {
AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);
- PhysBits = (UINT8)RegEax;
+ PhysBits = (UINT8)RegEax;
+ GuestPhysBits = (UINT8)(RegEax >> 16);
} else {
- PhysBits = 36;
+ PhysBits = 36;
+ GuestPhysBits = 0;
}
if (!QemuQuirk) {
Valid = TRUE;
+ } else if (GuestPhysBits) {
+ Valid = TRUE;
} else if (PhysBits >= 41) {
Valid = TRUE;
} else if (AsciiStrCmp (Signature, "GenuineIntel") == 0) {
@@ -675,15 +683,21 @@ PlatformAddressWidthFromCpuid (
DEBUG ((
DEBUG_INFO,
- "%a: Signature: '%a', PhysBits: %d, QemuQuirk: %a, la57: %a, Valid: %a\n",
+ "%a: Signature: '%a', PhysBits: %d, GuestPhysBits: %d, QemuQuirk: %a, la57: %a, Valid: %a\n",
__func__,
Signature,
PhysBits,
+ GuestPhysBits,
QemuQuirk ? "On" : "Off",
Cr4.Bits.LA57 ? "On" : "Off",
Valid ? "Yes" : "No"
));
+ if (GuestPhysBits && (PhysBits > GuestPhysBits)) {
+ DEBUG ((DEBUG_INFO, "%a: limit PhysBits to %d (GuestPhysBits)\n", __func__, GuestPhysBits));
+ PhysBits = GuestPhysBits;
+ }
+
if (Valid) {
/*
* Due to the sign extension we can use only the lower half of the
@@ -692,7 +706,7 @@ PlatformAddressWidthFromCpuid (
* and a 56 bit wide address space with 5 paging levels.
*/
if (Cr4.Bits.LA57) {
- if (PhysBits > 48) {
+ if ((PhysBits > 48) && !GuestPhysBits) {
/*
* Some Intel CPUs support 5-level paging, have more than 48
* phys-bits but support only 4-level EPT, which effectively
@@ -702,11 +716,11 @@ PlatformAddressWidthFromCpuid (
* problem: They can handle guest phys-bits larger than 48
* only in case the host runs in 5-level paging mode.
*
- * Until we have some way to communicate that kind of
- * limitations from hypervisor to guest, limit phys-bits
- * to 48 unconditionally.
+ * GuestPhysBits is used to communicate that kind of
+ * limitations from hypervisor to guest. If GuestPhysBits is
+ * not set play safe and limit phys-bits to 48.
*/
- DEBUG ((DEBUG_INFO, "%a: limit PhysBits to 48 (5-level paging)\n", __func__));
+ DEBUG ((DEBUG_INFO, "%a: limit PhysBits to 48 (5-level paging, no GuestPhysBits)\n", __func__));
PhysBits = 48;
}
} else {
@@ -982,6 +996,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 +1102,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/Microvm/MicrovmX64.fdf b/OvmfPkg/Microvm/MicrovmX64.fdf
index 825bf9f5e4..055e659a35 100644
--- a/OvmfPkg/Microvm/MicrovmX64.fdf
+++ b/OvmfPkg/Microvm/MicrovmX64.fdf
@@ -62,6 +62,9 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvm
0x00C000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize
+0x00D000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
0x010000|0x010000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 731f67b727..51be9a5959 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -278,6 +278,11 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase|0|UINT32|0x44
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupSize|0|UINT32|0x45
+ ## Specify the extra page table needed to mark the APIC MMIO range as unencrypted.
+ # The value should be a multiple of 4KB for each.
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|0x0|UINT32|0x72
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize|0x0|UINT32|0x73
+
## The base address and size of the SEV Launch Secret Area provisioned
# after remote attestation. If this is set in the .fdf, the platform
# is responsible for protecting the area from DXE phase overwrites.
diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 9db3ebd0e7..8ed950bb1c 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
@@ -876,6 +881,7 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
!include OvmfPkg/Include/Dsc/ShellComponents.dsc.inc
+!include OvmfPkg/Include/Dsc/MorLock.dsc.inc
!if $(SECURE_BOOT_ENABLE) == TRUE
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 6eb26f7d46..2d9cffb3f3 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
@@ -354,6 +359,7 @@ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
!include OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc
!include OvmfPkg/Include/Fdf/ShellDxe.fdf.inc
+!include OvmfPkg/Include/Fdf/MorLock.fdf.inc
!if $(LOAD_X64_ON_IA32_ENABLE) == TRUE
INF OvmfPkg/CompatImageLoaderDxe/CompatImageLoaderDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 4337812292..371a53232d 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
@@ -890,6 +895,7 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
!include OvmfPkg/Include/Dsc/ShellComponents.dsc.inc
+!include OvmfPkg/Include/Dsc/MorLock.dsc.inc
!if $(SECURE_BOOT_ENABLE) == TRUE
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 080784f722..0de247bb12 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)
@@ -361,6 +366,7 @@ INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf
!include OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc
!include OvmfPkg/Include/Fdf/ShellDxe.fdf.inc
+!include OvmfPkg/Include/Fdf/MorLock.fdf.inc
################################################################################
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 157ae6c0e4..b5e433e94f 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
@@ -958,6 +963,7 @@
MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf
!include OvmfPkg/Include/Dsc/ShellComponents.dsc.inc
+!include OvmfPkg/Include/Dsc/MorLock.dsc.inc
!if $(SECURE_BOOT_ENABLE) == TRUE
SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index c2d3cc901e..4398d3f3f4 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -97,7 +97,10 @@ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCpuidBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfCp
0x00F000|0x001000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecSvsmCaaSize
-0x010000|0x010000
+0x010000|0x001000
+gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
+
+0x011000|0x00F000
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase|gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
0x020000|0x0E0000
@@ -327,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)
@@ -398,6 +406,7 @@ INF OvmfPkg/Tcg/TdTcg2Dxe/TdTcg2Dxe.inf
!include OvmfPkg/Include/Fdf/OvmfTpmDxe.fdf.inc
!include OvmfPkg/Include/Fdf/ShellDxe.fdf.inc
+!include OvmfPkg/Include/Fdf/MorLock.fdf.inc
################################################################################
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/QemuVideoDxe/Driver.c b/OvmfPkg/QemuVideoDxe/Driver.c
index c28171d137..6feca83802 100644
--- a/OvmfPkg/QemuVideoDxe/Driver.c
+++ b/OvmfPkg/QemuVideoDxe/Driver.c
@@ -466,15 +466,6 @@ QemuVideoControllerDriverStart (
goto UninstallGop;
}
- #if defined MDE_CPU_IA32 || defined MDE_CPU_X64
- if ((Private->Variant == QEMU_VIDEO_BOCHS_MMIO) ||
- (Private->Variant == QEMU_VIDEO_BOCHS))
- {
- InstallVbeShim (Card->Name, Private->GraphicsOutput.Mode->FrameBufferBase);
- }
-
- #endif
-
gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
diff --git a/OvmfPkg/QemuVideoDxe/Qemu.h b/OvmfPkg/QemuVideoDxe/Qemu.h
index 57341a0bbf..bd6198dd50 100644
--- a/OvmfPkg/QemuVideoDxe/Qemu.h
+++ b/OvmfPkg/QemuVideoDxe/Qemu.h
@@ -495,10 +495,4 @@ QemuVideoBochsModeSetup (
BOOLEAN IsQxl
);
-VOID
-InstallVbeShim (
- IN CONST CHAR16 *CardName,
- IN EFI_PHYSICAL_ADDRESS FrameBufferBase
- );
-
#endif
diff --git a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
index 43a6e07faa..6b7baa8525 100644
--- a/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
+++ b/OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
@@ -33,10 +33,6 @@
Initialize.c
Qemu.h
-[Sources.Ia32, Sources.X64]
- VbeShim.c
- VbeShim.h
-
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.asm b/OvmfPkg/QemuVideoDxe/VbeShim.asm
deleted file mode 100644
index 1d284b2641..0000000000
--- a/OvmfPkg/QemuVideoDxe/VbeShim.asm
+++ /dev/null
@@ -1,281 +0,0 @@
-;------------------------------------------------------------------------------
-; @file
-; A minimal Int10h stub that allows the Windows 2008 R2 SP1 UEFI guest's buggy,
-; default VGA driver to switch to 1024x768x32, on the stdvga and QXL video
-; cards of QEMU.
-;
-; Copyright (C) 2014, Red Hat, Inc.
-; Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
-;
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-;------------------------------------------------------------------------------
-
-; enable this macro for debug messages
-;%define DEBUG
-
-%macro DebugLog 1
-%ifdef DEBUG
- push si
- mov si, %1
- call PrintStringSi
- pop si
-%endif
-%endmacro
-
-
-BITS 16
-ORG 0
-
-VbeInfo:
-TIMES 256 nop
-
-VbeModeInfo:
-TIMES 256 nop
-
-
-Handler:
- cmp ax, 0x4f00
- je GetInfo
- cmp ax, 0x4f01
- je GetModeInfo
- cmp ax, 0x4f02
- je SetMode
- cmp ax, 0x4f03
- je GetMode
- cmp ax, 0x4f10
- je GetPmCapabilities
- cmp ax, 0x4f15
- je ReadEdid
- cmp ah, 0x00
- je SetModeLegacy
- DebugLog StrUnknownFunction
-Hang:
- jmp Hang
-
-
-GetInfo:
- push es
- push di
- push ds
- push si
- push cx
-
- DebugLog StrEnterGetInfo
-
- ; target (es:di) set on input
- push cs
- pop ds
- mov si, VbeInfo
- ; source (ds:si) set now
-
- mov cx, 256
- cld
- rep movsb
-
- pop cx
- pop si
- pop ds
- pop di
- pop es
- jmp Success
-
-
-GetModeInfo:
- push es
- push di
- push ds
- push si
- push cx
-
- DebugLog StrEnterGetModeInfo
-
- and cx, ~0x4000 ; clear potentially set LFB bit in mode number
- cmp cx, 0x00f1
- je KnownMode1
- DebugLog StrUnknownMode
- jmp Hang
-KnownMode1:
- ; target (es:di) set on input
- push cs
- pop ds
- mov si, VbeModeInfo
- ; source (ds:si) set now
-
- mov cx, 256
- cld
- rep movsb
-
- pop cx
- pop si
- pop ds
- pop di
- pop es
- jmp Success
-
-
-%define ATT_ADDRESS_REGISTER 0x03c0
-%define VBE_DISPI_IOPORT_INDEX 0x01ce
-%define VBE_DISPI_IOPORT_DATA 0x01d0
-
-%define VBE_DISPI_INDEX_XRES 0x1
-%define VBE_DISPI_INDEX_YRES 0x2
-%define VBE_DISPI_INDEX_BPP 0x3
-%define VBE_DISPI_INDEX_ENABLE 0x4
-%define VBE_DISPI_INDEX_BANK 0x5
-%define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
-%define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
-%define VBE_DISPI_INDEX_X_OFFSET 0x8
-%define VBE_DISPI_INDEX_Y_OFFSET 0x9
-
-%define VBE_DISPI_ENABLED 0x01
-%define VBE_DISPI_LFB_ENABLED 0x40
-
-%macro BochsWrite 2
- push dx
- push ax
-
- mov dx, VBE_DISPI_IOPORT_INDEX
- mov ax, %1
- out dx, ax
-
- mov dx, VBE_DISPI_IOPORT_DATA
- mov ax, %2
- out dx, ax
-
- pop ax
- pop dx
-%endmacro
-
-SetMode:
- push dx
- push ax
-
- DebugLog StrEnterSetMode
-
- cmp bx, 0x40f1
- je KnownMode2
- DebugLog StrUnknownMode
- jmp Hang
-KnownMode2:
-
- ; unblank
- mov dx, ATT_ADDRESS_REGISTER
- mov al, 0x20
- out dx, al
-
- BochsWrite VBE_DISPI_INDEX_ENABLE, 0
- BochsWrite VBE_DISPI_INDEX_BANK, 0
- BochsWrite VBE_DISPI_INDEX_X_OFFSET, 0
- BochsWrite VBE_DISPI_INDEX_Y_OFFSET, 0
- BochsWrite VBE_DISPI_INDEX_BPP, 32
- BochsWrite VBE_DISPI_INDEX_XRES, 1024
- BochsWrite VBE_DISPI_INDEX_VIRT_WIDTH, 1024
- BochsWrite VBE_DISPI_INDEX_YRES, 768
- BochsWrite VBE_DISPI_INDEX_VIRT_HEIGHT, 768
- BochsWrite VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED
-
- pop ax
- pop dx
- jmp Success
-
-
-GetMode:
- DebugLog StrEnterGetMode
- mov bx, 0x40f1
- jmp Success
-
-
-GetPmCapabilities:
- DebugLog StrGetPmCapabilities
- jmp Unsupported
-
-
-ReadEdid:
- DebugLog StrReadEdid
- jmp Unsupported
-
-
-SetModeLegacy:
- DebugLog StrEnterSetModeLegacy
-
- cmp al, 0x03
- je KnownMode3
- cmp al, 0x12
- je KnownMode4
- DebugLog StrUnknownMode
- jmp Hang
-KnownMode3:
- mov al, 0x30
- jmp SetModeLegacyDone
-KnownMode4:
- mov al, 0x20
-SetModeLegacyDone:
- DebugLog StrExitSuccess
- iret
-
-
-Success:
- DebugLog StrExitSuccess
- mov ax, 0x004f
- iret
-
-
-Unsupported:
- DebugLog StrExitUnsupported
- mov ax, 0x014f
- iret
-
-
-%ifdef DEBUG
-PrintStringSi:
- pusha
- push ds ; save original
- push cs
- pop ds
- mov dx, 0x0402
-PrintStringSiLoop:
- lodsb
- cmp al, 0
- je PrintStringSiDone
- out dx, al
- jmp PrintStringSiLoop
-PrintStringSiDone:
- pop ds ; restore original
- popa
- ret
-
-
-StrExitSuccess:
- db 'Exit', 0x0a, 0
-
-StrExitUnsupported:
- db 'Unsupported', 0x0a, 0
-
-StrUnknownFunction:
- db 'Unknown Function', 0x0a, 0
-
-StrEnterGetInfo:
- db 'GetInfo', 0x0a, 0
-
-StrEnterGetModeInfo:
- db 'GetModeInfo', 0x0a, 0
-
-StrEnterGetMode:
- db 'GetMode', 0x0a, 0
-
-StrEnterSetMode:
- db 'SetMode', 0x0a, 0
-
-StrEnterSetModeLegacy:
- db 'SetModeLegacy', 0x0a, 0
-
-StrUnknownMode:
- db 'Unknown Mode', 0x0a, 0
-
-StrGetPmCapabilities:
- db 'GetPmCapabilities', 0x0a, 0
-
-StrReadEdid:
- db 'ReadEdid', 0x0a, 0
-%endif
diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.c b/OvmfPkg/QemuVideoDxe/VbeShim.c
deleted file mode 100644
index 8f151b96f9..0000000000
--- a/OvmfPkg/QemuVideoDxe/VbeShim.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/** @file
- Install a fake VGABIOS service handler (real mode Int10h) for the buggy
- Windows 2008 R2 SP1 UEFI guest.
-
- The handler is never meant to be directly executed by a VCPU; it's there for
- the internal real mode emulator of Windows 2008 R2 SP1.
-
- The code is based on Ralf Brown's Interrupt List:
- <http://www.cs.cmu.edu/~ralf/files.html>
- <http://www.ctyme.com/rbrown.htm>
-
- Copyright (C) 2014, Red Hat, Inc.
- Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-**/
-
-#include <IndustryStandard/LegacyVgaBios.h>
-#include <Library/DebugLib.h>
-#include <Library/PciLib.h>
-#include <Library/PrintLib.h>
-#include <OvmfPlatforms.h>
-
-#include "Qemu.h"
-#include "VbeShim.h"
-
-#pragma pack (1)
-typedef struct {
- UINT16 Offset;
- UINT16 Segment;
-} IVT_ENTRY;
-#pragma pack ()
-
-//
-// This string is displayed by Windows 2008 R2 SP1 in the Screen Resolution,
-// Advanced Settings dialog. It should be short.
-//
-STATIC CONST CHAR8 mProductRevision[] = "OVMF Int10h (fake)";
-
-/**
- Install the VBE Info and VBE Mode Info structures, and the VBE service
- handler routine in the C segment. Point the real-mode Int10h interrupt vector
- to the handler. The only advertised mode is 1024x768x32.
-
- @param[in] CardName Name of the video card to be exposed in the
- Product Name field of the VBE Info structure. The
- parameter must originate from a
- QEMU_VIDEO_CARD.Name field.
- @param[in] FrameBufferBase Guest-physical base address of the video card's
- frame buffer.
-**/
-VOID
-InstallVbeShim (
- IN CONST CHAR16 *CardName,
- IN EFI_PHYSICAL_ADDRESS FrameBufferBase
- )
-{
- EFI_PHYSICAL_ADDRESS Segment0, SegmentC, SegmentF;
- UINTN Segment0Pages;
- IVT_ENTRY *Int0x10;
- EFI_STATUS Segment0AllocationStatus;
- UINT16 HostBridgeDevId;
- UINTN Pam1Address;
- UINT8 Pam1;
- UINTN SegmentCPages;
- VBE_INFO *VbeInfoFull;
- VBE_INFO_BASE *VbeInfo;
- UINT8 *Ptr;
- UINTN Printed;
- VBE_MODE_INFO *VbeModeInfo;
-
- if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT0|BIT7)) == BIT0) {
- DEBUG ((
- DEBUG_WARN,
- "%a: page 0 protected, not installing VBE shim\n",
- __func__
- ));
- DEBUG ((
- DEBUG_WARN,
- "%a: page 0 protection prevents Windows 7 from booting anyway\n",
- __func__
- ));
- return;
- }
-
- Segment0 = 0x00000;
- SegmentC = 0xC0000;
- SegmentF = 0xF0000;
-
- //
- // Attempt to cover the real mode IVT with an allocation. This is a UEFI
- // driver, hence the arch protocols have been installed previously. Among
- // those, the CPU arch protocol has configured the IDT, so we can overwrite
- // the IVT used in real mode.
- //
- // The allocation request may fail, eg. if LegacyBiosDxe has already run.
- //
- Segment0Pages = 1;
- Int0x10 = (IVT_ENTRY *)(UINTN)(Segment0 + 0x10 * sizeof (IVT_ENTRY));
- Segment0AllocationStatus = gBS->AllocatePages (
- AllocateAddress,
- EfiBootServicesCode,
- Segment0Pages,
- &Segment0
- );
-
- if (EFI_ERROR (Segment0AllocationStatus)) {
- EFI_PHYSICAL_ADDRESS Handler;
-
- //
- // Check if a video BIOS handler has been installed previously -- we
- // shouldn't override a real video BIOS with our shim, nor our own shim if
- // it's already present.
- //
- Handler = (Int0x10->Segment << 4) + Int0x10->Offset;
- if ((Handler >= SegmentC) && (Handler < SegmentF)) {
- DEBUG ((
- DEBUG_INFO,
- "%a: Video BIOS handler found at %04x:%04x\n",
- __func__,
- Int0x10->Segment,
- Int0x10->Offset
- ));
- return;
- }
-
- //
- // Otherwise we'll overwrite the Int10h vector, even though we may not own
- // the page at zero.
- //
- DEBUG ((
- DEBUG_INFO,
- "%a: failed to allocate page at zero: %r\n",
- __func__,
- Segment0AllocationStatus
- ));
- } else {
- //
- // We managed to allocate the page at zero. SVN r14218 guarantees that it
- // is NUL-filled.
- //
- ASSERT (Int0x10->Segment == 0x0000);
- ASSERT (Int0x10->Offset == 0x0000);
- }
-
- //
- // Put the shim in place first.
- //
- // Start by determining the address of the PAM1 register.
- //
- HostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
- switch (HostBridgeDevId) {
- case INTEL_82441_DEVICE_ID:
- Pam1Address = PMC_REGISTER_PIIX4 (PIIX4_PAM1);
- break;
- case INTEL_Q35_MCH_DEVICE_ID:
- Pam1Address = DRAMC_REGISTER_Q35 (MCH_PAM1);
- break;
- case MICROVM_PSEUDO_DEVICE_ID:
- return;
- default:
- DEBUG ((
- DEBUG_ERROR,
- "%a: unknown host bridge device ID: 0x%04x\n",
- __func__,
- HostBridgeDevId
- ));
- ASSERT (FALSE);
-
- if (!EFI_ERROR (Segment0AllocationStatus)) {
- gBS->FreePages (Segment0, Segment0Pages);
- }
-
- return;
- }
-
- //
- // low nibble covers 0xC0000 to 0xC3FFF
- // high nibble covers 0xC4000 to 0xC7FFF
- // bit1 in each nibble is Write Enable
- // bit0 in each nibble is Read Enable
- //
- Pam1 = PciRead8 (Pam1Address);
- PciWrite8 (Pam1Address, Pam1 | (BIT1 | BIT0));
-
- //
- // We never added memory space during PEI or DXE for the C segment, so we
- // don't need to (and can't) allocate from there. Also, guest operating
- // systems will see a hole in the UEFI memory map there.
- //
- SegmentCPages = 4;
-
- ASSERT (sizeof mVbeShim <= EFI_PAGES_TO_SIZE (SegmentCPages));
- CopyMem ((VOID *)(UINTN)SegmentC, mVbeShim, sizeof mVbeShim);
-
- //
- // Fill in the VBE INFO structure.
- //
- VbeInfoFull = (VBE_INFO *)(UINTN)SegmentC;
- VbeInfo = &VbeInfoFull->Base;
- Ptr = VbeInfoFull->Buffer;
-
- CopyMem (VbeInfo->Signature, "VESA", 4);
- VbeInfo->VesaVersion = 0x0300;
-
- VbeInfo->OemNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
- CopyMem (Ptr, "QEMU", 5);
- Ptr += 5;
-
- VbeInfo->Capabilities = BIT0; // DAC can be switched into 8-bit mode
-
- VbeInfo->ModeListAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
- *(UINT16 *)Ptr = 0x00f1; // mode number
- Ptr += 2;
- *(UINT16 *)Ptr = 0xFFFF; // mode list terminator
- Ptr += 2;
-
- VbeInfo->VideoMem64K = (UINT16)((1024 * 768 * 4 + 65535) / 65536);
- VbeInfo->OemSoftwareVersion = 0x0000;
-
- VbeInfo->VendorNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
- CopyMem (Ptr, "OVMF", 5);
- Ptr += 5;
-
- VbeInfo->ProductNameAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
- Printed = AsciiSPrint (
- (CHAR8 *)Ptr,
- sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer),
- "%s",
- CardName
- );
- Ptr += Printed + 1;
-
- VbeInfo->ProductRevAddress = (UINT32)SegmentC << 12 | (UINT16)(UINTN)Ptr;
- CopyMem (Ptr, mProductRevision, sizeof mProductRevision);
- Ptr += sizeof mProductRevision;
-
- ASSERT (sizeof VbeInfoFull->Buffer >= Ptr - VbeInfoFull->Buffer);
- ZeroMem (Ptr, sizeof VbeInfoFull->Buffer - (Ptr - VbeInfoFull->Buffer));
-
- //
- // Fil in the VBE MODE INFO structure.
- //
- VbeModeInfo = (VBE_MODE_INFO *)(VbeInfoFull + 1);
-
- //
- // bit0: mode supported by present hardware configuration
- // bit1: optional information available (must be =1 for VBE v1.2+)
- // bit3: set if color, clear if monochrome
- // bit4: set if graphics mode, clear if text mode
- // bit5: mode is not VGA-compatible
- // bit7: linear framebuffer mode supported
- //
- VbeModeInfo->ModeAttr = BIT7 | BIT5 | BIT4 | BIT3 | BIT1 | BIT0;
-
- //
- // bit0: exists
- // bit1: bit1: readable
- // bit2: writeable
- //
- VbeModeInfo->WindowAAttr = BIT2 | BIT1 | BIT0;
-
- VbeModeInfo->WindowBAttr = 0x00;
- VbeModeInfo->WindowGranularityKB = 0x0040;
- VbeModeInfo->WindowSizeKB = 0x0040;
- VbeModeInfo->WindowAStartSegment = 0xA000;
- VbeModeInfo->WindowBStartSegment = 0x0000;
- VbeModeInfo->WindowPositioningAddress = 0x0000;
- VbeModeInfo->BytesPerScanLine = 1024 * 4;
-
- VbeModeInfo->Width = 1024;
- VbeModeInfo->Height = 768;
- VbeModeInfo->CharCellWidth = 8;
- VbeModeInfo->CharCellHeight = 16;
- VbeModeInfo->NumPlanes = 1;
- VbeModeInfo->BitsPerPixel = 32;
- VbeModeInfo->NumBanks = 1;
- VbeModeInfo->MemoryModel = 6; // direct color
- VbeModeInfo->BankSizeKB = 0;
- VbeModeInfo->NumImagePagesLessOne = 0;
- VbeModeInfo->Vbe3 = 0x01;
-
- VbeModeInfo->RedMaskSize = 8;
- VbeModeInfo->RedMaskPos = 16;
- VbeModeInfo->GreenMaskSize = 8;
- VbeModeInfo->GreenMaskPos = 8;
- VbeModeInfo->BlueMaskSize = 8;
- VbeModeInfo->BlueMaskPos = 0;
- VbeModeInfo->ReservedMaskSize = 8;
- VbeModeInfo->ReservedMaskPos = 24;
-
- //
- // bit1: Bytes in reserved field may be used by application
- //
- VbeModeInfo->DirectColorModeInfo = BIT1;
-
- VbeModeInfo->LfbAddress = (UINT32)FrameBufferBase;
- VbeModeInfo->OffScreenAddress = 0;
- VbeModeInfo->OffScreenSizeKB = 0;
-
- VbeModeInfo->BytesPerScanLineLinear = 1024 * 4;
- VbeModeInfo->NumImagesLessOneBanked = 0;
- VbeModeInfo->NumImagesLessOneLinear = 0;
- VbeModeInfo->RedMaskSizeLinear = 8;
- VbeModeInfo->RedMaskPosLinear = 16;
- VbeModeInfo->GreenMaskSizeLinear = 8;
- VbeModeInfo->GreenMaskPosLinear = 8;
- VbeModeInfo->BlueMaskSizeLinear = 8;
- VbeModeInfo->BlueMaskPosLinear = 0;
- VbeModeInfo->ReservedMaskSizeLinear = 8;
- VbeModeInfo->ReservedMaskPosLinear = 24;
- VbeModeInfo->MaxPixelClockHz = 0;
-
- ZeroMem (VbeModeInfo->Reserved, sizeof VbeModeInfo->Reserved);
-
- //
- // Clear Write Enable (bit1), keep Read Enable (bit0) set
- //
- PciWrite8 (Pam1Address, (Pam1 & ~BIT1) | BIT0);
-
- //
- // Second, point the Int10h vector at the shim.
- //
- Int0x10->Segment = (UINT16)((UINT32)SegmentC >> 4);
- Int0x10->Offset = (UINT16)((UINTN)(VbeModeInfo + 1) - SegmentC);
-
- DEBUG ((DEBUG_INFO, "%a: VBE shim installed\n", __func__));
-}
diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.h b/OvmfPkg/QemuVideoDxe/VbeShim.h
deleted file mode 100644
index cc9b6e14cd..0000000000
--- a/OvmfPkg/QemuVideoDxe/VbeShim.h
+++ /dev/null
@@ -1,701 +0,0 @@
-//
-// THIS FILE WAS GENERATED BY "VbeShim.sh". DO NOT EDIT.
-//
-#ifndef _VBE_SHIM_H_
-#define _VBE_SHIM_H_
-STATIC CONST UINT8 mVbeShim[] = {
- /* 00000000 nop */ 0x90,
- /* 00000001 nop */ 0x90,
- /* 00000002 nop */ 0x90,
- /* 00000003 nop */ 0x90,
- /* 00000004 nop */ 0x90,
- /* 00000005 nop */ 0x90,
- /* 00000006 nop */ 0x90,
- /* 00000007 nop */ 0x90,
- /* 00000008 nop */ 0x90,
- /* 00000009 nop */ 0x90,
- /* 0000000A nop */ 0x90,
- /* 0000000B nop */ 0x90,
- /* 0000000C nop */ 0x90,
- /* 0000000D nop */ 0x90,
- /* 0000000E nop */ 0x90,
- /* 0000000F nop */ 0x90,
- /* 00000010 nop */ 0x90,
- /* 00000011 nop */ 0x90,
- /* 00000012 nop */ 0x90,
- /* 00000013 nop */ 0x90,
- /* 00000014 nop */ 0x90,
- /* 00000015 nop */ 0x90,
- /* 00000016 nop */ 0x90,
- /* 00000017 nop */ 0x90,
- /* 00000018 nop */ 0x90,
- /* 00000019 nop */ 0x90,
- /* 0000001A nop */ 0x90,
- /* 0000001B nop */ 0x90,
- /* 0000001C nop */ 0x90,
- /* 0000001D nop */ 0x90,
- /* 0000001E nop */ 0x90,
- /* 0000001F nop */ 0x90,
- /* 00000020 nop */ 0x90,
- /* 00000021 nop */ 0x90,
- /* 00000022 nop */ 0x90,
- /* 00000023 nop */ 0x90,
- /* 00000024 nop */ 0x90,
- /* 00000025 nop */ 0x90,
- /* 00000026 nop */ 0x90,
- /* 00000027 nop */ 0x90,
- /* 00000028 nop */ 0x90,
- /* 00000029 nop */ 0x90,
- /* 0000002A nop */ 0x90,
- /* 0000002B nop */ 0x90,
- /* 0000002C nop */ 0x90,
- /* 0000002D nop */ 0x90,
- /* 0000002E nop */ 0x90,
- /* 0000002F nop */ 0x90,
- /* 00000030 nop */ 0x90,
- /* 00000031 nop */ 0x90,
- /* 00000032 nop */ 0x90,
- /* 00000033 nop */ 0x90,
- /* 00000034 nop */ 0x90,
- /* 00000035 nop */ 0x90,
- /* 00000036 nop */ 0x90,
- /* 00000037 nop */ 0x90,
- /* 00000038 nop */ 0x90,
- /* 00000039 nop */ 0x90,
- /* 0000003A nop */ 0x90,
- /* 0000003B nop */ 0x90,
- /* 0000003C nop */ 0x90,
- /* 0000003D nop */ 0x90,
- /* 0000003E nop */ 0x90,
- /* 0000003F nop */ 0x90,
- /* 00000040 nop */ 0x90,
- /* 00000041 nop */ 0x90,
- /* 00000042 nop */ 0x90,
- /* 00000043 nop */ 0x90,
- /* 00000044 nop */ 0x90,
- /* 00000045 nop */ 0x90,
- /* 00000046 nop */ 0x90,
- /* 00000047 nop */ 0x90,
- /* 00000048 nop */ 0x90,
- /* 00000049 nop */ 0x90,
- /* 0000004A nop */ 0x90,
- /* 0000004B nop */ 0x90,
- /* 0000004C nop */ 0x90,
- /* 0000004D nop */ 0x90,
- /* 0000004E nop */ 0x90,
- /* 0000004F nop */ 0x90,
- /* 00000050 nop */ 0x90,
- /* 00000051 nop */ 0x90,
- /* 00000052 nop */ 0x90,
- /* 00000053 nop */ 0x90,
- /* 00000054 nop */ 0x90,
- /* 00000055 nop */ 0x90,
- /* 00000056 nop */ 0x90,
- /* 00000057 nop */ 0x90,
- /* 00000058 nop */ 0x90,
- /* 00000059 nop */ 0x90,
- /* 0000005A nop */ 0x90,
- /* 0000005B nop */ 0x90,
- /* 0000005C nop */ 0x90,
- /* 0000005D nop */ 0x90,
- /* 0000005E nop */ 0x90,
- /* 0000005F nop */ 0x90,
- /* 00000060 nop */ 0x90,
- /* 00000061 nop */ 0x90,
- /* 00000062 nop */ 0x90,
- /* 00000063 nop */ 0x90,
- /* 00000064 nop */ 0x90,
- /* 00000065 nop */ 0x90,
- /* 00000066 nop */ 0x90,
- /* 00000067 nop */ 0x90,
- /* 00000068 nop */ 0x90,
- /* 00000069 nop */ 0x90,
- /* 0000006A nop */ 0x90,
- /* 0000006B nop */ 0x90,
- /* 0000006C nop */ 0x90,
- /* 0000006D nop */ 0x90,
- /* 0000006E nop */ 0x90,
- /* 0000006F nop */ 0x90,
- /* 00000070 nop */ 0x90,
- /* 00000071 nop */ 0x90,
- /* 00000072 nop */ 0x90,
- /* 00000073 nop */ 0x90,
- /* 00000074 nop */ 0x90,
- /* 00000075 nop */ 0x90,
- /* 00000076 nop */ 0x90,
- /* 00000077 nop */ 0x90,
- /* 00000078 nop */ 0x90,
- /* 00000079 nop */ 0x90,
- /* 0000007A nop */ 0x90,
- /* 0000007B nop */ 0x90,
- /* 0000007C nop */ 0x90,
- /* 0000007D nop */ 0x90,
- /* 0000007E nop */ 0x90,
- /* 0000007F nop */ 0x90,
- /* 00000080 nop */ 0x90,
- /* 00000081 nop */ 0x90,
- /* 00000082 nop */ 0x90,
- /* 00000083 nop */ 0x90,
- /* 00000084 nop */ 0x90,
- /* 00000085 nop */ 0x90,
- /* 00000086 nop */ 0x90,
- /* 00000087 nop */ 0x90,
- /* 00000088 nop */ 0x90,
- /* 00000089 nop */ 0x90,
- /* 0000008A nop */ 0x90,
- /* 0000008B nop */ 0x90,
- /* 0000008C nop */ 0x90,
- /* 0000008D nop */ 0x90,
- /* 0000008E nop */ 0x90,
- /* 0000008F nop */ 0x90,
- /* 00000090 nop */ 0x90,
- /* 00000091 nop */ 0x90,
- /* 00000092 nop */ 0x90,
- /* 00000093 nop */ 0x90,
- /* 00000094 nop */ 0x90,
- /* 00000095 nop */ 0x90,
- /* 00000096 nop */ 0x90,
- /* 00000097 nop */ 0x90,
- /* 00000098 nop */ 0x90,
- /* 00000099 nop */ 0x90,
- /* 0000009A nop */ 0x90,
- /* 0000009B nop */ 0x90,
- /* 0000009C nop */ 0x90,
- /* 0000009D nop */ 0x90,
- /* 0000009E nop */ 0x90,
- /* 0000009F nop */ 0x90,
- /* 000000A0 nop */ 0x90,
- /* 000000A1 nop */ 0x90,
- /* 000000A2 nop */ 0x90,
- /* 000000A3 nop */ 0x90,
- /* 000000A4 nop */ 0x90,
- /* 000000A5 nop */ 0x90,
- /* 000000A6 nop */ 0x90,
- /* 000000A7 nop */ 0x90,
- /* 000000A8 nop */ 0x90,
- /* 000000A9 nop */ 0x90,
- /* 000000AA nop */ 0x90,
- /* 000000AB nop */ 0x90,
- /* 000000AC nop */ 0x90,
- /* 000000AD nop */ 0x90,
- /* 000000AE nop */ 0x90,
- /* 000000AF nop */ 0x90,
- /* 000000B0 nop */ 0x90,
- /* 000000B1 nop */ 0x90,
- /* 000000B2 nop */ 0x90,
- /* 000000B3 nop */ 0x90,
- /* 000000B4 nop */ 0x90,
- /* 000000B5 nop */ 0x90,
- /* 000000B6 nop */ 0x90,
- /* 000000B7 nop */ 0x90,
- /* 000000B8 nop */ 0x90,
- /* 000000B9 nop */ 0x90,
- /* 000000BA nop */ 0x90,
- /* 000000BB nop */ 0x90,
- /* 000000BC nop */ 0x90,
- /* 000000BD nop */ 0x90,
- /* 000000BE nop */ 0x90,
- /* 000000BF nop */ 0x90,
- /* 000000C0 nop */ 0x90,
- /* 000000C1 nop */ 0x90,
- /* 000000C2 nop */ 0x90,
- /* 000000C3 nop */ 0x90,
- /* 000000C4 nop */ 0x90,
- /* 000000C5 nop */ 0x90,
- /* 000000C6 nop */ 0x90,
- /* 000000C7 nop */ 0x90,
- /* 000000C8 nop */ 0x90,
- /* 000000C9 nop */ 0x90,
- /* 000000CA nop */ 0x90,
- /* 000000CB nop */ 0x90,
- /* 000000CC nop */ 0x90,
- /* 000000CD nop */ 0x90,
- /* 000000CE nop */ 0x90,
- /* 000000CF nop */ 0x90,
- /* 000000D0 nop */ 0x90,
- /* 000000D1 nop */ 0x90,
- /* 000000D2 nop */ 0x90,
- /* 000000D3 nop */ 0x90,
- /* 000000D4 nop */ 0x90,
- /* 000000D5 nop */ 0x90,
- /* 000000D6 nop */ 0x90,
- /* 000000D7 nop */ 0x90,
- /* 000000D8 nop */ 0x90,
- /* 000000D9 nop */ 0x90,
- /* 000000DA nop */ 0x90,
- /* 000000DB nop */ 0x90,
- /* 000000DC nop */ 0x90,
- /* 000000DD nop */ 0x90,
- /* 000000DE nop */ 0x90,
- /* 000000DF nop */ 0x90,
- /* 000000E0 nop */ 0x90,
- /* 000000E1 nop */ 0x90,
- /* 000000E2 nop */ 0x90,
- /* 000000E3 nop */ 0x90,
- /* 000000E4 nop */ 0x90,
- /* 000000E5 nop */ 0x90,
- /* 000000E6 nop */ 0x90,
- /* 000000E7 nop */ 0x90,
- /* 000000E8 nop */ 0x90,
- /* 000000E9 nop */ 0x90,
- /* 000000EA nop */ 0x90,
- /* 000000EB nop */ 0x90,
- /* 000000EC nop */ 0x90,
- /* 000000ED nop */ 0x90,
- /* 000000EE nop */ 0x90,
- /* 000000EF nop */ 0x90,
- /* 000000F0 nop */ 0x90,
- /* 000000F1 nop */ 0x90,
- /* 000000F2 nop */ 0x90,
- /* 000000F3 nop */ 0x90,
- /* 000000F4 nop */ 0x90,
- /* 000000F5 nop */ 0x90,
- /* 000000F6 nop */ 0x90,
- /* 000000F7 nop */ 0x90,
- /* 000000F8 nop */ 0x90,
- /* 000000F9 nop */ 0x90,
- /* 000000FA nop */ 0x90,
- /* 000000FB nop */ 0x90,
- /* 000000FC nop */ 0x90,
- /* 000000FD nop */ 0x90,
- /* 000000FE nop */ 0x90,
- /* 000000FF nop */ 0x90,
- /* 00000100 nop */ 0x90,
- /* 00000101 nop */ 0x90,
- /* 00000102 nop */ 0x90,
- /* 00000103 nop */ 0x90,
- /* 00000104 nop */ 0x90,
- /* 00000105 nop */ 0x90,
- /* 00000106 nop */ 0x90,
- /* 00000107 nop */ 0x90,
- /* 00000108 nop */ 0x90,
- /* 00000109 nop */ 0x90,
- /* 0000010A nop */ 0x90,
- /* 0000010B nop */ 0x90,
- /* 0000010C nop */ 0x90,
- /* 0000010D nop */ 0x90,
- /* 0000010E nop */ 0x90,
- /* 0000010F nop */ 0x90,
- /* 00000110 nop */ 0x90,
- /* 00000111 nop */ 0x90,
- /* 00000112 nop */ 0x90,
- /* 00000113 nop */ 0x90,
- /* 00000114 nop */ 0x90,
- /* 00000115 nop */ 0x90,
- /* 00000116 nop */ 0x90,
- /* 00000117 nop */ 0x90,
- /* 00000118 nop */ 0x90,
- /* 00000119 nop */ 0x90,
- /* 0000011A nop */ 0x90,
- /* 0000011B nop */ 0x90,
- /* 0000011C nop */ 0x90,
- /* 0000011D nop */ 0x90,
- /* 0000011E nop */ 0x90,
- /* 0000011F nop */ 0x90,
- /* 00000120 nop */ 0x90,
- /* 00000121 nop */ 0x90,
- /* 00000122 nop */ 0x90,
- /* 00000123 nop */ 0x90,
- /* 00000124 nop */ 0x90,
- /* 00000125 nop */ 0x90,
- /* 00000126 nop */ 0x90,
- /* 00000127 nop */ 0x90,
- /* 00000128 nop */ 0x90,
- /* 00000129 nop */ 0x90,
- /* 0000012A nop */ 0x90,
- /* 0000012B nop */ 0x90,
- /* 0000012C nop */ 0x90,
- /* 0000012D nop */ 0x90,
- /* 0000012E nop */ 0x90,
- /* 0000012F nop */ 0x90,
- /* 00000130 nop */ 0x90,
- /* 00000131 nop */ 0x90,
- /* 00000132 nop */ 0x90,
- /* 00000133 nop */ 0x90,
- /* 00000134 nop */ 0x90,
- /* 00000135 nop */ 0x90,
- /* 00000136 nop */ 0x90,
- /* 00000137 nop */ 0x90,
- /* 00000138 nop */ 0x90,
- /* 00000139 nop */ 0x90,
- /* 0000013A nop */ 0x90,
- /* 0000013B nop */ 0x90,
- /* 0000013C nop */ 0x90,
- /* 0000013D nop */ 0x90,
- /* 0000013E nop */ 0x90,
- /* 0000013F nop */ 0x90,
- /* 00000140 nop */ 0x90,
- /* 00000141 nop */ 0x90,
- /* 00000142 nop */ 0x90,
- /* 00000143 nop */ 0x90,
- /* 00000144 nop */ 0x90,
- /* 00000145 nop */ 0x90,
- /* 00000146 nop */ 0x90,
- /* 00000147 nop */ 0x90,
- /* 00000148 nop */ 0x90,
- /* 00000149 nop */ 0x90,
- /* 0000014A nop */ 0x90,
- /* 0000014B nop */ 0x90,
- /* 0000014C nop */ 0x90,
- /* 0000014D nop */ 0x90,
- /* 0000014E nop */ 0x90,
- /* 0000014F nop */ 0x90,
- /* 00000150 nop */ 0x90,
- /* 00000151 nop */ 0x90,
- /* 00000152 nop */ 0x90,
- /* 00000153 nop */ 0x90,
- /* 00000154 nop */ 0x90,
- /* 00000155 nop */ 0x90,
- /* 00000156 nop */ 0x90,
- /* 00000157 nop */ 0x90,
- /* 00000158 nop */ 0x90,
- /* 00000159 nop */ 0x90,
- /* 0000015A nop */ 0x90,
- /* 0000015B nop */ 0x90,
- /* 0000015C nop */ 0x90,
- /* 0000015D nop */ 0x90,
- /* 0000015E nop */ 0x90,
- /* 0000015F nop */ 0x90,
- /* 00000160 nop */ 0x90,
- /* 00000161 nop */ 0x90,
- /* 00000162 nop */ 0x90,
- /* 00000163 nop */ 0x90,
- /* 00000164 nop */ 0x90,
- /* 00000165 nop */ 0x90,
- /* 00000166 nop */ 0x90,
- /* 00000167 nop */ 0x90,
- /* 00000168 nop */ 0x90,
- /* 00000169 nop */ 0x90,
- /* 0000016A nop */ 0x90,
- /* 0000016B nop */ 0x90,
- /* 0000016C nop */ 0x90,
- /* 0000016D nop */ 0x90,
- /* 0000016E nop */ 0x90,
- /* 0000016F nop */ 0x90,
- /* 00000170 nop */ 0x90,
- /* 00000171 nop */ 0x90,
- /* 00000172 nop */ 0x90,
- /* 00000173 nop */ 0x90,
- /* 00000174 nop */ 0x90,
- /* 00000175 nop */ 0x90,
- /* 00000176 nop */ 0x90,
- /* 00000177 nop */ 0x90,
- /* 00000178 nop */ 0x90,
- /* 00000179 nop */ 0x90,
- /* 0000017A nop */ 0x90,
- /* 0000017B nop */ 0x90,
- /* 0000017C nop */ 0x90,
- /* 0000017D nop */ 0x90,
- /* 0000017E nop */ 0x90,
- /* 0000017F nop */ 0x90,
- /* 00000180 nop */ 0x90,
- /* 00000181 nop */ 0x90,
- /* 00000182 nop */ 0x90,
- /* 00000183 nop */ 0x90,
- /* 00000184 nop */ 0x90,
- /* 00000185 nop */ 0x90,
- /* 00000186 nop */ 0x90,
- /* 00000187 nop */ 0x90,
- /* 00000188 nop */ 0x90,
- /* 00000189 nop */ 0x90,
- /* 0000018A nop */ 0x90,
- /* 0000018B nop */ 0x90,
- /* 0000018C nop */ 0x90,
- /* 0000018D nop */ 0x90,
- /* 0000018E nop */ 0x90,
- /* 0000018F nop */ 0x90,
- /* 00000190 nop */ 0x90,
- /* 00000191 nop */ 0x90,
- /* 00000192 nop */ 0x90,
- /* 00000193 nop */ 0x90,
- /* 00000194 nop */ 0x90,
- /* 00000195 nop */ 0x90,
- /* 00000196 nop */ 0x90,
- /* 00000197 nop */ 0x90,
- /* 00000198 nop */ 0x90,
- /* 00000199 nop */ 0x90,
- /* 0000019A nop */ 0x90,
- /* 0000019B nop */ 0x90,
- /* 0000019C nop */ 0x90,
- /* 0000019D nop */ 0x90,
- /* 0000019E nop */ 0x90,
- /* 0000019F nop */ 0x90,
- /* 000001A0 nop */ 0x90,
- /* 000001A1 nop */ 0x90,
- /* 000001A2 nop */ 0x90,
- /* 000001A3 nop */ 0x90,
- /* 000001A4 nop */ 0x90,
- /* 000001A5 nop */ 0x90,
- /* 000001A6 nop */ 0x90,
- /* 000001A7 nop */ 0x90,
- /* 000001A8 nop */ 0x90,
- /* 000001A9 nop */ 0x90,
- /* 000001AA nop */ 0x90,
- /* 000001AB nop */ 0x90,
- /* 000001AC nop */ 0x90,
- /* 000001AD nop */ 0x90,
- /* 000001AE nop */ 0x90,
- /* 000001AF nop */ 0x90,
- /* 000001B0 nop */ 0x90,
- /* 000001B1 nop */ 0x90,
- /* 000001B2 nop */ 0x90,
- /* 000001B3 nop */ 0x90,
- /* 000001B4 nop */ 0x90,
- /* 000001B5 nop */ 0x90,
- /* 000001B6 nop */ 0x90,
- /* 000001B7 nop */ 0x90,
- /* 000001B8 nop */ 0x90,
- /* 000001B9 nop */ 0x90,
- /* 000001BA nop */ 0x90,
- /* 000001BB nop */ 0x90,
- /* 000001BC nop */ 0x90,
- /* 000001BD nop */ 0x90,
- /* 000001BE nop */ 0x90,
- /* 000001BF nop */ 0x90,
- /* 000001C0 nop */ 0x90,
- /* 000001C1 nop */ 0x90,
- /* 000001C2 nop */ 0x90,
- /* 000001C3 nop */ 0x90,
- /* 000001C4 nop */ 0x90,
- /* 000001C5 nop */ 0x90,
- /* 000001C6 nop */ 0x90,
- /* 000001C7 nop */ 0x90,
- /* 000001C8 nop */ 0x90,
- /* 000001C9 nop */ 0x90,
- /* 000001CA nop */ 0x90,
- /* 000001CB nop */ 0x90,
- /* 000001CC nop */ 0x90,
- /* 000001CD nop */ 0x90,
- /* 000001CE nop */ 0x90,
- /* 000001CF nop */ 0x90,
- /* 000001D0 nop */ 0x90,
- /* 000001D1 nop */ 0x90,
- /* 000001D2 nop */ 0x90,
- /* 000001D3 nop */ 0x90,
- /* 000001D4 nop */ 0x90,
- /* 000001D5 nop */ 0x90,
- /* 000001D6 nop */ 0x90,
- /* 000001D7 nop */ 0x90,
- /* 000001D8 nop */ 0x90,
- /* 000001D9 nop */ 0x90,
- /* 000001DA nop */ 0x90,
- /* 000001DB nop */ 0x90,
- /* 000001DC nop */ 0x90,
- /* 000001DD nop */ 0x90,
- /* 000001DE nop */ 0x90,
- /* 000001DF nop */ 0x90,
- /* 000001E0 nop */ 0x90,
- /* 000001E1 nop */ 0x90,
- /* 000001E2 nop */ 0x90,
- /* 000001E3 nop */ 0x90,
- /* 000001E4 nop */ 0x90,
- /* 000001E5 nop */ 0x90,
- /* 000001E6 nop */ 0x90,
- /* 000001E7 nop */ 0x90,
- /* 000001E8 nop */ 0x90,
- /* 000001E9 nop */ 0x90,
- /* 000001EA nop */ 0x90,
- /* 000001EB nop */ 0x90,
- /* 000001EC nop */ 0x90,
- /* 000001ED nop */ 0x90,
- /* 000001EE nop */ 0x90,
- /* 000001EF nop */ 0x90,
- /* 000001F0 nop */ 0x90,
- /* 000001F1 nop */ 0x90,
- /* 000001F2 nop */ 0x90,
- /* 000001F3 nop */ 0x90,
- /* 000001F4 nop */ 0x90,
- /* 000001F5 nop */ 0x90,
- /* 000001F6 nop */ 0x90,
- /* 000001F7 nop */ 0x90,
- /* 000001F8 nop */ 0x90,
- /* 000001F9 nop */ 0x90,
- /* 000001FA nop */ 0x90,
- /* 000001FB nop */ 0x90,
- /* 000001FC nop */ 0x90,
- /* 000001FD nop */ 0x90,
- /* 000001FE nop */ 0x90,
- /* 000001FF nop */ 0x90,
- /* 00000200 cmp ax,0x4f00 */ 0x3D, 0x00, 0x4F,
- /* 00000203 jz 0x22d */ 0x74, 0x28,
- /* 00000205 cmp ax,0x4f01 */ 0x3D, 0x01, 0x4F,
- /* 00000208 jz 0x245 */ 0x74, 0x3B,
- /* 0000020A cmp ax,0x4f02 */ 0x3D, 0x02, 0x4F,
- /* 0000020D jz 0x269 */ 0x74, 0x5A,
- /* 0000020F cmp ax,0x4f03 */ 0x3D, 0x03, 0x4F,
- /* 00000212 jz word 0x331 */ 0x0F, 0x84, 0x1B, 0x01,
- /* 00000216 cmp ax,0x4f10 */ 0x3D, 0x10, 0x4F,
- /* 00000219 jz word 0x336 */ 0x0F, 0x84, 0x19, 0x01,
- /* 0000021D cmp ax,0x4f15 */ 0x3D, 0x15, 0x4F,
- /* 00000220 jz word 0x338 */ 0x0F, 0x84, 0x14, 0x01,
- /* 00000224 cmp ah,0x0 */ 0x80, 0xFC, 0x00,
- /* 00000227 jz word 0x33a */ 0x0F, 0x84, 0x0F, 0x01,
- /* 0000022B jmp short 0x22b */ 0xEB, 0xFE,
- /* 0000022D push es */ 0x06,
- /* 0000022E push di */ 0x57,
- /* 0000022F push ds */ 0x1E,
- /* 00000230 push si */ 0x56,
- /* 00000231 push cx */ 0x51,
- /* 00000232 push cs */ 0x0E,
- /* 00000233 pop ds */ 0x1F,
- /* 00000234 mov si,0x0 */ 0xBE, 0x00, 0x00,
- /* 00000237 mov cx,0x100 */ 0xB9, 0x00, 0x01,
- /* 0000023A cld */ 0xFC,
- /* 0000023B rep movsb */ 0xF3, 0xA4,
- /* 0000023D pop cx */ 0x59,
- /* 0000023E pop si */ 0x5E,
- /* 0000023F pop ds */ 0x1F,
- /* 00000240 pop di */ 0x5F,
- /* 00000241 pop es */ 0x07,
- /* 00000242 jmp word 0x34c */ 0xE9, 0x07, 0x01,
- /* 00000245 push es */ 0x06,
- /* 00000246 push di */ 0x57,
- /* 00000247 push ds */ 0x1E,
- /* 00000248 push si */ 0x56,
- /* 00000249 push cx */ 0x51,
- /* 0000024A and cx,0xbfff */ 0x81, 0xE1, 0xFF, 0xBF,
- /* 0000024E cmp cx,0xf1 */ 0x81, 0xF9, 0xF1, 0x00,
- /* 00000252 jz 0x256 */ 0x74, 0x02,
- /* 00000254 jmp short 0x22b */ 0xEB, 0xD5,
- /* 00000256 push cs */ 0x0E,
- /* 00000257 pop ds */ 0x1F,
- /* 00000258 mov si,0x100 */ 0xBE, 0x00, 0x01,
- /* 0000025B mov cx,0x100 */ 0xB9, 0x00, 0x01,
- /* 0000025E cld */ 0xFC,
- /* 0000025F rep movsb */ 0xF3, 0xA4,
- /* 00000261 pop cx */ 0x59,
- /* 00000262 pop si */ 0x5E,
- /* 00000263 pop ds */ 0x1F,
- /* 00000264 pop di */ 0x5F,
- /* 00000265 pop es */ 0x07,
- /* 00000266 jmp word 0x34c */ 0xE9, 0xE3, 0x00,
- /* 00000269 push dx */ 0x52,
- /* 0000026A push ax */ 0x50,
- /* 0000026B cmp bx,0x40f1 */ 0x81, 0xFB, 0xF1, 0x40,
- /* 0000026F jz 0x273 */ 0x74, 0x02,
- /* 00000271 jmp short 0x22b */ 0xEB, 0xB8,
- /* 00000273 mov dx,0x3c0 */ 0xBA, 0xC0, 0x03,
- /* 00000276 mov al,0x20 */ 0xB0, 0x20,
- /* 00000278 out dx,al */ 0xEE,
- /* 00000279 push dx */ 0x52,
- /* 0000027A push ax */ 0x50,
- /* 0000027B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 0000027E mov ax,0x4 */ 0xB8, 0x04, 0x00,
- /* 00000281 out dx,ax */ 0xEF,
- /* 00000282 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 00000285 mov ax,0x0 */ 0xB8, 0x00, 0x00,
- /* 00000288 out dx,ax */ 0xEF,
- /* 00000289 pop ax */ 0x58,
- /* 0000028A pop dx */ 0x5A,
- /* 0000028B push dx */ 0x52,
- /* 0000028C push ax */ 0x50,
- /* 0000028D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 00000290 mov ax,0x5 */ 0xB8, 0x05, 0x00,
- /* 00000293 out dx,ax */ 0xEF,
- /* 00000294 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 00000297 mov ax,0x0 */ 0xB8, 0x00, 0x00,
- /* 0000029A out dx,ax */ 0xEF,
- /* 0000029B pop ax */ 0x58,
- /* 0000029C pop dx */ 0x5A,
- /* 0000029D push dx */ 0x52,
- /* 0000029E push ax */ 0x50,
- /* 0000029F mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 000002A2 mov ax,0x8 */ 0xB8, 0x08, 0x00,
- /* 000002A5 out dx,ax */ 0xEF,
- /* 000002A6 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 000002A9 mov ax,0x0 */ 0xB8, 0x00, 0x00,
- /* 000002AC out dx,ax */ 0xEF,
- /* 000002AD pop ax */ 0x58,
- /* 000002AE pop dx */ 0x5A,
- /* 000002AF push dx */ 0x52,
- /* 000002B0 push ax */ 0x50,
- /* 000002B1 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 000002B4 mov ax,0x9 */ 0xB8, 0x09, 0x00,
- /* 000002B7 out dx,ax */ 0xEF,
- /* 000002B8 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 000002BB mov ax,0x0 */ 0xB8, 0x00, 0x00,
- /* 000002BE out dx,ax */ 0xEF,
- /* 000002BF pop ax */ 0x58,
- /* 000002C0 pop dx */ 0x5A,
- /* 000002C1 push dx */ 0x52,
- /* 000002C2 push ax */ 0x50,
- /* 000002C3 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 000002C6 mov ax,0x3 */ 0xB8, 0x03, 0x00,
- /* 000002C9 out dx,ax */ 0xEF,
- /* 000002CA mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 000002CD mov ax,0x20 */ 0xB8, 0x20, 0x00,
- /* 000002D0 out dx,ax */ 0xEF,
- /* 000002D1 pop ax */ 0x58,
- /* 000002D2 pop dx */ 0x5A,
- /* 000002D3 push dx */ 0x52,
- /* 000002D4 push ax */ 0x50,
- /* 000002D5 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 000002D8 mov ax,0x1 */ 0xB8, 0x01, 0x00,
- /* 000002DB out dx,ax */ 0xEF,
- /* 000002DC mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 000002DF mov ax,0x400 */ 0xB8, 0x00, 0x04,
- /* 000002E2 out dx,ax */ 0xEF,
- /* 000002E3 pop ax */ 0x58,
- /* 000002E4 pop dx */ 0x5A,
- /* 000002E5 push dx */ 0x52,
- /* 000002E6 push ax */ 0x50,
- /* 000002E7 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 000002EA mov ax,0x6 */ 0xB8, 0x06, 0x00,
- /* 000002ED out dx,ax */ 0xEF,
- /* 000002EE mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 000002F1 mov ax,0x400 */ 0xB8, 0x00, 0x04,
- /* 000002F4 out dx,ax */ 0xEF,
- /* 000002F5 pop ax */ 0x58,
- /* 000002F6 pop dx */ 0x5A,
- /* 000002F7 push dx */ 0x52,
- /* 000002F8 push ax */ 0x50,
- /* 000002F9 mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 000002FC mov ax,0x2 */ 0xB8, 0x02, 0x00,
- /* 000002FF out dx,ax */ 0xEF,
- /* 00000300 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 00000303 mov ax,0x300 */ 0xB8, 0x00, 0x03,
- /* 00000306 out dx,ax */ 0xEF,
- /* 00000307 pop ax */ 0x58,
- /* 00000308 pop dx */ 0x5A,
- /* 00000309 push dx */ 0x52,
- /* 0000030A push ax */ 0x50,
- /* 0000030B mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 0000030E mov ax,0x7 */ 0xB8, 0x07, 0x00,
- /* 00000311 out dx,ax */ 0xEF,
- /* 00000312 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 00000315 mov ax,0x300 */ 0xB8, 0x00, 0x03,
- /* 00000318 out dx,ax */ 0xEF,
- /* 00000319 pop ax */ 0x58,
- /* 0000031A pop dx */ 0x5A,
- /* 0000031B push dx */ 0x52,
- /* 0000031C push ax */ 0x50,
- /* 0000031D mov dx,0x1ce */ 0xBA, 0xCE, 0x01,
- /* 00000320 mov ax,0x4 */ 0xB8, 0x04, 0x00,
- /* 00000323 out dx,ax */ 0xEF,
- /* 00000324 mov dx,0x1d0 */ 0xBA, 0xD0, 0x01,
- /* 00000327 mov ax,0x41 */ 0xB8, 0x41, 0x00,
- /* 0000032A out dx,ax */ 0xEF,
- /* 0000032B pop ax */ 0x58,
- /* 0000032C pop dx */ 0x5A,
- /* 0000032D pop ax */ 0x58,
- /* 0000032E pop dx */ 0x5A,
- /* 0000032F jmp short 0x34c */ 0xEB, 0x1B,
- /* 00000331 mov bx,0x40f1 */ 0xBB, 0xF1, 0x40,
- /* 00000334 jmp short 0x34c */ 0xEB, 0x16,
- /* 00000336 jmp short 0x350 */ 0xEB, 0x18,
- /* 00000338 jmp short 0x350 */ 0xEB, 0x16,
- /* 0000033A cmp al,0x3 */ 0x3C, 0x03,
- /* 0000033C jz 0x345 */ 0x74, 0x07,
- /* 0000033E cmp al,0x12 */ 0x3C, 0x12,
- /* 00000340 jz 0x349 */ 0x74, 0x07,
- /* 00000342 jmp word 0x22b */ 0xE9, 0xE6, 0xFE,
- /* 00000345 mov al,0x30 */ 0xB0, 0x30,
- /* 00000347 jmp short 0x34b */ 0xEB, 0x02,
- /* 00000349 mov al,0x20 */ 0xB0, 0x20,
- /* 0000034B iretw */ 0xCF,
- /* 0000034C mov ax,0x4f */ 0xB8, 0x4F, 0x00,
- /* 0000034F iretw */ 0xCF,
- /* 00000350 mov ax,0x14f */ 0xB8, 0x4F, 0x01,
- /* 00000353 iretw */ 0xCF,
-};
-#endif
diff --git a/OvmfPkg/QemuVideoDxe/VbeShim.sh b/OvmfPkg/QemuVideoDxe/VbeShim.sh
deleted file mode 100755
index 7a0095a813..0000000000
--- a/OvmfPkg/QemuVideoDxe/VbeShim.sh
+++ /dev/null
@@ -1,82 +0,0 @@
-#!/bin/sh
-###
-# @file
-# Shell script to assemble and dump the fake Int10h handler from NASM source to
-# a C array.
-#
-# Copyright (C) 2014, Red Hat, Inc.
-# Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.<BR>
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-###
-
-set -e -u
-
-STEM=$(dirname -- "$0")/$(basename -- "$0" .sh)
-
-#
-# Install exit handler -- remove temporary files.
-#
-exit_handler()
-{
- rm -f -- "$STEM".bin "$STEM".disasm "$STEM".offsets "$STEM".insns \
- "$STEM".bytes
-}
-trap exit_handler EXIT
-
-#
-# Assemble the source file.
-# (nasm doesn't recognize the "--" end-of-options delimiter;
-# <https://bugzilla.nasm.us/show_bug.cgi?id=3392829>.)
-#
-nasm -o "$STEM".bin "$STEM".asm
-
-#
-# Disassemble it, in order to get a binary dump associated with the source.
-# (ndisasm doesn't recognize the "--" end-of-options delimiter;
-# <https://bugzilla.nasm.us/show_bug.cgi?id=3392829>.)
-#
-ndisasm "$STEM".bin >"$STEM".disasm
-
-#
-# Create three files, each with one column of the disassembly.
-#
-# The first column contains the offsets, and it starts the comment.
-#
-cut -c 1-8 -- "$STEM".disasm \
-| sed -e 's,^, /* ,' >"$STEM".offsets
-
-#
-# The second column contains the assembly-language instructions, and it closes
-# the comment. We first pad it to 30 characters.
-#
-cut -c 29- -- "$STEM".disasm \
-| sed -e 's,$, ,' \
- -e 's,^\(.\{30\}\).*$,\1 */,' >"$STEM".insns
-
-#
-# The third column contains the bytes corresponding to the instruction,
-# represented as C integer constants. First strip trailing whitespace from the
-# middle column of the input disassembly, then process pairs of nibbles.
-#
-cut -c 11-28 -- "$STEM".disasm \
-| sed -e 's, \+$,,' -e 's/\(..\)/ 0x\1,/g' >"$STEM".bytes
-
-#
-# Write the output file, recombining the columns. The output should have CRLF
-# line endings.
-#
-{
- printf '//\n'
- printf '// THIS FILE WAS GENERATED BY "%s". DO NOT EDIT.\n' \
- "$(basename -- "$0")"
- printf '//\n'
- printf '#ifndef _VBE_SHIM_H_\n'
- printf '#define _VBE_SHIM_H_\n'
- printf 'STATIC CONST UINT8 mVbeShim[] = {\n'
- paste -d ' ' -- "$STEM".offsets "$STEM".insns "$STEM".bytes
- printf '};\n'
- printf '#endif\n'
-} \
-| unix2dos >"$STEM".h
diff --git a/OvmfPkg/ResetVector/Ia32/AmdSev.asm b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
index 23e4c5ebbe..827c874312 100644
--- a/OvmfPkg/ResetVector/Ia32/AmdSev.asm
+++ b/OvmfPkg/ResetVector/Ia32/AmdSev.asm
@@ -162,11 +162,14 @@ SevClearPageEncMaskForGhcbPage:
;
; The initial GHCB will live at GHCB_BASE and needs to be un-encrypted.
; This requires the 2MB page for this range be broken down into 512 4KB
- ; pages. All will be marked encrypted, except for the GHCB.
+ ; pages. All will be marked encrypted, except for the GHCB. Since the
+ ; original PMD entry is no longer a leaf entry, remove the encryption
+ ; bit when pointing to the PTE page.
;
mov ecx, (GHCB_BASE >> 21)
mov eax, GHCB_PT_ADDR + PAGE_PDP_ATTR
mov [ecx * 8 + PT_ADDR (0x2000)], eax
+ mov [ecx * 8 + PT_ADDR (0x2000) + 4], strict dword 0
;
; Page Table Entries (512 * 4KB entries => 2MB)
diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 474d22dbfa..d913a39d46 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -67,7 +67,7 @@ BITS 32
;
; Create page tables for 4-level paging
;
-; Argument: upper 32 bits of the page table entries
+; Argument: upper 32 bits of the leaf page table entries
;
%macro CreatePageTables4Level 1
@@ -78,19 +78,19 @@ BITS 32
; Top level Page Directory Pointers (1 * 512GB entry)
;
mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (4)], %1
+ mov dword[PT_ADDR (4)], 0
;
; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
;
mov dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x1004)], %1
+ mov dword[PT_ADDR (0x1004)], 0
mov dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x100C)], %1
+ mov dword[PT_ADDR (0x100C)], 0
mov dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x1014)], %1
+ mov dword[PT_ADDR (0x1014)], 0
mov dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x101C)], %1
+ mov dword[PT_ADDR (0x101C)], 0
;
; Page Table Entries (2048 * 2MB entries => 4GB)
@@ -141,7 +141,7 @@ BITS 32
;
; Create page tables for 5-level paging with gigabyte pages
;
-; Argument: upper 32 bits of the page table entries
+; Argument: upper 32 bits of the leaf page table entries
;
; We have 6 pages available for the early page tables,
; we use four of them:
@@ -164,15 +164,15 @@ BITS 32
; level 5
mov dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (4)], %1
+ mov dword[PT_ADDR (4)], 0
; level 4
mov dword[PT_ADDR (0x1000)], PT_ADDR (0x3000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x1004)], %1
+ mov dword[PT_ADDR (0x1004)], 0
; level 3 (1x -> level 2, 3x 1GB)
mov dword[PT_ADDR (0x3000)], PT_ADDR (0x2000) + PAGE_PDE_DIRECTORY_ATTR
- mov dword[PT_ADDR (0x3004)], %1
+ mov dword[PT_ADDR (0x3004)], 0
mov dword[PT_ADDR (0x3008)], (1 << 30) + PAGE_PDE_LARGEPAGE_ATTR
mov dword[PT_ADDR (0x300c)], %1
mov dword[PT_ADDR (0x3010)], (2 << 30) + PAGE_PDE_LARGEPAGE_ATTR
diff --git a/OvmfPkg/Sec/AmdSev.c b/OvmfPkg/Sec/AmdSev.c
index 520b125132..89fba2fd18 100644
--- a/OvmfPkg/Sec/AmdSev.c
+++ b/OvmfPkg/Sec/AmdSev.c
@@ -8,7 +8,10 @@
**/
#include <Library/BaseLib.h>
+#include <Library/CpuLib.h>
+#include <Library/CpuPageTableLib.h>
#include <Library/DebugLib.h>
+#include <Library/LocalApicLib.h>
#include <Library/MemEncryptSevLib.h>
#include <Library/BaseMemoryLib.h>
#include <Register/Amd/Ghcb.h>
@@ -301,3 +304,58 @@ SecValidateSystemRam (
MemEncryptSevSnpPreValidateSystemRam (Start, EFI_SIZE_TO_PAGES ((UINTN)(End - Start)));
}
}
+
+/**
+ Map known MMIO regions unencrypted if SEV-ES is active.
+
+ During early booting, page table entries default to having the encryption bit
+ set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
+ encryption bit should be cleared. Clear it here for any known MMIO accesses
+ during SEC, which is currently just the APIC base address.
+
+**/
+VOID
+SecMapApicBaseUnencrypted (
+ VOID
+ )
+{
+ PHYSICAL_ADDRESS Cr3;
+ UINT64 ApicAddress;
+ VOID *Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ RETURN_STATUS Status;
+
+ if (!SevEsIsEnabled ()) {
+ return;
+ }
+
+ ApicAddress = (UINT64)GetLocalApicBaseAddress ();
+ Buffer = (VOID *)(UINTN)FixedPcdGet32 (PcdOvmfSecApicPageTableBase);
+ Cr3 = AsmReadCr3 ();
+
+ MapAttribute.Uint64 = ApicAddress;
+ MapAttribute.Bits.Present = 1;
+ MapAttribute.Bits.ReadWrite = 1;
+ MapMask.Uint64 = MAX_UINT64;
+ BufferSize = SIZE_4KB;
+
+ Status = PageTableMap (
+ (UINTN *)&Cr3,
+ Paging4Level,
+ Buffer,
+ &BufferSize,
+ ApicAddress,
+ SIZE_4KB,
+ &MapAttribute,
+ &MapMask,
+ NULL
+ );
+ if (RETURN_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to map APIC MMIO region as unencrypted: %d\n", Status));
+ ASSERT (FALSE);
+ }
+
+ CpuFlushTlb ();
+}
diff --git a/OvmfPkg/Sec/AmdSev.h b/OvmfPkg/Sec/AmdSev.h
index f75877096e..c5ab0d5a0b 100644
--- a/OvmfPkg/Sec/AmdSev.h
+++ b/OvmfPkg/Sec/AmdSev.h
@@ -91,4 +91,18 @@ SevSnpIsEnabled (
VOID
);
+/**
+ Map MMIO regions unencrypted if SEV-ES is active.
+
+ During early booting, page table entries default to having the encryption bit
+ set for SEV-ES/SEV-SNP guests. In cases where there is MMIO to an address, the
+ encryption bit should be cleared. Clear it here for any known MMIO accesses
+ during SEC, which is currently just the APIC base address.
+
+**/
+VOID
+SecMapApicBaseUnencrypted (
+ VOID
+ );
+
#endif
diff --git a/OvmfPkg/Sec/SecMain.c b/OvmfPkg/Sec/SecMain.c
index a30d4ce09e..60dfa61842 100644
--- a/OvmfPkg/Sec/SecMain.c
+++ b/OvmfPkg/Sec/SecMain.c
@@ -938,6 +938,7 @@ SecCoreStartupWithStack (
// interrupts before initializing the Debug Agent and the debug timer is
// enabled.
//
+ SecMapApicBaseUnencrypted ();
InitializeApicTimer (0, MAX_UINT32, TRUE, 5);
DisableApicTimerInterrupt ();
diff --git a/OvmfPkg/Sec/SecMain.inf b/OvmfPkg/Sec/SecMain.inf
index dca932a474..88c2d3fb6d 100644
--- a/OvmfPkg/Sec/SecMain.inf
+++ b/OvmfPkg/Sec/SecMain.inf
@@ -55,6 +55,7 @@
MemEncryptSevLib
CpuExceptionHandlerLib
CcProbeLib
+ CpuPageTableLib
[Ppis]
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
@@ -83,6 +84,8 @@
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecGhcbBackupBase
gUefiOvmfPkgTokenSpaceGuid.PcdTdxAcceptPageSize
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfWorkAreaBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecApicPageTableSize
[FeaturePcd]
gUefiOvmfPkgTokenSpaceGuid.PcdSmmSmramRequire
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/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c b/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
index 7b11f49d0d..93622733a5 100644
--- a/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
+++ b/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
@@ -4809,6 +4809,9 @@ ExplainPcieLinkCap (
case 5:
MaxLinkSpeed = L"32.0 GT/s";
break;
+ case 6:
+ MaxLinkSpeed = L"64.0 GT/s";
+ break;
default:
MaxLinkSpeed = L"Reserved";
break;
@@ -5015,6 +5018,9 @@ ExplainPcieLinkStatus (
case 5:
CurLinkSpeed = L"32.0 GT/s";
break;
+ case 6:
+ CurLinkSpeed = L"64.0 GT/s";
+ break;
default:
CurLinkSpeed = L"Reserved";
break;
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/CpuS3DataDxe/CpuS3Data.c b/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
index 86ce5303ca..c87f82bc22 100644
--- a/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
+++ b/UefiCpuPkg/CpuS3DataDxe/CpuS3Data.c
@@ -9,7 +9,7 @@ number of CPUs reported by the MP Services Protocol, so this module does not
support hot plug CPUs. This module can be copied into a CPU specific package
and customized if these additional features are required.
-Copyright (c) 2013 - 2021, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2013 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2015, Red Hat, Inc.
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -26,6 +26,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Library/DebugLib.h>
#include <Library/MtrrLib.h>
#include <Library/MemoryAllocationLib.h>
+#include <Library/LockBoxLib.h>
#include <Protocol/MpService.h>
#include <Guid/EventGroup.h>
@@ -131,6 +132,16 @@ CpuS3DataOnEndOfDxe (
MtrrGetAllMtrrs (&AcpiCpuDataEx->MtrrTable);
//
+ // Save MTRR in lockbox
+ //
+ Status = SaveLockBox (
+ &gEdkiiS3MtrrSettingGuid,
+ &AcpiCpuDataEx->MtrrTable,
+ sizeof (MTRR_SETTINGS)
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
// Close event, so it will not be invoked again.
//
gBS->CloseEvent (Event);
diff --git a/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf b/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
index 510133a614..c690f7df5b 100644
--- a/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
+++ b/UefiCpuPkg/CpuS3DataDxe/CpuS3DataDxe.inf
@@ -9,7 +9,7 @@
# support hot plug CPUs. This module can be copied into a CPU specific package
# and customized if these additional features are required.
#
-# Copyright (c) 2013-2016, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2013-2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2015, Red Hat, Inc.
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -46,9 +46,11 @@
BaseLib
MtrrLib
MemoryAllocationLib
+ LockBoxLib
[Guids]
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
+ gEdkiiS3MtrrSettingGuid
[Protocols]
gEfiMpServiceProtocolGuid ## CONSUMES
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/CpuPageTableLib/CpuPageTableMap.c b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
index b10a3008e4..bdc411338f 100644
--- a/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
+++ b/UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableMap.c
@@ -342,6 +342,7 @@ PageTableLibMapInLevel (
UINT64 PhysicalAddrInAttr;
IA32_PAGING_ENTRY OriginalParentPagingEntry;
IA32_PAGING_ENTRY OriginalCurrentPagingEntry;
+ IA32_PAGING_ENTRY TempPagingEntry;
ASSERT (Level != 0);
ASSERT ((Attribute != NULL) && (Mask != NULL));
@@ -359,6 +360,8 @@ PageTableLibMapInLevel (
OriginalParentPagingEntry.Uint64 = ParentPagingEntry->Uint64;
OneOfPagingEntry.Uint64 = 0;
+ TempPagingEntry.Uint64 = 0;
+
//
// RegionLength: 256T (1 << 48) 512G (1 << 39), 1G (1 << 30), 2M (1 << 21) or 4K (1 << 12).
//
@@ -441,8 +444,10 @@ PageTableLibMapInLevel (
// Non-leaf entry doesn't have PAT bit. So use ~IA32_PE_BASE_ADDRESS_MASK_40 is to make sure PAT bit
// (bit12) in original big-leaf entry is not assigned to PageTableBaseAddress field of non-leaf entry.
//
- PageTableLibSetPnle (&ParentPagingEntry->Pnle, &NopAttribute, &AllOneMask);
- ParentPagingEntry->Uint64 = ((UINTN)(VOID *)PagingEntry) | (ParentPagingEntry->Uint64 & (~IA32_PE_BASE_ADDRESS_MASK_40));
+ TempPagingEntry.Uint64 = ParentPagingEntry->Uint64;
+ PageTableLibSetPnle (&TempPagingEntry.Pnle, &NopAttribute, &AllOneMask);
+ TempPagingEntry.Uint64 = ((UINTN)(VOID *)PagingEntry) | (TempPagingEntry.Uint64 & (~IA32_PE_BASE_ADDRESS_MASK_40));
+ *(volatile UINT64 *)&(ParentPagingEntry->Uint64) = TempPagingEntry.Uint64;
}
} else {
//
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
index 57ddb86600..f9c5c92c22 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
@@ -1,7 +1,7 @@
/** @file
MP initialize support functions for DXE phase.
- Copyright (c) 2016 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -20,15 +20,11 @@
#define AP_SAFE_STACK_SIZE 128
-CPU_MP_DATA *mCpuMpData = NULL;
-EFI_EVENT mCheckAllApsEvent = NULL;
-EFI_EVENT mMpInitExitBootServicesEvent = NULL;
-EFI_EVENT mLegacyBootEvent = NULL;
-volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
-RELOCATE_AP_LOOP_ENTRY mReservedApLoop;
-UINTN mReservedTopOfApStack;
-volatile UINT32 mNumberToFinish = 0;
-UINTN mApPageTable;
+CPU_MP_DATA *mCpuMpData = NULL;
+EFI_EVENT mCheckAllApsEvent = NULL;
+EFI_EVENT mMpInitExitBootServicesEvent = NULL;
+EFI_EVENT mLegacyBootEvent = NULL;
+volatile BOOLEAN mStopCheckAllApsStatus = TRUE;
//
// Begin wakeup buffer allocation below 0x88000
@@ -369,57 +365,58 @@ GetProtectedModeCS (
}
/**
- Do sync on APs.
+ Allocate buffer for ApLoopCode.
- @param[in, out] Buffer Pointer to private data buffer.
+ @param[in] Pages Number of pages to allocate.
+ @param[in, out] Address Pointer to the allocated buffer.
**/
VOID
-EFIAPI
-RelocateApLoop (
- IN OUT VOID *Buffer
+AllocateApLoopCodeBuffer (
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Address
)
{
- CPU_MP_DATA *CpuMpData;
- BOOLEAN MwaitSupport;
- UINTN ProcessorNumber;
- UINTN StackStart;
+ EFI_STATUS Status;
- MpInitLibWhoAmI (&ProcessorNumber);
- CpuMpData = GetCpuMpData ();
- MwaitSupport = IsMwaitSupport ();
- if (CpuMpData->UseSevEsAPMethod) {
- //
- // 64-bit AMD processors with SEV-ES
- //
- StackStart = CpuMpData->SevEsAPResetStackStart;
- mReservedApLoop.AmdSevEntry (
- MwaitSupport,
- CpuMpData->ApTargetCState,
- CpuMpData->PmCodeSegment,
- StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
- (UINTN)&mNumberToFinish,
- CpuMpData->Pm16CodeSegment,
- CpuMpData->SevEsAPBuffer,
- CpuMpData->WakeupBuffer
- );
- } else {
- //
- // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
- //
- StackStart = mReservedTopOfApStack;
- mReservedApLoop.GenericEntry (
- MwaitSupport,
- CpuMpData->ApTargetCState,
- StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
- (UINTN)&mNumberToFinish,
- mApPageTable
- );
- }
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiReservedMemoryType,
+ Pages,
+ Address
+ );
+ ASSERT_EFI_ERROR (Status);
+}
+
+/**
+ Remove Nx protection for the range specific by BaseAddress and Length.
+
+ The PEI implementation uses CpuPageTableLib to change the attribute.
+ The DXE implementation uses gDS to change the attribute.
+
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+RemoveNxprotection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
//
- // It should never reach here
+ // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
+ // service.
//
- ASSERT (FALSE);
+ Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &MemDesc);
+ if (!EFI_ERROR (Status)) {
+ gDS->SetMemorySpaceAttributes (
+ BaseAddress,
+ Length,
+ MemDesc.Attributes & (~EFI_MEMORY_XP)
+ );
+ }
}
/**
@@ -477,16 +474,10 @@ InitMpGlobalData (
)
{
EFI_STATUS Status;
- EFI_PHYSICAL_ADDRESS Address;
UINTN Index;
EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc;
UINTN StackBase;
CPU_INFO_IN_HOB *CpuInfoInHob;
- MP_ASSEMBLY_ADDRESS_MAP *AddressMap;
- UINT8 *ApLoopFunc;
- UINTN ApLoopFuncSize;
- UINTN StackPages;
- UINTN FuncPages;
SaveCpuMpData (CpuMpData);
@@ -541,81 +532,7 @@ InitMpGlobalData (
}
}
- AddressMap = &CpuMpData->AddressMap;
- if (CpuMpData->UseSevEsAPMethod) {
- //
- // 64-bit AMD processors with SEV-ES
- //
- Address = BASE_4GB - 1;
- ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev;
- ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev;
- } else {
- //
- // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
- //
- Address = MAX_ADDRESS;
- ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric;
- ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric;
- }
-
- //
- // Avoid APs access invalid buffer data which allocated by BootServices,
- // so we will allocate reserved data for AP loop code. We also need to
- // allocate this buffer below 4GB due to APs may be transferred to 32bit
- // protected mode on long mode DXE.
- // Allocating it in advance since memory services are not available in
- // Exit Boot Services callback function.
- //
- // +------------+ (TopOfApStack)
- // | Stack * N |
- // +------------+ (stack base, 4k aligned)
- // | Padding |
- // +------------+
- // | Ap Loop |
- // +------------+ ((low address, 4k-aligned)
- //
-
- StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);
- FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize);
-
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiReservedMemoryType,
- StackPages + FuncPages,
- &Address
- );
- ASSERT_EFI_ERROR (Status);
-
- //
- // Make sure that the buffer memory is executable if NX protection is enabled
- // for EfiReservedMemoryType.
- //
- // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
- // service.
- //
- Status = gDS->GetMemorySpaceDescriptor (Address, &MemDesc);
- if (!EFI_ERROR (Status)) {
- gDS->SetMemorySpaceAttributes (
- Address,
- EFI_PAGES_TO_SIZE (FuncPages),
- MemDesc.Attributes & (~EFI_MEMORY_XP)
- );
- }
-
- mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages);
- ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
- mReservedApLoop.Data = (VOID *)(UINTN)Address;
- ASSERT (mReservedApLoop.Data != NULL);
- CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize);
- if (!CpuMpData->UseSevEsAPMethod) {
- //
- // processors without SEV-ES
- //
- mApPageTable = CreatePageTable (
- (UINTN)Address,
- EFI_PAGES_TO_SIZE (StackPages+FuncPages)
- );
- }
+ PrepareApLoopCode (CpuMpData);
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
index d117f09ef5..c0fe631635 100644
--- a/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
@@ -1,5 +1,5 @@
;------------------------------------------------------------------------------ ;
-; Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
+; Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
; SPDX-License-Identifier: BSD-2-Clause-Patent
;
; Module Name:
@@ -225,6 +225,10 @@ RendezvousFunnelProcEnd:
; specific to SEV-ES support and are not applicable on IA32.
;-------------------------------------------------------------------------------------
AsmRelocateApLoopGenericStart:
+ mov eax, cr0
+ btr eax, 31 ; Clear CR0.PG
+ mov cr0, eax ; Disable paging since the page table might be unavailiable
+
mov eax, esp
mov esp, [eax + 12] ; TopOfApStack
push dword [eax] ; push return address for stack trace
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c
index d724456502..f97298887f 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
@@ -17,6 +17,11 @@ EFI_GUID mCpuInitMpLibHobGuid = CPU_INIT_MP_LIB_HOB_GUID;
EFI_GUID mMpHandOffGuid = MP_HANDOFF_GUID;
EFI_GUID mMpHandOffConfigGuid = MP_HANDOFF_CONFIG_GUID;
+RELOCATE_AP_LOOP_ENTRY mReservedApLoop;
+UINTN mReservedTopOfApStack;
+volatile UINT32 mNumberToFinish = 0;
+UINTN mApPageTable;
+
/**
Save the volatile registers required to be restored following INIT IPI.
@@ -114,6 +119,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 +770,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 +807,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 +936,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 +2160,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 +2200,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 +2259,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 +2628,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
//
@@ -3227,3 +3245,140 @@ ConfidentialComputingGuestHas (
return (CurrentAttr == Attr);
}
+
+/**
+ Do sync on APs.
+
+ @param[in, out] Buffer Pointer to private data buffer.
+**/
+VOID
+EFIAPI
+RelocateApLoop (
+ IN OUT VOID *Buffer
+ )
+{
+ CPU_MP_DATA *CpuMpData;
+ BOOLEAN MwaitSupport;
+ UINTN ProcessorNumber;
+ UINTN StackStart;
+
+ MpInitLibWhoAmI (&ProcessorNumber);
+ CpuMpData = GetCpuMpData ();
+ MwaitSupport = IsMwaitSupport ();
+ if (CpuMpData->UseSevEsAPMethod) {
+ //
+ // 64-bit AMD processors with SEV-ES
+ //
+ StackStart = CpuMpData->SevEsAPResetStackStart;
+ mReservedApLoop.AmdSevEntry (
+ MwaitSupport,
+ CpuMpData->ApTargetCState,
+ CpuMpData->PmCodeSegment,
+ StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
+ (UINTN)&mNumberToFinish,
+ CpuMpData->Pm16CodeSegment,
+ CpuMpData->SevEsAPBuffer,
+ CpuMpData->WakeupBuffer
+ );
+ } else {
+ //
+ // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
+ //
+ StackStart = mReservedTopOfApStack;
+ mReservedApLoop.GenericEntry (
+ MwaitSupport,
+ CpuMpData->ApTargetCState,
+ StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
+ (UINTN)&mNumberToFinish,
+ mApPageTable
+ );
+ }
+
+ //
+ // It should never reach here
+ //
+ ASSERT (FALSE);
+}
+
+/**
+ Prepare ApLoopCode.
+
+ @param[in] CpuMpData Pointer to CpuMpData.
+**/
+VOID
+PrepareApLoopCode (
+ IN CPU_MP_DATA *CpuMpData
+ )
+{
+ EFI_PHYSICAL_ADDRESS Address;
+ MP_ASSEMBLY_ADDRESS_MAP *AddressMap;
+ UINT8 *ApLoopFunc;
+ UINTN ApLoopFuncSize;
+ UINTN StackPages;
+ UINTN FuncPages;
+ IA32_CR0 Cr0;
+
+ AddressMap = &CpuMpData->AddressMap;
+ if (CpuMpData->UseSevEsAPMethod) {
+ //
+ // 64-bit AMD processors with SEV-ES
+ //
+ Address = BASE_4GB - 1;
+ ApLoopFunc = AddressMap->RelocateApLoopFuncAddressAmdSev;
+ ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeAmdSev;
+ } else {
+ //
+ // Intel processors (32-bit or 64-bit), 32-bit AMD processors, or 64-bit AMD processors without SEV-ES
+ //
+ Address = MAX_ADDRESS;
+ ApLoopFunc = AddressMap->RelocateApLoopFuncAddressGeneric;
+ ApLoopFuncSize = AddressMap->RelocateApLoopFuncSizeGeneric;
+ }
+
+ //
+ // Avoid APs access invalid buffer data which allocated by BootServices,
+ // so we will allocate reserved data for AP loop code. We also need to
+ // allocate this buffer below 4GB due to APs may be transferred to 32bit
+ // protected mode on long mode DXE.
+ // Allocating it in advance since memory services are not available in
+ // Exit Boot Services callback function.
+ //
+ // +------------+ (TopOfApStack)
+ // | Stack * N |
+ // +------------+ (stack base, 4k aligned)
+ // | Padding |
+ // +------------+
+ // | Ap Loop |
+ // +------------+ ((low address, 4k-aligned)
+ //
+
+ StackPages = EFI_SIZE_TO_PAGES (CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);
+ FuncPages = EFI_SIZE_TO_PAGES (ApLoopFuncSize);
+
+ AllocateApLoopCodeBuffer (StackPages + FuncPages, &Address);
+ ASSERT (Address != 0);
+
+ Cr0.UintN = AsmReadCr0 ();
+ if (Cr0.Bits.PG != 0) {
+ //
+ // Make sure that the buffer memory is executable if NX protection is enabled
+ // for EfiReservedMemoryType.
+ //
+ RemoveNxprotection (Address, EFI_PAGES_TO_SIZE (FuncPages));
+ }
+
+ mReservedTopOfApStack = (UINTN)Address + EFI_PAGES_TO_SIZE (StackPages+FuncPages);
+ ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
+ mReservedApLoop.Data = (VOID *)(UINTN)Address;
+ ASSERT (mReservedApLoop.Data != NULL);
+ CopyMem (mReservedApLoop.Data, ApLoopFunc, ApLoopFuncSize);
+ if (!CpuMpData->UseSevEsAPMethod) {
+ //
+ // processors without SEV-ES and paging is enabled
+ //
+ mApPageTable = CreatePageTable (
+ (UINTN)Address,
+ EFI_PAGES_TO_SIZE (StackPages+FuncPages)
+ );
+ }
+}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 179f8e585b..cc850c7dd5 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -1,7 +1,7 @@
/** @file
Common header file for MP Initialize Library.
- Copyright (c) 2016 - 2023, 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
@@ -33,6 +33,7 @@
#include <Library/HobLib.h>
#include <Library/PcdLib.h>
#include <Library/MicrocodeLib.h>
+#include <Library/CpuPageTableLib.h>
#include <ConfidentialComputingGuestAttr.h>
#include <Register/Amd/Fam17Msr.h>
@@ -68,6 +69,8 @@
//
#define DEFAULT_MAX_MICROCODE_PATCH_NUM 8
+#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
+
//
// Data structure for microcode patch information
//
@@ -357,7 +360,8 @@ typedef
IN UINTN StackStart
);
-extern EFI_GUID mCpuInitMpLibHobGuid;
+extern EFI_GUID mCpuInitMpLibHobGuid;
+extern volatile UINT32 mNumberToFinish;
/**
Assembly code to place AP into safe loop mode.
@@ -933,4 +937,52 @@ AmdSevUpdateCpuMpData (
IN CPU_MP_DATA *CpuMpData
);
+/**
+ Prepare ApLoopCode.
+
+ @param[in] CpuMpData Pointer to CpuMpData.
+**/
+VOID
+PrepareApLoopCode (
+ IN CPU_MP_DATA *CpuMpData
+ );
+
+/**
+ Do sync on APs.
+
+ @param[in, out] Buffer Pointer to private data buffer.
+**/
+VOID
+EFIAPI
+RelocateApLoop (
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Allocate buffer for ApLoopCode.
+
+ @param[in] Pages Number of pages to allocate.
+ @param[in, out] Address Pointer to the allocated buffer.
+**/
+VOID
+AllocateApLoopCodeBuffer (
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Address
+ );
+
+/**
+ Remove Nx protection for the range specific by BaseAddress and Length.
+
+ The PEI implementation uses CpuPageTableLib to change the attribute.
+ The DXE implementation uses gDS to change the attribute.
+
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+RemoveNxprotection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ );
+
#endif
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
index e31e34b6f9..e4a7485fef 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
@@ -1,7 +1,7 @@
## @file
# MP Initialize Library instance for PEI driver.
#
-# Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2024, Loongson Technology Corporation Limited. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -25,10 +25,12 @@
[Sources.IA32]
Ia32/AmdSev.c
Ia32/MpFuncs.nasm
+ Ia32/CreatePageTable.c
[Sources.X64]
X64/AmdSev.c
X64/MpFuncs.nasm
+ X64/CreatePageTable.c
[Sources.IA32, Sources.X64]
AmdSev.c
@@ -64,6 +66,7 @@
LocalApicLib
MicrocodeLib
MtrrLib
+ CpuPageTableLib
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ## CONSUMES
@@ -87,6 +90,7 @@
gEdkiiS3SmmInitDoneGuid
gEdkiiMicrocodePatchHobGuid
gGhcbApicIdsGuid ## SOMETIMES_CONSUMES
+ gEdkiiEndOfS3ResumeGuid
[Guids.LoongArch64]
gProcessorResourceHobGuid ## SOMETIMES_CONSUMES ## HOB
diff --git a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
index 4d3acb491f..16a858d542 100644
--- a/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/PeiMpLib.c
@@ -1,7 +1,7 @@
/** @file
MP initialize support functions for PEI phase.
- 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
**/
@@ -9,6 +9,7 @@
#include "MpLib.h"
#include <Library/PeiServicesLib.h>
#include <Guid/S3SmmInitDone.h>
+#include <Guid/EndOfS3Resume.h>
#include <Ppi/ShadowMicrocode.h>
STATIC UINT64 mSevEsPeiWakeupBuffer = BASE_1MB;
@@ -450,6 +451,47 @@ BuildMicrocodeCacheHob (
}
/**
+ S3 SMM Init Done notification function.
+
+ @param PeiServices Indirect reference to the PEI Services Table.
+ @param NotifyDesc Address of the notification descriptor data structure.
+ @param InvokePpi Address of the PPI that was invoked.
+
+ @retval EFI_SUCCESS The function completes successfully.
+
+**/
+EFI_STATUS
+EFIAPI
+NotifyOnEndOfS3Resume (
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *InvokePpi
+ )
+{
+ CPU_MP_DATA *CpuMpData;
+
+ CpuMpData = GetCpuMpData ();
+ mNumberToFinish = CpuMpData->CpuCount - 1;
+ WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, NULL, TRUE);
+ while (mNumberToFinish > 0) {
+ CpuPause ();
+ }
+
+ DEBUG ((DEBUG_INFO, "%a() done!\n", __func__));
+
+ return EFI_SUCCESS;
+}
+
+//
+// Global function
+//
+EFI_PEI_NOTIFY_DESCRIPTOR mEndOfS3ResumeNotifyDesc = {
+ EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+ &gEdkiiEndOfS3ResumeGuid,
+ NotifyOnEndOfS3Resume
+};
+
+/**
Initialize global data for MP support.
@param[in] CpuMpData The pointer to CPU MP Data structure.
@@ -463,12 +505,16 @@ InitMpGlobalData (
BuildMicrocodeCacheHob (CpuMpData);
SaveCpuMpData (CpuMpData);
+ PrepareApLoopCode (CpuMpData);
///
/// Install Notify
///
Status = PeiServicesNotifyPpi (&mS3SmmInitDoneNotifyDesc);
ASSERT_EFI_ERROR (Status);
+
+ Status = PeiServicesNotifyPpi (&mEndOfS3ResumeNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
}
/**
@@ -815,3 +861,109 @@ PlatformShadowMicrocode (
return EFI_SUCCESS;
}
+
+/**
+ Allocate buffer for ApLoopCode.
+
+ @param[in] Pages Number of pages to allocate.
+ @param[in, out] Address Pointer to the allocated buffer.
+**/
+VOID
+AllocateApLoopCodeBuffer (
+ IN UINTN Pages,
+ IN OUT EFI_PHYSICAL_ADDRESS *Address
+ )
+{
+ EFI_STATUS Status;
+
+ Status = PeiServicesAllocatePages (EfiACPIMemoryNVS, Pages, Address);
+ if (EFI_ERROR (Status)) {
+ *Address = 0;
+ }
+}
+
+/**
+ Remove Nx protection for the range specific by BaseAddress and Length.
+
+ The PEI implementation uses CpuPageTableLib to change the attribute.
+ The DXE implementation uses gDS to change the attribute.
+
+ @param[in] BaseAddress BaseAddress of the range.
+ @param[in] Length Length of the range.
+**/
+VOID
+RemoveNxprotection (
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,
+ IN UINTN Length
+ )
+{
+ EFI_STATUS Status;
+ UINTN PageTable;
+ EFI_PHYSICAL_ADDRESS Buffer;
+ UINTN BufferSize;
+ IA32_MAP_ATTRIBUTE MapAttribute;
+ IA32_MAP_ATTRIBUTE MapMask;
+ PAGING_MODE PagingMode;
+ IA32_CR4 Cr4;
+ BOOLEAN Page5LevelSupport;
+ UINT32 RegEax;
+ BOOLEAN Page1GSupport;
+ CPUID_EXTENDED_CPU_SIG_EDX RegEdx;
+
+ if (sizeof (UINTN) == sizeof (UINT64)) {
+ //
+ // Check Page5Level Support or not.
+ //
+ Cr4.UintN = AsmReadCr4 ();
+ Page5LevelSupport = (Cr4.Bits.LA57 ? TRUE : FALSE);
+
+ //
+ // Check Page1G Support or not.
+ //
+ Page1GSupport = FALSE;
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
+ AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx.Uint32);
+ if (RegEdx.Bits.Page1GB != 0) {
+ Page1GSupport = TRUE;
+ }
+ }
+
+ //
+ // Decide Paging Mode according Page5LevelSupport & Page1GSupport.
+ //
+ if (Page5LevelSupport) {
+ PagingMode = Page1GSupport ? Paging5Level1GB : Paging5Level;
+ } else {
+ PagingMode = Page1GSupport ? Paging4Level1GB : Paging4Level;
+ }
+ } else {
+ PagingMode = PagingPae;
+ }
+
+ MapAttribute.Uint64 = 0;
+ MapMask.Uint64 = 0;
+ MapMask.Bits.Nx = 1;
+ PageTable = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;
+ BufferSize = 0;
+
+ //
+ // Get required buffer size for changing the pagetable.
+ //
+ Status = PageTableMap (&PageTable, PagingMode, 0, &BufferSize, BaseAddress, Length, &MapAttribute, &MapMask, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate required Buffer.
+ //
+ Status = PeiServicesAllocatePages (
+ EfiBootServicesData,
+ EFI_SIZE_TO_PAGES (BufferSize),
+ &Buffer
+ );
+ ASSERT_EFI_ERROR (Status);
+ Status = PageTableMap (&PageTable, PagingMode, (VOID *)(UINTN)Buffer, &BufferSize, BaseAddress, Length, &MapAttribute, &MapMask, NULL);
+ }
+
+ ASSERT_EFI_ERROR (Status);
+ AsmWriteCr3 (PageTable);
+}
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..c37a2d4d1b 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -1,74 +1,15 @@
/** @file
Code for Processor S3 restoration
-Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PiSmmCpuDxeSmm.h"
#include <PiPei.h>
-#include <Ppi/MpServices2.h>
-#pragma pack(1)
-typedef struct {
- UINTN Lock;
- VOID *StackStart;
- UINTN StackSize;
- VOID *ApFunction;
- IA32_DESCRIPTOR GdtrProfile;
- IA32_DESCRIPTOR IdtrProfile;
- UINT32 BufferStart;
- UINT32 Cr3;
- UINTN InitializeFloatingPointUnitsAddress;
-} MP_CPU_EXCHANGE_INFO;
-#pragma pack()
-
-typedef struct {
- UINT8 *RendezvousFunnelAddress;
- UINTN PModeEntryOffset;
- UINTN FlatJumpOffset;
- UINTN Size;
- UINTN LModeEntryOffset;
- UINTN LongJumpOffset;
-} MP_ASSEMBLY_ADDRESS_MAP;
-
-//
-// Flags used when program the register.
-//
-typedef struct {
- volatile UINTN MemoryMappedLock; // Spinlock used to program mmio
- volatile UINT32 *CoreSemaphoreCount; // Semaphore container used to program
- // core level semaphore.
- volatile UINT32 *PackageSemaphoreCount; // Semaphore container used to program
- // package level semaphore.
-} PROGRAM_CPU_REGISTER_FLAGS;
-
-//
-// Signal that SMM BASE relocation is complete.
-//
-volatile BOOLEAN mInitApsAfterSmmBaseReloc;
-
-/**
- Get starting address and size of the rendezvous entry for APs.
- Information for fixing a jump instruction in the code is also returned.
-
- @param AddressMap Output buffer for address map information.
-**/
-VOID *
-EFIAPI
-AsmGetAddressMap (
- MP_ASSEMBLY_ADDRESS_MAP *AddressMap
- );
-
-#define LEGACY_REGION_SIZE (2 * 0x1000)
-#define LEGACY_REGION_BASE (0xA0000 - LEGACY_REGION_SIZE)
-
-PROGRAM_CPU_REGISTER_FLAGS mCpuFlags;
-ACPI_CPU_DATA mAcpiCpuData;
-volatile UINT32 mNumberToFinish;
-MP_CPU_EXCHANGE_INFO *mExchangeInfo;
-BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;
+BOOLEAN mRestoreSmmConfigurationInS3 = FALSE;
//
// S3 boot flag
@@ -82,664 +23,6 @@ SMM_S3_RESUME_STATE *mSmmS3ResumeState = NULL;
BOOLEAN mAcpiS3Enable = TRUE;
-UINT8 *mApHltLoopCode = NULL;
-UINT8 mApHltLoopCodeTemplate[] = {
- 0x8B, 0x44, 0x24, 0x04, // mov eax, dword ptr [esp+4]
- 0xF0, 0xFF, 0x08, // lock dec dword ptr [eax]
- 0xFA, // cli
- 0xF4, // hlt
- 0xEB, 0xFC // jmp $-2
-};
-
-/**
- Sync up the MTRR values for all processors.
-
- @param MtrrTable Table holding fixed/variable MTRR values to be loaded.
-**/
-VOID
-EFIAPI
-LoadMtrrData (
- EFI_PHYSICAL_ADDRESS MtrrTable
- )
-
-/*++
-
-Routine Description:
-
- Sync up the MTRR values for all processors.
-
-Arguments:
-
-Returns:
- None
-
---*/
-{
- MTRR_SETTINGS *MtrrSettings;
-
- MtrrSettings = (MTRR_SETTINGS *)(UINTN)MtrrTable;
- MtrrSetAllMtrrs (MtrrSettings);
-}
-
-/**
- Increment semaphore by 1.
-
- @param Sem IN: 32-bit unsigned integer
-
-**/
-VOID
-S3ReleaseSemaphore (
- IN OUT volatile UINT32 *Sem
- )
-{
- InterlockedIncrement (Sem);
-}
-
-/**
- Decrement the semaphore by 1 if it is not zero.
-
- Performs an atomic decrement operation for semaphore.
- The compare exchange operation must be performed using
- MP safe mechanisms.
-
- @param Sem IN: 32-bit unsigned integer
-
-**/
-VOID
-S3WaitForSemaphore (
- IN OUT volatile UINT32 *Sem
- )
-{
- UINT32 Value;
-
- do {
- Value = *Sem;
- } while (Value == 0 ||
- InterlockedCompareExchange32 (
- Sem,
- Value,
- Value - 1
- ) != Value);
-}
-
-/**
- Read / write CR value.
-
- @param[in] CrIndex The CR index which need to read/write.
- @param[in] Read Read or write. TRUE is read.
- @param[in,out] CrValue CR value.
-
- @retval EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.
-**/
-UINTN
-ReadWriteCr (
- IN UINT32 CrIndex,
- IN BOOLEAN Read,
- IN OUT UINTN *CrValue
- )
-{
- switch (CrIndex) {
- case 0:
- if (Read) {
- *CrValue = AsmReadCr0 ();
- } else {
- AsmWriteCr0 (*CrValue);
- }
-
- break;
- case 2:
- if (Read) {
- *CrValue = AsmReadCr2 ();
- } else {
- AsmWriteCr2 (*CrValue);
- }
-
- break;
- case 3:
- if (Read) {
- *CrValue = AsmReadCr3 ();
- } else {
- AsmWriteCr3 (*CrValue);
- }
-
- break;
- case 4:
- if (Read) {
- *CrValue = AsmReadCr4 ();
- } else {
- AsmWriteCr4 (*CrValue);
- }
-
- break;
- default:
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Initialize the CPU registers from a register table.
-
- @param[in] RegisterTable The register table for this AP.
- @param[in] ApLocation AP location info for this ap.
- @param[in] CpuStatus CPU status info for this CPU.
- @param[in] CpuFlags Flags data structure used when program the register.
-
- @note This service could be called by BSP/APs.
-**/
-VOID
-ProgramProcessorRegister (
- IN CPU_REGISTER_TABLE *RegisterTable,
- IN EFI_CPU_PHYSICAL_LOCATION *ApLocation,
- IN CPU_STATUS_INFORMATION *CpuStatus,
- IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags
- )
-{
- CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
- UINTN Index;
- UINTN Value;
- CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
- volatile UINT32 *SemaphorePtr;
- UINT32 FirstThread;
- UINT32 CurrentThread;
- UINT32 CurrentCore;
- UINTN ProcessorIndex;
- UINT32 *ThreadCountPerPackage;
- UINT8 *ThreadCountPerCore;
- EFI_STATUS Status;
- UINT64 CurrentValue;
-
- //
- // Traverse Register Table of this logical processor
- //
- RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *)(UINTN)RegisterTable->RegisterTableEntry;
-
- for (Index = 0; Index < RegisterTable->TableLength; Index++) {
- RegisterTableEntry = &RegisterTableEntryHead[Index];
-
- //
- // Check the type of specified register
- //
- switch (RegisterTableEntry->RegisterType) {
- //
- // The specified register is Control Register
- //
- case ControlRegister:
- Status = ReadWriteCr (RegisterTableEntry->Index, TRUE, &Value);
- if (EFI_ERROR (Status)) {
- break;
- }
-
- if (RegisterTableEntry->TestThenWrite) {
- CurrentValue = BitFieldRead64 (
- Value,
- RegisterTableEntry->ValidBitStart,
- RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1
- );
- if (CurrentValue == RegisterTableEntry->Value) {
- break;
- }
- }
-
- Value = (UINTN)BitFieldWrite64 (
- Value,
- RegisterTableEntry->ValidBitStart,
- RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
- RegisterTableEntry->Value
- );
- ReadWriteCr (RegisterTableEntry->Index, FALSE, &Value);
- break;
- //
- // The specified register is Model Specific Register
- //
- case Msr:
- if (RegisterTableEntry->TestThenWrite) {
- Value = (UINTN)AsmReadMsr64 (RegisterTableEntry->Index);
- if (RegisterTableEntry->ValidBitLength >= 64) {
- if (Value == RegisterTableEntry->Value) {
- break;
- }
- } else {
- CurrentValue = BitFieldRead64 (
- Value,
- RegisterTableEntry->ValidBitStart,
- RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1
- );
- if (CurrentValue == RegisterTableEntry->Value) {
- break;
- }
- }
- }
-
- //
- // If this function is called to restore register setting after INIT signal,
- // there is no need to restore MSRs in register table.
- //
- if (RegisterTableEntry->ValidBitLength >= 64) {
- //
- // If length is not less than 64 bits, then directly write without reading
- //
- AsmWriteMsr64 (
- RegisterTableEntry->Index,
- RegisterTableEntry->Value
- );
- } else {
- //
- // Set the bit section according to bit start and length
- //
- AsmMsrBitFieldWrite64 (
- RegisterTableEntry->Index,
- RegisterTableEntry->ValidBitStart,
- RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
- RegisterTableEntry->Value
- );
- }
-
- break;
- //
- // MemoryMapped operations
- //
- case MemoryMapped:
- AcquireSpinLock (&CpuFlags->MemoryMappedLock);
- MmioBitFieldWrite32 (
- (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),
- RegisterTableEntry->ValidBitStart,
- RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
- (UINT32)RegisterTableEntry->Value
- );
- ReleaseSpinLock (&CpuFlags->MemoryMappedLock);
- break;
- //
- // Enable or disable cache
- //
- case CacheControl:
- //
- // If value of the entry is 0, then disable cache. Otherwise, enable cache.
- //
- if (RegisterTableEntry->Value == 0) {
- AsmDisableCache ();
- } else {
- AsmEnableCache ();
- }
-
- break;
-
- case Semaphore:
- // Semaphore works logic like below:
- //
- // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);
- // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);
- //
- // All threads (T0...Tn) waits in P() line and continues running
- // together.
- //
- //
- // T0 T1 ... Tn
- //
- // V(0...n) V(0...n) ... V(0...n)
- // n * P(0) n * P(1) ... n * P(n)
- //
- ASSERT (
- (ApLocation != NULL) &&
- (CpuStatus->ThreadCountPerPackage != 0) &&
- (CpuStatus->ThreadCountPerCore != 0) &&
- (CpuFlags->CoreSemaphoreCount != NULL) &&
- (CpuFlags->PackageSemaphoreCount != NULL)
- );
- switch (RegisterTableEntry->Value) {
- case CoreDepType:
- SemaphorePtr = CpuFlags->CoreSemaphoreCount;
- ThreadCountPerCore = (UINT8 *)(UINTN)CpuStatus->ThreadCountPerCore;
-
- CurrentCore = ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core;
- //
- // Get Offset info for the first thread in the core which current thread belongs to.
- //
- FirstThread = CurrentCore * CpuStatus->MaxThreadCount;
- CurrentThread = FirstThread + ApLocation->Thread;
-
- //
- // Different cores may have different valid threads in them. If driver maintail clearly
- // thread index in different cores, the logic will be much complicated.
- // Here driver just simply records the max thread number in all cores and use it as expect
- // thread number for all cores.
- // In below two steps logic, first current thread will Release semaphore for each thread
- // in current core. Maybe some threads are not valid in this core, but driver don't
- // care. Second, driver will let current thread wait semaphore for all valid threads in
- // current core. Because only the valid threads will do release semaphore for this
- // thread, driver here only need to wait the valid thread count.
- //
-
- //
- // First Notify ALL THREADs in current Core that this thread is ready.
- //
- for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex++) {
- S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);
- }
-
- //
- // Second, check whether all VALID THREADs (not all threads) in current core are ready.
- //
- for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerCore[CurrentCore]; ProcessorIndex++) {
- S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);
- }
-
- break;
-
- case PackageDepType:
- SemaphorePtr = CpuFlags->PackageSemaphoreCount;
- ThreadCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ThreadCountPerPackage;
- //
- // Get Offset info for the first thread in the package which current thread belongs to.
- //
- FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount;
- //
- // Get the possible threads count for current package.
- //
- CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;
-
- //
- // Different packages may have different valid threads in them. If driver maintail clearly
- // thread index in different packages, the logic will be much complicated.
- // Here driver just simply records the max thread number in all packages and use it as expect
- // thread number for all packages.
- // In below two steps logic, first current thread will Release semaphore for each thread
- // in current package. Maybe some threads are not valid in this package, but driver don't
- // care. Second, driver will let current thread wait semaphore for all valid threads in
- // current package. Because only the valid threads will do release semaphore for this
- // thread, driver here only need to wait the valid thread count.
- //
-
- //
- // First Notify ALL THREADS in current package that this thread is ready.
- //
- for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; ProcessorIndex++) {
- S3ReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);
- }
-
- //
- // Second, check whether VALID THREADS (not all threads) in current package are ready.
- //
- for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerPackage[ApLocation->Package]; ProcessorIndex++) {
- S3WaitForSemaphore (&SemaphorePtr[CurrentThread]);
- }
-
- break;
-
- default:
- break;
- }
-
- break;
-
- default:
- break;
- }
- }
-}
-
-/**
-
- Set Processor register for one AP.
-
- @param PreSmmRegisterTable Use pre Smm register table or register table.
-
-**/
-VOID
-SetRegister (
- IN BOOLEAN PreSmmRegisterTable
- )
-{
- CPU_FEATURE_INIT_DATA *FeatureInitData;
- CPU_REGISTER_TABLE *RegisterTable;
- CPU_REGISTER_TABLE *RegisterTables;
- UINT32 InitApicId;
- UINTN ProcIndex;
- UINTN Index;
-
- FeatureInitData = &mAcpiCpuData.CpuFeatureInitData;
-
- if (PreSmmRegisterTable) {
- RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)FeatureInitData->PreSmmInitRegisterTable;
- } else {
- RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)FeatureInitData->RegisterTable;
- }
-
- if (RegisterTables == NULL) {
- return;
- }
-
- InitApicId = GetInitialApicId ();
- RegisterTable = NULL;
- ProcIndex = (UINTN)-1;
- for (Index = 0; Index < mAcpiCpuData.NumberOfCpus; Index++) {
- if (RegisterTables[Index].InitialApicId == InitApicId) {
- RegisterTable = &RegisterTables[Index];
- ProcIndex = Index;
- break;
- }
- }
-
- ASSERT (RegisterTable != NULL);
-
- if (FeatureInitData->ApLocation != 0) {
- ProgramProcessorRegister (
- RegisterTable,
- (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)FeatureInitData->ApLocation + ProcIndex,
- &FeatureInitData->CpuStatus,
- &mCpuFlags
- );
- } else {
- ProgramProcessorRegister (
- RegisterTable,
- NULL,
- &FeatureInitData->CpuStatus,
- &mCpuFlags
- );
- }
-}
-
-/**
- The function is invoked before SMBASE relocation in S3 path to restores CPU status.
-
- The function is invoked before SMBASE relocation in S3 path. It does first time microcode load
- and restores MTRRs for both BSP and APs.
-
- @param IsBsp The CPU this function executes on is BSP or not.
-
-**/
-VOID
-InitializeCpuBeforeRebase (
- IN BOOLEAN IsBsp
- )
-{
- LoadMtrrData (mAcpiCpuData.MtrrTable);
-
- SetRegister (TRUE);
-
- ProgramVirtualWireMode ();
- if (!IsBsp) {
- DisableLvtInterrupts ();
- }
-
- //
- // Count down the number with lock mechanism.
- //
- InterlockedDecrement (&mNumberToFinish);
-
- if (IsBsp) {
- //
- // Bsp wait here till all AP finish the initialization before rebase
- //
- while (mNumberToFinish > 0) {
- CpuPause ();
- }
- }
-}
-
-/**
- The function is invoked after SMBASE relocation in S3 path to restores CPU status.
-
- The function is invoked after SMBASE relocation in S3 path. It restores configuration according to
- data saved by normal boot path for both BSP and APs.
-
- @param IsBsp The CPU this function executes on is BSP or not.
-
-**/
-VOID
-InitializeCpuAfterRebase (
- IN BOOLEAN IsBsp
- )
-{
- UINTN TopOfStack;
- UINT8 Stack[128];
-
- SetRegister (FALSE);
-
- if (mSmmS3ResumeState->MpService2Ppi == 0) {
- if (IsBsp) {
- while (mNumberToFinish > 0) {
- CpuPause ();
- }
- } else {
- //
- // Place AP into the safe code, count down the number with lock mechanism in the safe code.
- //
- TopOfStack = (UINTN)Stack + sizeof (Stack);
- TopOfStack &= ~(UINTN)(CPU_STACK_ALIGNMENT - 1);
- CopyMem ((VOID *)(UINTN)mApHltLoopCode, mApHltLoopCodeTemplate, sizeof (mApHltLoopCodeTemplate));
- TransferApToSafeState ((UINTN)mApHltLoopCode, TopOfStack, (UINTN)&mNumberToFinish);
- }
- }
-}
-
-/**
- Cpu initialization procedure.
-
- @param[in,out] Buffer The pointer to private data buffer.
-
-**/
-VOID
-EFIAPI
-InitializeCpuProcedure (
- IN OUT VOID *Buffer
- )
-{
- BOOLEAN IsBsp;
-
- IsBsp = (BOOLEAN)(mBspApicId == GetApicId ());
-
- //
- // Skip initialization if mAcpiCpuData is not valid
- //
- if (mAcpiCpuData.NumberOfCpus > 0) {
- //
- // First time microcode load and restore MTRRs
- //
- InitializeCpuBeforeRebase (IsBsp);
- }
-
- 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!!!
- //
- 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 ();
- }
- }
-
- //
- // Skip initialization if mAcpiCpuData is not valid
- //
- if (mAcpiCpuData.NumberOfCpus > 0) {
- if (IsBsp) {
- //
- // mNumberToFinish should be set before AP executes InitializeCpuAfterRebase()
- //
- mNumberToFinish = (UINT32)(mNumberOfCpus - 1);
- //
- // Signal that SMM base relocation is complete and to continue initialization for all APs.
- //
- mInitApsAfterSmmBaseReloc = TRUE;
- } else {
- //
- // AP Wait for BSP to signal SMM Base relocation done.
- //
- while (!mInitApsAfterSmmBaseReloc) {
- CpuPause ();
- }
- }
-
- //
- // Restore MSRs for BSP and all APs
- //
- InitializeCpuAfterRebase (IsBsp);
- }
-}
-
-/**
- Prepares startup vector for APs.
-
- This function prepares startup vector for APs.
-
- @param WorkingBuffer The address of the work buffer.
-**/
-VOID
-PrepareApStartupVector (
- EFI_PHYSICAL_ADDRESS WorkingBuffer
- )
-{
- EFI_PHYSICAL_ADDRESS StartupVector;
- MP_ASSEMBLY_ADDRESS_MAP AddressMap;
-
- //
- // Get the address map of startup code for AP,
- // including code size, and offset of long jump instructions to redirect.
- //
- ZeroMem (&AddressMap, sizeof (AddressMap));
- AsmGetAddressMap (&AddressMap);
-
- StartupVector = WorkingBuffer;
-
- //
- // Copy AP startup code to startup vector, and then redirect the long jump
- // instructions for mode switching.
- //
- CopyMem ((VOID *)(UINTN)StartupVector, AddressMap.RendezvousFunnelAddress, AddressMap.Size);
- *(UINT32 *)(UINTN)(StartupVector + AddressMap.FlatJumpOffset + 3) = (UINT32)(StartupVector + AddressMap.PModeEntryOffset);
- if (AddressMap.LongJumpOffset != 0) {
- *(UINT32 *)(UINTN)(StartupVector + AddressMap.LongJumpOffset + 2) = (UINT32)(StartupVector + AddressMap.LModeEntryOffset);
- }
-
- //
- // Get the start address of exchange data between BSP and AP.
- //
- mExchangeInfo = (MP_CPU_EXCHANGE_INFO *)(UINTN)(StartupVector + AddressMap.Size);
- ZeroMem ((VOID *)mExchangeInfo, sizeof (MP_CPU_EXCHANGE_INFO));
-
- CopyMem ((VOID *)(UINTN)&mExchangeInfo->GdtrProfile, (VOID *)(UINTN)mAcpiCpuData.GdtrProfile, sizeof (IA32_DESCRIPTOR));
- CopyMem ((VOID *)(UINTN)&mExchangeInfo->IdtrProfile, (VOID *)(UINTN)mAcpiCpuData.IdtrProfile, sizeof (IA32_DESCRIPTOR));
-
- mExchangeInfo->StackStart = (VOID *)(UINTN)mAcpiCpuData.StackAddress;
- mExchangeInfo->StackSize = mAcpiCpuData.StackSize;
- mExchangeInfo->BufferStart = (UINT32)StartupVector;
- mExchangeInfo->Cr3 = (UINT32)(AsmReadCr3 ());
- mExchangeInfo->InitializeFloatingPointUnitsAddress = (UINTN)InitializeFloatingPointUnits;
- mExchangeInfo->ApFunction = (VOID *)(UINTN)InitializeCpuProcedure;
-}
-
/**
Restore SMM Configuration in S3 boot path.
@@ -788,12 +71,11 @@ SmmRestoreCpu (
VOID
)
{
- SMM_S3_RESUME_STATE *SmmS3ResumeState;
- IA32_DESCRIPTOR Ia32Idtr;
- IA32_DESCRIPTOR X64Idtr;
- IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
- EFI_STATUS Status;
- EDKII_PEI_MP_SERVICES2_PPI *Mp2ServicePpi;
+ SMM_S3_RESUME_STATE *SmmS3ResumeState;
+ IA32_DESCRIPTOR Ia32Idtr;
+ IA32_DESCRIPTOR X64Idtr;
+ IA32_IDT_GATE_DESCRIPTOR IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
+ EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "SmmRestoreCpu()\n"));
@@ -842,38 +124,10 @@ SmmRestoreCpu (
}
}
- mBspApicId = GetApicId ();
//
- // Skip AP initialization if mAcpiCpuData is not valid
+ // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
//
- if (mAcpiCpuData.NumberOfCpus > 0) {
- if (FeaturePcdGet (PcdCpuHotPlugSupport)) {
- ASSERT (mNumberOfCpus <= mAcpiCpuData.NumberOfCpus);
- } else {
- ASSERT (mNumberOfCpus == mAcpiCpuData.NumberOfCpus);
- }
-
- mNumberToFinish = (UINT32)mNumberOfCpus;
-
- //
- // Execute code for before SmmBaseReloc. Note: This flag is maintained across S3 boots.
- //
- mInitApsAfterSmmBaseReloc = FALSE;
-
- if (mSmmS3ResumeState->MpService2Ppi != 0) {
- Mp2ServicePpi = (EDKII_PEI_MP_SERVICES2_PPI *)(UINTN)mSmmS3ResumeState->MpService2Ppi;
- Mp2ServicePpi->StartupAllCPUs (Mp2ServicePpi, InitializeCpuProcedure, 0, NULL);
- } else {
- PrepareApStartupVector (mAcpiCpuData.StartupVector);
- //
- // Send INIT IPI - SIPI to all APs
- //
- SendInitSipiSipiAllExcludingSelf ((UINT32)mAcpiCpuData.StartupVector);
- InitializeCpuProcedure (NULL);
- }
- } else {
- InitializeCpuProcedure (NULL);
- }
+ ExecuteFirstSmiInit ();
//
// Set a flag to restore SMM configuration in S3 path.
@@ -944,8 +198,6 @@ InitSmmS3ResumeState (
VOID *GuidHob;
EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
SMM_S3_RESUME_STATE *SmmS3ResumeState;
- EFI_PHYSICAL_ADDRESS Address;
- EFI_STATUS Status;
if (!mAcpiS3Enable) {
return;
@@ -980,9 +232,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;
@@ -997,246 +249,6 @@ InitSmmS3ResumeState (
//
InitSmmS3Cr3 ();
}
-
- //
- // Allocate safe memory in ACPI NVS for AP to execute hlt loop in
- // protected mode on S3 path
- //
- Address = BASE_4GB - 1;
- Status = gBS->AllocatePages (
- AllocateMaxAddress,
- EfiACPIMemoryNVS,
- EFI_SIZE_TO_PAGES (sizeof (mApHltLoopCodeTemplate)),
- &Address
- );
- ASSERT_EFI_ERROR (Status);
- mApHltLoopCode = (UINT8 *)(UINTN)Address;
-}
-
-/**
- Copy register table from non-SMRAM into SMRAM.
-
- @param[in] DestinationRegisterTableList Points to destination register table.
- @param[in] SourceRegisterTableList Points to source register table.
- @param[in] NumberOfCpus Number of CPUs.
-
-**/
-VOID
-CopyRegisterTable (
- IN CPU_REGISTER_TABLE *DestinationRegisterTableList,
- IN CPU_REGISTER_TABLE *SourceRegisterTableList,
- IN UINT32 NumberOfCpus
- )
-{
- UINTN Index;
- CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
-
- CopyMem (DestinationRegisterTableList, SourceRegisterTableList, NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
- for (Index = 0; Index < NumberOfCpus; Index++) {
- if (DestinationRegisterTableList[Index].TableLength != 0) {
- DestinationRegisterTableList[Index].AllocatedSize = DestinationRegisterTableList[Index].TableLength * sizeof (CPU_REGISTER_TABLE_ENTRY);
- RegisterTableEntry = AllocateCopyPool (
- DestinationRegisterTableList[Index].AllocatedSize,
- (VOID *)(UINTN)SourceRegisterTableList[Index].RegisterTableEntry
- );
- ASSERT (RegisterTableEntry != NULL);
- DestinationRegisterTableList[Index].RegisterTableEntry = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTableEntry;
- }
- }
-}
-
-/**
- Check whether the register table is empty or not.
-
- @param[in] RegisterTable Point to the register table.
- @param[in] NumberOfCpus Number of CPUs.
-
- @retval TRUE The register table is empty.
- @retval FALSE The register table is not empty.
-**/
-BOOLEAN
-IsRegisterTableEmpty (
- IN CPU_REGISTER_TABLE *RegisterTable,
- IN UINT32 NumberOfCpus
- )
-{
- UINTN Index;
-
- if (RegisterTable != NULL) {
- for (Index = 0; Index < NumberOfCpus; Index++) {
- if (RegisterTable[Index].TableLength != 0) {
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
-/**
- Copy the data used to initialize processor register into SMRAM.
-
- @param[in,out] CpuFeatureInitDataDst Pointer to the destination CPU_FEATURE_INIT_DATA structure.
- @param[in] CpuFeatureInitDataSrc Pointer to the source CPU_FEATURE_INIT_DATA structure.
-
-**/
-VOID
-CopyCpuFeatureInitDatatoSmram (
- IN OUT CPU_FEATURE_INIT_DATA *CpuFeatureInitDataDst,
- IN CPU_FEATURE_INIT_DATA *CpuFeatureInitDataSrc
- )
-{
- CPU_STATUS_INFORMATION *CpuStatus;
-
- if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->PreSmmInitRegisterTable, mAcpiCpuData.NumberOfCpus)) {
- CpuFeatureInitDataDst->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
- ASSERT (CpuFeatureInitDataDst->PreSmmInitRegisterTable != 0);
-
- CopyRegisterTable (
- (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataDst->PreSmmInitRegisterTable,
- (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->PreSmmInitRegisterTable,
- mAcpiCpuData.NumberOfCpus
- );
- }
-
- if (!IsRegisterTableEmpty ((CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->RegisterTable, mAcpiCpuData.NumberOfCpus)) {
- CpuFeatureInitDataDst->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (mAcpiCpuData.NumberOfCpus * sizeof (CPU_REGISTER_TABLE));
- ASSERT (CpuFeatureInitDataDst->RegisterTable != 0);
-
- CopyRegisterTable (
- (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataDst->RegisterTable,
- (CPU_REGISTER_TABLE *)(UINTN)CpuFeatureInitDataSrc->RegisterTable,
- mAcpiCpuData.NumberOfCpus
- );
- }
-
- CpuStatus = &CpuFeatureInitDataDst->CpuStatus;
- CopyMem (CpuStatus, &CpuFeatureInitDataSrc->CpuStatus, sizeof (CPU_STATUS_INFORMATION));
-
- if (CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerPackage != 0) {
- CpuStatus->ThreadCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
- sizeof (UINT32) * CpuStatus->PackageCount,
- (UINT32 *)(UINTN)CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerPackage
- );
- ASSERT (CpuStatus->ThreadCountPerPackage != 0);
- }
-
- if (CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerCore != 0) {
- CpuStatus->ThreadCountPerCore = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
- sizeof (UINT8) * (CpuStatus->PackageCount * CpuStatus->MaxCoreCount),
- (UINT32 *)(UINTN)CpuFeatureInitDataSrc->CpuStatus.ThreadCountPerCore
- );
- ASSERT (CpuStatus->ThreadCountPerCore != 0);
- }
-
- if (CpuFeatureInitDataSrc->ApLocation != 0) {
- CpuFeatureInitDataDst->ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocateCopyPool (
- mAcpiCpuData.NumberOfCpus * sizeof (EFI_CPU_PHYSICAL_LOCATION),
- (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)CpuFeatureInitDataSrc->ApLocation
- );
- ASSERT (CpuFeatureInitDataDst->ApLocation != 0);
- }
-}
-
-/**
- Get ACPI CPU data.
-
-**/
-VOID
-GetAcpiCpuData (
- VOID
- )
-{
- ACPI_CPU_DATA *AcpiCpuData;
- IA32_DESCRIPTOR *Gdtr;
- IA32_DESCRIPTOR *Idtr;
- VOID *GdtForAp;
- VOID *IdtForAp;
- VOID *MachineCheckHandlerForAp;
- CPU_STATUS_INFORMATION *CpuStatus;
-
- if (!mAcpiS3Enable) {
- return;
- }
-
- //
- // Prevent use of mAcpiCpuData by initialize NumberOfCpus to 0
- //
- mAcpiCpuData.NumberOfCpus = 0;
-
- //
- // If PcdCpuS3DataAddress was never set, then do not copy CPU S3 Data into SMRAM
- //
- AcpiCpuData = (ACPI_CPU_DATA *)(UINTN)PcdGet64 (PcdCpuS3DataAddress);
- if (AcpiCpuData == 0) {
- return;
- }
-
- //
- // For a native platform, copy the CPU S3 data into SMRAM for use on CPU S3 Resume.
- //
- CopyMem (&mAcpiCpuData, AcpiCpuData, sizeof (mAcpiCpuData));
-
- mAcpiCpuData.MtrrTable = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (MTRR_SETTINGS));
- ASSERT (mAcpiCpuData.MtrrTable != 0);
-
- CopyMem ((VOID *)(UINTN)mAcpiCpuData.MtrrTable, (VOID *)(UINTN)AcpiCpuData->MtrrTable, sizeof (MTRR_SETTINGS));
-
- mAcpiCpuData.GdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (IA32_DESCRIPTOR));
- ASSERT (mAcpiCpuData.GdtrProfile != 0);
-
- CopyMem ((VOID *)(UINTN)mAcpiCpuData.GdtrProfile, (VOID *)(UINTN)AcpiCpuData->GdtrProfile, sizeof (IA32_DESCRIPTOR));
-
- mAcpiCpuData.IdtrProfile = (EFI_PHYSICAL_ADDRESS)(UINTN)AllocatePool (sizeof (IA32_DESCRIPTOR));
- ASSERT (mAcpiCpuData.IdtrProfile != 0);
-
- CopyMem ((VOID *)(UINTN)mAcpiCpuData.IdtrProfile, (VOID *)(UINTN)AcpiCpuData->IdtrProfile, sizeof (IA32_DESCRIPTOR));
-
- //
- // Copy AP's GDT, IDT and Machine Check handler into SMRAM.
- //
- Gdtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.GdtrProfile;
- Idtr = (IA32_DESCRIPTOR *)(UINTN)mAcpiCpuData.IdtrProfile;
-
- GdtForAp = AllocatePool ((Gdtr->Limit + 1) + (Idtr->Limit + 1) + mAcpiCpuData.ApMachineCheckHandlerSize);
- ASSERT (GdtForAp != NULL);
- IdtForAp = (VOID *)((UINTN)GdtForAp + (Gdtr->Limit + 1));
- MachineCheckHandlerForAp = (VOID *)((UINTN)IdtForAp + (Idtr->Limit + 1));
-
- CopyMem (GdtForAp, (VOID *)Gdtr->Base, Gdtr->Limit + 1);
- CopyMem (IdtForAp, (VOID *)Idtr->Base, Idtr->Limit + 1);
- CopyMem (MachineCheckHandlerForAp, (VOID *)(UINTN)mAcpiCpuData.ApMachineCheckHandlerBase, mAcpiCpuData.ApMachineCheckHandlerSize);
-
- Gdtr->Base = (UINTN)GdtForAp;
- Idtr->Base = (UINTN)IdtForAp;
- mAcpiCpuData.ApMachineCheckHandlerBase = (EFI_PHYSICAL_ADDRESS)(UINTN)MachineCheckHandlerForAp;
-
- ZeroMem (&mAcpiCpuData.CpuFeatureInitData, sizeof (CPU_FEATURE_INIT_DATA));
-
- if (!PcdGetBool (PcdCpuFeaturesInitOnS3Resume)) {
- //
- // If the CPU features will not be initialized by CpuFeaturesPei module during
- // next ACPI S3 resume, copy the CPU features initialization data into SMRAM,
- // which will be consumed in SmmRestoreCpu during next S3 resume.
- //
- CopyCpuFeatureInitDatatoSmram (&mAcpiCpuData.CpuFeatureInitData, &AcpiCpuData->CpuFeatureInitData);
-
- CpuStatus = &mAcpiCpuData.CpuFeatureInitData.CpuStatus;
-
- mCpuFlags.CoreSemaphoreCount = AllocateZeroPool (
- sizeof (UINT32) * CpuStatus->PackageCount *
- CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount
- );
- ASSERT (mCpuFlags.CoreSemaphoreCount != NULL);
-
- mCpuFlags.PackageSemaphoreCount = AllocateZeroPool (
- sizeof (UINT32) * CpuStatus->PackageCount *
- CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount
- );
- ASSERT (mCpuFlags.PackageSemaphoreCount != NULL);
-
- InitializeSpinLock ((SPIN_LOCK *)&mCpuFlags.MemoryMappedLock);
- }
}
/**
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.nasm
deleted file mode 100644
index dbd1418c0d..0000000000
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/MpFuncs.nasm
+++ /dev/null
@@ -1,153 +0,0 @@
-;------------------------------------------------------------------------------ ;
-; Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Module Name:
-;
-; MpFuncs.nasm
-;
-; Abstract:
-;
-; This is the assembly code for Multi-processor S3 support
-;
-;-------------------------------------------------------------------------------
-
-SECTION .text
-
-extern ASM_PFX(InitializeFloatingPointUnits)
-
-%define VacantFlag 0x0
-%define NotVacantFlag 0xff
-
-%define LockLocation RendezvousFunnelProcEnd - RendezvousFunnelProcStart
-%define StackStart LockLocation + 0x4
-%define StackSize LockLocation + 0x8
-%define RendezvousProc LockLocation + 0xC
-%define GdtrProfile LockLocation + 0x10
-%define IdtrProfile LockLocation + 0x16
-%define BufferStart LockLocation + 0x1C
-
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
-;procedure serializes all the AP processors through an Init sequence. It must be
-;noted that APs arrive here very raw...ie: real mode, no stack.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
-
-BITS 16
-global ASM_PFX(RendezvousFunnelProc)
-ASM_PFX(RendezvousFunnelProc):
-RendezvousFunnelProcStart:
-
-; At this point CS = 0x(vv00) and ip= 0x0.
-
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- xor ax, ax
- mov fs, ax
- mov gs, ax
-
-flat32Start:
-
- mov si, BufferStart
- mov edx,dword [si] ; EDX is keeping the start address of wakeup buffer
-
- mov si, GdtrProfile
-o32 lgdt [cs:si]
-
- mov si, IdtrProfile
-o32 lidt [cs:si]
-
- xor ax, ax
- mov ds, ax
-
- mov eax, cr0 ; Get control register 0
- or eax, 0x000000001 ; Set PE bit (bit #0)
- mov cr0, eax
-
-FLAT32_JUMP:
-
-a32 jmp dword 0x20:0x0
-
-BITS 32
-PMODE_ENTRY: ; protected mode entry point
-
- mov ax, 0x8
-o16 mov ds, ax
-o16 mov es, ax
-o16 mov fs, ax
-o16 mov gs, ax
-o16 mov ss, ax ; Flat mode setup.
-
- mov esi, edx
-
- mov edi, esi
- add edi, LockLocation
- mov al, NotVacantFlag
-TestLock:
- xchg byte [edi], al
- cmp al, NotVacantFlag
- jz TestLock
-
-ProgramStack:
-
- mov edi, esi
- add edi, StackSize
- mov eax, dword [edi]
- mov edi, esi
- add edi, StackStart
- add eax, dword [edi]
- mov esp, eax
- mov dword [edi], eax
-
-Releaselock:
-
- mov al, VacantFlag
- mov edi, esi
- add edi, LockLocation
- xchg byte [edi], al
-
- ;
- ; Call assembly function to initialize FPU.
- ;
- mov ebx, ASM_PFX(InitializeFloatingPointUnits)
- call ebx
- ;
- ; Call C Function
- ;
- mov edi, esi
- add edi, RendezvousProc
- mov eax, dword [edi]
-
- test eax, eax
- jz GoToSleep
- call eax ; Call C function
-
-GoToSleep:
- cli
- hlt
- jmp $-2
-
-RendezvousFunnelProcEnd:
-;-------------------------------------------------------------------------------------
-; AsmGetAddressMap (&AddressMap);
-;-------------------------------------------------------------------------------------
-global ASM_PFX(AsmGetAddressMap)
-ASM_PFX(AsmGetAddressMap):
-
- pushad
- mov ebp,esp
-
- mov ebx, dword [ebp+0x24]
- mov dword [ebx], RendezvousFunnelProcStart
- mov dword [ebx+0x4], PMODE_ENTRY - RendezvousFunnelProcStart
- mov dword [ebx+0x8], FLAT32_JUMP - RendezvousFunnelProcStart
- mov dword [ebx+0xc], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
-
- popad
- ret
-
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
index 636dc8d92f..0c1cc51ada 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmmFuncsArch.c
@@ -1,7 +1,7 @@
/** @file
SMM CPU misc functions for Ia32 arch specific.
-Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -142,33 +142,6 @@ InitGdt (
}
/**
- Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
-
- @param[in] ApHltLoopCode The address of the safe hlt-loop function.
- @param[in] TopOfStack A pointer to the new stack to use for the ApHltLoopCode.
- @param[in] NumberToFinishAddress Address of Semaphore of APs finish count.
-
-**/
-VOID
-TransferApToSafeState (
- IN UINTN ApHltLoopCode,
- IN UINTN TopOfStack,
- IN UINTN NumberToFinishAddress
- )
-{
- SwitchStack (
- (SWITCH_STACK_ENTRY_POINT)ApHltLoopCode,
- (VOID *)NumberToFinishAddress,
- NULL,
- (VOID *)TopOfStack
- );
- //
- // It should never reach here
- //
- ASSERT (FALSE);
-}
-
-/**
Initialize the shadow stack related data structure.
@param CpuIndex The index of CPU.
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..20a1a9cdbc 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -1,9 +1,9 @@
/** @file
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) 2009 - 2024, 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,111 +433,10 @@ 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
- perform additional lock actions that must be performed from SMM on the next SMI.
+ mSmmReadyToLock is set to perform additional lock actions that must be
+ performed from SMM on the next SMI.
@param[in] Protocol Points to the protocol's unique identifier.
@param[in] Interface Points to the interface instance.
@@ -577,8 +452,6 @@ SmmReadyToLockEventNotify (
IN EFI_HANDLE Handle
)
{
- GetAcpiCpuData ();
-
//
// Cache a copy of UEFI memory map before we start profiling feature.
//
@@ -751,6 +624,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 +736,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 +839,6 @@ PiCpuSmmEntry (
{
EFI_STATUS Status;
UINTN Index;
- VOID *Buffer;
- UINTN BufferPages;
UINTN TileCodeSize;
UINTN TileDataSize;
UINTN TileSize;
@@ -903,7 +857,6 @@ PiCpuSmmEntry (
//
// Initialize address fixup
//
- PiSmmCpuSmmInitFixupAddress ();
PiSmmCpuSmiEntryFixupAddress ();
//
@@ -1115,62 +1068,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 +1121,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 +1217,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 +1257,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 +1657,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..315a33d578 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -1,7 +1,7 @@
/** @file
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) 2009 - 2024, 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>
@@ -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.
//
@@ -1139,15 +1049,6 @@ InitSmmS3ResumeState (
);
/**
- Get ACPI CPU data.
-
-**/
-VOID
-GetAcpiCpuData (
- VOID
- );
-
-/**
Restore SMM Configuration in S3 boot path.
**/
@@ -1166,21 +1067,6 @@ GetAcpiS3EnableFlag (
);
/**
- Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
-
- @param[in] ApHltLoopCode The address of the safe hlt-loop function.
- @param[in] TopOfStack A pointer to the new stack to use for the ApHltLoopCode.
- @param[in] NumberToFinishAddress Address of Semaphore of APs finish count.
-
-**/
-VOID
-TransferApToSafeState (
- IN UINTN ApHltLoopCode,
- IN UINTN TopOfStack,
- IN UINTN NumberToFinishAddress
- );
-
-/**
Set ShadowStack memory.
@param[in] Cr3 The page table base address.
@@ -1304,15 +1190,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..f0598b0364 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -4,9 +4,9 @@
# This SMM driver performs SMM initialization, deploy SMM Entry Vector,
# provides CPU specific services in SMM.
#
-# Copyright (c) 2009 - 2023, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2009 - 2024, 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,27 +47,21 @@
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
X64/Cet.nasm
[Packages]
@@ -114,6 +108,7 @@
gEdkiiSmmMemoryAttributeProtocolGuid ## PRODUCES
gEfiMmMpProtocolGuid ## PRODUCES
gEdkiiSmmCpuRendezvousProtocolGuid ## PRODUCES
+ gEfiMpServiceProtocolGuid ## CONSUMES
[Guids]
gEfiAcpiVariableGuid ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot.
@@ -139,7 +134,6 @@
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmProfileSize ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStackSize ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout ## CONSUMES
- gUefiCpuPkgTokenSpaceGuid.PcdCpuS3DataAddress ## SOMETIMES_CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress ## SOMETIMES_PRODUCES
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmCodeAccessCheckEnable ## CONSUMES
gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode ## CONSUMES
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/PiSmmCpuDxeSmm/X64/MpFuncs.nasm b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.nasm
deleted file mode 100644
index a12538f72b..0000000000
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/MpFuncs.nasm
+++ /dev/null
@@ -1,189 +0,0 @@
-;------------------------------------------------------------------------------ ;
-; Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
-; SPDX-License-Identifier: BSD-2-Clause-Patent
-;
-; Module Name:
-;
-; MpFuncs.nasm
-;
-; Abstract:
-;
-; This is the assembly code for Multi-processor S3 support
-;
-;-------------------------------------------------------------------------------
-
-%define VacantFlag 0x0
-%define NotVacantFlag 0xff
-
-%define LockLocation RendezvousFunnelProcEnd - RendezvousFunnelProcStart
-%define StackStartAddressLocation LockLocation + 0x8
-%define StackSizeLocation LockLocation + 0x10
-%define CProcedureLocation LockLocation + 0x18
-%define GdtrLocation LockLocation + 0x20
-%define IdtrLocation LockLocation + 0x2A
-%define BufferStartLocation LockLocation + 0x34
-%define Cr3OffsetLocation LockLocation + 0x38
-%define InitializeFloatingPointUnitsAddress LockLocation + 0x3C
-
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc procedure follows. All APs execute their procedure. This
-;procedure serializes all the AP processors through an Init sequence. It must be
-;noted that APs arrive here very raw...ie: real mode, no stack.
-;ALSO THIS PROCEDURE IS EXECUTED BY APs ONLY ON 16 BIT MODE. HENCE THIS PROC
-;IS IN MACHINE CODE.
-;-------------------------------------------------------------------------------------
-;RendezvousFunnelProc (&WakeUpBuffer,MemAddress);
-
-;text SEGMENT
-DEFAULT REL
-SECTION .text
-
-BITS 16
-global ASM_PFX(RendezvousFunnelProc)
-ASM_PFX(RendezvousFunnelProc):
-RendezvousFunnelProcStart:
-
-; At this point CS = 0x(vv00) and ip= 0x0.
-
- mov ax, cs
- mov ds, ax
- mov es, ax
- mov ss, ax
- xor ax, ax
- mov fs, ax
- mov gs, ax
-
-flat32Start:
-
- mov si, BufferStartLocation
- mov edx,dword [si] ; EDX is keeping the start address of wakeup buffer
-
- mov si, Cr3OffsetLocation
- mov ecx,dword [si] ; ECX is keeping the value of CR3
-
- mov si, GdtrLocation
-o32 lgdt [cs:si]
-
- mov si, IdtrLocation
-o32 lidt [cs:si]
-
- xor ax, ax
- mov ds, ax
-
- mov eax, cr0 ; Get control register 0
- or eax, 0x000000001 ; Set PE bit (bit #0)
- mov cr0, eax
-
-FLAT32_JUMP:
-
-a32 jmp dword 0x20:0x0
-
-BITS 32
-PMODE_ENTRY: ; protected mode entry point
-
- mov ax, 0x18
-o16 mov ds, ax
-o16 mov es, ax
-o16 mov fs, ax
-o16 mov gs, ax
-o16 mov ss, ax ; Flat mode setup.
-
- mov eax, cr4
- bts eax, 5
- mov cr4, eax
-
- mov cr3, ecx
-
- mov esi, edx ; Save wakeup buffer address
-
- mov ecx, 0xc0000080 ; EFER MSR number.
- rdmsr ; Read EFER.
- bts eax, 8 ; Set LME=1.
- wrmsr ; Write EFER.
-
- mov eax, cr0 ; Read CR0.
- bts eax, 31 ; Set PG=1.
- mov cr0, eax ; Write CR0.
-
-LONG_JUMP:
-
-a16 jmp dword 0x38:0x0
-
-BITS 64
-LongModeStart:
-
- mov ax, 0x30
-o16 mov ds, ax
-o16 mov es, ax
-o16 mov ss, ax
-
- mov edi, esi
- add edi, LockLocation
- mov al, NotVacantFlag
-TestLock:
- xchg byte [edi], al
- cmp al, NotVacantFlag
- jz TestLock
-
-ProgramStack:
-
- mov edi, esi
- add edi, StackSizeLocation
- mov rax, qword [edi]
- mov edi, esi
- add edi, StackStartAddressLocation
- add rax, qword [edi]
- mov rsp, rax
- mov qword [edi], rax
-
-Releaselock:
-
- mov al, VacantFlag
- mov edi, esi
- add edi, LockLocation
- xchg byte [edi], al
-
- ;
- ; Call assembly function to initialize FPU.
- ;
- mov rax, qword [esi + InitializeFloatingPointUnitsAddress]
- sub rsp, 0x20
- call rax
- add rsp, 0x20
-
- ;
- ; Call C Function
- ;
- mov edi, esi
- add edi, CProcedureLocation
- mov rax, qword [edi]
-
- test rax, rax
- jz GoToSleep
-
- sub rsp, 0x20
- call rax
- add rsp, 0x20
-
-GoToSleep:
- cli
- hlt
- jmp $-2
-
-RendezvousFunnelProcEnd:
-
-;-------------------------------------------------------------------------------------
-; AsmGetAddressMap (&AddressMap);
-;-------------------------------------------------------------------------------------
-; comments here for definition of address map
-global ASM_PFX(AsmGetAddressMap)
-ASM_PFX(AsmGetAddressMap):
- lea rax, [RendezvousFunnelProcStart]
- mov qword [rcx], rax
- mov qword [rcx+0x8], PMODE_ENTRY - RendezvousFunnelProcStart
- mov qword [rcx+0x10], FLAT32_JUMP - RendezvousFunnelProcStart
- mov qword [rcx+0x18], RendezvousFunnelProcEnd - RendezvousFunnelProcStart
- mov qword [rcx+0x20], LongModeStart - RendezvousFunnelProcStart
- mov qword [rcx+0x28], LONG_JUMP - RendezvousFunnelProcStart
- ret
-
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
index c4f21e2155..ca706ee32c 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
@@ -1,7 +1,7 @@
/** @file
SMM CPU misc functions for x64 arch specific.
-Copyright (c) 2015 - 2023, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -133,34 +133,6 @@ GetProtectedModeCS (
}
/**
- Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.
-
- @param[in] ApHltLoopCode The address of the safe hlt-loop function.
- @param[in] TopOfStack A pointer to the new stack to use for the ApHltLoopCode.
- @param[in] NumberToFinishAddress Address of Semaphore of APs finish count.
-
-**/
-VOID
-TransferApToSafeState (
- IN UINTN ApHltLoopCode,
- IN UINTN TopOfStack,
- IN UINTN NumberToFinishAddress
- )
-{
- AsmDisablePaging64 (
- GetProtectedModeCS (),
- (UINT32)ApHltLoopCode,
- (UINT32)NumberToFinishAddress,
- 0,
- (UINT32)TopOfStack
- );
- //
- // It should never reach here
- //
- ASSERT (FALSE);
-}
-
-/**
Initialize the shadow stack related data structure.
@param CpuIndex The index of CPU.
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index f412ac0ce2..73bae90ddb 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -1,7 +1,7 @@
## @file UefiCpuPkg.dec
# This Package provides UEFI compatible CPU modules and libraries.
#
-# Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (C) 2023 - 2024, Advanced Micro Devices, Inc. All rights reserved.<BR>
# Copyright (c) 2024, Loongson Technology Corporation Limited. All rights reserved.<BR>
#
@@ -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.
##
@@ -307,7 +310,7 @@
## Specifies if CPU features will be initialized during S3 resume.
# @Prompt If CPU features will be initialized during S3 resume.
- gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|FALSE|BOOLEAN|0x0000001D
+ gUefiCpuPkgTokenSpaceGuid.PcdCpuFeaturesInitOnS3Resume|TRUE|BOOLEAN|0x0000001D
## Specifies CPUID Leaf 0x15 Time Stamp Counter and Nominal Core Crystal Clock Frequency.
# TSC Frequency = ECX (core crystal clock frequency) * EBX/EAX.
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 9426641eb2..1b52760e1a 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -1,7 +1,7 @@
## @file
# UefiCpuPkg Package
#
-# Copyright (c) 2007 - 2023, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2007 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (C) 2023 - 2024, Advanced Micro Devices, Inc. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -68,6 +68,7 @@
UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf
UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceLibNull/UnitTestPersistenceLibNull.inf
UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultReportLib/UnitTestResultReportLibDebugLib.inf
+ LockBoxLib|MdeModulePkg/Library/SmmLockBoxLib/SmmLockBoxDxeLib.inf
[LibraryClasses.common.SEC]
PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.inf
@@ -201,6 +202,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/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
index 4cf676fb3e..3e64a115bf 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -4,7 +4,7 @@
This module will execute the boot script saved during last boot and after that,
control is passed to OS waking up handler.
- Copyright (c) 2006 - 2023, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2006 - 2024, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -39,6 +39,7 @@
#include <Library/DebugAgentLib.h>
#include <Library/LocalApicLib.h>
#include <Library/ReportStatusCodeLib.h>
+#include <Library/MtrrLib.h>
#include <Library/HobLib.h>
#include <Library/LockBoxLib.h>
@@ -259,6 +260,12 @@ EFI_PEI_PPI_DESCRIPTOR mPpiListS3SmmInitDoneTable = {
0
};
+EFI_PEI_PPI_DESCRIPTOR mPpiListEndOfS3ResumeTable = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiEndOfS3ResumeGuid,
+ 0
+};
+
//
// Global Descriptor Table (GDT)
//
@@ -489,6 +496,13 @@ S3ResumeBootOs (
PERF_INMODULE_BEGIN ("EndOfS3Resume");
DEBUG ((DEBUG_INFO, "Signal EndOfS3Resume\n"));
+
+ //
+ // Install EndOfS3Resume.
+ //
+ Status = PeiServicesInstallPpi (&mPpiListEndOfS3ResumeTable);
+ ASSERT_EFI_ERROR (Status);
+
//
// Signal EndOfS3Resume to SMM.
//
@@ -939,6 +953,20 @@ S3ResumeExecuteBootScript (
}
/**
+ Sync up the MTRR values for all processors.
+
+ @param[in] MtrrTable Address of MTRR setting.
+**/
+VOID
+EFIAPI
+LoadMtrrData (
+ IN VOID *MtrrTable
+ )
+{
+ MtrrSetAllMtrrs (MtrrTable);
+}
+
+/**
Restores the platform to its preboot configuration for an S3 resume and
jumps to the OS waking vector.
@@ -990,6 +1018,7 @@ S3RestoreConfig2 (
BOOLEAN InterruptStatus;
IA32_CR0 Cr0;
EDKII_PEI_MP_SERVICES2_PPI *MpService2Ppi;
+ MTRR_SETTINGS MtrrTable;
TempAcpiS3Context = 0;
TempEfiBootScriptExecutorVariable = 0;
@@ -1082,6 +1111,39 @@ S3RestoreConfig2 (
Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
}
+ //
+ // Get MP Services2 Ppi to pass it to Smm S3.
+ //
+ Status = PeiServicesLocatePpi (
+ &gEdkiiPeiMpServices2PpiGuid,
+ 0,
+ NULL,
+ (VOID **)&MpService2Ppi
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Restore MTRR setting
+ //
+ VarSize = sizeof (MTRR_SETTINGS);
+ Status = RestoreLockBox (
+ &gEdkiiS3MtrrSettingGuid,
+ &MtrrTable,
+ &VarSize
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // Sync up the MTRR values for all processors.
+ //
+ Status = MpService2Ppi->StartupAllCPUs (
+ MpService2Ppi,
+ (EFI_AP_PROCEDURE)LoadMtrrData,
+ 0,
+ (VOID *)&MtrrTable
+ );
+ ASSERT_EFI_ERROR (Status);
+
SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *)GET_GUID_HOB_DATA (GuidHob);
SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
@@ -1090,7 +1152,6 @@ S3RestoreConfig2 (
SmmS3ResumeState->ReturnContext1 = (EFI_PHYSICAL_ADDRESS)(UINTN)AcpiS3Context;
SmmS3ResumeState->ReturnContext2 = (EFI_PHYSICAL_ADDRESS)(UINTN)EfiBootScriptExecutorVariable;
SmmS3ResumeState->ReturnStackPointer = (EFI_PHYSICAL_ADDRESS)STACK_ALIGN_DOWN (&Status);
- SmmS3ResumeState->MpService2Ppi = 0;
DEBUG ((DEBUG_INFO, "SMM S3 Signature = %x\n", SmmS3ResumeState->Signature));
DEBUG ((DEBUG_INFO, "SMM S3 Stack Base = %x\n", SmmS3ResumeState->SmmS3StackBase));
@@ -1119,19 +1180,6 @@ S3RestoreConfig2 (
if (((SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_32) && (sizeof (UINTN) == sizeof (UINT32))) ||
((SmmS3ResumeState->Signature == SMM_S3_RESUME_SMM_64) && (sizeof (UINTN) == sizeof (UINT64))))
{
- //
- // Get MP Services2 Ppi to pass it to Smm S3.
- //
- Status = PeiServicesLocatePpi (
- &gEdkiiPeiMpServices2PpiGuid,
- 0,
- NULL,
- (VOID **)&MpService2Ppi
- );
- ASSERT_EFI_ERROR (Status);
- SmmS3ResumeState->MpService2Ppi = (EFI_PHYSICAL_ADDRESS)(UINTN)MpService2Ppi;
- DEBUG ((DEBUG_INFO, "SMM S3 MpService2Ppi Point = %lx\n", SmmS3ResumeState->MpService2Ppi));
-
SwitchStack (
(SWITCH_STACK_ENTRY_POINT)(UINTN)SmmS3ResumeState->SmmS3ResumeEntryPoint,
(VOID *)AcpiS3Context,
diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
index 9c9b6f3db3..54de8bc91f 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume2Pei.inf
@@ -5,7 +5,7 @@
# This module will excute the boot script saved during last boot and after that,
# control is passed to OS waking up handler.
#
-# Copyright (c) 2010 - 2023, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2010 - 2024, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
@@ -67,6 +67,7 @@
LocalApicLib
ReportStatusCodeLib
LockBoxLib
+ MtrrLib
[Guids]
gEfiBootScriptExecutorVariableGuid ## SOMETIMES_CONSUMES ## UNDEFINED # LockBox
@@ -79,6 +80,7 @@
## SOMETIMES_PRODUCES ## UNDEFINED # Install PPI
## SOMETIMES_CONSUMES ## UNDEFINED # Used to do smm communication
gEdkiiS3SmmInitDoneGuid
+ gEdkiiS3MtrrSettingGuid
[Ppis]
gEfiPeiS3Resume2PpiGuid ## PRODUCES
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/UefiPayloadEntry/LoadDxeCore.c b/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
index 898d610951..3e13496147 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
+++ b/UefiPayloadPkg/UefiPayloadEntry/LoadDxeCore.c
@@ -211,14 +211,15 @@ FileFindSection (
if (IS_FFS_FILE2 (FileHeader)) {
FileSize = FFS_FILE2_SIZE (FileHeader);
+ Section = (EFI_COMMON_SECTION_HEADER *)(((EFI_FFS_FILE_HEADER2 *)FileHeader) + 1);
} else {
FileSize = FFS_FILE_SIZE (FileHeader);
+ Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1);
}
FileSize -= sizeof (EFI_FFS_FILE_HEADER);
- Section = (EFI_COMMON_SECTION_HEADER *)(FileHeader + 1);
- Index = 0;
+ Index = 0;
while (Index < FileSize) {
if (Section->Type == SectionType) {
if (IS_SECTION2 (Section)) {
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/UefiPayloadPkg/UniversalPayloadBuild.py b/UefiPayloadPkg/UniversalPayloadBuild.py
index 0423e6da17..59c78a21b4 100644
--- a/UefiPayloadPkg/UniversalPayloadBuild.py
+++ b/UefiPayloadPkg/UniversalPayloadBuild.py
@@ -112,6 +112,8 @@ def RunCommand(cmd):
raise Exception("ERROR: when run command: %s"%cmd)
def BuildUniversalPayload(Args):
+ DscPath = os.path.normpath(Args.DscPath)
+ print("Building FIT for DSC file %s"%DscPath)
BuildTarget = Args.Target
ToolChain = Args.ToolChain
Quiet = "--quiet" if Args.Quiet else ""
@@ -140,7 +142,6 @@ def BuildUniversalPayload(Args):
EntryOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, PayloadEntryToolChain), os.path.normpath("{}/UefiPayloadPkg/UefiPayloadEntry/{}/DEBUG/{}.dll".format (Args.Arch, UpldEntryFile, UpldEntryFile)))
EntryModuleInf = os.path.normpath("UefiPayloadPkg/UefiPayloadEntry/{}.inf".format (UpldEntryFile))
- DscPath = os.path.normpath("UefiPayloadPkg/UefiPayloadPkg.dsc")
DxeFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/DXEFV.Fv"))
BdsFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/BDSFV.Fv"))
NetworkFvOutputDir = os.path.join(BuildDir, "{}_{}".format (BuildTarget, ToolChain), os.path.normpath("FV/NETWORKFV.Fv"))
@@ -321,6 +322,7 @@ def main():
parser.add_argument("-af", "--AddFv", type=ValidateAddFv, action='append', help='Add or replace specific FV into payload, Ex: uefi_fv=XXX.fv')
parser.add_argument("-f", "--Fit", action='store_true', help='Build UniversalPayload file as UniversalPayload.fit', default=False)
parser.add_argument('-l', "--LoadAddress", type=int, help='Specify payload load address', default =0x000800000)
+ parser.add_argument('-c', '--DscPath', type=str, default="UefiPayloadPkg/UefiPayloadPkg.dsc", help='Path to the DSC file')
args = parser.parse_args()
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